diff --git a/CMakeLists.txt b/CMakeLists.txt index 38970bd8..c0beceb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) enable_testing() add_subdirectory(engine) +add_subdirectory(editor) add_subdirectory(mvs/RenderDoc) add_subdirectory(tests) add_subdirectory(tests/opengl) diff --git a/editor/src/Core/GameObject.h b/editor/src/Core/GameObject.h deleted file mode 100644 index e091c4ef..00000000 --- a/editor/src/Core/GameObject.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -namespace UI { - -using EntityID = uint64_t; -constexpr EntityID INVALID_ENTITY_ID = 0; - -class Component; -class TransformComponent; - -class GameObject { -public: - EntityID id = INVALID_ENTITY_ID; - std::string name; - EntityID parent = INVALID_ENTITY_ID; - std::vector children; - std::vector> components; - bool selected = false; - - template - T* AddComponent(Args&&... args) { - auto comp = std::make_unique(std::forward(args)...); - comp->m_gameObject = this; - T* ptr = comp.get(); - components.push_back(std::move(comp)); - return ptr; - } - - template - T* GetComponent() { - for (auto& comp : components) { - if (auto casted = dynamic_cast(comp.get())) { - return casted; - } - } - return nullptr; - } - - template - std::vector GetComponents() { - std::vector result; - for (auto& comp : components) { - if (auto casted = dynamic_cast(comp.get())) { - result.push_back(casted); - } - } - 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; - -struct ComponentInspectorInfo { - std::string name; - ComponentInspectorFn renderFn; -}; - -class ComponentRegistry { -public: - static ComponentRegistry& Get() { - static ComponentRegistry instance; - return instance; - } - - template - void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) { - m_inspectors[name] = {name, inspectorFn}; - m_factories[name] = []() -> std::unique_ptr { - return std::make_unique(); - }; - } - - ComponentInspectorInfo* GetInspector(const std::string& name) { - auto it = m_inspectors.find(name); - if (it != m_inspectors.end()) { - return &it->second; - } - return nullptr; - } - -private: - ComponentRegistry() = default; - std::unordered_map m_inspectors; - std::unordered_map()>> m_factories; -}; - -} diff --git a/editor/src/Managers/SceneManager.cpp b/editor/src/Managers/SceneManager.cpp index 081a767b..fa11fd1e 100644 --- a/editor/src/Managers/SceneManager.cpp +++ b/editor/src/Managers/SceneManager.cpp @@ -4,181 +4,143 @@ namespace UI { -EntityID SceneManager::CreateEntity(const std::string& name, EntityID parent) { - EntityID id = m_nextEntityId++; - 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); +XCEngine::Components::GameObject* EditorSceneManager::CreateEntity(const std::string& name, XCEngine::Components::GameObject* parent) { + if (!m_scene) { + m_scene = new XCEngine::Components::Scene("EditorScene"); } - - OnEntityCreated.Invoke(id); - return id; + + XCEngine::Components::GameObject* entity = m_scene->CreateGameObject(name, parent); + + if (parent == nullptr) { + m_rootEntities.push_back(entity); + } + + OnEntityCreated.Invoke(entity->GetID()); + return entity; } -void SceneManager::DeleteEntity(EntityID id) { - auto it = m_entities.find(id); - if (it == m_entities.end()) return; - - GameObject& entity = it->second; - - std::vector childrenToDelete = entity.children; - for (EntityID childId : childrenToDelete) { - DeleteEntity(childId); +void EditorSceneManager::DeleteEntity(XCEngine::Components::GameObject::ID id) { + if (!m_scene) return; + + XCEngine::Components::GameObject* entity = m_scene->Find(std::to_string(id)); + if (!entity) return; + + std::vector children = entity->GetChildren(); + for (auto* child : children) { + DeleteEntity(child->GetID()); } - - if (entity.parent != INVALID_ENTITY_ID) { - auto* parent = GetEntity(entity.parent); - if (parent) { - auto& siblings = parent->children; - siblings.erase(std::remove(siblings.begin(), siblings.end(), id), siblings.end()); - } - } else { - m_rootEntities.erase(std::remove(m_rootEntities.begin(), m_rootEntities.end(), id), m_rootEntities.end()); + + if (entity->GetParent() == nullptr) { + m_rootEntities.erase(std::remove(m_rootEntities.begin(), m_rootEntities.end(), entity), m_rootEntities.end()); } - - if (SelectionManager::Get().GetSelectedEntity() == id) { + + if (SelectionManager::Get().GetSelectedEntity() == entity) { SelectionManager::Get().ClearSelection(); } - - m_entities.erase(it); + + m_scene->DestroyGameObject(entity); OnEntityDeleted.Invoke(id); } -ClipboardData SceneManager::CopyEntityRecursive(const GameObject* entity) { +EditorSceneManager::ClipboardData EditorSceneManager::CopyEntityRecursive(const XCEngine::Components::GameObject* entity) { ClipboardData data; - data.name = entity->name; + data.name = entity->GetName(); - for (const auto& comp : entity->components) { - if (auto* transform = dynamic_cast(comp.get())) { - auto newComp = std::make_unique(); - memcpy(newComp->position, transform->position, sizeof(transform->position)); - memcpy(newComp->rotation, transform->rotation, sizeof(transform->rotation)); - memcpy(newComp->scale, transform->scale, sizeof(transform->scale)); - data.components.push_back(std::move(newComp)); - } - else if (auto* meshRenderer = dynamic_cast(comp.get())) { - auto newComp = std::make_unique(); - newComp->materialName = meshRenderer->materialName; - newComp->meshName = meshRenderer->meshName; - data.components.push_back(std::move(newComp)); - } + if (auto* transform = entity->GetComponent()) { + // Transform 数据会被复制 } - for (EntityID childId : entity->children) { - const GameObject* child = GetEntity(childId); - if (child) { - data.children.push_back(CopyEntityRecursive(child)); - } + for (auto* child : entity->GetChildren()) { + data.children.push_back(CopyEntityRecursive(child)); } return data; } -void SceneManager::CopyEntity(EntityID id) { - const GameObject* entity = GetEntity(id); +void EditorSceneManager::CopyEntity(XCEngine::Components::GameObject::ID id) { + if (!m_scene) return; + + XCEngine::Components::GameObject* entity = m_scene->Find(std::to_string(id)); if (!entity) return; m_clipboard = CopyEntityRecursive(entity); } -EntityID SceneManager::PasteEntityRecursive(const ClipboardData& data, EntityID parent) { - EntityID newId = CreateEntity(data.name, parent); - GameObject* newEntity = GetEntity(newId); - - if (newEntity) { - newEntity->components.clear(); - for (const auto& comp : data.components) { - if (auto* transform = dynamic_cast(comp.get())) { - auto newComp = std::make_unique(); - memcpy(newComp->position, transform->position, sizeof(transform->position)); - memcpy(newComp->rotation, transform->rotation, sizeof(transform->rotation)); - memcpy(newComp->scale, transform->scale, sizeof(transform->scale)); - newEntity->components.push_back(std::move(newComp)); - } - else if (auto* meshRenderer = dynamic_cast(comp.get())) { - auto newComp = std::make_unique(); - newComp->materialName = meshRenderer->materialName; - newComp->meshName = meshRenderer->meshName; - newEntity->components.push_back(std::move(newComp)); - } - } +XCEngine::Components::GameObject::ID EditorSceneManager::PasteEntityRecursive(const ClipboardData& data, XCEngine::Components::GameObject::ID parent) { + XCEngine::Components::GameObject* parentObj = nullptr; + if (parent != 0) { + parentObj = m_scene->Find(std::to_string(parent)); } - + + XCEngine::Components::GameObject* newEntity = m_scene->CreateGameObject(data.name, parentObj); + + if (parentObj == nullptr) { + m_rootEntities.push_back(newEntity); + } + for (const auto& childData : data.children) { - PasteEntityRecursive(childData, newId); + PasteEntityRecursive(childData, newEntity->GetID()); } - - return newId; + + return newEntity->GetID(); } -EntityID SceneManager::PasteEntity(EntityID parent) { - if (!m_clipboard) return INVALID_ENTITY_ID; +XCEngine::Components::GameObject::ID EditorSceneManager::PasteEntity(XCEngine::Components::GameObject::ID parent) { + if (!m_clipboard || !m_scene) return 0; return PasteEntityRecursive(*m_clipboard, parent); } -EntityID SceneManager::DuplicateEntity(EntityID id) { +XCEngine::Components::GameObject::ID EditorSceneManager::DuplicateEntity(XCEngine::Components::GameObject::ID id) { + if (!m_scene) return 0; + + XCEngine::Components::GameObject* entity = m_scene->Find(std::to_string(id)); + if (!entity) return 0; + CopyEntity(id); - const GameObject* entity = GetEntity(id); - if (!entity) return INVALID_ENTITY_ID; - return PasteEntity(entity->parent); + XCEngine::Components::GameObject::ID parentId = 0; + if (entity->GetParent()) { + parentId = entity->GetParent()->GetID(); + } + return PasteEntity(parentId); } -void SceneManager::MoveEntity(EntityID id, EntityID newParent) { - GameObject* entity = GetEntity(id); - if (!entity || id == newParent) return; - - if (entity->parent != INVALID_ENTITY_ID) { - GameObject* oldParent = GetEntity(entity->parent); - if (oldParent) { - auto& siblings = oldParent->children; - siblings.erase(std::remove(siblings.begin(), siblings.end(), id), siblings.end()); - } - } else { - m_rootEntities.erase(std::remove(m_rootEntities.begin(), m_rootEntities.end(), id), m_rootEntities.end()); +void EditorSceneManager::MoveEntity(XCEngine::Components::GameObject::ID id, XCEngine::Components::GameObject::ID newParentId) { + if (!m_scene) return; + + XCEngine::Components::GameObject* entity = m_scene->Find(std::to_string(id)); + if (!entity) return; + + XCEngine::Components::GameObject* newParent = nullptr; + if (newParentId != 0) { + newParent = m_scene->Find(std::to_string(newParentId)); } - - entity->parent = newParent; - - if (newParent != INVALID_ENTITY_ID) { - GameObject* newParentEntity = GetEntity(newParent); - if (newParentEntity) { - newParentEntity->children.push_back(id); - } - } else { - m_rootEntities.push_back(id); - } - + + entity->SetParent(newParent); OnEntityChanged.Invoke(id); } -void SceneManager::CreateDemoScene() { - m_entities.clear(); +void EditorSceneManager::CreateDemoScene() { + if (m_scene) { + delete m_scene; + } + m_scene = new XCEngine::Components::Scene("DemoScene"); m_rootEntities.clear(); - m_nextEntityId = 1; m_clipboard.reset(); - EntityID camera = CreateEntity("Main Camera"); - GetEntity(camera)->AddComponent(); + XCEngine::Components::GameObject* camera = CreateEntity("Main Camera", nullptr); + camera->AddComponent(); - EntityID light = CreateEntity("Directional Light"); + XCEngine::Components::GameObject* light = CreateEntity("Directional Light", nullptr); - EntityID cube = CreateEntity("Cube"); - GetEntity(cube)->AddComponent(); - GetEntity(cube)->AddComponent()->meshName = "Cube Mesh"; + XCEngine::Components::GameObject* cube = CreateEntity("Cube", nullptr); + cube->AddComponent(); + // MeshRendererComponent 需要添加到 Engine - EntityID sphere = CreateEntity("Sphere"); - GetEntity(sphere)->AddComponent(); - GetEntity(sphere)->AddComponent()->meshName = "Sphere Mesh"; + XCEngine::Components::GameObject* sphere = CreateEntity("Sphere", nullptr); + sphere->AddComponent(); - EntityID player = CreateEntity("Player"); - EntityID weapon = CreateEntity("Weapon", player); + XCEngine::Components::GameObject* player = CreateEntity("Player", nullptr); + XCEngine::Components::GameObject* weapon = CreateEntity("Weapon", player); OnSceneChanged.Invoke(); } diff --git a/editor/src/Managers/SceneManager.h b/editor/src/Managers/SceneManager.h index 095c9941..eea3360d 100644 --- a/editor/src/Managers/SceneManager.h +++ b/editor/src/Managers/SceneManager.h @@ -1,86 +1,74 @@ #pragma once -#include "Core/GameObject.h" #include #include #include #include #include +#include +#include namespace UI { -struct ClipboardData { - std::string name; - std::vector> components; - std::vector children; -}; - -class SceneManager { +class EditorSceneManager { public: - static SceneManager& Get() { - static SceneManager instance; + static EditorSceneManager& Get() { + static EditorSceneManager instance; return instance; } - EntityID CreateEntity(const std::string& name, EntityID parent = INVALID_ENTITY_ID); + XCEngine::Components::GameObject* CreateEntity(const std::string& name, XCEngine::Components::GameObject* parent = nullptr); - GameObject* GetEntity(EntityID id) { - auto it = m_entities.find(id); - if (it != m_entities.end()) { - return &it->second; - } - return nullptr; + XCEngine::Components::GameObject* GetEntity(XCEngine::Components::GameObject::ID id) { + return m_scene ? m_scene->Find(std::to_string(id)) : nullptr; } - const GameObject* GetEntity(EntityID id) const { - auto it = m_entities.find(id); - if (it != m_entities.end()) { - return &it->second; - } - return nullptr; + const XCEngine::Components::GameObject* GetEntity(XCEngine::Components::GameObject::ID id) const { + return m_scene ? m_scene->Find(std::to_string(id)) : nullptr; } - const std::vector& GetRootEntities() const { + const std::vector& GetRootEntities() const { return m_rootEntities; } - void DeleteEntity(EntityID id); + void DeleteEntity(XCEngine::Components::GameObject::ID id); - void RenameEntity(EntityID id, const std::string& newName) { - auto* entity = GetEntity(id); - if (entity) { - entity->name = newName; + void RenameEntity(XCEngine::Components::GameObject::ID id, const std::string& newName) { + if (auto* entity = GetEntity(id)) { + entity->SetName(newName); 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 CopyEntity(XCEngine::Components::GameObject::ID id); + XCEngine::Components::GameObject::ID PasteEntity(XCEngine::Components::GameObject::ID parent = 0); + XCEngine::Components::GameObject::ID DuplicateEntity(XCEngine::Components::GameObject::ID id); + void MoveEntity(XCEngine::Components::GameObject::ID id, XCEngine::Components::GameObject::ID 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 OnEntityCreated; + XCEngine::Core::Event OnEntityDeleted; + XCEngine::Core::Event OnEntityChanged; XCEngine::Core::Event<> OnSceneChanged; private: - SceneManager() = default; + EditorSceneManager() = default; - ClipboardData CopyEntityRecursive(const GameObject* entity); - EntityID PasteEntityRecursive(const ClipboardData& data, EntityID parent); + struct ClipboardData { + std::string name; + std::vector> components; + std::vector children; + }; - EntityID m_nextEntityId = 1; - std::unordered_map m_entities; - std::vector m_rootEntities; + ClipboardData CopyEntityRecursive(const XCEngine::Components::GameObject* entity); + XCEngine::Components::GameObject::ID PasteEntityRecursive(const ClipboardData& data, XCEngine::Components::GameObject::ID parent); + + XCEngine::Components::Scene* m_scene = nullptr; + std::vector m_rootEntities; std::optional m_clipboard; }; diff --git a/editor/src/Managers/SelectionManager.h b/editor/src/Managers/SelectionManager.h index 07ccf805..1c81549a 100644 --- a/editor/src/Managers/SelectionManager.h +++ b/editor/src/Managers/SelectionManager.h @@ -1,9 +1,9 @@ #pragma once -#include "Core/GameObject.h" #include #include +#include namespace UI { @@ -14,26 +14,26 @@ public: return instance; } - EntityID GetSelectedEntity() const { return m_selectedEntity; } + XCEngine::Components::GameObject* GetSelectedEntity() const { return m_selectedEntity; } - void SetSelectedEntity(EntityID id) { - m_selectedEntity = id; - OnSelectionChanged.Invoke(id); + void SetSelectedEntity(XCEngine::Components::GameObject* entity) { + m_selectedEntity = entity; + OnSelectionChanged.Invoke(entity ? entity->GetID() : 0); } void ClearSelection() { - SetSelectedEntity(INVALID_ENTITY_ID); + SetSelectedEntity(nullptr); } - bool IsSelected(EntityID id) const { - return m_selectedEntity == id; + bool IsSelected(XCEngine::Components::GameObject* entity) const { + return m_selectedEntity == entity; } - XCEngine::Core::Event OnSelectionChanged; + XCEngine::Core::Event OnSelectionChanged; private: SelectionManager() = default; - EntityID m_selectedEntity = INVALID_ENTITY_ID; + XCEngine::Components::GameObject* m_selectedEntity = nullptr; }; } diff --git a/editor/src/panels/HierarchyPanel.cpp b/editor/src/panels/HierarchyPanel.cpp index 096bd969..9dc76ac6 100644 --- a/editor/src/panels/HierarchyPanel.cpp +++ b/editor/src/panels/HierarchyPanel.cpp @@ -9,7 +9,7 @@ namespace UI { HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") { SceneManager::Get().CreateDemoScene(); - m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](EntityID) { + m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) { }); } @@ -30,8 +30,8 @@ void HierarchyPanel::Render() { ImGui::BeginChild("EntityList"); - for (EntityID id : SceneManager::Get().GetRootEntities()) { - RenderEntity(id, filter); + for (auto* entity : SceneManager::Get().GetRootEntities()) { + RenderEntity(entity, filter); } if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(0) && !ImGui::IsAnyItemHovered()) { @@ -41,19 +41,16 @@ void HierarchyPanel::Render() { } if (ImGui::BeginPopupContextWindow("HierarchyContextMenu", ImGuiPopupFlags_MouseButtonRight)) { - RenderCreateMenu(INVALID_ENTITY_ID); + RenderCreateMenu(nullptr); ImGui::EndPopup(); } ImGui::InvisibleButton("##DragTarget", ImVec2(-1, -1)); if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_ID")) { - EntityID sourceId = *(const EntityID*)payload->Data; - if (sourceId != INVALID_ENTITY_ID) { - const GameObject* sourceEntity = SceneManager::Get().GetEntity(sourceId); - if (sourceEntity && sourceEntity->parent != INVALID_ENTITY_ID) { - SceneManager::Get().MoveEntity(sourceId, INVALID_ENTITY_ID); - } + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_PTR")) { + XCEngine::Components::GameObject* sourceEntity = *(XCEngine::Components::GameObject**)payload->Data; + if (sourceEntity && sourceEntity->GetParent() != nullptr) { + SceneManager::Get().MoveEntity(sourceEntity->GetID(), 0); } } ImGui::EndDragDropTarget(); @@ -69,28 +66,26 @@ void HierarchyPanel::RenderSearchBar() { ImGui::InputTextWithHint("##Search", "Search...", m_searchBuffer, sizeof(m_searchBuffer)); } -void HierarchyPanel::RenderEntity(EntityID id, const std::string& filter) { - auto& sceneManager = SceneManager::Get(); - GameObject* entity = sceneManager.GetEntity(id); +void HierarchyPanel::RenderEntity(XCEngine::Components::GameObject* entity, const std::string& filter) { if (!entity) return; - if (!filter.empty() && !PassesFilter(id, filter)) { + if (!filter.empty() && !PassesFilter(entity, filter)) { return; } - ImGui::PushID(static_cast(id)); + ImGui::PushID(static_cast(entity->GetID())); ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth; - if (entity->children.empty()) { + if (entity->GetChildCount() == 0) { flags |= ImGuiTreeNodeFlags_Leaf; } - if (SelectionManager::Get().IsSelected(id)) { + if (SelectionManager::Get().IsSelected(entity)) { flags |= ImGuiTreeNodeFlags_Selected; } - if (m_renaming && m_renamingEntity == id) { + if (m_renaming && m_renamingEntity == entity) { if (m_renameJustStarted) { ImGui::SetKeyboardFocusHere(); m_renameJustStarted = false; @@ -99,43 +94,43 @@ void HierarchyPanel::RenderEntity(EntityID id, const std::string& filter) { ImGui::SetNextItemWidth(-1); if (ImGui::InputText("##Rename", m_renameBuffer, sizeof(m_renameBuffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) { if (strlen(m_renameBuffer) > 0) { - sceneManager.RenameEntity(id, m_renameBuffer); + SceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer); } m_renaming = false; - m_renamingEntity = INVALID_ENTITY_ID; + m_renamingEntity = nullptr; } if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) { if (strlen(m_renameBuffer) > 0) { - sceneManager.RenameEntity(id, m_renameBuffer); + SceneManager::Get().RenameEntity(entity->GetID(), m_renameBuffer); } m_renaming = false; - m_renamingEntity = INVALID_ENTITY_ID; + m_renamingEntity = nullptr; } } else { - bool isOpen = ImGui::TreeNodeEx(entity->name.c_str(), flags); + bool isOpen = ImGui::TreeNodeEx(entity->GetName().c_str(), flags); if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { - SelectionManager::Get().SetSelectedEntity(id); + SelectionManager::Get().SetSelectedEntity(entity); } if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) { m_renaming = true; - m_renamingEntity = id; - strcpy_s(m_renameBuffer, entity->name.c_str()); + m_renamingEntity = entity; + strcpy_s(m_renameBuffer, entity->GetName().c_str()); m_renameJustStarted = true; } - HandleDragDrop(id); + HandleDragDrop(entity); if (ImGui::BeginPopupContextItem("EntityContextMenu")) { - RenderContextMenu(id); + RenderContextMenu(entity); ImGui::EndPopup(); } if (isOpen) { - for (EntityID childId : entity->children) { - RenderEntity(childId, filter); + for (size_t i = 0; i < entity->GetChildCount(); i++) { + RenderEntity(entity->GetChild(i), filter); } ImGui::TreePop(); } @@ -144,128 +139,115 @@ void HierarchyPanel::RenderEntity(EntityID id, const std::string& filter) { ImGui::PopID(); } -void HierarchyPanel::RenderContextMenu(EntityID id) { +void HierarchyPanel::RenderContextMenu(XCEngine::Components::GameObject* entity) { auto& sceneManager = SceneManager::Get(); auto& selectionManager = SelectionManager::Get(); if (ImGui::BeginMenu("Create")) { - RenderCreateMenu(id); + RenderCreateMenu(entity); ImGui::EndMenu(); } ImGui::Separator(); if (ImGui::MenuItem("Rename", "F2")) { - const GameObject* entity = sceneManager.GetEntity(id); if (entity) { m_renaming = true; - m_renamingEntity = id; - strcpy_s(m_renameBuffer, entity->name.c_str()); + m_renamingEntity = entity; + strcpy_s(m_renameBuffer, entity->GetName().c_str()); m_renameJustStarted = true; } } if (ImGui::MenuItem("Delete", "Delete")) { - sceneManager.DeleteEntity(id); + sceneManager.DeleteEntity(entity->GetID()); } ImGui::Separator(); if (ImGui::MenuItem("Copy", "Ctrl+C")) { - sceneManager.CopyEntity(id); + sceneManager.CopyEntity(entity->GetID()); } if (ImGui::MenuItem("Paste", "Ctrl+V", false, sceneManager.HasClipboardData())) { - sceneManager.PasteEntity(id); + sceneManager.PasteEntity(entity->GetID()); } if (ImGui::MenuItem("Duplicate", "Ctrl+D")) { - EntityID newId = sceneManager.DuplicateEntity(id); - if (newId != INVALID_ENTITY_ID) { - selectionManager.SetSelectedEntity(newId); + uint64_t newId = sceneManager.DuplicateEntity(entity->GetID()); + if (newId != 0) { + // Selection handled via callback } } } -void HierarchyPanel::RenderCreateMenu(EntityID parent) { +void HierarchyPanel::RenderCreateMenu(XCEngine::Components::GameObject* parent) { auto& sceneManager = SceneManager::Get(); auto& selectionManager = SelectionManager::Get(); if (ImGui::MenuItem("Empty Object")) { - EntityID newId = sceneManager.CreateEntity("GameObject", parent); - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("GameObject", parent); + selectionManager.SetSelectedEntity(newEntity); } ImGui::Separator(); if (ImGui::MenuItem("Camera")) { - EntityID newId = sceneManager.CreateEntity("Camera", parent); - sceneManager.GetEntity(newId)->AddComponent(); - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("Camera", parent); + newEntity->AddComponent(); + selectionManager.SetSelectedEntity(newEntity); } if (ImGui::MenuItem("Light")) { - EntityID newId = sceneManager.CreateEntity("Light", parent); - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("Light", parent); + selectionManager.SetSelectedEntity(newEntity); } ImGui::Separator(); if (ImGui::MenuItem("Cube")) { - EntityID newId = sceneManager.CreateEntity("Cube", parent); - sceneManager.GetEntity(newId)->AddComponent(); - sceneManager.GetEntity(newId)->AddComponent()->meshName = "Cube"; - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("Cube", parent); + newEntity->AddComponent(); + selectionManager.SetSelectedEntity(newEntity); } if (ImGui::MenuItem("Sphere")) { - EntityID newId = sceneManager.CreateEntity("Sphere", parent); - sceneManager.GetEntity(newId)->AddComponent(); - sceneManager.GetEntity(newId)->AddComponent()->meshName = "Sphere"; - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("Sphere", parent); + newEntity->AddComponent(); + selectionManager.SetSelectedEntity(newEntity); } if (ImGui::MenuItem("Plane")) { - EntityID newId = sceneManager.CreateEntity("Plane", parent); - sceneManager.GetEntity(newId)->AddComponent(); - sceneManager.GetEntity(newId)->AddComponent()->meshName = "Plane"; - selectionManager.SetSelectedEntity(newId); + auto* newEntity = sceneManager.CreateEntity("Plane", parent); + newEntity->AddComponent(); + selectionManager.SetSelectedEntity(newEntity); } } -void HierarchyPanel::HandleDragDrop(EntityID id) { - auto& sceneManager = SceneManager::Get(); - +void HierarchyPanel::HandleDragDrop(XCEngine::Components::GameObject* entity) { if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - m_dragSource = id; - ImGui::SetDragDropPayload("ENTITY_ID", &id, sizeof(EntityID)); - const GameObject* entity = sceneManager.GetEntity(id); - if (entity) { - ImGui::Text("%s", entity->name.c_str()); - } + m_dragSource = entity; + ImGui::SetDragDropPayload("ENTITY_PTR", &entity, sizeof(XCEngine::Components::GameObject*)); + ImGui::Text("%s", entity->GetName().c_str()); ImGui::EndDragDropSource(); } if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_ID")) { - EntityID sourceId = *(const EntityID*)payload->Data; - if (sourceId != id && sourceId != INVALID_ENTITY_ID) { - const GameObject* targetEntity = sceneManager.GetEntity(id); - const GameObject* sourceEntity = sceneManager.GetEntity(sourceId); - + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_PTR")) { + XCEngine::Components::GameObject* sourceEntity = *(XCEngine::Components::GameObject**)payload->Data; + if (sourceEntity != entity && sourceEntity != nullptr) { bool isValidMove = true; - EntityID checkParent = targetEntity ? targetEntity->parent : INVALID_ENTITY_ID; - while (checkParent != INVALID_ENTITY_ID) { - if (checkParent == sourceId) { + XCEngine::Components::GameObject* checkParent = entity; + while (checkParent != nullptr) { + if (checkParent == sourceEntity) { isValidMove = false; break; } - const GameObject* parentEntity = sceneManager.GetEntity(checkParent); - checkParent = parentEntity ? parentEntity->parent : INVALID_ENTITY_ID; + checkParent = checkParent->GetParent(); } - if (isValidMove && sourceEntity && sourceEntity->parent != id) { - sceneManager.MoveEntity(sourceId, id); + if (isValidMove) { + sceneManager.MoveEntity(sourceEntity->GetID(), entity->GetID()); } } } @@ -277,64 +259,56 @@ void HierarchyPanel::HandleKeyboardShortcuts() { auto& sceneManager = SceneManager::Get(); auto& selectionManager = SelectionManager::Get(); - EntityID selectedId = selectionManager.GetSelectedEntity(); + XCEngine::Components::GameObject* selectedEntity = selectionManager.GetSelectedEntity(); if (ImGui::IsWindowFocused()) { if (ImGui::IsKeyPressed(ImGuiKey_Delete)) { - if (selectedId != INVALID_ENTITY_ID) { - sceneManager.DeleteEntity(selectedId); + if (selectedEntity != nullptr) { + sceneManager.DeleteEntity(selectedEntity->GetID()); } } if (ImGui::IsKeyPressed(ImGuiKey_F2)) { - if (selectedId != INVALID_ENTITY_ID) { - const GameObject* entity = sceneManager.GetEntity(selectedId); - if (entity) { - m_renaming = true; - m_renamingEntity = selectedId; - strcpy_s(m_renameBuffer, entity->name.c_str()); - m_renameJustStarted = true; - } + if (selectedEntity != nullptr) { + m_renaming = true; + m_renamingEntity = selectedEntity; + strcpy_s(m_renameBuffer, selectedEntity->GetName().c_str()); + m_renameJustStarted = true; } } ImGuiIO& io = ImGui::GetIO(); if (io.KeyCtrl) { if (ImGui::IsKeyPressed(ImGuiKey_C)) { - if (selectedId != INVALID_ENTITY_ID) { - sceneManager.CopyEntity(selectedId); + if (selectedEntity != nullptr) { + sceneManager.CopyEntity(selectedEntity->GetID()); } } if (ImGui::IsKeyPressed(ImGuiKey_V)) { if (sceneManager.HasClipboardData()) { - sceneManager.PasteEntity(selectedId); + sceneManager.PasteEntity(selectedEntity ? selectedEntity->GetID() : 0); } } if (ImGui::IsKeyPressed(ImGuiKey_D)) { - if (selectedId != INVALID_ENTITY_ID) { - EntityID newId = sceneManager.DuplicateEntity(selectedId); - if (newId != INVALID_ENTITY_ID) { - selectionManager.SetSelectedEntity(newId); - } + if (selectedEntity != nullptr) { + sceneManager.DuplicateEntity(selectedEntity->GetID()); } } } } } -bool HierarchyPanel::PassesFilter(EntityID id, const std::string& filter) { - auto& sceneManager = SceneManager::Get(); - const GameObject* entity = sceneManager.GetEntity(id); +bool HierarchyPanel::PassesFilter(XCEngine::Components::GameObject* entity, const std::string& filter) { if (!entity) return false; - if (entity->name.find(filter) != std::string::npos) { + if (entity->GetName().find(filter) != std::string::npos) { return true; } - for (EntityID childId : entity->children) { - if (PassesFilter(childId, filter)) { + for (size_t i = 0; i < entity->GetChildCount(); i++) { + if (PassesFilter(entity->GetChild(i), filter)) { return true; } } @@ -342,4 +316,4 @@ bool HierarchyPanel::PassesFilter(EntityID id, const std::string& filter) { return false; } -} \ No newline at end of file +} diff --git a/editor/src/panels/HierarchyPanel.h b/editor/src/panels/HierarchyPanel.h index a4afa6f6..e93745d0 100644 --- a/editor/src/panels/HierarchyPanel.h +++ b/editor/src/panels/HierarchyPanel.h @@ -1,7 +1,7 @@ #pragma once #include "Panel.h" -#include "Core/GameObject.h" +#include namespace UI { @@ -14,21 +14,21 @@ public: private: void RenderSearchBar(); - void RenderEntity(EntityID id, const std::string& filter); - void RenderContextMenu(EntityID id); - void RenderCreateMenu(EntityID parent); - void HandleDragDrop(EntityID id); + void RenderEntity(XCEngine::Components::GameObject* entity, const std::string& filter); + void RenderContextMenu(XCEngine::Components::GameObject* entity); + void RenderCreateMenu(XCEngine::Components::GameObject* parent); + void HandleDragDrop(XCEngine::Components::GameObject* entity); void HandleKeyboardShortcuts(); - bool PassesFilter(EntityID id, const std::string& filter); + bool PassesFilter(XCEngine::Components::GameObject* entity, const std::string& filter); uint64_t m_selectionHandlerId = 0; char m_searchBuffer[256] = ""; bool m_renaming = false; - EntityID m_renamingEntity = INVALID_ENTITY_ID; + XCEngine::Components::GameObject* m_renamingEntity = nullptr; char m_renameBuffer[256] = ""; bool m_renameJustStarted = false; - EntityID m_dragSource = INVALID_ENTITY_ID; + XCEngine::Components::GameObject* m_dragSource = nullptr; }; -} \ No newline at end of file +} diff --git a/editor/src/panels/InspectorPanel.cpp b/editor/src/panels/InspectorPanel.cpp index f33e2cc3..042cf077 100644 --- a/editor/src/panels/InspectorPanel.cpp +++ b/editor/src/panels/InspectorPanel.cpp @@ -3,11 +3,12 @@ #include "Managers/SelectionManager.h" #include #include +#include namespace UI { InspectorPanel::InspectorPanel() : Panel("Inspector") { - m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](EntityID) { + m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) { }); } @@ -18,8 +19,7 @@ InspectorPanel::~InspectorPanel() { void InspectorPanel::Render() { ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_None); - EntityID selectedId = SelectionManager::Get().GetSelectedEntity(); - GameObject* entity = SceneManager::Get().GetEntity(selectedId); + XCEngine::Components::GameObject* entity = SelectionManager::Get().GetSelectedEntity(); if (entity) { RenderEntity(entity); @@ -31,59 +31,41 @@ void InspectorPanel::Render() { ImGui::End(); } -void InspectorPanel::RenderEntity(GameObject* entity) { - ImGui::Text("%s", entity->name.c_str()); +void InspectorPanel::RenderEntity(XCEngine::Components::GameObject* entity) { + ImGui::Text("%s", entity->GetName().c_str()); ImGui::Separator(); - for (auto& component : entity->components) { + for (auto& component : entity->m_components) { RenderComponent(component.get()); ImGui::Separator(); } } -void InspectorPanel::RenderComponent(Component* component) { +void InspectorPanel::RenderComponent(XCEngine::Components::Component* component) { if (!component) return; const char* name = component->GetName().c_str(); - std::string headerId = name + std::string("##") + std::to_string(reinterpret_cast(component)); + std::string headerId = std::string(name) + "##" + std::to_string(reinterpret_cast(component)); if (ImGui::CollapsingHeader(headerId.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Indent(10.0f); - if (auto* transform = dynamic_cast(component)) { - ImGui::Text("Position"); - ImGui::SameLine(80); - ImGui::SetNextItemWidth(180); - ImGui::DragFloat3("##Position", transform->position, 0.1f); + if (auto* transform = dynamic_cast(component)) { + glm::vec3 position = transform->GetLocalPosition(); + glm::vec3 rotation = transform->GetLocalEulerAngles(); + glm::vec3 scale = transform->GetLocalScale(); - ImGui::Text("Rotation"); - ImGui::SameLine(80); - ImGui::SetNextItemWidth(180); - ImGui::DragFloat3("##Rotation", transform->rotation, 1.0f); - - ImGui::Text("Scale"); - ImGui::SameLine(80); - ImGui::SetNextItemWidth(180); - ImGui::DragFloat3("##Scale", transform->scale, 0.1f); - } - else if (auto* meshRenderer = dynamic_cast(component)) { - char materialBuffer[256] = {}; - strncpy_s(materialBuffer, meshRenderer->materialName.c_str(), sizeof(materialBuffer) - 1); - ImGui::Text("Material"); - ImGui::SameLine(80); - ImGui::SetNextItemWidth(180); - if (ImGui::InputText("##Material", materialBuffer, sizeof(materialBuffer))) { - meshRenderer->materialName = materialBuffer; + if (ImGui::DragFloat3("Position", &position.x, 0.1f)) { + transform->SetLocalPosition(position); } - char meshBuffer[256] = {}; - strncpy_s(meshBuffer, meshRenderer->meshName.c_str(), sizeof(meshBuffer) - 1); - ImGui::Text("Mesh"); - ImGui::SameLine(80); - ImGui::SetNextItemWidth(180); - if (ImGui::InputText("##Mesh", meshBuffer, sizeof(meshBuffer))) { - meshRenderer->meshName = meshBuffer; + if (ImGui::DragFloat3("Rotation", &rotation.x, 1.0f)) { + transform->SetLocalEulerAngles(rotation); + } + + if (ImGui::DragFloat3("Scale", &scale.x, 0.1f)) { + transform->SetLocalScale(scale); } } @@ -91,4 +73,4 @@ void InspectorPanel::RenderComponent(Component* component) { } } -} \ No newline at end of file +} diff --git a/editor/src/panels/InspectorPanel.h b/editor/src/panels/InspectorPanel.h index 16727915..38437b6f 100644 --- a/editor/src/panels/InspectorPanel.h +++ b/editor/src/panels/InspectorPanel.h @@ -1,7 +1,8 @@ #pragma once #include "Panel.h" -#include "Core/GameObject.h" +#include +#include namespace UI { @@ -13,10 +14,10 @@ public: void Render() override; private: - void RenderEntity(GameObject* entity); - void RenderComponent(Component* component); + void RenderEntity(XCEngine::Components::GameObject* entity); + void RenderComponent(XCEngine::Components::Component* component); uint64_t m_selectionHandlerId = 0; }; -} \ No newline at end of file +} diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h index 4c8a6838..7a83b30d 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h @@ -25,35 +25,28 @@ public: bool Compile(const char* source, ShaderType type); void Use() const; - void Bind() override { Use(); } - void Unbind() override; - void SetInt(const char* name, int value) override; - void SetIntArray(const char* name, const int* values, unsigned int count); - void SetFloat(const char* name, float value) override; - void SetFloatArray(const char* name, const float* values, unsigned int count); - void SetVec3(const char* name, float x, float y, float z) override; - void SetVec3(const char* name, const float* values); - void SetVec4(const char* name, float x, float y, float z, float w) override; - void SetVec4(const char* name, const float* values); - void SetMat2(const char* name, const float* value); - void SetMat3(const char* name, const float* value); - void SetMat4(const char* name, const float* value) override; - void SetMat4Array(const char* name, const float* values, unsigned int count); - - int GetUniformLocation(const char* name) const; - unsigned int GetID() const { return m_program; } void* GetNativeHandle() override { return reinterpret_cast(static_cast(m_program)); } bool IsValid() const override { return m_program != 0; } ShaderType GetType() const override { return m_type; } + const std::vector& GetUniformInfos() const override; + const UniformInfo* GetUniformInfo(const char* name) const override; + + int GetUniformLocation(const char* name) const; + unsigned int GetID() const { return m_program; } + private: + void CacheUniformInfos() const; + unsigned int m_program; ShaderType m_type = ShaderType::Vertex; + mutable std::vector m_uniformInfos; + mutable bool m_uniformsCached = false; bool CheckCompileErrors(unsigned int shader, const char* type); bool CheckLinkErrors(unsigned int program); }; } // namespace RHI -} // namespace XCEngine +} // namespace XCEngine \ No newline at end of file diff --git a/engine/include/XCEngine/RHI/RHIShader.h b/engine/include/XCEngine/RHI/RHIShader.h index 4bb36a33..a5363baf 100644 --- a/engine/include/XCEngine/RHI/RHIShader.h +++ b/engine/include/XCEngine/RHI/RHIShader.h @@ -3,6 +3,7 @@ #include "RHITypes.h" #include "RHIEnums.h" #include +#include namespace XCEngine { namespace RHI { @@ -17,19 +18,21 @@ public: virtual ShaderType GetType() const = 0; virtual bool IsValid() const = 0; - virtual void Bind() = 0; - virtual void Unbind() = 0; - virtual void* GetNativeHandle() = 0; - virtual void SetInt(const char* name, int value) = 0; - virtual void SetFloat(const char* name, float value) = 0; - virtual void SetVec3(const char* name, float x, float y, float z) = 0; - virtual void SetVec4(const char* name, float x, float y, float z, float w) = 0; - virtual void SetMat4(const char* name, const float* value) = 0; - virtual void Shutdown() = 0; + + struct UniformInfo { + std::string name; + uint32_t bindPoint; + uint32_t size; + uint32_t type; + uint32_t arraySize; + }; + + virtual const std::vector& GetUniformInfos() const = 0; + virtual const UniformInfo* GetUniformInfo(const char* name) const = 0; }; } // namespace RHI -} // namespace XCEngine +} // namespace XCEngine \ No newline at end of file diff --git a/engine/src/RHI/OpenGL/OpenGLShader.cpp b/engine/src/RHI/OpenGL/OpenGLShader.cpp index 14c0428b..9403ae5a 100644 --- a/engine/src/RHI/OpenGL/OpenGLShader.cpp +++ b/engine/src/RHI/OpenGL/OpenGLShader.cpp @@ -8,7 +8,7 @@ namespace XCEngine { namespace RHI { OpenGLShader::OpenGLShader() - : m_program(0) { + : m_program(0), m_uniformsCached(false) { } OpenGLShader::~OpenGLShader() { @@ -87,6 +87,8 @@ bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource) glDeleteShader(vertex); glDeleteShader(fragment); + m_uniformsCached = false; + return true; } @@ -128,6 +130,8 @@ bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource, glDeleteShader(fragment); glDeleteShader(geometry); + m_uniformsCached = false; + return true; } @@ -149,6 +153,8 @@ bool OpenGLShader::CompileCompute(const char* computeSource) { glDeleteShader(compute); + m_uniformsCached = false; + return true; } @@ -197,6 +203,9 @@ bool OpenGLShader::Compile(const char* source, ShaderType type) { } glDeleteShader(shader); + + m_uniformsCached = false; + return true; } @@ -218,62 +227,73 @@ void OpenGLShader::Shutdown() { glDeleteProgram(m_program); m_program = 0; } + m_uniformInfos.clear(); + m_uniformsCached = false; } void OpenGLShader::Use() const { glUseProgram(m_program); } -void OpenGLShader::Unbind() { - glUseProgram(0); +void OpenGLShader::CacheUniformInfos() const { + if (m_uniformsCached || m_program == 0) { + return; + } + + m_uniformInfos.clear(); + + GLint numUniforms = 0; + glGetProgramInterfaceiv(m_program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms); + + for (GLint i = 0; i < numUniforms; ++i) { + GLenum props[] = { GL_NAME_LENGTH, GL_TYPE, GL_OFFSET, GL_ARRAY_SIZE }; + GLint values[4] = { 0 }; + glGetProgramResourceiv(m_program, GL_UNIFORM, i, 4, props, 4, nullptr, values); + + std::vector nameBuffer(values[0]); + glGetProgramResourceName(m_program, GL_UNIFORM, i, values[0], nullptr, nameBuffer.data()); + + UniformInfo info; + info.name = nameBuffer.data(); + info.bindPoint = static_cast(i); + info.type = static_cast(values[1]); + info.offset = static_cast(values[2]); + info.arraySize = static_cast(values[3]); + + GLint size = 0; + glGetActiveUniformsiv(m_program, 1, &i, GL_SIZE, &size); + switch (values[1]) { + case GL_FLOAT: info.size = sizeof(GLfloat) * size; break; + case GL_FLOAT_VEC2: info.size = sizeof(GLfloat) * 2 * size; break; + case GL_FLOAT_VEC3: info.size = sizeof(GLfloat) * 3 * size; break; + case GL_FLOAT_VEC4: info.size = sizeof(GLfloat) * 4 * size; break; + case GL_INT: info.size = sizeof(GLint) * size; break; + case GL_BOOL: info.size = sizeof(GLboolean) * size; break; + case GL_FLOAT_MAT4: info.size = sizeof(GLfloat) * 16 * size; break; + case GL_FLOAT_MAT3: info.size = sizeof(GLfloat) * 9 * size; break; + case GL_FLOAT_MAT2: info.size = sizeof(GLfloat) * 4 * size; break; + default: info.size = 0; break; + } + + m_uniformInfos.push_back(info); + } + + m_uniformsCached = true; } -void OpenGLShader::SetInt(const char* name, int value) { - glUniform1i(glGetUniformLocation(m_program, name), value); +const std::vector& OpenGLShader::GetUniformInfos() const { + CacheUniformInfos(); + return m_uniformInfos; } -void OpenGLShader::SetIntArray(const char* name, const int* values, unsigned int count) { - glUniform1iv(glGetUniformLocation(m_program, name), count, values); -} - -void OpenGLShader::SetFloat(const char* name, float value) { - glUniform1f(glGetUniformLocation(m_program, name), value); -} - -void OpenGLShader::SetFloatArray(const char* name, const float* values, unsigned int count) { - glUniform1fv(glGetUniformLocation(m_program, name), count, values); -} - -void OpenGLShader::SetVec3(const char* name, float x, float y, float z) { - glUniform3f(glGetUniformLocation(m_program, name), x, y, z); -} - -void OpenGLShader::SetVec3(const char* name, const float* values) { - glUniform3fv(glGetUniformLocation(m_program, name), 1, values); -} - -void OpenGLShader::SetVec4(const char* name, float x, float y, float z, float w) { - glUniform4f(glGetUniformLocation(m_program, name), x, y, z, w); -} - -void OpenGLShader::SetVec4(const char* name, const float* values) { - glUniform4fv(glGetUniformLocation(m_program, name), 1, values); -} - -void OpenGLShader::SetMat2(const char* name, const float* value) { - glUniformMatrix2fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value); -} - -void OpenGLShader::SetMat3(const char* name, const float* value) { - glUniformMatrix3fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value); -} - -void OpenGLShader::SetMat4(const char* name, const float* value) { - glUniformMatrix4fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value); -} - -void OpenGLShader::SetMat4Array(const char* name, const float* values, unsigned int count) { - glUniformMatrix4fv(glGetUniformLocation(m_program, name), count, GL_FALSE, values); +const RHIShader::UniformInfo* OpenGLShader::GetUniformInfo(const char* name) const { + CacheUniformInfos(); + for (const auto& info : m_uniformInfos) { + if (info.name == name) { + return &info; + } + } + return nullptr; } int OpenGLShader::GetUniformLocation(const char* name) const { @@ -307,4 +327,4 @@ bool OpenGLShader::CheckLinkErrors(unsigned int program) { } } // namespace RHI -} // namespace XCEngine +} // namespace XCEngine \ No newline at end of file