diff --git a/editor/AGENTS.md b/editor/AGENTS.md index 83862a16..b8d5c412 100644 --- a/editor/AGENTS.md +++ b/editor/AGENTS.md @@ -34,6 +34,7 @@ - `ProjectPanel` 只消费由 `EditorContext` / `EditorPanelServices` 提供的 `EditorProjectRuntime`,不再拥有或初始化自己的 project runtime。测试也应显式创建 `EditorProjectRuntime` 并通过 `SetProjectRuntime()` 注入,不要把 `projectRoot` 传给 panel。 - `EditorEngineServices` 是 editor 接入 engine 全局 runtime 的唯一生产 adapter。`Application` 创建它并向 `EditorContext`、window shell runtime、viewport runtime 传递;下游只消费显式服务。 - `EditorSceneBackend` 是 scene document/backend 的显式边界;`EngineEditorSceneBackend` 由 `EditorEngineServices` 创建,并通过显式 `SceneManager&` / `ResourceManager&` 接入真实 engine runtime。`EditorSceneRuntime` 负责 startup scene 编排、editor scene camera、hierarchy selection、component list、transform edit history 和 scene tool state,但不直接访问 engine 单例。 +- scene object graph 写入必须停在 `EditorSceneBackend` 生产 adapter 内。`EditorSceneRuntime` 可以编排 undo/redo、selection stamp、inspector revision 和 tool state,但组件移除、component mutation、Transform inspector 写入、gizmo 预览/撤销写入都应通过 backend command 执行,不要在 runtime / feature / panel 层直接 `RemoveComponent()`、`SetPosition()`、`SetRotation()`、`SetScale()`、`SetLocal*()`。 - `EditorSceneRuntime::BuildHierarchySnapshot()` 是 hierarchy 面板的 scene 读入口;`HierarchyModel` 从该快照构建 UI tree。不要重新把 hierarchy 绑定回 `Scene*`。 - transform gizmo support 只负责几何计算和 hit/drag 状态;预览写入通过 `SceneGizmoUndoBridge` 调回 `EditorSceneRuntime::ApplyTransformTool*Preview()`。不要在 `SceneViewportTransformGizmoSupport.*` 里直接写 `GameObject` transform。 @@ -133,6 +134,7 @@ ctest --test-dir build -C Debug -R "editor|xceditor" --output-on-failure - 已新增 `EditorEngineServices` 边界,把 `SceneManager::Get()`、`ResourceManager::Get()`、`RenderObjectIdRegistry::Get()` 从 `Application`、`EditorContext` 和 viewport shader/object-id 路径收口到 `app/Services/Engine/EngineEditorServices.*`;`EditorContext` 现在通过显式 engine service 创建 scene backend,并会在 scene runtime 初始化失败时返回失败。 - 已把 hierarchy 面板的 scene 读取改为 `EditorSceneHierarchySnapshot` 快照路径,`HierarchyModel` 不再由 panel 直接拿 `Scene*` 构建;已把 inspector 添加组件动作收口到 `EditorSceneBackend::AddComponent()`,让 `ComponentFactoryRegistry::Get()` 留在 engine adapter 内。 - 已把 scene transform gizmo 的拖拽预览写入从 feature support 层移到 `EditorSceneRuntime`,support 层不再直接 `SetPosition()` / `SetRotation()` / `SetLocalScale()`。 +- 已把 `EditorSceneRuntime` 内的组件移除、Transform inspector 写入、component mutation、transform snapshot restore 和 gizmo preview 写入继续收口到 `EditorSceneBackend` command;真实 engine object graph 写入现在由 `EngineEditorSceneBackend` 执行,runtime 只负责状态编排和 revision/undo 维护。 - 本次改动验证过: - `cmake --build build --config Debug --target XCEditor` - `cmake --build build --config Debug --target editor_app_core_tests` diff --git a/editor/app/Core/Scene/EditorSceneBackend.h b/editor/app/Core/Scene/EditorSceneBackend.h index 2c15bd29..46f60622 100644 --- a/editor/app/Core/Scene/EditorSceneBackend.h +++ b/editor/app/Core/Scene/EditorSceneBackend.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -13,9 +14,17 @@ namespace XCEngine::Components { class Scene; class GameObject; +class Component; } // namespace XCEngine::Components +namespace XCEngine::Math { + +struct Quaternion; +struct Vector3; + +} // namespace XCEngine::Math + namespace XCEngine::UI::Editor::App { struct EditorStartupSceneResult { @@ -43,6 +52,19 @@ struct EditorSceneHierarchySnapshot { } }; +struct EditorSceneComponentDescriptor { + std::string componentId = {}; + std::string typeName = {}; + const ::XCEngine::Components::Component* component = nullptr; + bool removable = false; + + bool IsValid() const { + return !componentId.empty() && + !typeName.empty() && + component != nullptr; + } +}; + class EditorSceneBackend { public: virtual ~EditorSceneBackend() = default; @@ -57,6 +79,92 @@ public: virtual bool AddComponent( std::string_view itemId, std::string_view componentTypeName) = 0; + virtual std::vector GetComponents( + std::string_view itemId) const { + (void)itemId; + return {}; + } + virtual bool RemoveComponent( + std::string_view itemId, + std::string_view componentId) { + (void)itemId; + (void)componentId; + return false; + } + virtual bool SetTransformLocalPosition( + std::string_view itemId, + std::string_view componentId, + const ::XCEngine::Math::Vector3& position) { + (void)itemId; + (void)componentId; + (void)position; + return false; + } + virtual bool SetTransformLocalEulerAngles( + std::string_view itemId, + std::string_view componentId, + const ::XCEngine::Math::Vector3& eulerAngles) { + (void)itemId; + (void)componentId; + (void)eulerAngles; + return false; + } + virtual bool SetTransformLocalScale( + std::string_view itemId, + std::string_view componentId, + const ::XCEngine::Math::Vector3& scale) { + (void)itemId; + (void)componentId; + (void)scale; + return false; + } + virtual bool MutateComponent( + std::string_view itemId, + std::string_view componentId, + const std::function& mutation) { + (void)itemId; + (void)componentId; + (void)mutation; + return false; + } + virtual bool QueryWorldTransform( + EditorSceneObjectId objectId, + ::XCEngine::Math::Vector3& outPosition, + ::XCEngine::Math::Quaternion& outRotation, + ::XCEngine::Math::Vector3& outScale) const { + (void)objectId; + (void)outPosition; + (void)outRotation; + (void)outScale; + return false; + } + virtual bool SetWorldTransform( + EditorSceneObjectId objectId, + const ::XCEngine::Math::Vector3& position, + const ::XCEngine::Math::Quaternion& rotation, + const ::XCEngine::Math::Vector3& scale) { + (void)objectId; + (void)position; + (void)rotation; + (void)scale; + return false; + } + virtual bool SetWorldPositionRotation( + EditorSceneObjectId objectId, + const ::XCEngine::Math::Vector3& position, + const ::XCEngine::Math::Quaternion& rotation) { + (void)objectId; + (void)position; + (void)rotation; + return false; + } + virtual bool SetObjectLocalScale( + EditorSceneObjectId objectId, + const ::XCEngine::Math::Vector3& localScale) { + (void)objectId; + (void)localScale; + return false; + } virtual bool RenameGameObject( std::string_view itemId, std::string_view newName) = 0; diff --git a/editor/app/Services/Engine/EngineEditorServices.cpp b/editor/app/Services/Engine/EngineEditorServices.cpp index 57df6df2..19164d7d 100644 --- a/editor/app/Services/Engine/EngineEditorServices.cpp +++ b/editor/app/Services/Engine/EngineEditorServices.cpp @@ -11,11 +11,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -29,11 +31,15 @@ using ::XCEngine::Components::GameObject; using ::XCEngine::Components::Scene; using ::XCEngine::Components::SceneManager; using ::XCEngine::Components::TransformComponent; +using ::XCEngine::Math::Quaternion; +using ::XCEngine::Math::Vector3; using ::XCEngine::Rendering::RenderObjectId; using ::XCEngine::Rendering::RenderObjectIdRegistry; using ::XCEngine::Resources::ResourceManager; using ::XCEngine::Resources::Shader; +constexpr char kComponentIdSeparator = '#'; + void TraceSceneStartup(std::string message) { ::XCEngine::UI::Editor::AppendUIEditorRuntimeTrace("startup", std::move(message)); } @@ -207,6 +213,82 @@ EditorSceneHierarchyNode BuildHierarchySnapshotNodeRecursive( return node; } +std::string BuildEditorComponentId( + std::string_view typeName, + std::size_t ordinal) { + std::string componentId(typeName); + componentId.push_back(kComponentIdSeparator); + componentId += std::to_string(ordinal); + return componentId; +} + +bool ParseEditorComponentId( + std::string_view componentId, + std::string& outTypeName, + std::size_t& outOrdinal) { + const std::size_t separatorIndex = componentId.find(kComponentIdSeparator); + if (separatorIndex == std::string_view::npos || + separatorIndex == 0u || + separatorIndex + 1u >= componentId.size()) { + return false; + } + + outTypeName = std::string(componentId.substr(0u, separatorIndex)); + std::size_t ordinal = 0u; + const std::string_view ordinalText = + componentId.substr(separatorIndex + 1u); + const char* first = ordinalText.data(); + const char* last = ordinalText.data() + ordinalText.size(); + const std::from_chars_result result = + std::from_chars(first, last, ordinal); + if (result.ec != std::errc() || result.ptr != last) { + outTypeName.clear(); + return false; + } + + outOrdinal = ordinal; + return true; +} + +EditorSceneComponentDescriptor BuildComponentDescriptor( + const Component& component, + std::size_t ordinal) { + EditorSceneComponentDescriptor descriptor = {}; + descriptor.typeName = component.GetName(); + descriptor.componentId = + BuildEditorComponentId(descriptor.typeName, ordinal); + descriptor.component = &component; + descriptor.removable = + component.GetGameObject() != nullptr && + component.GetGameObject()->GetTransform() != &component; + return descriptor; +} + +EditorSceneComponentDescriptor ResolveComponentDescriptor( + const GameObject& gameObject, + std::string_view componentId) { + std::string typeName = {}; + std::size_t ordinal = 0u; + if (!ParseEditorComponentId(componentId, typeName, ordinal)) { + return {}; + } + + std::size_t currentOrdinal = 0u; + for (const Component* component : gameObject.GetComponents()) { + if (component == nullptr || component->GetName() != typeName) { + continue; + } + + if (currentOrdinal == ordinal) { + return BuildComponentDescriptor(*component, currentOrdinal); + } + + ++currentOrdinal; + } + + return {}; +} + bool MoveGameObjectRelativeToTarget( SceneManager& sceneManager, std::string_view itemId, @@ -403,6 +485,179 @@ public: return addedComponent != nullptr; } + std::vector GetComponents( + std::string_view itemId) const override { + std::vector descriptors = {}; + const GameObject* gameObject = FindGameObject(itemId); + if (gameObject == nullptr) { + return descriptors; + } + + const std::vector components = + gameObject->GetComponents(); + descriptors.reserve(components.size()); + std::unordered_map ordinalsByType = {}; + for (const Component* component : components) { + if (component == nullptr) { + continue; + } + + const std::string typeName = component->GetName(); + const std::size_t ordinal = ordinalsByType[typeName]; + descriptors.push_back(BuildComponentDescriptor(*component, ordinal)); + ordinalsByType[typeName] = ordinal + 1u; + } + + return descriptors; + } + + bool RemoveComponent( + std::string_view itemId, + std::string_view componentId) override { + GameObject* gameObject = FindGameObject(itemId); + if (gameObject == nullptr) { + return false; + } + + const EditorSceneComponentDescriptor descriptor = + ResolveComponentDescriptor(*gameObject, componentId); + Component* component = + const_cast(descriptor.component); + if (!descriptor.IsValid() || + !descriptor.removable || + component == nullptr) { + return false; + } + + return gameObject->RemoveComponent(component); + } + + bool SetTransformLocalPosition( + std::string_view itemId, + std::string_view componentId, + const Vector3& position) override { + TransformComponent* transform = + ResolveTransformComponent(itemId, componentId); + if (transform == nullptr) { + return false; + } + + transform->SetLocalPosition(position); + return true; + } + + bool SetTransformLocalEulerAngles( + std::string_view itemId, + std::string_view componentId, + const Vector3& eulerAngles) override { + TransformComponent* transform = + ResolveTransformComponent(itemId, componentId); + if (transform == nullptr) { + return false; + } + + transform->SetLocalEulerAngles(eulerAngles); + return true; + } + + bool SetTransformLocalScale( + std::string_view itemId, + std::string_view componentId, + const Vector3& scale) override { + TransformComponent* transform = + ResolveTransformComponent(itemId, componentId); + if (transform == nullptr) { + return false; + } + + transform->SetLocalScale(scale); + return true; + } + + bool MutateComponent( + std::string_view itemId, + std::string_view componentId, + const std::function& mutation) override { + if (!mutation) { + return false; + } + + GameObject* gameObject = FindGameObject(itemId); + if (gameObject == nullptr) { + return false; + } + + const EditorSceneComponentDescriptor descriptor = + ResolveComponentDescriptor(*gameObject, componentId); + Component* component = + const_cast(descriptor.component); + return descriptor.IsValid() && + component != nullptr && + mutation(*component); + } + + bool QueryWorldTransform( + EditorSceneObjectId objectId, + Vector3& outPosition, + Quaternion& outRotation, + Vector3& outScale) const override { + Scene* scene = ResolvePrimaryScene(m_sceneManager); + GameObject* gameObject = + scene != nullptr ? scene->FindByID(objectId) : nullptr; + const TransformComponent* transform = + gameObject != nullptr ? gameObject->GetTransform() : nullptr; + if (transform == nullptr) { + return false; + } + + outPosition = transform->GetPosition(); + outRotation = transform->GetRotation(); + outScale = transform->GetScale(); + return true; + } + + bool SetWorldTransform( + EditorSceneObjectId objectId, + const Vector3& position, + const Quaternion& rotation, + const Vector3& scale) override { + TransformComponent* transform = ResolveTransformComponent(objectId); + if (transform == nullptr) { + return false; + } + + transform->SetPosition(position); + transform->SetRotation(rotation); + transform->SetScale(scale); + return true; + } + + bool SetWorldPositionRotation( + EditorSceneObjectId objectId, + const Vector3& position, + const Quaternion& rotation) override { + TransformComponent* transform = ResolveTransformComponent(objectId); + if (transform == nullptr) { + return false; + } + + transform->SetPosition(position); + transform->SetRotation(rotation); + return true; + } + + bool SetObjectLocalScale( + EditorSceneObjectId objectId, + const Vector3& localScale) override { + TransformComponent* transform = ResolveTransformComponent(objectId); + if (transform == nullptr) { + return false; + } + + transform->SetLocalScale(localScale); + return true; + } + bool RenameGameObject( std::string_view itemId, std::string_view newName) override { @@ -488,6 +743,27 @@ public: } private: + TransformComponent* ResolveTransformComponent(EditorSceneObjectId objectId) const { + Scene* scene = ResolvePrimaryScene(m_sceneManager); + GameObject* gameObject = + scene != nullptr ? scene->FindByID(objectId) : nullptr; + return gameObject != nullptr ? gameObject->GetTransform() : nullptr; + } + + TransformComponent* ResolveTransformComponent( + std::string_view itemId, + std::string_view componentId) const { + GameObject* gameObject = FindGameObject(itemId); + if (gameObject == nullptr) { + return nullptr; + } + + const EditorSceneComponentDescriptor descriptor = + ResolveComponentDescriptor(*gameObject, componentId); + return const_cast( + dynamic_cast(descriptor.component)); + } + SceneManager& m_sceneManager; ResourceManager& m_resourceManager; }; diff --git a/editor/app/Services/Scene/EditorSceneRuntime.cpp b/editor/app/Services/Scene/EditorSceneRuntime.cpp index bcd10ff4..3859861c 100644 --- a/editor/app/Services/Scene/EditorSceneRuntime.cpp +++ b/editor/app/Services/Scene/EditorSceneRuntime.cpp @@ -3,12 +3,9 @@ #include #include #include -#include #include -#include #include -#include namespace XCEngine::UI::Editor::App { @@ -16,13 +13,10 @@ namespace { using ::XCEngine::Components::GameObject; using ::XCEngine::Components::Scene; -using ::XCEngine::Components::TransformComponent; using ::XCEngine::Components::Component; using ::XCEngine::Math::Quaternion; using ::XCEngine::Math::Vector3; -constexpr char kComponentIdSeparator = '#'; - std::string ResolveGameObjectDisplayName(const GameObject& gameObject) { return gameObject.GetName().empty() ? std::string("GameObject") @@ -54,57 +48,6 @@ bool TransformSnapshotsMatch( NearlyEqual(lhs.scale, rhs.scale); } -std::string BuildEditorComponentId( - std::string_view typeName, - std::size_t ordinal) { - std::string componentId(typeName); - componentId.push_back(kComponentIdSeparator); - componentId += std::to_string(ordinal); - return componentId; -} - -bool ParseEditorComponentId( - std::string_view componentId, - std::string& outTypeName, - std::size_t& outOrdinal) { - const std::size_t separatorIndex = componentId.find(kComponentIdSeparator); - if (separatorIndex == std::string_view::npos || - separatorIndex == 0u || - separatorIndex + 1u >= componentId.size()) { - return false; - } - - outTypeName = std::string(componentId.substr(0u, separatorIndex)); - std::size_t ordinal = 0u; - const std::string_view ordinalText = - componentId.substr(separatorIndex + 1u); - const char* first = ordinalText.data(); - const char* last = ordinalText.data() + ordinalText.size(); - const std::from_chars_result result = - std::from_chars(first, last, ordinal); - if (result.ec != std::errc() || result.ptr != last) { - outTypeName.clear(); - return false; - } - - outOrdinal = ordinal; - return true; -} - -EditorSceneComponentDescriptor BuildComponentDescriptor( - const Component& component, - std::size_t ordinal) { - EditorSceneComponentDescriptor descriptor = {}; - descriptor.typeName = component.GetName(); - descriptor.componentId = - BuildEditorComponentId(descriptor.typeName, ordinal); - descriptor.component = &component; - descriptor.removable = - component.GetGameObject() != nullptr && - component.GetGameObject()->GetTransform() != &component; - return descriptor; -} - } // namespace std::string_view GetSceneToolModeName(SceneToolMode mode) { @@ -276,17 +219,12 @@ void EditorSceneRuntime::ApplySceneViewportCameraInput( } bool EditorSceneRuntime::FocusSceneSelection() { - const GameObject* selectedGameObject = GetSelectedGameObject(); - if (selectedGameObject == nullptr || !EnsureSceneViewCamera()) { + SceneTransformSnapshot snapshot = {}; + if (!CaptureSelectedTransformSnapshot(snapshot) || !EnsureSceneViewCamera()) { return false; } - const auto* transform = selectedGameObject->GetTransform(); - if (transform == nullptr) { - return false; - } - - m_sceneViewCamera.controller.Focus(transform->GetPosition()); + m_sceneViewCamera.controller.Focus(snapshot.position); ApplySceneViewCameraController(); return true; } @@ -328,28 +266,10 @@ const GameObject* EditorSceneRuntime::GetSelectedGameObject() const { } std::vector EditorSceneRuntime::GetSelectedComponents() const { - std::vector descriptors = {}; - const GameObject* gameObject = GetSelectedGameObject(); - if (gameObject == nullptr) { - return descriptors; - } - - const std::vector components = - gameObject->GetComponents(); - descriptors.reserve(components.size()); - std::unordered_map ordinalsByType = {}; - for (const Component* component : components) { - if (component == nullptr) { - continue; - } - - const std::string typeName = component->GetName(); - const std::size_t ordinal = ordinalsByType[typeName]; - descriptors.push_back(BuildComponentDescriptor(*component, ordinal)); - ordinalsByType[typeName] = ordinal + 1u; - } - - return descriptors; + const std::string selectedItemId = GetSelectedItemId(); + return m_backend != nullptr && !selectedItemId.empty() + ? m_backend->GetComponents(selectedItemId) + : std::vector{}; } std::uint64_t EditorSceneRuntime::GetSelectionStamp() const { @@ -556,21 +476,10 @@ bool EditorSceneRuntime::RemoveSelectedComponent(std::string_view componentId) { return false; } - const std::optional selectedId = GetSelectedGameObjectId(); - Scene* scene = GetActiveScene(); - if (!selectedId.has_value() || scene == nullptr) { - return false; - } - - GameObject* gameObject = scene->FindByID(selectedId.value()); - Component* component = - const_cast(descriptor.component); - if (gameObject == nullptr || component == nullptr) { - return false; - } - ResetTransformEditHistory(); - const bool removed = gameObject->RemoveComponent(component); + const bool removed = + m_backend != nullptr && + m_backend->RemoveComponent(GetSelectedItemId(), componentId); if (removed) { IncrementInspectorRevision(); } @@ -583,10 +492,7 @@ bool EditorSceneRuntime::SetSelectedTransformLocalPosition( const Vector3& position) { const EditorSceneComponentDescriptor descriptor = ResolveSelectedComponentDescriptor(componentId); - auto* transform = - const_cast( - dynamic_cast(descriptor.component)); - if (transform == nullptr) { + if (m_backend == nullptr || descriptor.typeName != "Transform") { return false; } @@ -595,7 +501,12 @@ bool EditorSceneRuntime::SetSelectedTransformLocalPosition( return false; } - transform->SetLocalPosition(position); + if (!m_backend->SetTransformLocalPosition( + GetSelectedItemId(), + componentId, + position)) { + return false; + } SceneTransformSnapshot afterSnapshot = {}; CaptureSelectedTransformSnapshot(afterSnapshot); @@ -611,10 +522,7 @@ bool EditorSceneRuntime::SetSelectedTransformLocalEulerAngles( const Vector3& eulerAngles) { const EditorSceneComponentDescriptor descriptor = ResolveSelectedComponentDescriptor(componentId); - auto* transform = - const_cast( - dynamic_cast(descriptor.component)); - if (transform == nullptr) { + if (m_backend == nullptr || descriptor.typeName != "Transform") { return false; } @@ -623,7 +531,12 @@ bool EditorSceneRuntime::SetSelectedTransformLocalEulerAngles( return false; } - transform->SetLocalEulerAngles(eulerAngles); + if (!m_backend->SetTransformLocalEulerAngles( + GetSelectedItemId(), + componentId, + eulerAngles)) { + return false; + } SceneTransformSnapshot afterSnapshot = {}; CaptureSelectedTransformSnapshot(afterSnapshot); @@ -639,10 +552,7 @@ bool EditorSceneRuntime::SetSelectedTransformLocalScale( const Vector3& scale) { const EditorSceneComponentDescriptor descriptor = ResolveSelectedComponentDescriptor(componentId); - auto* transform = - const_cast( - dynamic_cast(descriptor.component)); - if (transform == nullptr) { + if (m_backend == nullptr || descriptor.typeName != "Transform") { return false; } @@ -651,7 +561,12 @@ bool EditorSceneRuntime::SetSelectedTransformLocalScale( return false; } - transform->SetLocalScale(scale); + if (!m_backend->SetTransformLocalScale( + GetSelectedItemId(), + componentId, + scale)) { + return false; + } SceneTransformSnapshot afterSnapshot = {}; CaptureSelectedTransformSnapshot(afterSnapshot); @@ -669,14 +584,15 @@ bool EditorSceneRuntime::ApplySelectedComponentMutation( return false; } - const EditorSceneComponentDescriptor descriptor = - ResolveSelectedComponentDescriptor(componentId); - Component* component = const_cast(descriptor.component); - if (!descriptor.IsValid() || component == nullptr) { + if (m_backend == nullptr || + !ResolveSelectedComponentDescriptor(componentId).IsValid()) { return false; } - if (!mutation(*component)) { + if (!m_backend->MutateComponent( + GetSelectedItemId(), + componentId, + mutation)) { return false; } @@ -750,23 +666,22 @@ void EditorSceneRuntime::ResetToolInteractionState() { bool EditorSceneRuntime::CaptureSelectedTransformSnapshot( SceneTransformSnapshot& outSnapshot) const { - const GameObject* selectedGameObject = GetSelectedGameObject(); - if (selectedGameObject == nullptr) { - outSnapshot = {}; - return false; - } - - const TransformComponent* transform = selectedGameObject->GetTransform(); - if (transform == nullptr) { + const std::optional selectedId = GetSelectedGameObjectId(); + if (!selectedId.has_value() || m_backend == nullptr) { outSnapshot = {}; return false; } outSnapshot = {}; - outSnapshot.targetId = selectedGameObject->GetID(); - outSnapshot.position = transform->GetPosition(); - outSnapshot.rotation = transform->GetRotation(); - outSnapshot.scale = transform->GetScale(); + outSnapshot.targetId = selectedId.value(); + if (!m_backend->QueryWorldTransform( + selectedId.value(), + outSnapshot.position, + outSnapshot.rotation, + outSnapshot.scale)) { + outSnapshot = {}; + return false; + } outSnapshot.valid = true; return true; } @@ -777,24 +692,15 @@ bool EditorSceneRuntime::ApplyTransformSnapshot( return false; } - Scene* scene = GetActiveScene(); - if (scene == nullptr) { + if (m_backend == nullptr || + !m_backend->SetWorldTransform( + snapshot.targetId, + snapshot.position, + snapshot.rotation, + snapshot.scale)) { return false; } - GameObject* gameObject = scene->FindByID(snapshot.targetId); - if (gameObject == nullptr) { - return false; - } - - TransformComponent* transform = gameObject->GetTransform(); - if (transform == nullptr) { - return false; - } - - transform->SetPosition(snapshot.position); - transform->SetRotation(snapshot.rotation); - transform->SetScale(snapshot.scale); IncrementInspectorRevision(); return true; } @@ -869,12 +775,13 @@ bool EditorSceneRuntime::ApplyTransformToolWorldPreview( return false; } - SceneTransformSnapshot snapshot = m_toolState.dragState.initialTransform; - snapshot.targetId = targetId; - snapshot.position = position; - snapshot.rotation = rotation; - snapshot.valid = true; - return ApplyTransformSnapshot(snapshot); + if (m_backend == nullptr || + !m_backend->SetWorldPositionRotation(targetId, position, rotation)) { + return false; + } + + IncrementInspectorRevision(); + return true; } bool EditorSceneRuntime::ApplyTransformToolLocalScalePreview( @@ -886,17 +793,11 @@ bool EditorSceneRuntime::ApplyTransformToolLocalScalePreview( return false; } - Scene* scene = GetActiveScene(); - if (scene == nullptr) { + if (m_backend == nullptr || + !m_backend->SetObjectLocalScale(targetId, localScale)) { return false; } - GameObject* gameObject = scene->FindByID(targetId); - if (gameObject == nullptr || gameObject->GetTransform() == nullptr) { - return false; - } - - gameObject->GetTransform()->SetLocalScale(localScale); IncrementInspectorRevision(); return true; } @@ -1040,28 +941,11 @@ bool EditorSceneRuntime::HasValidSelection() const { EditorSceneComponentDescriptor EditorSceneRuntime::ResolveSelectedComponentDescriptor( std::string_view componentId) const { - std::string typeName = {}; - std::size_t ordinal = 0u; - if (!ParseEditorComponentId(componentId, typeName, ordinal)) { - return {}; - } - - const GameObject* gameObject = GetSelectedGameObject(); - if (gameObject == nullptr) { - return {}; - } - - std::size_t currentOrdinal = 0u; - for (const Component* component : gameObject->GetComponents()) { - if (component == nullptr || component->GetName() != typeName) { - continue; + for (const EditorSceneComponentDescriptor& descriptor : + GetSelectedComponents()) { + if (descriptor.componentId == componentId) { + return descriptor; } - - if (currentOrdinal == ordinal) { - return BuildComponentDescriptor(*component, currentOrdinal); - } - - ++currentOrdinal; } return {}; diff --git a/editor/app/Services/Scene/EditorSceneRuntime.h b/editor/app/Services/Scene/EditorSceneRuntime.h index a4fe2474..ad8f8e27 100644 --- a/editor/app/Services/Scene/EditorSceneRuntime.h +++ b/editor/app/Services/Scene/EditorSceneRuntime.h @@ -34,19 +34,6 @@ struct Vector3; namespace XCEngine::UI::Editor::App { -struct EditorSceneComponentDescriptor { - std::string componentId = {}; - std::string typeName = {}; - const ::XCEngine::Components::Component* component = nullptr; - bool removable = false; - - bool IsValid() const { - return !componentId.empty() && - !typeName.empty() && - component != nullptr; - } -}; - class EditorSceneRuntime { public: EditorSceneRuntime() = default;