1#include "EntityEditor.h"
3#include "Renderer/IRenderer.h"
4#include "Renderer/InspectorGui/InspectorGuiHelper.h"
5#include "Renderer/InspectorGui/EntityInspector.h"
7#include "MaterialEditor.h"
9#include "Components/Core/PropertiesComponent.h"
11#include "Systems/Core/TransformSystem.h"
12#include "Systems/Core/CameraSystem.h"
14#include "Resources/MaterialInstance.h"
15#include "Resources/Mesh.h"
17#include "Bridge/Bridge.h"
18#include "Bridge/SceneFunctions.h"
20#include "Commands/FieldCommands.h"
24#include "Foundation/Geometry/BoundingBox.hpp"
25#include "Foundation/Reflection/TypeDatabase.h"
38 std::span<const Cogs::Core::PropertyInfo> headers = props.getHeaders();
41 const std::string propName = props.getKey(header).
to_string();
44 case Cogs::Core::PropertyType::Bool: {
45 editor.
showText(
"%s: %s", propName.c_str(), header.boolValue ?
"true" :
"false");
48 case Cogs::Core::PropertyType::Integer: {
49 editor.
showText(
"%s: %d", propName.c_str(), header.intValue);
52 case Cogs::Core::PropertyType::Int2: {
53 editor.
showText(
"%s: (%d, %d)", propName.c_str(), header.int2Value[0], header.int2Value[1]);
56 case Cogs::Core::PropertyType::UnsignedInteger: {
57 editor.
showText(
"%s: %u", propName.c_str(), header.uintValue);
60 case Cogs::Core::PropertyType::UInt2: {
61 editor.
showText(
"%s: (%u, %u)", propName.c_str(), header.uint2Value[0], header.uint2Value[1]);
64 case Cogs::Core::PropertyType::Float: {
65 editor.
showText(
"%s: %f", propName.c_str(), header.floatValue);
68 case Cogs::Core::PropertyType::Float2: {
69 editor.
showText(
"%s: (%f, %f)", propName.c_str(), header.float2Value[0], header.float2Value[1]);
72 case Cogs::Core::PropertyType::Double: {
73 editor.
showText(
"%s: %f", propName.c_str(), header.doubleValue);
76 case Cogs::Core::PropertyType::StringRef: {
77 editor.
showText(
"%s: %s", propName.c_str(), Cogs::Core::Strings::getC(header.stringRefValue));
80 case Cogs::Core::PropertyType::String: {
81 editor.
showText(
"%s: %s", propName.c_str(), props.getString(header).
to_string().c_str());
84 case Cogs::Core::PropertyType::FloatArray: {
85 std::span<const float> floats = props.getFloatArray(header);
87 editor.
showText(
"%s: Empty", propName.c_str());
90 if (ImGui::TreeNode((propName +
" [size=" + std::to_string(floats.size()) +
"]").c_str())) {
91 for (
size_t i = 0; i < floats.size(); i++) {
92 editor.
showText(
"%zu: %f", i, floats[i]);
99 case Cogs::Core::PropertyType::IntArray: {
100 std::span<const int32_t> ints = props.getIntArray(header);
102 editor.
showText(
"%s: Empty", propName.c_str());
105 if (ImGui::TreeNode((propName +
" [size=" + std::to_string(ints.size()) +
"]").c_str())) {
106 for (
size_t i = 0; i < ints.size(); i++) {
107 editor.
showText(
"%zu: %d", i, ints[i]);
114 case Cogs::Core::PropertyType::UIntArray: {
115 std::span<const uint32_t> uints = props.getUIntArray(header);
117 editor.
showText(
"%s: Empty", propName.c_str());
120 if (ImGui::TreeNode((propName +
" [size=" + std::to_string(uints.size()) +
"]").c_str())) {
121 for (
size_t i = 0; i < uints.size(); i++) {
122 editor.
showText(
"%zu: %u", i, uints[i]);
129 case Cogs::Core::PropertyType::DoubleArray: {
130 std::span<const double> doubles = props.getDoubleArray(header);
131 if (doubles.empty()) {
132 editor.
showText(
"%s: Empty", propName.c_str());
135 if (ImGui::TreeNode((propName +
" [size=" + std::to_string(doubles.size()) +
"]").c_str())) {
136 for (
size_t i = 0; i < doubles.size(); i++) {
137 editor.
showText(
"%zu: %f", i, doubles[i]);
145 assert(
false &&
"Unsupported PropertyType");
152void Cogs::Core::EntityEditor::showEntityEditor(Context* context, Editor* editor,
ComponentModel::Entity* entity)
154 editor->showText(
"%s", entity->
getName().c_str());
155 const char* entityTemplate = ::getEntityTemplate(context, entity->
getId());
156 if (entityTemplate) {
157 editor->showText(
"Type: %s", entityTemplate);
160 editor->showText(
"Id: %zd", entity->
getId());
164 std::string componentHeader;
165 componentHeader.reserve(128);
167 for (
auto& c : components) {
169 showComponentEditor(context, editor, entity, component);
178 if (ImGui::TreeNodeEx(typeName.
c_str(), ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog)) {
179 ScopedIndent componentIndent;
181 ImGui::PushID(component);
185 if (typeName ==
"TransformComponent") {
186 const TransformComponent* transform =
static_cast<const TransformComponent*
>(component);
187 for (FieldId fieldId = 0; fieldId < numFields; ++fieldId) {
190 if (fieldName ==
"transformFlags") {
193 }
else if (fieldName ==
"transform") {
195 if (!transform->transformFlags) {
201 if (transform->transformFlags) {
207 if (fieldName ==
"coordinates" && context->store->getEntityParent(entity) && transform->coordinates == glm::dvec3(0, 0, 0)) {
211 showFieldEditor(context, editor, component, fieldId);
215 for (FieldId fieldId = 0; fieldId < numFields; ++fieldId) {
216 showFieldEditor(context, editor, component, fieldId);
230 FieldInfo fieldInfo{ componentType->
getTypeId(), fieldId };
232 const std::string& fieldHeader = fieldName.
getName();
236 if (fieldType == TypeDatabase::getType<int32_t>()) {
237 auto value = *field->
getPtr<int32_t>(component);
240 const int32_t min = std::min(range->getMin(), value);
241 const int32_t max = std::max(range->getMax(), value);
242 if (ImGui::SliderInt(fieldHeader.c_str(), &value, min, max)) {
243 editor->applySelected<SetFieldCommand<int32_t>>(fieldInfo, value);
247 if (ImGui::DragInt(fieldHeader.c_str(), &value)) {
248 editor->applySelected<SetFieldCommand<int32_t>>(fieldInfo, value);
252 else if (fieldType == TypeDatabase::getType<float>()) {
253 auto value = *field->
getPtr<
float>(component);
257 const float min = std::min(range ? range->getMin() : 0.0f, value);
258 const float max = std::max(range ? range->getMax() : 100.0f, value);
259 const float stepValue = (max - min) / 100.f;
261 if (ImGui::DragFloat(fieldHeader.c_str(), &value, stepValue, min, max)) {
262 editor->applySelected<SetFieldCommand<float>>(fieldInfo, value);
266 if (ImGui::DragFloat(fieldHeader.c_str(), &value)) {
267 editor->applySelected<SetFieldCommand<float>>(fieldInfo, value);
271 else if (fieldType == TypeDatabase::getType<glm::vec2>()) {
272 auto value = *field->
getPtr<glm::vec2>(component);
274 if (ImGui::DragFloat2(fieldHeader.c_str(), glm::value_ptr(value))) {
275 editor->applySelected<SetFieldCommand<glm::vec2>>(fieldInfo, value);
278 else if (fieldType == TypeDatabase::getType<glm::vec3>()) {
279 auto value = *field->
getPtr<glm::vec3>(component);
281 if (ImGui::DragFloat3(fieldHeader.c_str(), glm::value_ptr(value))) {
282 editor->applySelected<SetFieldCommand<glm::vec3>>(fieldInfo, value);
285 else if (fieldType == TypeDatabase::getType<glm::vec4>()) {
286 auto value = *field->
getPtr<glm::vec4>(component);
290 if (ca || (fieldName.
getName().find(
"olor") != std::string::npos)) {
291 if (ImGui::ColorEdit4(fieldHeader.c_str(), glm::value_ptr(value))) {
292 editor->applySelected<SetFieldCommand<glm::vec4>>(fieldInfo, value);
295 if (ImGui::DragFloat4(fieldHeader.c_str(), glm::value_ptr(value))) {
296 editor->applySelected<SetFieldCommand<glm::vec4>>(fieldInfo, value);
300 else if (fieldType == TypeDatabase::getType<glm::ivec2>()) {
301 auto value = *field->
getPtr<glm::ivec2>(component);
302 if (ImGui::DragInt2(fieldHeader.c_str(), glm::value_ptr(value))) {
303 editor->applySelected<SetFieldCommand<glm::ivec2>>(fieldInfo, value);
306 else if (fieldType == TypeDatabase::getType<glm::ivec3>()) {
307 auto value = *field->
getPtr<glm::ivec3>(component);
308 if (ImGui::DragInt3(fieldHeader.c_str(), glm::value_ptr(value))) {
309 editor->applySelected<SetFieldCommand<glm::ivec3>>(fieldInfo, value);
312 else if (fieldType == TypeDatabase::getType<glm::ivec4>()) {
313 auto value = *field->
getPtr<glm::ivec4>(component);
314 if (ImGui::DragInt4(fieldHeader.c_str(), glm::value_ptr(value))) {
315 editor->applySelected<SetFieldCommand<glm::ivec4>>(fieldInfo, value);
318 else if (fieldType == TypeDatabase::getType<glm::uvec2>()) {
319 auto fieldValue = field->
getPtr<glm::uvec2>(component);
320 glm::ivec2 tmp = *fieldValue;
321 if (ImGui::DragInt2(fieldHeader.c_str(), glm::value_ptr(tmp))) {
322 editor->applySelected<SetFieldCommand<glm::uvec2>>(fieldInfo, tmp);
325 else if (fieldType == TypeDatabase::getType<glm::uvec3>()) {
326 auto fieldValue = field->
getPtr<glm::uvec3>(component);
327 glm::ivec3 tmp = *fieldValue;
328 if (ImGui::DragInt3(fieldHeader.c_str(), glm::value_ptr(tmp))) {
329 editor->applySelected<SetFieldCommand<glm::uvec3>>(fieldInfo, tmp);
332 else if (fieldType == TypeDatabase::getType<glm::uvec4>()) {
333 auto fieldValue = field->
getPtr<glm::uvec4>(component);
334 glm::ivec4 tmp = *fieldValue;
335 if (ImGui::DragInt4(fieldHeader.c_str(), glm::value_ptr(tmp))) {
336 editor->applySelected<SetFieldCommand<glm::uvec4>>(fieldInfo, tmp);
339 else if (fieldType == TypeDatabase::getType<glm::dvec2>()) {
340 auto fieldValue = field->
getPtr<glm::dvec2>(component);
342 glm::vec2 fValues(*fieldValue);
344 if (ImGui::DragFloat2(fieldHeader.c_str(), glm::value_ptr(fValues))) {
345 editor->applySelected<SetFieldCommand<glm::dvec2>>(fieldInfo, fValues);
348 else if (fieldType == TypeDatabase::getType<glm::dvec3>()) {
349 auto fieldValue = field->
getPtr<glm::dvec3>(component);
351 glm::vec3 fValues(*fieldValue);
353 if (ImGui::DragFloat3(fieldHeader.c_str(), glm::value_ptr(fValues))) {
354 editor->applySelected<SetFieldCommand<glm::dvec3>>(fieldInfo, fValues);
357 else if (fieldType == TypeDatabase::getType<glm::quat>()) {
358 auto value = *field->
getPtr<glm::quat>(component);
360 glm::vec3 euler = glm::eulerAngles(value);
361 if (ImGui::DragFloat3(
"Euler", glm::value_ptr(euler), 0.01f, -glm::pi<float>(), glm::pi<float>())) {
362 float eps = 0.00001f;
363 if (euler.y >= glm::pi<float>() / 2.0f - eps)
364 euler.y = glm::pi<float>() / 2.0f - eps;
365 else if (euler.y <= -glm::pi<float>() / 2.0f + eps)
366 euler.y = -glm::pi<float>() / 2.0f + eps;
368 value = glm::quat(euler);
369 editor->applySelected<SetFieldCommand<glm::quat>>(fieldInfo, value);
372 if (ImGui::DragFloat4(fieldHeader.c_str(), glm::value_ptr(value), 0.01f, 0, 1)) {
373 editor->applySelected<SetFieldCommand<glm::quat>>(fieldInfo, value);
376 else if (fieldType == TypeDatabase::getType<glm::mat4>()) {
377 auto fieldValue = field->
getPtr<glm::mat4>(component);
378 auto value = *fieldValue;
380 ImGui::PushID(field);
382 if (showMatrix(fieldHeader, *fieldValue)) {
383 editor->applySelected<SetFieldCommand<glm::mat4>>(fieldInfo, value);
387 else if (fieldType == TypeDatabase::getType<bool>()) {
388 auto value = *field->
getPtr<
bool>(component);
390 if (ImGui::Checkbox(fieldHeader.c_str(), &value)) {
391 editor->applySelected<SetFieldCommand<bool>>(fieldInfo, value);
394 else if (fieldType == TypeDatabase::getType<uint32_t>()) {
395 auto fieldValue = field->
getPtr<uint32_t>(component);
396 editor->showText(
"%s: 0x%08x", fieldHeader.c_str(), *fieldValue);
398 int tmp =
static_cast<int>(*fieldValue);
401 const int min = std::min(tmp,
static_cast<int>(range->getMin()));
402 const int max = std::max(tmp,
static_cast<int>(range->getMax()));
403 if (ImGui::SliderInt(fieldHeader.c_str(), &tmp, min, max)) {
404 editor->applySelected<SetFieldCommand<uint32_t>>(fieldInfo,
static_cast<uint32_t
>(tmp));
408 if (ImGui::DragInt(fieldHeader.c_str(), &tmp)) {
409 editor->applySelected<SetFieldCommand<uint32_t>>(fieldInfo,
static_cast<uint32_t
>(tmp));
413 else if (fieldType.
isEnum()) {
414 auto fieldValue = field->
getPtr<uint32_t>(component);
415 auto value = *fieldValue;
418 editor->showText(
"%s:", fieldHeader.c_str());
421 ImGui::PushID(field);
425 for (
size_t i = 0; i < numEnums; ++i) {
427 auto enumeratorValue = enumerator->
getValue();
429 if (std::popcount(
static_cast<uint32_t
>(enumeratorValue)) != 1)
continue;
431 if (ImGui::CheckboxFlags(enumerator->getName().c_str(), &value, enumeratorValue)) {
432 editor->applySelected<SetFieldCommand<uint32_t>>(fieldInfo, value);
441 std::vector<const char *> enumNames(enums);
442 std::vector<int> enumValues(enums);
444 for (
size_t i = 0; i < enums; ++i) {
447 if (enumValues[i] ==
static_cast<int>(*fieldValue)) index =
static_cast<int>(i);
450 if (ImGui::Combo(fieldHeader.c_str(), &index, enumNames.data(),
static_cast<int>(enumNames.size()))) {
451 editor->applySelected<SetFieldCommand<uint32_t>>(fieldInfo, enumValues[index]);
455 else if (fieldType == TypeDatabase::getType<MeshHandle>()) {
456 auto & fieldValue = *field->
getPtr<MeshHandle>(component);
459 showMesh(context, fieldValue.resolve(), fieldHeader);
461 editor->showText(
"None");
464 else if (fieldType == TypeDatabase::getType<TextureHandle>()) {
467 if (editor->showTexture(field->
getName().
c_str(), *fieldValue)) {
471 else if (fieldType == TypeDatabase::getType<WeakEntityPtr>()) {
473 if (
auto spt = fieldValue->lock())
475 showEntityEditor(context, editor, &(*spt));
480 else if (fieldType == TypeDatabase::getType<std::string>()) {
481 auto fieldValue = field->
getPtr<std::string>(component);
482 std::string buffer = *fieldValue;
484 if (ImGui::InputText(field->
getName().
c_str(), &buffer[0], buffer.size())) {
485 for (
size_t i = 0; i < buffer.size(); i++) {
486 if (buffer[i] ==
'\0') {
492 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
494 guiRenderer->addTextToGlyphBuilder(buffer.c_str());
497 *fieldValue = std::move(buffer);
501 auto fieldValue = field->
getPtr<std::vector<std::string>>(component);
502 if (fieldValue->empty())
504 editor->showText(
"%s: Empty", field->
getName().
c_str());
508 if (ImGui::CollapsingHeader(std::string(fieldHeader +
" [size=" + std::to_string(fieldValue->size()) +
"]").c_str()))
511 for (
auto& s : *fieldValue) {
512 auto label = std::to_string(i++);
513 std::string buffer = s;
515 if (ImGui::InputText(label.c_str(), &buffer[0], buffer.size())) {
517 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
519 guiRenderer->addTextToGlyphBuilder(buffer.c_str());
529 auto fieldValue = field->
getPtr<std::vector<float>>(component);
535 auto fieldValue = field->
getPtr<std::vector<glm::vec3>>(component);
536 if (showArray3D(fieldHeader, *fieldValue)) {
541 auto fieldValue = field->
getPtr<std::vector<glm::vec2>>(component);
542 if (fieldValue->empty())
544 editor->showText(
"%s: Empty", field->
getName().
c_str());
546 else if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
549 for (
auto& v : *fieldValue) {
550 std::string label = std::to_string(i++);
551 if (ImGui::DragFloat2(label.c_str(), glm::value_ptr(v))) {
558 auto fieldValue = field->
getPtr<std::vector<glm::vec4>>(component);
559 if (fieldValue->empty()) {
560 editor->showText(
"%s: Empty", field->
getName().
c_str());
562 else if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
565 for (
auto& v : *fieldValue) {
566 std::string label = std::to_string(i++);
567 if (ImGui::DragFloat4(label.c_str(), glm::value_ptr(v))) {
573 else if (fieldType == TypeDatabase::getType<MaterialInstanceHandle>()) {
574 auto fieldValue = field->
getPtr<MaterialInstanceHandle>(component);
576 editor->showText(
"%s:", fieldHeader.c_str());
579 editor->showMaterialInstance(fieldInfo, *fieldValue);
581 else if (fieldType == TypeDatabase::getType<EntityPtr>()) {
583 if (fieldValue->get()) {
584 if (ImGui::CollapsingHeader(fieldHeader.c_str())) {
586 showEntityEditor(context, editor, fieldValue->get());
593 else if (fieldType == TypeDatabase::getType<Cogs::Core::FontHandle>()) {
595 if (fieldValue->get()) {
598 editor->showText(
"%d", fieldValue->getId());
604 else if (fieldType == TypeDatabase::getType<ModelHandle>()) {
605 auto fieldValue = field->
getPtr<ModelHandle>(component);
606 editor->showModel(*fieldValue);
608 else if (fieldType == TypeDatabase::getType<PropertyStore>()) {
609 PropertyStore* propStore = field->
getPtr<PropertyStore>(component);
610 assert(propStore !=
nullptr);
611 showPropertyStore(*editor, *propStore);
619 Cogs::Core::showFieldInspector(context, component, fieldId, std::string_view(), std::string_view());
624void Cogs::Core::EntityEditor::showEntityGizmo(Context * context, Editor * editor)
626 auto state = editor->getState();
628 if (state->mode == EditingMode::Select) {
630 state->wasUsingGizmo =
false;
631 }
else if (state->hasSelected()) {
632 ImGuizmo::OPERATION currentOperation = ImGuizmo::TRANSLATE;
633 ImGuizmo::MODE currentGizmoMode = ImGuizmo::WORLD;
635 float snap = state->translateSnap;
637 if (state->mode == EditingMode::Rotate) {
638 currentOperation = ImGuizmo::ROTATE;
639 currentGizmoMode = ImGuizmo::LOCAL;
640 snap = state->rotateSnap;
641 }
else if (state->mode == EditingMode::Scale) {
642 currentOperation = ImGuizmo::SCALE;
643 currentGizmoMode = ImGuizmo::LOCAL;
644 snap = state->scaleSnap;
647 const Entity* entity = state->getSelected();
650 const TransformComponent* transformComponent = entity->
getComponent<TransformComponent>();
651 if (!transformComponent)
return;
653 if (!state->wasUsingGizmo) {
654 Geometry::DBoundingBox bounds;
655 ::calculateBoundingBoxWorld(context, entity->
getId(), bounds.data());
656 if (Cogs::Geometry::isEmpty(bounds))
return;
658 glm::dvec3 center = 0.5 * (bounds.min + bounds.max);
661 if (state->pivot == EditingPivot::ObjectPivot) {
662 state->startTranslation = transformComponent->position;
664 state->startTranslation = center;
666 state->endTranslation = state->startTranslation;
668 state->startRotation = transformComponent->rotation;
669 state->endRotation = state->startRotation;
671 state->startScale = transformComponent->scale;
672 state->endScale = state->startScale;
674 state->startTranslations.resize(state->selected.size());
675 state->startRotations.resize(state->selected.size());
676 state->startScales.resize(state->selected.size());
678 for (
size_t i = 0; i < state->selected.size(); ++i) {
679 const Entity* e = context->store->getEntityPtr(state->selected[i]);
682 state->startTranslations[i] = t->position;
683 state->startRotations[i] = t->rotation;
684 state->startScales[i] = t->scale;
687 const EntityData* entityData =
static_cast<EntityData*
>(state->getSelected()->getUserData());
689 glm::mat4 localTransform;
690 if (entityData->entityContext) {
691 localTransform = entityData->entityContext->transformSystem->getLocalTransform(transformComponent);
693 localTransform = context->transformSystem->getLocalTransform(transformComponent);
696 glm::mat4 invLocal = glm::inverse(localTransform);
698 state->startMin = glm::vec3(invLocal * glm::vec4(bounds.min, 1));
699 state->startMax = glm::vec3(invLocal * glm::vec4(bounds.max, 1));
702 const glm::vec3 rads = glm::eulerAngles(state->endRotation);
703 const glm::vec3 euler = glm::degrees(rads);
706 ImGuizmo::RecomposeMatrixFromComponents(glm::value_ptr(state->endTranslation), glm::value_ptr(euler), glm::value_ptr(state->endScale), transform);
708 const auto cameraHandle = state->editorCamera.lock()->getComponentHandle<CameraComponent>();
709 const auto camera = cameraHandle.resolveComponent<CameraComponent>();
710 const auto & cameraData = context->cameraSystem->getData(camera);
712 ImGuizmo::SetRect(camera->viewportOrigin.x, camera->viewportOrigin.y, camera->viewportSize.x, camera->viewportSize.y);
714 glm::vec3 snapValue(snap);
715 ImGuizmo::Manipulate(glm::value_ptr(cameraData.viewMatrix), glm::value_ptr(cameraData.rawProjectionMatrix), currentOperation, currentGizmoMode, transform,
nullptr, glm::value_ptr(snapValue));
718 ImGuizmo::DecomposeMatrixToComponents(transform, glm::value_ptr(state->endTranslation), glm::value_ptr(rotate), glm::value_ptr(state->endScale));
720 if (!ImGuizmo::IsUsing()) {
721 state->wasUsingGizmo =
false;
725 if (!state->wasUsingGizmo) {
727 state->wasUsingGizmo =
true;
730 if (state->mode == EditingMode::Translate) {
731 glm::vec3 diff = state->endTranslation - state->startTranslation;
732 editor->apply<TranslateCommand>(state->selected, diff);
733 }
else if (state->mode == EditingMode::Rotate) {
734 glm::vec3 angles = glm::radians(rotate);
735 state->endRotation = glm::quat(angles);
736 glm::quat diff = state->endRotation * glm::inverse(state->startRotation);
737 editor->apply<RotateCommand>(state->selected, diff);
738 }
else if (state->mode == EditingMode::Scale) {
739 glm::vec3 diff = state->endScale - state->startScale;
740 editor->apply<ScaleCommand>(state->selected, diff);
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.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
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.
void showText(const char *format,...) const
Show the same type of label as ImGui::Text, but with the added ability to highlight and copy text....
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.
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.
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.
std::string to_string() const
String conversion method.
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.
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.