refactor(editor): Complete architecture refactoring

- SceneManager: remove singleton, use dependency injection via EditorContext
- SelectionManager: already interface-based via ISelectionManager
- Panel: now receives IEditorContext for accessing managers
- HierarchyPanel: migrated to use IEditorContext instead of singletons
- Add ISceneManager interface and SceneManagerImpl
- EditorContextImpl: holds all editor subsystems

Architecture now follows dependency injection pattern:
Application -> EditorContext -> SceneManager/SelectionManager
EditorLayer -> Panels (receive context via SetContext)

All Manager singletons removed: EditorSceneManager::Get(), SelectionManager::Get()
This commit is contained in:
2026-03-25 15:51:27 +08:00
parent 56ec2e9b85
commit 008fb98dee
18 changed files with 1491 additions and 181 deletions

View File

@@ -1,6 +1,5 @@
#include "HierarchyPanel.h"
#include "Managers/SceneManager.h"
#include "Managers/SelectionManager.h"
#include "Core/IEditorContext.h"
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <imgui.h>
@@ -10,14 +9,14 @@ namespace XCEngine {
namespace Editor {
HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") {
EditorSceneManager::Get().CreateDemoScene();
m_selectionHandlerId = SelectionManager::Get().OnSelectionChanged.Subscribe([this](uint64_t) {
});
}
HierarchyPanel::~HierarchyPanel() {
SelectionManager::Get().OnSelectionChanged.Unsubscribe(m_selectionHandlerId);
}
void HierarchyPanel::OnAttach() {
auto* sceneManager = static_cast<SceneManager*>(m_context->GetSceneManager());
sceneManager->CreateDemoScene();
}
void HierarchyPanel::Render() {
@@ -33,7 +32,8 @@ void HierarchyPanel::Render() {
ImGui::BeginChild("EntityList");
auto rootEntities = EditorSceneManager::Get().GetRootEntities();
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
auto rootEntities = sceneManager.GetRootEntities();
SortEntities(const_cast<std::vector<::XCEngine::Components::GameObject*>&>(rootEntities));
for (auto* gameObject : rootEntities) {
@@ -42,7 +42,7 @@ void HierarchyPanel::Render() {
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(0) && !ImGui::IsAnyItemHovered()) {
if (!m_renaming) {
SelectionManager::Get().ClearSelection();
m_context->GetSelectionManager().ClearSelection();
}
}
@@ -56,7 +56,8 @@ void HierarchyPanel::Render() {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_PTR")) {
::XCEngine::Components::GameObject* sourceGameObject = *(::XCEngine::Components::GameObject**)payload->Data;
if (sourceGameObject && sourceGameObject->GetParent() != nullptr) {
EditorSceneManager::Get().MoveEntity(sourceGameObject->GetID(), 0);
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
sceneManager.MoveEntity(sourceGameObject->GetID(), 0);
}
}
ImGui::EndDragDropTarget();
@@ -94,7 +95,7 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
flags |= ImGuiTreeNodeFlags_Leaf;
}
if (SelectionManager::Get().IsSelected(gameObject)) {
if (m_context->GetSelectionManager().IsSelected(gameObject->GetID())) {
flags |= ImGuiTreeNodeFlags_Selected;
}
@@ -107,7 +108,7 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
ImGui::SetNextItemWidth(-1);
if (ImGui::InputText("##Rename", m_renameBuffer, sizeof(m_renameBuffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
if (strlen(m_renameBuffer) > 0) {
EditorSceneManager::Get().RenameEntity(gameObject->GetID(), m_renameBuffer);
static_cast<SceneManager*>(m_context->GetSceneManager())->RenameEntity(gameObject->GetID(), m_renameBuffer);
}
m_renaming = false;
m_renamingEntity = nullptr;
@@ -115,7 +116,7 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) {
if (strlen(m_renameBuffer) > 0) {
EditorSceneManager::Get().RenameEntity(gameObject->GetID(), m_renameBuffer);
static_cast<SceneManager*>(m_context->GetSceneManager())->RenameEntity(gameObject->GetID(), m_renameBuffer);
}
m_renaming = false;
m_renamingEntity = nullptr;
@@ -126,11 +127,11 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
ImGuiIO& io = ImGui::GetIO();
if (io.KeyCtrl) {
if (!SelectionManager::Get().IsSelected(gameObject)) {
SelectionManager::Get().AddToSelection(gameObject);
if (!m_context->GetSelectionManager().IsSelected(gameObject->GetID())) {
m_context->GetSelectionManager().AddToSelection(gameObject->GetID());
}
} else {
SelectionManager::Get().SetSelectedEntity(gameObject);
m_context->GetSelectionManager().SetSelectedEntity(gameObject->GetID());
}
}
@@ -160,8 +161,8 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
}
void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* gameObject) {
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
auto& selectionManager = m_context->GetSelectionManager();
if (ImGui::BeginMenu("Create")) {
RenderCreateMenu(gameObject);
@@ -170,7 +171,7 @@ void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* gameO
if (gameObject != nullptr && ImGui::MenuItem("Create Child")) {
auto* child = sceneManager.CreateEntity("GameObject", gameObject);
selectionManager.SetSelectedEntity(child);
selectionManager.SetSelectedEntity(child->GetID());
}
ImGui::Separator();
@@ -212,12 +213,12 @@ void HierarchyPanel::RenderContextMenu(::XCEngine::Components::GameObject* gameO
}
void HierarchyPanel::RenderCreateMenu(::XCEngine::Components::GameObject* parent) {
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
auto& selectionManager = m_context->GetSelectionManager();
if (ImGui::MenuItem("Empty Object")) {
auto* newEntity = sceneManager.CreateEntity("GameObject", parent);
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
ImGui::Separator();
@@ -225,12 +226,12 @@ void HierarchyPanel::RenderCreateMenu(::XCEngine::Components::GameObject* parent
if (ImGui::MenuItem("Camera")) {
auto* newEntity = sceneManager.CreateEntity("Camera", parent);
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
if (ImGui::MenuItem("Light")) {
auto* newEntity = sceneManager.CreateEntity("Light", parent);
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
ImGui::Separator();
@@ -238,24 +239,24 @@ void HierarchyPanel::RenderCreateMenu(::XCEngine::Components::GameObject* parent
if (ImGui::MenuItem("Cube")) {
auto* newEntity = sceneManager.CreateEntity("Cube", parent);
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
if (ImGui::MenuItem("Sphere")) {
auto* newEntity = sceneManager.CreateEntity("Sphere", parent);
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
if (ImGui::MenuItem("Plane")) {
auto* newEntity = sceneManager.CreateEntity("Plane", parent);
newEntity->AddComponent<::XCEngine::Components::TransformComponent>();
selectionManager.SetSelectedEntity(newEntity);
selectionManager.SetSelectedEntity(newEntity->GetID());
}
}
void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* gameObject) {
auto& sceneManager = EditorSceneManager::Get();
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
ImGui::SetDragDropPayload("ENTITY_PTR", &gameObject, sizeof(::XCEngine::Components::GameObject*));
@@ -296,10 +297,10 @@ void HierarchyPanel::HandleDragDrop(::XCEngine::Components::GameObject* gameObje
}
void HierarchyPanel::HandleKeyboardShortcuts() {
auto& sceneManager = EditorSceneManager::Get();
auto& selectionManager = SelectionManager::Get();
auto& sceneManager = *static_cast<SceneManager*>(m_context->GetSceneManager());
auto& selectionManager = m_context->GetSelectionManager();
::XCEngine::Components::GameObject* selectedGameObject = selectionManager.GetSelectedEntity();
::XCEngine::Components::GameObject* selectedGameObject = sceneManager.GetEntity(selectionManager.GetSelectedEntity());
if (ImGui::IsWindowFocused()) {
if (ImGui::IsKeyPressed(ImGuiKey_Delete)) {