diff --git a/ui_editor/src/Core/GameObject.h b/ui_editor/src/Core/GameObject.h index 064b3c9d..e091c4ef 100644 --- a/ui_editor/src/Core/GameObject.h +++ b/ui_editor/src/Core/GameObject.h @@ -14,45 +14,10 @@ namespace UI { using EntityID = uint64_t; constexpr EntityID INVALID_ENTITY_ID = 0; -class Component { -public: - virtual ~Component() = default; - virtual std::string GetName() const = 0; - - virtual void Awake() {} - virtual void Start() {} - virtual void Update(float deltaTime) {} - virtual void OnDestroy() {} - - class Entity* GetEntity() const { return m_entity; } - bool IsEnabled() const { return m_enabled; } - void SetEnabled(bool enabled) { m_enabled = enabled; } - -protected: - class Entity* m_entity = nullptr; - bool m_enabled = true; - - friend class Entity; -}; +class Component; +class TransformComponent; -class TransformComponent : public Component { -public: - float position[3] = {0.0f, 0.0f, 0.0f}; - float rotation[3] = {0.0f, 0.0f, 0.0f}; - float scale[3] = {1.0f, 1.0f, 1.0f}; - - std::string GetName() const override { return "Transform"; } -}; - -class MeshRendererComponent : public Component { -public: - std::string materialName = "Default-Material"; - std::string meshName = ""; - - std::string GetName() const override { return "Mesh Renderer"; } -}; - -class Entity { +class GameObject { public: EntityID id = INVALID_ENTITY_ID; std::string name; @@ -60,16 +25,16 @@ public: std::vector children; std::vector> components; bool selected = false; - + template T* AddComponent(Args&&... args) { auto comp = std::make_unique(std::forward(args)...); - comp->m_entity = this; + comp->m_gameObject = this; T* ptr = comp.get(); components.push_back(std::move(comp)); return ptr; } - + template T* GetComponent() { for (auto& comp : components) { @@ -79,7 +44,7 @@ public: } return nullptr; } - + template std::vector GetComponents() { std::vector result; @@ -90,6 +55,48 @@ public: } return result; } + + TransformComponent* GetTransform() { + return GetComponent(); + } +}; + +class Component { +public: + virtual ~Component() = default; + virtual std::string GetName() const = 0; + + virtual void Awake() {} + virtual void Start() {} + virtual void Update(float deltaTime) {} + virtual void OnDestroy() {} + + GameObject* GetGameObject() const { return m_gameObject; } + bool IsEnabled() const { return m_enabled; } + void SetEnabled(bool enabled) { m_enabled = enabled; } + +protected: + GameObject* m_gameObject = nullptr; + bool m_enabled = true; + + friend class GameObject; +}; + +class TransformComponent : public Component { +public: + float position[3] = {0.0f, 0.0f, 0.0f}; + float rotation[3] = {0.0f, 0.0f, 0.0f}; + float scale[3] = {1.0f, 1.0f, 1.0f}; + + std::string GetName() const override { return "Transform"; } +}; + +class MeshRendererComponent : public Component { +public: + std::string materialName = "Default-Material"; + std::string meshName = ""; + + std::string GetName() const override { return "Mesh Renderer"; } }; using ComponentInspectorFn = std::function; @@ -105,7 +112,7 @@ public: static ComponentRegistry instance; return instance; } - + template void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) { m_inspectors[name] = {name, inspectorFn}; @@ -113,7 +120,7 @@ public: return std::make_unique(); }; } - + ComponentInspectorInfo* GetInspector(const std::string& name) { auto it = m_inspectors.find(name); if (it != m_inspectors.end()) { @@ -121,7 +128,7 @@ public: } return nullptr; } - + private: ComponentRegistry() = default; std::unordered_map m_inspectors; diff --git a/ui_editor/src/Managers/SceneManager.cpp b/ui_editor/src/Managers/SceneManager.cpp index 9cd480d5..081a767b 100644 --- a/ui_editor/src/Managers/SceneManager.cpp +++ b/ui_editor/src/Managers/SceneManager.cpp @@ -6,18 +6,18 @@ namespace UI { EntityID SceneManager::CreateEntity(const std::string& name, EntityID parent) { EntityID id = m_nextEntityId++; - Entity entity; + GameObject entity; entity.id = id; entity.name = name; entity.parent = parent; m_entities[id] = std::move(entity); - + if (parent != INVALID_ENTITY_ID) { m_entities[parent].children.push_back(id); } else { m_rootEntities.push_back(id); } - + OnEntityCreated.Invoke(id); return id; } @@ -25,14 +25,14 @@ EntityID SceneManager::CreateEntity(const std::string& name, EntityID parent) { void SceneManager::DeleteEntity(EntityID id) { auto it = m_entities.find(id); if (it == m_entities.end()) return; - - Entity& entity = it->second; - + + GameObject& entity = it->second; + std::vector childrenToDelete = entity.children; for (EntityID childId : childrenToDelete) { DeleteEntity(childId); } - + if (entity.parent != INVALID_ENTITY_ID) { auto* parent = GetEntity(entity.parent); if (parent) { @@ -42,19 +42,19 @@ void SceneManager::DeleteEntity(EntityID id) { } else { m_rootEntities.erase(std::remove(m_rootEntities.begin(), m_rootEntities.end(), id), m_rootEntities.end()); } - + if (SelectionManager::Get().GetSelectedEntity() == id) { SelectionManager::Get().ClearSelection(); } - + m_entities.erase(it); OnEntityDeleted.Invoke(id); } -ClipboardData SceneManager::CopyEntityRecursive(const Entity* entity) { +ClipboardData SceneManager::CopyEntityRecursive(const GameObject* entity) { ClipboardData data; data.name = entity->name; - + for (const auto& comp : entity->components) { if (auto* transform = dynamic_cast(comp.get())) { auto newComp = std::make_unique(); @@ -70,28 +70,28 @@ ClipboardData SceneManager::CopyEntityRecursive(const Entity* entity) { data.components.push_back(std::move(newComp)); } } - + for (EntityID childId : entity->children) { - const Entity* child = GetEntity(childId); + const GameObject* child = GetEntity(childId); if (child) { data.children.push_back(CopyEntityRecursive(child)); } } - + return data; } void SceneManager::CopyEntity(EntityID id) { - const Entity* entity = GetEntity(id); + const GameObject* entity = GetEntity(id); if (!entity) return; - + m_clipboard = CopyEntityRecursive(entity); } EntityID SceneManager::PasteEntityRecursive(const ClipboardData& data, EntityID parent) { EntityID newId = CreateEntity(data.name, parent); - Entity* newEntity = GetEntity(newId); - + GameObject* newEntity = GetEntity(newId); + if (newEntity) { newEntity->components.clear(); for (const auto& comp : data.components) { @@ -110,11 +110,11 @@ EntityID SceneManager::PasteEntityRecursive(const ClipboardData& data, EntityID } } } - + for (const auto& childData : data.children) { PasteEntityRecursive(childData, newId); } - + return newId; } @@ -125,17 +125,17 @@ EntityID SceneManager::PasteEntity(EntityID parent) { EntityID SceneManager::DuplicateEntity(EntityID id) { CopyEntity(id); - const Entity* entity = GetEntity(id); + const GameObject* entity = GetEntity(id); if (!entity) return INVALID_ENTITY_ID; return PasteEntity(entity->parent); } void SceneManager::MoveEntity(EntityID id, EntityID newParent) { - Entity* entity = GetEntity(id); + GameObject* entity = GetEntity(id); if (!entity || id == newParent) return; - + if (entity->parent != INVALID_ENTITY_ID) { - Entity* oldParent = GetEntity(entity->parent); + GameObject* oldParent = GetEntity(entity->parent); if (oldParent) { auto& siblings = oldParent->children; siblings.erase(std::remove(siblings.begin(), siblings.end(), id), siblings.end()); @@ -143,18 +143,18 @@ void SceneManager::MoveEntity(EntityID id, EntityID newParent) { } else { m_rootEntities.erase(std::remove(m_rootEntities.begin(), m_rootEntities.end(), id), m_rootEntities.end()); } - + entity->parent = newParent; - + if (newParent != INVALID_ENTITY_ID) { - Entity* newParentEntity = GetEntity(newParent); + GameObject* newParentEntity = GetEntity(newParent); if (newParentEntity) { newParentEntity->children.push_back(id); } } else { m_rootEntities.push_back(id); } - + OnEntityChanged.Invoke(id); } @@ -163,24 +163,24 @@ void SceneManager::CreateDemoScene() { m_rootEntities.clear(); m_nextEntityId = 1; m_clipboard.reset(); - + EntityID camera = CreateEntity("Main Camera"); GetEntity(camera)->AddComponent(); - + EntityID light = CreateEntity("Directional Light"); - + EntityID cube = CreateEntity("Cube"); GetEntity(cube)->AddComponent(); GetEntity(cube)->AddComponent()->meshName = "Cube Mesh"; - + EntityID sphere = CreateEntity("Sphere"); GetEntity(sphere)->AddComponent(); GetEntity(sphere)->AddComponent()->meshName = "Sphere Mesh"; - + EntityID player = CreateEntity("Player"); EntityID weapon = CreateEntity("Weapon", player); - + OnSceneChanged.Invoke(); } -} \ No newline at end of file +} diff --git a/ui_editor/src/Managers/SceneManager.h b/ui_editor/src/Managers/SceneManager.h index d76a067b..095c9941 100644 --- a/ui_editor/src/Managers/SceneManager.h +++ b/ui_editor/src/Managers/SceneManager.h @@ -22,31 +22,31 @@ public: static SceneManager instance; return instance; } - + EntityID CreateEntity(const std::string& name, EntityID parent = INVALID_ENTITY_ID); - - Entity* GetEntity(EntityID id) { + + GameObject* GetEntity(EntityID id) { auto it = m_entities.find(id); if (it != m_entities.end()) { return &it->second; } return nullptr; } - - const Entity* GetEntity(EntityID id) const { + + const GameObject* GetEntity(EntityID id) const { auto it = m_entities.find(id); if (it != m_entities.end()) { return &it->second; } return nullptr; } - + const std::vector& GetRootEntities() const { return m_rootEntities; } - + void DeleteEntity(EntityID id); - + void RenameEntity(EntityID id, const std::string& newName) { auto* entity = GetEntity(id); if (entity) { @@ -54,32 +54,32 @@ public: OnEntityChanged.Invoke(id); } } - + void CopyEntity(EntityID id); - + EntityID PasteEntity(EntityID parent = INVALID_ENTITY_ID); - + EntityID DuplicateEntity(EntityID id); - + void MoveEntity(EntityID id, EntityID newParent); - + void CreateDemoScene(); - + bool HasClipboardData() const { return m_clipboard.has_value(); } - + XCEngine::Core::Event OnEntityCreated; XCEngine::Core::Event OnEntityDeleted; XCEngine::Core::Event OnEntityChanged; XCEngine::Core::Event<> OnSceneChanged; - + private: SceneManager() = default; - - ClipboardData CopyEntityRecursive(const Entity* entity); + + ClipboardData CopyEntityRecursive(const GameObject* entity); EntityID PasteEntityRecursive(const ClipboardData& data, EntityID parent); - + EntityID m_nextEntityId = 1; - std::unordered_map m_entities; + std::unordered_map m_entities; std::vector m_rootEntities; std::optional m_clipboard; }; diff --git a/ui_editor/src/panels/HierarchyPanel.cpp b/ui_editor/src/panels/HierarchyPanel.cpp index e3bb8f80..096bd969 100644 --- a/ui_editor/src/panels/HierarchyPanel.cpp +++ b/ui_editor/src/panels/HierarchyPanel.cpp @@ -50,7 +50,7 @@ void HierarchyPanel::Render() { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_ID")) { EntityID sourceId = *(const EntityID*)payload->Data; if (sourceId != INVALID_ENTITY_ID) { - const Entity* sourceEntity = SceneManager::Get().GetEntity(sourceId); + const GameObject* sourceEntity = SceneManager::Get().GetEntity(sourceId); if (sourceEntity && sourceEntity->parent != INVALID_ENTITY_ID) { SceneManager::Get().MoveEntity(sourceId, INVALID_ENTITY_ID); } @@ -71,7 +71,7 @@ void HierarchyPanel::RenderSearchBar() { void HierarchyPanel::RenderEntity(EntityID id, const std::string& filter) { auto& sceneManager = SceneManager::Get(); - Entity* entity = sceneManager.GetEntity(id); + GameObject* entity = sceneManager.GetEntity(id); if (!entity) return; if (!filter.empty() && !PassesFilter(id, filter)) { @@ -156,7 +156,7 @@ void HierarchyPanel::RenderContextMenu(EntityID id) { ImGui::Separator(); if (ImGui::MenuItem("Rename", "F2")) { - const Entity* entity = sceneManager.GetEntity(id); + const GameObject* entity = sceneManager.GetEntity(id); if (entity) { m_renaming = true; m_renamingEntity = id; @@ -239,7 +239,7 @@ void HierarchyPanel::HandleDragDrop(EntityID id) { if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { m_dragSource = id; ImGui::SetDragDropPayload("ENTITY_ID", &id, sizeof(EntityID)); - const Entity* entity = sceneManager.GetEntity(id); + const GameObject* entity = sceneManager.GetEntity(id); if (entity) { ImGui::Text("%s", entity->name.c_str()); } @@ -250,8 +250,8 @@ void HierarchyPanel::HandleDragDrop(EntityID id) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_ID")) { EntityID sourceId = *(const EntityID*)payload->Data; if (sourceId != id && sourceId != INVALID_ENTITY_ID) { - const Entity* targetEntity = sceneManager.GetEntity(id); - const Entity* sourceEntity = sceneManager.GetEntity(sourceId); + const GameObject* targetEntity = sceneManager.GetEntity(id); + const GameObject* sourceEntity = sceneManager.GetEntity(sourceId); bool isValidMove = true; EntityID checkParent = targetEntity ? targetEntity->parent : INVALID_ENTITY_ID; @@ -260,7 +260,7 @@ void HierarchyPanel::HandleDragDrop(EntityID id) { isValidMove = false; break; } - const Entity* parentEntity = sceneManager.GetEntity(checkParent); + const GameObject* parentEntity = sceneManager.GetEntity(checkParent); checkParent = parentEntity ? parentEntity->parent : INVALID_ENTITY_ID; } @@ -288,7 +288,7 @@ void HierarchyPanel::HandleKeyboardShortcuts() { if (ImGui::IsKeyPressed(ImGuiKey_F2)) { if (selectedId != INVALID_ENTITY_ID) { - const Entity* entity = sceneManager.GetEntity(selectedId); + const GameObject* entity = sceneManager.GetEntity(selectedId); if (entity) { m_renaming = true; m_renamingEntity = selectedId; @@ -326,7 +326,7 @@ void HierarchyPanel::HandleKeyboardShortcuts() { bool HierarchyPanel::PassesFilter(EntityID id, const std::string& filter) { auto& sceneManager = SceneManager::Get(); - const Entity* entity = sceneManager.GetEntity(id); + const GameObject* entity = sceneManager.GetEntity(id); if (!entity) return false; if (entity->name.find(filter) != std::string::npos) { diff --git a/ui_editor/src/panels/InspectorPanel.cpp b/ui_editor/src/panels/InspectorPanel.cpp index b3899edf..f33e2cc3 100644 --- a/ui_editor/src/panels/InspectorPanel.cpp +++ b/ui_editor/src/panels/InspectorPanel.cpp @@ -19,7 +19,7 @@ void InspectorPanel::Render() { ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); EntityID selectedId = SelectionManager::Get().GetSelectedEntity(); - Entity* entity = SceneManager::Get().GetEntity(selectedId); + GameObject* entity = SceneManager::Get().GetEntity(selectedId); if (entity) { RenderEntity(entity); @@ -31,7 +31,7 @@ void InspectorPanel::Render() { ImGui::End(); } -void InspectorPanel::RenderEntity(Entity* entity) { +void InspectorPanel::RenderEntity(GameObject* entity) { ImGui::Text("%s", entity->name.c_str()); ImGui::Separator(); diff --git a/ui_editor/src/panels/InspectorPanel.h b/ui_editor/src/panels/InspectorPanel.h index c3c234f5..16727915 100644 --- a/ui_editor/src/panels/InspectorPanel.h +++ b/ui_editor/src/panels/InspectorPanel.h @@ -13,7 +13,7 @@ public: void Render() override; private: - void RenderEntity(Entity* entity); + void RenderEntity(GameObject* entity); void RenderComponent(Component* component); uint64_t m_selectionHandlerId = 0;