Refactor new editor state ownership model

This commit is contained in:
2026-04-19 04:36:52 +08:00
parent 48bfde28e3
commit f45b34a03a
46 changed files with 1979 additions and 217 deletions

View File

@@ -1,7 +1,5 @@
#include "Scene/EditorSceneRuntime.h"
#include "State/EditorSelectionStamp.h"
#include <XCEngine/Components/CameraComponent.h>
#include <XCEngine/Components/Component.h>
#include <XCEngine/Components/GameObject.h>
@@ -174,6 +172,8 @@ std::string_view GetSceneToolInteractionLockName(SceneToolInteractionLock lock)
bool EditorSceneRuntime::Initialize(const std::filesystem::path& projectRoot) {
m_projectRoot = projectRoot;
m_ownedSelectionService = {};
m_selectionService = &m_ownedSelectionService;
m_startupSceneResult = EnsureEditorStartupScene(projectRoot);
EnsureSceneViewCamera();
ResetTransformEditHistory();
@@ -182,17 +182,29 @@ bool EditorSceneRuntime::Initialize(const std::filesystem::path& projectRoot) {
return m_startupSceneResult.ready;
}
void EditorSceneRuntime::BindSelectionService(
EditorSelectionService* selectionService) {
m_selectionService =
selectionService != nullptr ? selectionService : &m_ownedSelectionService;
}
void EditorSceneRuntime::RefreshScene() {
if (m_selectedGameObjectId.has_value() && !HasValidSelection()) {
m_selectedGameObjectId.reset();
m_selectionStamp = GenerateEditorSelectionStamp();
if (HasHierarchySelection()) {
if (!HasValidSelection()) {
ClearSelection();
} else {
RevalidateSelection();
}
} else if (m_toolState.dragState.active) {
ResetToolInteractionState();
}
ClearInvalidToolInteractionState();
}
void EditorSceneRuntime::EnsureSceneSelection() {
if (HasValidSelection()) {
if (HasValidSelection() ||
SelectionService().HasSelectionKind(EditorSelectionKind::ProjectItem)) {
return;
}
@@ -262,7 +274,11 @@ bool EditorSceneRuntime::HasSceneSelection() const {
}
std::optional<GameObject::ID> EditorSceneRuntime::GetSelectedGameObjectId() const {
return HasValidSelection() ? m_selectedGameObjectId : std::nullopt;
if (!HasHierarchySelection()) {
return std::nullopt;
}
return ParseEditorGameObjectItemId(SelectionService().GetSelection().itemId);
}
std::string EditorSceneRuntime::GetSelectedItemId() const {
@@ -280,14 +296,13 @@ std::string EditorSceneRuntime::GetSelectedDisplayName() const {
}
const GameObject* EditorSceneRuntime::GetSelectedGameObject() const {
if (!m_selectedGameObjectId.has_value()) {
const std::optional<GameObject::ID> selectedId = GetSelectedGameObjectId();
if (!selectedId.has_value()) {
return nullptr;
}
Scene* scene = GetActiveScene();
return scene != nullptr
? scene->FindByID(m_selectedGameObjectId.value())
: nullptr;
return scene != nullptr ? scene->FindByID(selectedId.value()) : nullptr;
}
std::vector<EditorSceneComponentDescriptor> EditorSceneRuntime::GetSelectedComponents() const {
@@ -316,7 +331,7 @@ std::vector<EditorSceneComponentDescriptor> EditorSceneRuntime::GetSelectedCompo
}
std::uint64_t EditorSceneRuntime::GetSelectionStamp() const {
return m_selectionStamp;
return SelectionService().GetStamp();
}
bool EditorSceneRuntime::SetSelection(std::string_view itemId) {
@@ -335,26 +350,29 @@ bool EditorSceneRuntime::SetSelection(GameObject::ID id) {
}
Scene* scene = GetActiveScene();
if (scene == nullptr || scene->FindByID(id) == nullptr) {
GameObject* gameObject = scene != nullptr ? scene->FindByID(id) : nullptr;
if (gameObject == nullptr) {
return false;
}
const std::optional<GameObject::ID> previousId = GetSelectedGameObjectId();
const bool changed =
!m_selectedGameObjectId.has_value() ||
m_selectedGameObjectId.value() != id;
!previousId.has_value() ||
previousId.value() != id ||
!HasHierarchySelection();
if (changed) {
ResetToolInteractionState();
m_selectionStamp = GenerateEditorSelectionStamp();
}
m_selectedGameObjectId = id;
SelectionService().SetHierarchySelection(
MakeEditorGameObjectItemId(id),
ResolveGameObjectDisplayName(*gameObject));
ClearInvalidToolInteractionState();
return changed;
}
void EditorSceneRuntime::ClearSelection() {
ResetToolInteractionState();
m_selectedGameObjectId.reset();
m_selectionStamp = GenerateEditorSelectionStamp();
SelectionService().ClearSelection();
}
bool EditorSceneRuntime::OpenSceneAsset(const std::filesystem::path& scenePath) {
@@ -374,6 +392,7 @@ bool EditorSceneRuntime::OpenSceneAsset(const std::filesystem::path& scenePath)
ResetTransformEditHistory();
ResetToolInteractionState();
SelectionService().ClearSelection();
RefreshScene();
EnsureSceneSelection();
return true;
@@ -836,6 +855,29 @@ void EditorSceneRuntime::ApplySceneViewCameraController() {
}
}
EditorSelectionService& EditorSceneRuntime::SelectionService() {
return *m_selectionService;
}
const EditorSelectionService& EditorSceneRuntime::SelectionService() const {
return *m_selectionService;
}
bool EditorSceneRuntime::HasHierarchySelection() const {
return SelectionService().HasSelectionKind(EditorSelectionKind::HierarchyNode);
}
void EditorSceneRuntime::RevalidateSelection() {
const GameObject* gameObject = GetSelectedGameObject();
if (gameObject == nullptr) {
return;
}
SelectionService().SetHierarchySelection(
MakeEditorGameObjectItemId(gameObject->GetID()),
ResolveGameObjectDisplayName(*gameObject));
}
bool EditorSceneRuntime::HasValidSelection() const {
return GetSelectedGameObject() != nullptr;
}
@@ -872,7 +914,7 @@ EditorSceneComponentDescriptor EditorSceneRuntime::ResolveSelectedComponentDescr
bool EditorSceneRuntime::SelectFirstAvailableGameObject() {
Scene* scene = GetActiveScene();
if (scene == nullptr) {
if (m_selectedGameObjectId.has_value()) {
if (HasHierarchySelection()) {
ClearSelection();
}
return false;
@@ -886,7 +928,7 @@ bool EditorSceneRuntime::SelectFirstAvailableGameObject() {
return SetSelection(root->GetID());
}
if (m_selectedGameObjectId.has_value()) {
if (HasHierarchySelection()) {
ClearSelection();
}
return false;