From 77fe0a97a4b375672f8d6e0465e3c2547363ec71 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 22 Apr 2026 15:01:03 +0800 Subject: [PATCH] refactor(new_editor): split shell runtime update stages --- new_editor/CMakeLists.txt | 2 + .../EditorShellHostedPanelCoordinator.cpp | 153 ++++++++++++++++ .../EditorShellHostedPanelCoordinator.h | 47 +++++ .../app/Composition/EditorShellRuntime.cpp | 173 ++++-------------- .../app/Composition/EditorShellRuntime.h | 4 + .../EditorShellSessionCoordinator.cpp | 42 +++++ .../EditorShellSessionCoordinator.h | 41 +++++ 7 files changed, 328 insertions(+), 134 deletions(-) create mode 100644 new_editor/app/Composition/EditorShellHostedPanelCoordinator.cpp create mode 100644 new_editor/app/Composition/EditorShellHostedPanelCoordinator.h create mode 100644 new_editor/app/Composition/EditorShellSessionCoordinator.cpp create mode 100644 new_editor/app/Composition/EditorShellSessionCoordinator.h diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index 5be1bbc2..488bfb0b 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -221,7 +221,9 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) app/Composition/EditorShellAssetBuilder.cpp app/Composition/EditorContext.cpp app/Composition/EditorShellDrawComposer.cpp + app/Composition/EditorShellHostedPanelCoordinator.cpp app/Composition/EditorShellRuntime.cpp + app/Composition/EditorShellSessionCoordinator.cpp app/Composition/EditorWindowWorkspaceStore.cpp app/Composition/WorkspaceEventSync.cpp ) diff --git a/new_editor/app/Composition/EditorShellHostedPanelCoordinator.cpp b/new_editor/app/Composition/EditorShellHostedPanelCoordinator.cpp new file mode 100644 index 00000000..cd8ea005 --- /dev/null +++ b/new_editor/app/Composition/EditorShellHostedPanelCoordinator.cpp @@ -0,0 +1,153 @@ +#include "Composition/EditorShellHostedPanelCoordinator.h" + +#include "Composition/EditorContext.h" +#include "Composition/EditorPanelIds.h" +#include "Features/ColorPicker/ColorPickerPanel.h" +#include "Features/Console/ConsolePanel.h" +#include "Features/Hierarchy/HierarchyPanel.h" +#include "Features/Inspector/InspectorPanel.h" +#include "Features/PanelInputContext.h" +#include "Features/Project/ProjectPanel.h" +#include "Features/Scene/SceneViewportFeature.h" + +#include +#include + +namespace XCEngine::UI::Editor::App { + +namespace { + +using ::XCEngine::UI::UIInputEvent; + +PanelInputContext BuildHostedPanelInputContext( + const UIEditorWorkspaceInteractionFrame& workspaceFrame, + bool allowInteraction, + std::string_view panelId) { + PanelInputContext inputContext = {}; + inputContext.allowInteraction = allowInteraction; + inputContext.hasInputFocus = + IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.inputOwner, panelId); + inputContext.focusGained = + !IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.previousInputOwner, panelId) && + inputContext.hasInputFocus; + inputContext.focusLost = + IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.previousInputOwner, panelId) && + !inputContext.hasInputFocus; + return inputContext; +} + +bool ShouldHostedContentYieldPointerStream( + const UIEditorShellInteractionFrame& shellFrame, + bool shellInteractiveCaptureActive) { + if (shellInteractiveCaptureActive || + shellFrame.result.requestPointerCapture || + shellFrame.result.releasePointerCapture) { + return true; + } + + return shellFrame.result.workspaceResult.dockHostResult.hitTarget.kind == + Widgets::UIEditorDockHostHitTargetKind::SplitterHandle; +} + +std::vector FilterHostedContentInputEventsForShellOwnership( + const std::vector& inputEvents, + bool shellOwnsPointerStream) { + if (!shellOwnsPointerStream) { + return inputEvents; + } + + std::vector filteredEvents = {}; + filteredEvents.reserve(inputEvents.size() + 1u); + + bool strippedPointerInput = false; + UIInputEvent lastPointerEvent = {}; + for (const UIInputEvent& event : inputEvents) { + if (event.type == ::XCEngine::UI::UIInputEventType::PointerMove || + event.type == ::XCEngine::UI::UIInputEventType::PointerEnter || + event.type == ::XCEngine::UI::UIInputEventType::PointerLeave || + event.type == ::XCEngine::UI::UIInputEventType::PointerButtonDown || + event.type == ::XCEngine::UI::UIInputEventType::PointerButtonUp || + event.type == ::XCEngine::UI::UIInputEventType::PointerWheel) { + strippedPointerInput = true; + lastPointerEvent = event; + continue; + } + + filteredEvents.push_back(event); + } + + if (strippedPointerInput) { + UIInputEvent leaveEvent = {}; + leaveEvent.type = ::XCEngine::UI::UIInputEventType::PointerLeave; + leaveEvent.position = lastPointerEvent.position; + leaveEvent.modifiers = lastPointerEvent.modifiers; + filteredEvents.push_back(leaveEvent); + } + + return filteredEvents; +} + +} // namespace + +void EditorShellHostedPanelCoordinator::Update( + const EditorShellHostedPanelCoordinatorContext& context) const { + const bool shellOwnsHostedContentPointerStream = + ShouldHostedContentYieldPointerStream( + context.shellFrame, + context.shellInteractiveCaptureActive); + const std::vector hostedContentEvents = + FilterHostedContentInputEventsForShellOwnership( + context.inputEvents, + shellOwnsHostedContentPointerStream); + + const bool allowHostedInteraction = !context.shellFrame.result.workspaceInputSuppressed; + const PanelInputContext hierarchyInputContext = BuildHostedPanelInputContext( + context.shellFrame.workspaceInteractionFrame, + allowHostedInteraction, + kHierarchyPanelId); + const PanelInputContext projectInputContext = BuildHostedPanelInputContext( + context.shellFrame.workspaceInteractionFrame, + allowHostedInteraction, + kProjectPanelId); + const PanelInputContext inspectorInputContext = BuildHostedPanelInputContext( + context.shellFrame.workspaceInteractionFrame, + allowHostedInteraction, + kInspectorPanelId); + const PanelInputContext colorPickerInputContext = BuildHostedPanelInputContext( + context.shellFrame.workspaceInteractionFrame, + allowHostedInteraction, + kColorPickerPanelId); + + context.sceneViewportFeature.Update( + context.context.GetSceneRuntime(), + context.shellInteractionState.workspaceInteractionState.composeState, + context.shellFrame.workspaceInteractionFrame.composeFrame); + context.projectPanel.SetProjectRuntime(&context.context.GetProjectRuntime()); + context.projectPanel.SetCommandFocusService(&context.context.GetCommandFocusService()); + context.projectPanel.SetSystemInteractionHost(context.context.GetSystemInteractionHost()); + context.inspectorPanel.SetCommandFocusService(&context.context.GetCommandFocusService()); + context.hierarchyPanel.Update( + context.shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, + hostedContentEvents, + hierarchyInputContext); + context.projectPanel.Update( + context.shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, + hostedContentEvents, + projectInputContext); + context.colorPickerPanel.Update( + context.context, + context.shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, + hostedContentEvents, + colorPickerInputContext); + context.inspectorPanel.Update( + context.context, + context.shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, + hostedContentEvents, + inspectorInputContext); + context.context.SyncSessionFromCommandFocusService(); + context.consolePanel.Update( + context.context.GetSession(), + context.shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame); +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Composition/EditorShellHostedPanelCoordinator.h b/new_editor/app/Composition/EditorShellHostedPanelCoordinator.h new file mode 100644 index 00000000..b9d6a643 --- /dev/null +++ b/new_editor/app/Composition/EditorShellHostedPanelCoordinator.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +namespace XCEngine::UI { + +struct UIInputEvent; + +} // namespace XCEngine::UI + +namespace XCEngine::UI::Editor { + +struct UIEditorShellInteractionFrame; +struct UIEditorShellInteractionState; + +} // namespace XCEngine::UI::Editor + +namespace XCEngine::UI::Editor::App { + +class ColorPickerPanel; +class ConsolePanel; +class EditorContext; +class HierarchyPanel; +class InspectorPanel; +class ProjectPanel; +class SceneViewportFeature; + +struct EditorShellHostedPanelCoordinatorContext { + EditorContext& context; + UIEditorShellInteractionFrame& shellFrame; + UIEditorShellInteractionState& shellInteractionState; + const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents; + bool shellInteractiveCaptureActive = false; + ConsolePanel& consolePanel; + ColorPickerPanel& colorPickerPanel; + HierarchyPanel& hierarchyPanel; + InspectorPanel& inspectorPanel; + ProjectPanel& projectPanel; + SceneViewportFeature& sceneViewportFeature; +}; + +class EditorShellHostedPanelCoordinator final { +public: + void Update(const EditorShellHostedPanelCoordinatorContext& context) const; +}; + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Composition/EditorShellRuntime.cpp b/new_editor/app/Composition/EditorShellRuntime.cpp index 77a84817..6c725d0a 100644 --- a/new_editor/app/Composition/EditorShellRuntime.cpp +++ b/new_editor/app/Composition/EditorShellRuntime.cpp @@ -295,23 +295,6 @@ const UIEditorPanelDescriptor* ResolveSingleVisibleToolWindowPanelDescriptor( : nullptr; } -PanelInputContext BuildHostedPanelInputContext( - const UIEditorWorkspaceInteractionFrame& workspaceFrame, - bool allowInteraction, - std::string_view panelId) { - PanelInputContext inputContext = {}; - inputContext.allowInteraction = allowInteraction; - inputContext.hasInputFocus = - IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.inputOwner, panelId); - inputContext.focusGained = - !IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.previousInputOwner, panelId) && - inputContext.hasInputFocus; - inputContext.focusLost = - IsUIEditorWorkspaceHostedPanelInputOwner(workspaceFrame.previousInputOwner, panelId) && - !inputContext.hasInputFocus; - return inputContext; -} - } // namespace std::vector FilterShellInputEventsForHostedContentCapture( @@ -335,52 +318,6 @@ std::vector FilterShellInputEventsForHostedContentCapture( return filteredEvents; } -bool ShouldHostedContentYieldPointerStream( - const UIEditorShellInteractionFrame& shellFrame, - bool shellInteractiveCaptureActive) { - if (shellInteractiveCaptureActive || - shellFrame.result.requestPointerCapture || - shellFrame.result.releasePointerCapture) { - return true; - } - - return shellFrame.result.workspaceResult.dockHostResult.hitTarget.kind == - UIEditorDockHostHitTargetKind::SplitterHandle; -} - -std::vector FilterHostedContentInputEventsForShellOwnership( - const std::vector& inputEvents, - bool shellOwnsPointerStream) { - if (!shellOwnsPointerStream) { - return inputEvents; - } - - std::vector filteredEvents = {}; - filteredEvents.reserve(inputEvents.size() + 1u); - - bool strippedPointerInput = false; - UIInputEvent lastPointerEvent = {}; - for (const UIInputEvent& event : inputEvents) { - if (IsPointerInputEventType(event.type)) { - strippedPointerInput = true; - lastPointerEvent = event; - continue; - } - - filteredEvents.push_back(event); - } - - if (strippedPointerInput) { - UIInputEvent leaveEvent = {}; - leaveEvent.type = UIInputEventType::PointerLeave; - leaveEvent.position = lastPointerEvent.position; - leaveEvent.modifiers = lastPointerEvent.modifiers; - filteredEvents.push_back(leaveEvent); - } - - return filteredEvents; -} - } // namespace XCEngine::UI::Editor::App namespace XCEngine::UI::Editor::App { @@ -424,21 +361,19 @@ void EditorShellRuntime::Update( const Widgets::UIEditorDockHostLayout preUpdateDockLayout = m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout; - m_hierarchyPanel.SetSceneRuntime(&context.GetSceneRuntime()); - m_hierarchyPanel.SetCommandFocusService(&context.GetCommandFocusService()); - m_sceneEditCommandRoute.BindSceneRuntime(&context.GetSceneRuntime()); - m_sceneViewportFeature.SetCommandFocusService(&context.GetCommandFocusService()); - // Keep the previous render request available for readback-based picking during - // this update, then refresh it again after camera/navigation state changes. - m_sceneViewportFeature.SyncRenderRequest(context.GetSceneRuntime()); - context.BindEditCommandRoutes( - &m_hierarchyPanel, - &m_projectPanel, - &m_sceneEditCommandRoute, - &m_inspectorPanel); - context.SyncSessionFromWorkspace(workspaceController); UIEditorShellInteractionDefinition definition = - context.BuildShellDefinition(workspaceController, captureText, shellVariant); + m_sessionCoordinator.PrepareShellDefinition( + EditorShellSessionCoordinatorContext{ + .context = context, + .workspaceController = workspaceController, + .captureText = captureText, + .shellVariant = shellVariant, + .hierarchyPanel = m_hierarchyPanel, + .inspectorPanel = m_inspectorPanel, + .projectPanel = m_projectPanel, + .sceneEditCommandRoute = m_sceneEditCommandRoute, + .sceneViewportFeature = m_sceneViewportFeature, + }); m_viewportHostService.BeginFrame(); const std::vector<::XCEngine::UI::UIInputEvent> shellEvents = HasHostedContentCapture() @@ -461,9 +396,19 @@ void EditorShellRuntime::Update( preUpdateDockLayout, workspaceController, metrics.shellMetrics.dockHostMetrics)) { - context.SyncSessionFromWorkspace(workspaceController); definition = - context.BuildShellDefinition(workspaceController, captureText, shellVariant); + m_sessionCoordinator.PrepareShellDefinition( + EditorShellSessionCoordinatorContext{ + .context = context, + .workspaceController = workspaceController, + .captureText = captureText, + .shellVariant = shellVariant, + .hierarchyPanel = m_hierarchyPanel, + .inspectorPanel = m_inspectorPanel, + .projectPanel = m_projectPanel, + .sceneEditCommandRoute = m_sceneEditCommandRoute, + .sceneViewportFeature = m_sceneViewportFeature, + }); m_shellFrame = UpdateUIEditorShellInteraction( m_shellInteractionState, workspaceController, @@ -474,64 +419,24 @@ void EditorShellRuntime::Update( metrics); } - const bool shellOwnsHostedContentPointerStream = - ShouldHostedContentYieldPointerStream(m_shellFrame, HasShellInteractiveCapture()); - const std::vector<::XCEngine::UI::UIInputEvent> hostedContentEvents = - FilterHostedContentInputEventsForShellOwnership( - inputEvents, - shellOwnsHostedContentPointerStream); - m_sceneViewportFeature.Update( - context.GetSceneRuntime(), - m_shellInteractionState.workspaceInteractionState.composeState, - m_shellFrame.workspaceInteractionFrame.composeFrame); ApplyViewportFramesToShellFrame(m_shellFrame, m_viewportHostService); - context.SyncSessionFromWorkspace(workspaceController); - context.UpdateStatusFromShellResult(workspaceController, m_shellFrame.result); + m_sessionCoordinator.FinalizeFrame(context, workspaceController, m_shellFrame.result); - const bool allowHostedInteraction = !m_shellFrame.result.workspaceInputSuppressed; - const PanelInputContext hierarchyInputContext = BuildHostedPanelInputContext( - m_shellFrame.workspaceInteractionFrame, - allowHostedInteraction, - kHierarchyPanelId); - const PanelInputContext projectInputContext = BuildHostedPanelInputContext( - m_shellFrame.workspaceInteractionFrame, - allowHostedInteraction, - kProjectPanelId); - const PanelInputContext inspectorInputContext = BuildHostedPanelInputContext( - m_shellFrame.workspaceInteractionFrame, - allowHostedInteraction, - kInspectorPanelId); - const PanelInputContext colorPickerInputContext = BuildHostedPanelInputContext( - m_shellFrame.workspaceInteractionFrame, - allowHostedInteraction, - kColorPickerPanelId); - m_projectPanel.SetProjectRuntime(&context.GetProjectRuntime()); - m_projectPanel.SetCommandFocusService(&context.GetCommandFocusService()); - m_projectPanel.SetSystemInteractionHost(context.GetSystemInteractionHost()); - m_inspectorPanel.SetCommandFocusService(&context.GetCommandFocusService()); - m_hierarchyPanel.Update( - m_shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, - hostedContentEvents, - hierarchyInputContext); - m_projectPanel.Update( - m_shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, - hostedContentEvents, - projectInputContext); + m_hostedPanelCoordinator.Update( + EditorShellHostedPanelCoordinatorContext{ + .context = context, + .shellFrame = m_shellFrame, + .shellInteractionState = m_shellInteractionState, + .inputEvents = inputEvents, + .shellInteractiveCaptureActive = HasShellInteractiveCapture(), + .consolePanel = m_consolePanel, + .colorPickerPanel = m_colorPickerPanel, + .hierarchyPanel = m_hierarchyPanel, + .inspectorPanel = m_inspectorPanel, + .projectPanel = m_projectPanel, + .sceneViewportFeature = m_sceneViewportFeature, + }); m_traceEntries = SyncWorkspaceEvents(context, *this); - m_colorPickerPanel.Update( - context, - m_shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, - hostedContentEvents, - colorPickerInputContext); - m_inspectorPanel.Update( - context, - m_shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame, - hostedContentEvents, - inspectorInputContext); - context.SyncSessionFromCommandFocusService(); - m_consolePanel.Update( - context.GetSession(), - m_shellFrame.workspaceInteractionFrame.composeFrame.contentHostFrame); } } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Composition/EditorShellRuntime.h b/new_editor/app/Composition/EditorShellRuntime.h index 5e945564..41556a62 100644 --- a/new_editor/app/Composition/EditorShellRuntime.h +++ b/new_editor/app/Composition/EditorShellRuntime.h @@ -1,7 +1,9 @@ #pragma once #include "Composition/EditorShellDrawComposer.h" +#include "Composition/EditorShellHostedPanelCoordinator.h" #include "Composition/EditorShellPointerInteraction.h" +#include "Composition/EditorShellSessionCoordinator.h" #include "Composition/EditorShellVariant.h" #include "Features/Console/ConsolePanel.h" #include "Features/ColorPicker/ColorPickerPanel.h" @@ -115,6 +117,8 @@ private: std::vector m_traceEntries = {}; UIEditorWorkspaceSplitterDragCorrectionState m_splitterDragCorrectionState = {}; EditorShellDrawComposer m_drawComposer = {}; + EditorShellHostedPanelCoordinator m_hostedPanelCoordinator = {}; + EditorShellSessionCoordinator m_sessionCoordinator = {}; }; } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Composition/EditorShellSessionCoordinator.cpp b/new_editor/app/Composition/EditorShellSessionCoordinator.cpp new file mode 100644 index 00000000..711944a2 --- /dev/null +++ b/new_editor/app/Composition/EditorShellSessionCoordinator.cpp @@ -0,0 +1,42 @@ +#include "Composition/EditorShellSessionCoordinator.h" + +#include "Composition/EditorContext.h" +#include "Features/Hierarchy/HierarchyPanel.h" +#include "Features/Inspector/InspectorPanel.h" +#include "Features/Project/ProjectPanel.h" +#include "Features/Scene/SceneEditCommandRoute.h" +#include "Features/Scene/SceneViewportFeature.h" + +namespace XCEngine::UI::Editor::App { + +UIEditorShellInteractionDefinition EditorShellSessionCoordinator::PrepareShellDefinition( + const EditorShellSessionCoordinatorContext& context) const { + context.hierarchyPanel.SetSceneRuntime(&context.context.GetSceneRuntime()); + context.hierarchyPanel.SetCommandFocusService(&context.context.GetCommandFocusService()); + context.sceneEditCommandRoute.BindSceneRuntime(&context.context.GetSceneRuntime()); + context.sceneViewportFeature.SetCommandFocusService( + &context.context.GetCommandFocusService()); + // Keep the previous render request available for readback-based picking during + // this update, then refresh it again after camera/navigation state changes. + context.sceneViewportFeature.SyncRenderRequest(context.context.GetSceneRuntime()); + context.context.BindEditCommandRoutes( + &context.hierarchyPanel, + &context.projectPanel, + &context.sceneEditCommandRoute, + &context.inspectorPanel); + context.context.SyncSessionFromWorkspace(context.workspaceController); + return context.context.BuildShellDefinition( + context.workspaceController, + context.captureText, + context.shellVariant); +} + +void EditorShellSessionCoordinator::FinalizeFrame( + EditorContext& context, + UIEditorWorkspaceController& workspaceController, + const UIEditorShellInteractionResult& shellResult) const { + context.SyncSessionFromWorkspace(workspaceController); + context.UpdateStatusFromShellResult(workspaceController, shellResult); +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Composition/EditorShellSessionCoordinator.h b/new_editor/app/Composition/EditorShellSessionCoordinator.h new file mode 100644 index 00000000..e917782f --- /dev/null +++ b/new_editor/app/Composition/EditorShellSessionCoordinator.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Composition/EditorShellVariant.h" + +#include +#include + +#include + +namespace XCEngine::UI::Editor::App { + +class EditorContext; +class HierarchyPanel; +class InspectorPanel; +class ProjectPanel; +class SceneEditCommandRoute; +class SceneViewportFeature; + +struct EditorShellSessionCoordinatorContext { + EditorContext& context; + UIEditorWorkspaceController& workspaceController; + std::string_view captureText; + EditorShellVariant shellVariant = EditorShellVariant::Primary; + HierarchyPanel& hierarchyPanel; + InspectorPanel& inspectorPanel; + ProjectPanel& projectPanel; + SceneEditCommandRoute& sceneEditCommandRoute; + SceneViewportFeature& sceneViewportFeature; +}; + +class EditorShellSessionCoordinator final { +public: + UIEditorShellInteractionDefinition PrepareShellDefinition( + const EditorShellSessionCoordinatorContext& context) const; + void FinalizeFrame( + EditorContext& context, + UIEditorWorkspaceController& workspaceController, + const UIEditorShellInteractionResult& shellResult) const; +}; + +} // namespace XCEngine::UI::Editor::App