refactor(editor): Phase 1 architecture refactoring

- Decouple Panel from Core::Layer (P0 issue resolved)
- Add EventBus with type-safe event system
- Add ISelectionManager interface with SelectionManagerImpl
- Add IEditorContext for dependency injection
- Update EditorLayer to use new architecture
- Update Application to create and inject EditorContext

New files:
- editor/src/Core/EventBus.h
- editor/src/Core/EditorEvents.h
- editor/src/Core/ISelectionManager.h
- editor/src/Core/SelectionManagerImpl.h
- editor/src/Core/IEditorContext.h
- editor/src/Core/EditorContextImpl.h

This enables future improvements: Undo/Redo, serialization, component extensibility.
This commit is contained in:
2026-03-25 15:35:00 +08:00
parent 3478fb414a
commit 56ec2e9b85
13 changed files with 941 additions and 20 deletions

View File

@@ -0,0 +1,83 @@
#pragma once
#include <functional>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <typeinfo>
namespace XCEngine {
namespace Editor {
class EventBus {
public:
using EventHandler = std::function<void()>;
template<typename T>
uint64_t Subscribe(std::function<void(const T&)> handler) {
static_assert(sizeof(T) > 0, "Event type must be defined");
size_t typeId = typeid(T).hash_code();
uint64_t handlerId = m_nextHandlerId++;
auto it = m_handlers.find(typeId);
if (it == m_handlers.end()) {
m_handlers[typeId] = std::vector<HandlerEntry>();
}
HandlerEntry entry;
entry.id = handlerId;
entry.handler = [handler](const void* data) {
handler(*static_cast<const T*>(data));
};
m_handlers[typeId].push_back(entry);
return handlerId;
}
template<typename T>
void Unsubscribe(uint64_t handlerId) {
static_assert(sizeof(T) > 0, "Event type must be defined");
size_t typeId = typeid(T).hash_code();
auto it = m_handlers.find(typeId);
if (it != m_handlers.end()) {
auto& handlers = it->second;
handlers.erase(
std::remove_if(handlers.begin(), handlers.end(),
[handlerId](const HandlerEntry& entry) { return entry.id == handlerId; }),
handlers.end()
);
}
}
template<typename T>
void Publish(const T& event) {
static_assert(sizeof(T) > 0, "Event type must be defined");
size_t typeId = typeid(T).hash_code();
auto it = m_handlers.find(typeId);
if (it != m_handlers.end()) {
for (const auto& entry : it->second) {
entry.handler(&event);
}
}
}
void Clear() {
m_handlers.clear();
}
private:
struct HandlerEntry {
uint64_t id;
std::function<void(const void*)> handler;
};
std::unordered_map<size_t, std::vector<HandlerEntry>> m_handlers;
uint64_t m_nextHandlerId = 0;
};
}
}