1#include "EntityInspector.h"
5#include "EntityStore.h"
8#include "Editor/IEditor.h"
10#include "InspectorGuiHelper.h"
11#include "Inspectors.h"
13#include "Components/Core/PropertiesComponent.h"
14#include "Components/Core/SceneComponent.h"
16#include "Resources/Resources.h"
17#include "Resources/TextureManager.h"
18#include "Renderer/Renderer.h"
19#include "Renderer/RenderTexture.h"
20#include "Resources/MaterialInstance.h"
21#include "Resources/Model.h"
22#include "Resources/Mesh.h"
24#include "Foundation/ComponentModel/Entity.h"
25#include "Foundation/Reflection/TypeDatabase.h"
29#include <glm/vec2.hpp>
30#include <glm/vec3.hpp>
31#include <glm/vec4.hpp>
32#include <glm/mat4x4.hpp>
33#include <glm/ext/quaternion_float.hpp>
46void Cogs::Core::showCollapsableEntityInspector(
Cogs::Core::Context* context,
const ComponentModel::Entity* entity, std::string_view entityNamePattern, std::string_view componentNamePattern,
bool showBorder)
49 std::array<char, 128> header = {};
50 std::snprintf(header.data(), header.size(),
"%s Id: %zu", entity->
getName().c_str(), entity->
getId());
52 ImGui::PushID(entity);
54 if (ImGui::TreeNodeEx(header.data(), ImGuiTreeNodeFlags_NoAutoOpenOnLog | (showBorder ? ImGuiTreeNodeFlags_Framed : 0))) {
56 showEntityInspector(context, entity, entityNamePattern, componentNamePattern, showBorder);
65void Cogs::Core::showEntities(Context * context, std::span<const EntityPtr> entities, std::string_view entityNamePattern, std::string_view componentNamePattern)
67 for (
const EntityPtr & e : entities) {
68 showCollapsableEntityInspector(context, e.get(), entityNamePattern, componentNamePattern);
72void Cogs::Core::showEntityInspector(Context* context,
const ComponentModel::Entity* entity, std::string_view entityNamePattern, std::string_view componentNamePattern,
bool showBorder)
74 ImGui::Text(
"Id: %zd", entity->
getId());
76 const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
77 static std::array<char, 65> buffer;
78 ImGui::SameLine(0.0f, spacing);
79 constexpr int widthInputText = 120;
80 ImGui::PushItemWidth(widthInputText);
81 ImGui::Text(
"Filter: ");
82 ImGui::SameLine(0.0f, spacing);
83 if (ImGui::InputText(
" ", buffer.data(), buffer.size(), ImGuiInputTextFlags_None)) {
84 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
86 guiRenderer->addTextToGlyphBuilder(buffer.data());
89 ImGui::PopItemWidth();
91 std::string_view findPattern = buffer.data();
96 bool showComponent = (bool)component;
97 if(showComponent && !findPattern.empty()) {
102 showComponentInspector(context, component, entityNamePattern, componentNamePattern, showBorder);
107void Cogs::Core::showComponentInspector(Context* context,
ComponentModel::Component* component, std::string_view entityNamePattern, std::string_view componentNamePattern,
bool showBorder)
111 if (ImGui::TreeNodeEx(componentType->
getName().
getName().c_str(), ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog | (showBorder ? ImGuiTreeNodeFlags_Framed : 0))) {
112 ImGui::PushID(component);
114 const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
115 static std::array<char, 65> buffer;
116 ImGui::SameLine(0.0f, spacing);
117 constexpr int widthInputText = 120;
118 ImGui::PushItemWidth(widthInputText);
119 ImGui::Text(
"Filter: ");
120 ImGui::SameLine(0.0f, spacing);
121 if (ImGui::InputText(
" ", buffer.data(), buffer.size(), ImGuiInputTextFlags_None)) {
122 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
124 guiRenderer->addTextToGlyphBuilder(buffer.data());
127 ImGui::PopItemWidth();
128 auto updateGui = componentType->
getMethod(
"updateGui");
130 updateGui->
call(component);
135 std::string_view findPattern = buffer.data();
138 ScopedIndent si_type;
141 for (FieldId fieldId = 0; fieldId < numFields; ++fieldId) {
142 bool showField =
true;
143 if(!findPattern.empty()) {
144 showField = containsInvariantCase(componentType->
getField(fieldId)->
getName().
c_str(), findPattern);
148 showFieldInspector(context, component, fieldId, entityNamePattern, componentNamePattern, showBorder);
156void Cogs::Core::showFieldInspector(Context* context,
ComponentModel::Component* component, FieldId fieldId, std::string_view entityNamePattern, std::string_view componentNamePattern,
bool showBorder)
163 const std::string & fieldHeader = fieldName.
getName();
167 if (fieldType == TypeDatabase::getType<int32_t>()) {
168 auto fieldValue = field->
getPtr<int32_t>(component);
171 const int32_t min = std::min(range->getMin(), *fieldValue);
172 const int32_t max = std::max(range->getMax(), *fieldValue);
173 if (ImGui::SliderInt(fieldHeader.c_str(), fieldValue, min, max)) {
178 if (ImGui::DragInt(fieldHeader.c_str(), fieldValue)) {
183 else if (fieldType == TypeDatabase::getType<float>()) {
184 auto fieldValue = field->
getPtr<
float>(component);
188 const float min = std::min(range ? range->getMin() : 0.0f, *fieldValue);
189 const float max = std::max(range ? range->getMax() : 100.0f, *fieldValue);
190 const float stepValue = (max - min) / 100.f;
192 if (ImGui::DragFloat(fieldHeader.c_str(), fieldValue, stepValue, min, max)) {
197 if (ImGui::DragFloat(fieldHeader.c_str(), fieldValue)) {
202 else if (fieldType == TypeDatabase::getType<glm::vec2>()) {
203 auto fieldValue = field->
getPtr<glm::vec2>(component);
205 if (ImGui::DragFloat2(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
209 else if (fieldType == TypeDatabase::getType<glm::vec3>()) {
210 auto fieldValue = field->
getPtr<glm::vec3>(component);
212 if (ImGui::DragFloat3(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
216 else if (fieldType == TypeDatabase::getType<glm::vec4>()) {
217 auto fieldValue = field->
getPtr<glm::vec4>(component);
221 if (ca || (fieldName.
getName().find(
"olor") != std::string::npos)) {
222 if (ImGui::ColorEdit4(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
226 if (ImGui::DragFloat4(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
231 else if (fieldType == TypeDatabase::getType<glm::ivec2>()) {
232 auto fieldValue = field->
getPtr<glm::ivec2>(component);
233 if (ImGui::DragInt2(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
237 else if (fieldType == TypeDatabase::getType<glm::ivec3>()) {
238 auto fieldValue = field->
getPtr<glm::ivec3>(component);
239 if (ImGui::DragInt3(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
243 else if (fieldType == TypeDatabase::getType<glm::ivec4>()) {
244 auto fieldValue = field->
getPtr<glm::ivec4>(component);
245 if (ImGui::DragInt4(fieldHeader.c_str(), glm::value_ptr(*fieldValue))) {
249 else if (fieldType == TypeDatabase::getType<glm::uvec2>()) {
250 auto fieldValue = field->
getPtr<glm::uvec2>(component);
251 glm::ivec2 tmp = *fieldValue;
252 if (ImGui::DragInt2(fieldHeader.c_str(), glm::value_ptr(tmp))) {
257 else if (fieldType == TypeDatabase::getType<glm::uvec3>()) {
258 auto fieldValue = field->
getPtr<glm::uvec3>(component);
259 glm::ivec3 tmp = *fieldValue;
260 if (ImGui::DragInt3(fieldHeader.c_str(), glm::value_ptr(tmp))) {
265 else if (fieldType == TypeDatabase::getType<glm::uvec4>()) {
266 auto fieldValue = field->
getPtr<glm::uvec4>(component);
267 glm::ivec4 tmp = *fieldValue;
268 if (ImGui::DragInt4(fieldHeader.c_str(), glm::value_ptr(tmp))) {
273 else if (fieldType == TypeDatabase::getType<glm::dvec2>()) {
274 auto fieldValue = field->
getPtr<glm::dvec2>(component);
276 glm::vec2 fValues(*fieldValue);
278 if (ImGui::DragFloat2(fieldHeader.c_str(), glm::value_ptr(fValues))) {
279 *fieldValue = glm::dvec2(fValues);
283 else if (fieldType == TypeDatabase::getType<glm::dvec3>()) {
284 auto fieldValue = field->
getPtr<glm::dvec3>(component);
286 glm::vec3 fValues(*fieldValue);
288 if (ImGui::DragFloat3(fieldHeader.c_str(), glm::value_ptr(fValues))) {
289 *fieldValue = glm::dvec3(fValues);
293 else if (fieldType == TypeDatabase::getType<glm::quat>()) {
294 auto fieldValue = field->
getPtr<glm::quat>(component);
296 glm::vec3 euler = glm::eulerAngles(*fieldValue);
297 if (ImGui::DragFloat3(
"Euler", glm::value_ptr(euler), 0.01f, -3.14f, 3.14f)) {
298 float eps = 0.00001f;
299 if (euler.y >= glm::pi<float>() / 2.0f - eps)
300 euler.y = glm::pi<float>() / 2.0f - eps;
301 else if (euler.y <= -glm::pi<float>() / 2.0f + eps)
302 euler.y = -glm::pi<float>() / 2.0f + eps;
303 *fieldValue = glm::quat(euler);
308 if (ImGui::DragFloat4(fieldHeader.c_str(), glm::value_ptr(*fieldValue), 0.01f, 0, 1)) {
312 else if (fieldType == TypeDatabase::getType<glm::mat4>()) {
313 auto fieldValue = field->
getPtr<glm::mat4>(component);
315 ImGui::PushID(field);
317 if (showMatrix(fieldHeader, *fieldValue)) {
322 else if (fieldType == TypeDatabase::getType<bool>()) {
323 auto fieldValue = field->
getPtr<
bool>(component);
325 if (ImGui::Checkbox(fieldHeader.c_str(), fieldValue)) {
329 else if (fieldType == TypeDatabase::getType<uint32_t>()) {
330 auto fieldValue = field->
getPtr<uint32_t>(component);
331 ImGui::Text(
"%s: 0x%08x", fieldHeader.c_str(), *fieldValue);
333 int tmp =
static_cast<int>(*fieldValue);
336 const int min = std::min(tmp,
static_cast<int>(range->getMin()));
337 const int max = std::max(tmp,
static_cast<int>(range->getMax()));
338 if (ImGui::SliderInt(fieldHeader.c_str(), &tmp, min, max)) {
339 *fieldValue =
static_cast<uint32_t
>(tmp);
344 if (ImGui::DragInt(fieldHeader.c_str(), &tmp)) {
345 *fieldValue =
static_cast<uint32_t
>(tmp);
350 else if (fieldType.
isEnum()) {
351 auto fieldValue = field->
getPtr<uint32_t>(component);
352 auto value = *fieldValue;
355 ImGui::Text(
"%s (%d = 0x%08X):", fieldHeader.c_str(), value, value);
358 ImGui::PushID(field);
362 for (
size_t i = 0; i < numEnums; ++i) {
364 auto enumeratorValue = enumerator->
getValue();
366 if (std::popcount(
static_cast<uint32_t
>(enumeratorValue)) != 1)
continue;
368 if (ImGui::CheckboxFlags(enumerator->getName().c_str(), &value, enumeratorValue)) {
378 std::vector<const char *> enumNames(enums);
379 std::vector<int> enumValues(enums);
381 for (
size_t i = 0; i < enums; ++i) {
384 if (enumValues[i] ==
static_cast<int>(*fieldValue)) index =
static_cast<int>(i);
387 if (ImGui::Combo(fieldHeader.c_str(), &index, enumNames.data(),
static_cast<int>(enumNames.size()))) {
388 *fieldValue = enumValues[index];
394 auto fieldValue = field->
getPtr<std::vector<EntityPtr>>(component);
395 showEntities(context, *fieldValue, entityNamePattern, componentNamePattern);
397 else if (fieldType == TypeDatabase::getType<MeshHandle>()) {
398 auto & fieldValue = *field->
getPtr<MeshHandle>(component);
401 showMesh(context, fieldValue.resolve(), fieldHeader);
406 else if (fieldType == TypeDatabase::getType<TextureHandle>()) {
409 auto editor = context->engine->getEditor();
410 if (editor && editor->isActive()) {
411 if (editor->showTexture(field->
getName().
c_str(), *fieldValue)) {
417 if (ImGui::CollapsingHeader(field->
getName().
c_str())) {
418 Texture* texture = fieldValue->resolve();
420 showTexture(context, renderer, texture);
428 else if (fieldType == TypeDatabase::getType<WeakEntityPtr>()) {
430 if (
auto spt = fieldValue->lock())
432 showEntityInspector(context, &(*spt), entityNamePattern, componentNamePattern, showBorder);
437 else if (fieldType == TypeDatabase::getType<std::string>()) {
438 auto fieldValue = field->
getPtr<std::string>(component);
439 std::string buffer = *fieldValue;
441 if (ImGui::InputText(field->
getName().
c_str(), &buffer[0], buffer.size())) {
442 for (
size_t i = 0; i < buffer.size(); i++) {
443 if (buffer[i] ==
'\0') {
449 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
451 guiRenderer->addTextToGlyphBuilder(buffer.c_str());
454 *fieldValue = std::move(buffer);
458 auto fieldValue = field->
getPtr<std::vector<std::string>>(component);
459 if (fieldValue->empty())
465 if (ImGui::CollapsingHeader(std::string(fieldHeader +
" [size=" + std::to_string(fieldValue->size()) +
"]").c_str()))
468 for (
auto& s : *fieldValue) {
469 auto label = std::to_string(i++);
470 std::string buffer = s;
472 if (ImGui::InputText(label.c_str(), &buffer[0], buffer.size())) {
474 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
476 guiRenderer->addTextToGlyphBuilder(buffer.c_str());
486 auto fieldValue = field->
getPtr<std::vector<int32_t>>(component);
492 auto fieldValue = field->
getPtr<std::vector<uint32_t>>(component);
498 auto fieldValue = field->
getPtr<std::vector<float>>(component);
504 auto fieldValue = field->
getPtr<std::vector<glm::vec3>>(component);
505 if (showArray3D(fieldHeader, *fieldValue)) {
510 auto fieldValue = field->
getPtr<std::vector<glm::vec2>>(component);
511 if (fieldValue->empty())
515 else if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
518 for (
auto& v : *fieldValue) {
519 auto label = std::to_string(i++);
520 if (ImGui::DragFloat2(label.c_str(), glm::value_ptr(v))) {
527 auto fieldValue = field->
getPtr<std::vector<glm::vec4>>(component);
528 if (fieldValue->empty()) {
531 else if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
534 for (
auto& v : *fieldValue) {
535 auto label = std::to_string(i++);
536 if (ImGui::DragFloat4(label.c_str(), glm::value_ptr(v))) {
542 else if (fieldType == TypeDatabase::getType<MaterialInstanceHandle>()) {
543 auto fieldValue = field->
getPtr<MaterialInstanceHandle>(component);
545 auto * material = fieldValue->resolve();
547 showMaterialInstance(context, material, header);
550 ImGui::Text(
"%s: NULL", header.c_str());
554 auto fieldValue = field->
getPtr<std::vector<MaterialInstanceHandle>>(component);
555 if (fieldValue->empty()) {
558 else if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
561 for (
auto& v : *fieldValue) {
562 auto* material = v.resolve();
564 auto label =
"Mat: " + std::to_string(i++);
566 showMaterialInstance(context, material, label);
569 ImGui::Text(
"%s: NULL", label.c_str());
574 else if (fieldType == TypeDatabase::getType<EntityPtr>()) {
576 if (fieldValue->get()) {
577 showEntityInspector(context, fieldValue->get(), entityNamePattern, componentNamePattern, showBorder);
583 else if (fieldType == TypeDatabase::getType<Cogs::Core::FontHandle>()) {
585 if (fieldValue->get()) {
588 ImGui::Text(
"%d", fieldValue->getId());
594 else if (fieldType == TypeDatabase::getType<ModelHandle>()) {
595 auto fieldValue = field->
getPtr<ModelHandle>(component);
597 Model * model = fieldValue->resolve();
599 auto header = (!model->getName().empty() ? model->getName() :
"Model");
600 showModel(context, model, std::string(header));
605 else if (fieldType == TypeDatabase::getType<PropertyStore>()) {
606 PropertyStore* propStore = field->
getPtr<PropertyStore>(component);
607 assert(propStore !=
nullptr);
610 const std::string propName(propStore->getKey(header));
612 switch(header.type) {
613 case Cogs::Core::PropertyType::Bool: {
614 ImGui::Text(
"%s: %s", propName.c_str(), header.boolValue ?
"true" :
"false");
617 case Cogs::Core::PropertyType::Integer: {
618 ImGui::Text(
"%s: %d", propName.c_str(), header.intValue);
621 case Cogs::Core::PropertyType::Int2: {
622 ImGui::Text(
"%s: (%d, %d)", propName.c_str(), header.int2Value[0], header.int2Value[1]);
625 case Cogs::Core::PropertyType::UnsignedInteger: {
626 ImGui::Text(
"%s: %u", propName.c_str(), header.uintValue);
629 case Cogs::Core::PropertyType::UInt2: {
630 ImGui::Text(
"%s: (%u, %u)", propName.c_str(), header.uint2Value[0], header.uint2Value[1]);
633 case Cogs::Core::PropertyType::Float: {
634 ImGui::Text(
"%s: %f", propName.c_str(), header.floatValue);
637 case Cogs::Core::PropertyType::Float2: {
638 ImGui::Text(
"%s: (%f, %f)", propName.c_str(), header.float2Value[0], header.float2Value[1]);
641 case Cogs::Core::PropertyType::Double: {
642 ImGui::Text(
"%s: %f", propName.c_str(), header.doubleValue);
645 case Cogs::Core::PropertyType::StringRef: {
646 ImGui::Text(
"%s: %s", propName.c_str(), Cogs::Core::Strings::getC(header.stringRefValue));
649 case Cogs::Core::PropertyType::String: {
650 ImGui::Text(
"%s: %.*s", propName.c_str(), StringViewFormat(propStore->getString(header)));
653 case Cogs::Core::PropertyType::FloatArray: {
654 showArray1D(propName, propStore->getFloatArray(header));
657 case Cogs::Core::PropertyType::IntArray: {
658 showArray1D(propName, propStore->getIntArray(header));
661 case Cogs::Core::PropertyType::UIntArray: {
662 showArray1D(propName, propStore->getUIntArray(header));
665 case Cogs::Core::PropertyType::DoubleArray: {
666 showArray1D(propName, propStore->getDoubleArray(header));
670 assert(
false &&
"Unsupported PropertyType");
680void Cogs::Core::entityInspector(Context * context,
bool * show)
683 ImGui::SetNextWindowSize(ImVec2(400, 1000), ImGuiCond_Once);
685 guiBegin(
"Entities", show);
687 const std::unordered_map<EntityId, EntityPtr>& entities = context->store->getEntities();
690 static bool onlyRootEntities =
true;
691 size_t numEntities = 0;
692 if (onlyRootEntities) {
693 for (
const auto& [
id, entity] : entities) {
694 if (context->store->getEntityParent(entity.get()) ==
nullptr) {
700 numEntities = entities.size();
703 ImGui::Text(
"Entities: %zu", numEntities);
705 const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
706 ImGui::SameLine(0.0f, spacing);
708 ImGui::SameLine(0.0f, spacing);
709 if (ImGui::RadioButton(
"Root Entities", onlyRootEntities ==
true)) { onlyRootEntities =
true; }
710 ImGui::SameLine(0.0f, spacing);
711 if (ImGui::RadioButton(
"All User", onlyRootEntities ==
false)) { onlyRootEntities =
false; }
714 std::string_view entityNamePattern;
716 static std::array<char, 33> nameFilterBuffer;
717 constexpr int widthInputText = 120;
718 ImGui::PushItemWidth(widthInputText);
719 ImGui::Text(
"Name:");
720 ImGui::SameLine(0.0f, spacing);
721 if (ImGui::InputText(
" ", nameFilterBuffer.data(), nameFilterBuffer.size(), ImGuiInputTextFlags_None)) {
722 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
724 guiRenderer->addTextToGlyphBuilder(nameFilterBuffer.data());
727 entityNamePattern = nameFilterBuffer.data();
730 std::string_view componentNamePattern;
732 static std::array<char, 33> componentFilterBuffer;
733 ImGui::SameLine(0.0f, spacing);
734 ImGui::Text(
"Componen:");
735 ImGui::SameLine(0.0f, spacing);
736 if (ImGui::InputText(
" ", componentFilterBuffer.data(), componentFilterBuffer.size(), ImGuiInputTextFlags_None)) {
737 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
739 guiRenderer->addTextToGlyphBuilder(componentFilterBuffer.data());
742 componentNamePattern = componentFilterBuffer.data();
745 ImGui::PopItemWidth();
749 bool showOnlyMultiRefs =
false;
750 if (!entityNamePattern.empty() && entityNamePattern[0] ==
'+') {
751 showOnlyMultiRefs =
true;
752 entityNamePattern = entityNamePattern.substr(1);
756 ImGui::BeginChild(
"Child");
757 for (
const auto& [
id, entity] : entities) {
758 bool showEntity = entity.operator bool();
759 if (showOnlyMultiRefs) {
760 showEntity = entity.use_count() > 1;
763 if (showEntity && (!entityNamePattern.empty() || !componentNamePattern.empty())) {
767 if (showEntity && onlyRootEntities) {
768 showEntity = context->store->getEntityParent(entity.get()) ==
nullptr;
772 showCollapsableEntityInspector(context, entity.get(), entityNamePattern, componentNamePattern);
Base class for Component instances.
void setFieldChanged(const Reflection::FieldId fieldId)
Sets the component to the ComponentFlags::Changed state without carry.
COGSFOUNDATION_API const Reflection::Type & getType() const
Get the full Reflection::Type of the component.
Container for components, providing composition of dynamic entities.
constexpr size_t getId() const noexcept
Get the unique identifier of this entity.
void getComponents(ComponentCollection< T > &collection) const
Get all the components implementing the templated type.
const std::string & getName() const noexcept
Get the name of this entity.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Field definition describing a single data member of a data structure.
const Name & getName() const
Get the name of the field.
const T * get() const
Retrieve an attribute of the given type from storage, if present.
TypeId getTypeId() const
Get the type id of the field.
FieldValueType * getPtr(void *container) const
Get a pointer to this field on the given container.
void call(Class *object, Arg... arg) const
Call the method named name on the given object, with the given arguments.
static const Type & getType()
Get the Type of the given template argument.
Represents a discrete type definition, describing a native type class.
const Enumerator * getEnumerator(const Name &name) const
Get a pointer to the enumerator with the given name.
const Method * getMethod(const Name &name) const
Get a pointer to the method with the given name.
bool isEnum() const
Get if the type is an enumeration type.
constexpr const Name & getName() const
Get the unique name of the type.
bool isEnumFlags() const
Get if the type is a flag enumeration type.
size_t getNumHierarchyFields() const
Get the number of fields in the type + types in all base types.
size_t getNumEnumerators() const
Get the number of enumerators in the type.
const Field * getField(const Name &name) const
Get a pointer to the field info of the field with the given name.
constexpr TypeId getTypeId() const
Get the unique Reflection::TypeId of this instance.
Contains code for composing and managing entities built from components.
bool findHierarchyWithMatch(const Cogs::ComponentModel::Entity &entity, std::string_view entityNamePattern, std::string_view componentNamePattern)
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
std::weak_ptr< ComponentModel::Entity > WeakEntityPtr
Weak Smart pointer for Entity access.
bool showArray1D(const std::string &header, std::span< T > array)
Contains reflection support.
Tags an object as being able to represent a color.
Handle to a Component instance.
Adds range information to an object.
const Name & getName() const
Get the name of the enumerator.
int getValue() const
Get the value of the enumerator.
Represents an unique name.
const char * c_str() const
Gets the name as a null-terminated string.
const std::string & getName() const
Get the string name. This can be empty, even in valid instances of Name.