From ffc79ccdf47c076e185c7e684e421c843b0f1f3a Mon Sep 17 00:00:00 2001 From: WiggleWizard <1405402+WiggleWizard@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:53:32 +0100 Subject: [PATCH] Initial reflection for components using the entt reflection API Currently the only system using reflection is the drop down box when clicking "Add Component" in the entity inspector. The other systems and architecture is still designed around concrete compile time typing --- Editor/src/Windows/EditorSelectionPanel.cpp | 41 +++++++------------ Nuake/src/Core/Object/Object.h | 38 +++++++++++++++++ .../Scene/Components/AudioEmitterComponent.h | 4 ++ Nuake/src/Scene/Components/BoneComponent.h | 4 ++ Nuake/src/Scene/Components/BoxCollider.h | 4 ++ Nuake/src/Scene/Components/CameraComponent.h | 6 +++ .../Components/CapsuleColliderComponent.h | 4 ++ .../Components/CharacterControllerComponent.h | 4 ++ .../Components/CylinderColliderComponent.h | 4 ++ Nuake/src/Scene/Components/LightComponent.h | 5 +++ Nuake/src/Scene/Components/MeshCollider.h | 4 ++ Nuake/src/Scene/Components/ModelComponent.h | 3 ++ .../Scene/Components/NavMeshVolumeComponent.h | 4 ++ .../src/Scene/Components/NetScriptComponent.h | 9 +++- .../Components/ParticleEmitterComponent.h | 4 ++ Nuake/src/Scene/Components/QuakeMap.h | 3 ++ .../src/Scene/Components/RigidbodyComponent.h | 4 ++ .../Scene/Components/SkinnedModelComponent.h | 3 ++ Nuake/src/Scene/Components/SphereCollider.h | 4 ++ Nuake/src/Scene/Components/SpriteComponent.h | 4 ++ Nuake/src/Scene/Entities/Entity.h | 28 +++++++++++++ 21 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 Nuake/src/Core/Object/Object.h diff --git a/Editor/src/Windows/EditorSelectionPanel.cpp b/Editor/src/Windows/EditorSelectionPanel.cpp index eddec7e0..1e7316dc 100644 --- a/Editor/src/Windows/EditorSelectionPanel.cpp +++ b/Editor/src/Windows/EditorSelectionPanel.cpp @@ -13,6 +13,8 @@ #include #include +#include + using namespace Nuake; EditorSelectionPanel::EditorSelectionPanel() @@ -151,32 +153,19 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity) if (ImGui::BeginPopup("ComponentPopup")) { - MenuItemComponent("Wren Script", WrenScriptComponent); - MenuItemComponent("C# Script", NetScriptComponent); - MenuItemComponent("Camera", CameraComponent); - MenuItemComponent("Light", LightComponent); - ImGui::Separator(); - MenuItemComponent("Model", ModelComponent); - MenuItemComponent("Skinned Model", SkinnedModelComponent); - MenuItemComponent("Bone", BoneComponent) - ImGui::Separator(); - MenuItemComponent("Sprite", SpriteComponent) - MenuItemComponent("Particle Emitter", ParticleEmitterComponent) - ImGui::Separator(); - MenuItemComponent("Character Controller", CharacterControllerComponent) - MenuItemComponent("Rigid body", RigidBodyComponent) - ImGui::Separator(); - MenuItemComponent("Box collider", BoxColliderComponent) - MenuItemComponent("Capsule collider", CapsuleColliderComponent) - MenuItemComponent("Cylinder collider", CylinderColliderComponent) - MenuItemComponent("Sphere collider", SphereColliderComponent) - MenuItemComponent("Mesh collider", MeshColliderComponent) - ImGui::Separator(); - MenuItemComponent("Quake map", QuakeMapComponent); - ImGui::Separator(); - MenuItemComponent("Audio Emitter", AudioEmitterComponent); - ImGui::Separator(); - MenuItemComponent("NavMesh Volume", NavMeshVolumeComponent); + for(entt::meta_type t : entt::resolve()) + { + if (entt::meta_func func = t.func(HashedFnName::GetComponentName)) + { + entt::meta_any ret = func.invoke(t); + std::string className = ret.cast(); + if (ImGui::MenuItem(className.c_str())) + { + entity.AddComponent(t); + } + } + } + ImGui::EndPopup(); } diff --git a/Nuake/src/Core/Object/Object.h b/Nuake/src/Core/Object/Object.h new file mode 100644 index 00000000..8c065dc6 --- /dev/null +++ b/Nuake/src/Core/Object/Object.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#define NK_HASHED_FN_NAME_IMPL(name) inline static constexpr entt::hashed_string name = entt::hashed_string(#name); + +namespace Nuake +{ + struct HashedFnName + { + NK_HASHED_FN_NAME_IMPL(GetComponentName) + NK_HASHED_FN_NAME_IMPL(AddToEntity) + }; +} + +#define NUAKECOMPONENT(klass, componentName) \ +public: \ + static std::string ClassName() \ + { \ + static std::string className = #klass; \ + return className; \ + } \ + \ + static std::string ComponentName() \ + { \ + static std::string name = componentName; \ + return name; \ + } \ + \ + static void AddToEntity(entt::entity entity, entt::registry* enttRegistry) \ + { \ + enttRegistry->emplace_or_replace(entity); \ + } \ + \ + inline static auto ComponentFactory = entt::meta() \ + .type(entt::hashed_string(#klass)) \ + .func<&klass::ComponentName>(HashedFnName::GetComponentName) \ + .func<&klass::AddToEntity>(HashedFnName::AddToEntity); diff --git a/Nuake/src/Scene/Components/AudioEmitterComponent.h b/Nuake/src/Scene/Components/AudioEmitterComponent.h index 52d609b7..bebfd6fb 100644 --- a/Nuake/src/Scene/Components/AudioEmitterComponent.h +++ b/Nuake/src/Scene/Components/AudioEmitterComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Core/Core.h" #include "src/Resource/Serializable.h" @@ -6,6 +8,8 @@ namespace Nuake { class AudioEmitterComponent { + NUAKECOMPONENT(AudioEmitterComponent, "Audio Emitter") + public: std::string FilePath; diff --git a/Nuake/src/Scene/Components/BoneComponent.h b/Nuake/src/Scene/Components/BoneComponent.h index 824484b9..f1c9a8b8 100644 --- a/Nuake/src/Scene/Components/BoneComponent.h +++ b/Nuake/src/Scene/Components/BoneComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Core/Core.h" #include "src/Resource/Serializable.h" @@ -7,6 +9,8 @@ namespace Nuake { class BoneComponent { + NUAKECOMPONENT(BoneComponent, "Bone") + public: BoneComponent() = default; ~BoneComponent() = default; diff --git a/Nuake/src/Scene/Components/BoxCollider.h b/Nuake/src/Scene/Components/BoxCollider.h index 44223399..80c84d60 100644 --- a/Nuake/src/Scene/Components/BoxCollider.h +++ b/Nuake/src/Scene/Components/BoxCollider.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/PhysicsShapes.h" #include "src/Core/Core.h" @@ -6,6 +8,8 @@ namespace Nuake { class BoxColliderComponent { + NUAKECOMPONENT(BoxColliderComponent, "Box Collider") + public: Ref Box; Vector3 Size = Vector3(0.5f, 0.5f, 0.5f); diff --git a/Nuake/src/Scene/Components/CameraComponent.h b/Nuake/src/Scene/Components/CameraComponent.h index 6bd1ede6..b62b7cf8 100644 --- a/Nuake/src/Scene/Components/CameraComponent.h +++ b/Nuake/src/Scene/Components/CameraComponent.h @@ -1,4 +1,7 @@ #pragma once + +#include "src/Core/Object/Object.h" + #include "TransformComponent.h" #include "src/Core/Core.h" #include "src/Resource/Serializable.h" @@ -6,8 +9,11 @@ namespace Nuake { + class CameraComponent { + NUAKECOMPONENT(CameraComponent, "Camera") + public: Ref CameraInstance; TransformComponent* transformComponent; diff --git a/Nuake/src/Scene/Components/CapsuleColliderComponent.h b/Nuake/src/Scene/Components/CapsuleColliderComponent.h index 4e2170ea..a0114945 100644 --- a/Nuake/src/Scene/Components/CapsuleColliderComponent.h +++ b/Nuake/src/Scene/Components/CapsuleColliderComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/PhysicsShapes.h" #include "src/Core/Core.h" @@ -6,6 +8,8 @@ namespace Nuake { class CapsuleColliderComponent { + NUAKECOMPONENT(CapsuleColliderComponent, "Capsule Collider") + public: Ref Capsule; diff --git a/Nuake/src/Scene/Components/CharacterControllerComponent.h b/Nuake/src/Scene/Components/CharacterControllerComponent.h index 621f7f66..7d39bec1 100644 --- a/Nuake/src/Scene/Components/CharacterControllerComponent.h +++ b/Nuake/src/Scene/Components/CharacterControllerComponent.h @@ -1,10 +1,14 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/CharacterController.h" namespace Nuake { class CharacterControllerComponent { + NUAKECOMPONENT(CharacterControllerComponent, "Character Controller") + private: Ref m_CharacterController; diff --git a/Nuake/src/Scene/Components/CylinderColliderComponent.h b/Nuake/src/Scene/Components/CylinderColliderComponent.h index d9a71217..3aa31b29 100644 --- a/Nuake/src/Scene/Components/CylinderColliderComponent.h +++ b/Nuake/src/Scene/Components/CylinderColliderComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/PhysicsShapes.h" #include "src/Core/Core.h" @@ -6,6 +8,8 @@ namespace Nuake { class CylinderColliderComponent { + NUAKECOMPONENT(CylinderColliderComponent, "Cylinder Collider") + public: Ref Cylinder; diff --git a/Nuake/src/Scene/Components/LightComponent.h b/Nuake/src/Scene/Components/LightComponent.h index e4cc77fc..95204b52 100644 --- a/Nuake/src/Scene/Components/LightComponent.h +++ b/Nuake/src/Scene/Components/LightComponent.h @@ -1,4 +1,7 @@ #pragma once + +#include "src/Core/Object/Object.h" + #include #include #include "TransformComponent.h" @@ -19,6 +22,8 @@ namespace Nuake const int CSM_AMOUNT = 4; class LightComponent { + NUAKECOMPONENT(LightComponent, "Light") + public: LightType Type = Point; Vector3 Direction; diff --git a/Nuake/src/Scene/Components/MeshCollider.h b/Nuake/src/Scene/Components/MeshCollider.h index 0d93fc86..8c2c32ec 100644 --- a/Nuake/src/Scene/Components/MeshCollider.h +++ b/Nuake/src/Scene/Components/MeshCollider.h @@ -1,10 +1,14 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/PhysicsShapes.h" #include "src/Core/Core.h" namespace Nuake { class MeshColliderComponent { + NUAKECOMPONENT(MeshColliderComponent, "Mesh Collider") + public: uint32_t SubMesh = 0; bool IsTrigger; diff --git a/Nuake/src/Scene/Components/ModelComponent.h b/Nuake/src/Scene/Components/ModelComponent.h index 2296ba90..d130b677 100644 --- a/Nuake/src/Scene/Components/ModelComponent.h +++ b/Nuake/src/Scene/Components/ModelComponent.h @@ -1,5 +1,6 @@ #pragma once +#include "src/Core/Object/Object.h" #include "src/Core/String.h" #include "src/Resource/Model.h" #include "src/Resource/ResourceLoader.h" @@ -13,6 +14,8 @@ namespace Nuake { struct ModelComponent { + NUAKECOMPONENT(ModelComponent, "Model") + Ref ModelResource; std::string ModelPath; diff --git a/Nuake/src/Scene/Components/NavMeshVolumeComponent.h b/Nuake/src/Scene/Components/NavMeshVolumeComponent.h index 7c8f829e..0b551ca4 100644 --- a/Nuake/src/Scene/Components/NavMeshVolumeComponent.h +++ b/Nuake/src/Scene/Components/NavMeshVolumeComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "../Entities/Entity.h" #include "Engine.h" #include @@ -7,6 +9,8 @@ namespace Nuake { struct NavMeshVolumeComponent { + NUAKECOMPONENT(NavMeshVolumeComponent, "Nav Mesh Volume") + Vector3 VolumeSize = { 1.0f, 1.0f, 1.0f }; bool OnlyIncludeMapGeometry = true; diff --git a/Nuake/src/Scene/Components/NetScriptComponent.h b/Nuake/src/Scene/Components/NetScriptComponent.h index 752f7e41..8cd6bcfe 100644 --- a/Nuake/src/Scene/Components/NetScriptComponent.h +++ b/Nuake/src/Scene/Components/NetScriptComponent.h @@ -1,5 +1,6 @@ - #pragma once + +#include "src/Core/Object/Object.h" #include "src/Core/Core.h" #include "src/Core/Maths.h" #include "src/FileSystem/FileSystem.h" @@ -8,6 +9,8 @@ #include "src/Resource/File.h" #include +#include "src/Core/Object/Object.h" + namespace Nuake { enum class NetScriptExposedVarType @@ -33,6 +36,8 @@ namespace Nuake { class NetScriptComponent { + NUAKECOMPONENT(NetScriptComponent, "Net Script") + public: std::string ScriptPath; std::string Class; @@ -234,4 +239,4 @@ namespace Nuake { return true; } }; -} \ No newline at end of file +} diff --git a/Nuake/src/Scene/Components/ParticleEmitterComponent.h b/Nuake/src/Scene/Components/ParticleEmitterComponent.h index 7a046fa4..fb309038 100644 --- a/Nuake/src/Scene/Components/ParticleEmitterComponent.h +++ b/Nuake/src/Scene/Components/ParticleEmitterComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Core/Core.h" #include "src/Core/Maths.h" #include "src/Resource/Serializable.h" @@ -10,6 +12,8 @@ namespace Nuake { class ParticleEmitterComponent { + NUAKECOMPONENT(ParticleEmitterComponent, "Particle Emitter") + public: ParticleEmitterComponent() = default; ~ParticleEmitterComponent() = default; diff --git a/Nuake/src/Scene/Components/QuakeMap.h b/Nuake/src/Scene/Components/QuakeMap.h index 4fe0c250..9d9169b0 100644 --- a/Nuake/src/Scene/Components/QuakeMap.h +++ b/Nuake/src/Scene/Components/QuakeMap.h @@ -2,6 +2,7 @@ #include #include +#include "src/Core/Object/Object.h" #include "src/Rendering/Mesh/Mesh.h" #include "src/Resource/Serializable.h" #include "src/Scene/Systems/QuakeMapBuilder.h" @@ -12,6 +13,8 @@ namespace Nuake { class QuakeMapComponent { + NUAKECOMPONENT(QuakeMapComponent, "Quake Map") + public: std::vector> m_Meshes; std::vector m_Brushes; diff --git a/Nuake/src/Scene/Components/RigidbodyComponent.h b/Nuake/src/Scene/Components/RigidbodyComponent.h index 240fbc70..06ad21f6 100644 --- a/Nuake/src/Scene/Components/RigidbodyComponent.h +++ b/Nuake/src/Scene/Components/RigidbodyComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "TransformComponent.h" #include "BaseComponent.h" #include "src/Core/Core.h" @@ -11,6 +13,8 @@ namespace Nuake { class RigidBodyComponent { + NUAKECOMPONENT(RigidBodyComponent, "Rigid Body") + public: float Mass; bool LockX = false; diff --git a/Nuake/src/Scene/Components/SkinnedModelComponent.h b/Nuake/src/Scene/Components/SkinnedModelComponent.h index b0abed18..b33c9a07 100644 --- a/Nuake/src/Scene/Components/SkinnedModelComponent.h +++ b/Nuake/src/Scene/Components/SkinnedModelComponent.h @@ -1,6 +1,7 @@ #pragma once #include +#include "src/Core/Object/Object.h" #include "src/Resource/Serializable.h" #include "src/Resource/SkinnedModel.h" @@ -11,6 +12,8 @@ namespace Nuake { struct SkinnedModelComponent { + NUAKECOMPONENT(SkinnedModelComponent, "Skinned Model") + Ref ModelResource; std::string ModelPath; diff --git a/Nuake/src/Scene/Components/SphereCollider.h b/Nuake/src/Scene/Components/SphereCollider.h index 52f44786..bd79f3d6 100644 --- a/Nuake/src/Scene/Components/SphereCollider.h +++ b/Nuake/src/Scene/Components/SphereCollider.h @@ -1,10 +1,14 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Physics/PhysicsShapes.h" #include "src/Core/Core.h" namespace Nuake { class SphereColliderComponent { + NUAKECOMPONENT(SphereColliderComponent, "Sphere Component") + public: Ref Sphere; diff --git a/Nuake/src/Scene/Components/SpriteComponent.h b/Nuake/src/Scene/Components/SpriteComponent.h index e22dc0ff..f5b06c19 100644 --- a/Nuake/src/Scene/Components/SpriteComponent.h +++ b/Nuake/src/Scene/Components/SpriteComponent.h @@ -1,4 +1,6 @@ #pragma once + +#include "src/Core/Object/Object.h" #include "src/Core/Core.h" #include "src/Resource/Serializable.h" #include "src/Rendering/Textures/Texture.h" @@ -8,6 +10,8 @@ namespace Nuake { class SpriteComponent { + NUAKECOMPONENT(SpriteComponent, "Sprite") + public: bool Billboard; bool LockYRotation; diff --git a/Nuake/src/Scene/Entities/Entity.h b/Nuake/src/Scene/Entities/Entity.h index 26d75949..2abff3dc 100644 --- a/Nuake/src/Scene/Entities/Entity.h +++ b/Nuake/src/Scene/Entities/Entity.h @@ -1,6 +1,8 @@ #pragma once #include #include + +#include "src/Core/Logger.h" #include "../Scene.h" #include "../Components/BaseComponent.h" #include "../Resource/Serializable.h" @@ -31,6 +33,32 @@ namespace Nuake return m_EntityHandle != (entt::entity)-1 && m_Scene->m_Registry.valid((entt::entity)GetHandle()); } + void AddComponent(entt::meta_type& enttMetaType) + { + if (!enttMetaType) + { + Logger::Log("Meta data empty/invalid", "Entity", WARNING); + return; + } + + entt::meta_any newComponent = enttMetaType.construct(); + if (!newComponent) + { + Logger::Log("Could not create a component from the meta type", "Entity", CRITICAL); + return; + } + + auto func = enttMetaType.func(HashedFnName::AddToEntity); + // TODO: [WiggleWizard] Needs a lot more validation + if (!func) + { + Logger::Log("No such function exists or is registered on component", "Entity", CRITICAL); + return; + } + + func.invoke(newComponent, m_EntityHandle, &m_Scene->m_Registry); + } + template T& AddComponent() {