diff --git a/docs/plan/editor-core-refactor-plan.md b/docs/plan/editor-core-refactor-plan.md index 9ad8248e..ef4b5636 100644 --- a/docs/plan/editor-core-refactor-plan.md +++ b/docs/plan/editor-core-refactor-plan.md @@ -38,7 +38,9 @@ incomplete: - `XCEditorCore` exists, but its include surface still exposes the whole `editor/app` root to app code. -- Some feature panels still use `Composition/EditorContext.h` directly. +- Feature panels no longer use `Composition/EditorContext.h` directly, but the + app include surface still needs to be narrowed before this boundary is + build-enforced. - Win32 and D3D12 currently know about each other through concrete headers. - App-side tests exist but are not consistently wired into CMake; some are stale and reference removed headers. @@ -56,6 +58,11 @@ Completed boundary cuts: `editor/app/Core/UtilityWindows`; concrete Color Picker/Add Component panel creation lives under `editor/app/Features/EditorUtilityWindowRegistry.*` and is injected from `Application`. +- Panel-facing app services live under + `editor/app/Core/Panels/EditorPanelServices.h`. Workspace-panel and + utility-window runtime contracts accept this service view instead of + `EditorContext`, so concrete feature panels no longer depend on + `Composition/EditorContext.h`. The root issue is not the existence of a single executable target by itself. The root issue is that shared app contracts are stored inside concrete layer @@ -199,12 +206,22 @@ Expected dependency improvement: ```text Composition -> Core/WorkspacePanels Features -> Core/WorkspacePanels -Features -> Composition only where concrete panels still need EditorContext +Features -> Core/Panels ``` This does not fully solve all cycles, but it removes the worst misplaced public contract and creates the landing zone for the next cut. +Completed follow-up: + +- `EditorPanelServices` now carries the panel-facing references to session, + project runtime, scene runtime, command focus, color-picker state, system + interaction, text measurement, and utility-window requests. +- `EditorWorkspacePanelRuntimeSet` updates a single phase at a time; Composition + owns the command-focus sync point between main panels and after-focus panels. +- Concrete workspace and utility panels use `EditorPanelServices` and no longer + include `Composition/EditorContext.h`. + ## Phase 2: Introduce XCEditorCore Create: diff --git a/editor/AGENTS.md b/editor/AGENTS.md index 55f8b42a..d4fe5769 100644 --- a/editor/AGENTS.md +++ b/editor/AGENTS.md @@ -44,7 +44,8 @@ change. - `app/Core/` contains app-level contracts and shared app model definitions that are not owned by a concrete feature or composition implementation. Current examples are panel IDs, shared window type contracts, the - workspace-panel runtime interface, and utility-window runtime/descriptors. + panel-facing service view, workspace-panel runtime interface, and + utility-window runtime/descriptors. - `app/Composition/` builds the editor shell asset, coordinates shell update phases, and connects app state to hosted panel runtimes. - `app/Windowing/` owns window instances, content controllers, frame transfer @@ -199,6 +200,10 @@ inside pure shell/widget code. capture root, and status-bar definitions. - Panel IDs are centralized in `app/Core/Panels/EditorPanelIds.h`; prefer these constants over raw string literals in app code. +- `EditorPanelServices` is the Core service view passed into concrete + workspace and utility panels. Panels should use it instead of including + `Composition/EditorContext.h`; `EditorContext` remains a composition-owned + aggregate and request bridge. - Workspace panels are adapted behind `EditorWorkspacePanelRuntimeSet`, whose contract lives in `app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h`. Composition code should ask that runtime set to initialize, prepare command @@ -210,9 +215,9 @@ inside pure shell/widget code. their own dispatch entries from that frame. - `EditorShellHostedPanelCoordinator` filters hosted-panel input when shell capture owns the pointer stream, then updates `EditorWorkspacePanelRuntimeSet`. - Concrete adapters wire app services into their panels and the runtime set - syncs command focus before after-focus panels such as Console read session - state. + Concrete adapters wire app services into their panels through + `EditorPanelServices`. The coordinator syncs command focus between the main + update phase and after-focus panels such as Console. - `EditorHostCommandBridge` routes host commands to focused edit routes, project asset routes, scene routes, inspector routes, workspace commands, or the app exit handler. @@ -381,6 +386,10 @@ ownership rule. under `app/Core/Panels`, and the workspace-panel runtime interface lives under `app/Core/WorkspacePanels`. `Application` is the current composition root for the concrete workspace panel factory. +- Panel-facing app services now live behind + `app/Core/Panels/EditorPanelServices.h`. Workspace-panel and utility-window + runtime contracts no longer expose `EditorContext`, and concrete feature + panels no longer include `Composition/EditorContext.h`. - Project service ownership moved out of `app/Features`: `ProjectBrowserModel` and `EditorProjectRuntime` now live under `app/Services/Project`, and the Project panel owns the widget-tree projection instead of making the service diff --git a/editor/app/Composition/EditorContext.cpp b/editor/app/Composition/EditorContext.cpp index f487bae1..5e788efd 100644 --- a/editor/app/Composition/EditorContext.cpp +++ b/editor/app/Composition/EditorContext.cpp @@ -14,6 +14,15 @@ using ::XCEngine::UI::Editor::BuildEditorShellShortcutManager; using ::XCEngine::UI::Editor::UIEditorWorkspacePanelPresentationModel; using ::XCEngine::UI::Editor::AppendUIEditorRuntimeTrace; +void RequestEditorContextUtilityWindow( + void* requester, + EditorUtilityWindowKind kind) { + auto* context = static_cast(requester); + if (context != nullptr) { + context->RequestOpenUtilityWindow(kind); + } +} + std::string ComposeStatusText( std::string_view status, std::string_view message) { @@ -213,6 +222,20 @@ const UIEditorShellInteractionServices& EditorContext::GetShellServices() const return m_shellServices; } +EditorPanelServices EditorContext::BuildPanelServices() { + return EditorPanelServices{ + .session = m_session, + .projectRuntime = m_projectRuntime, + .sceneRuntime = m_sceneRuntime, + .commandFocusService = m_commandFocusService, + .colorPickerToolState = m_colorPickerToolState, + .systemInteractionHost = m_systemInteractionHost, + .textMeasurer = m_shellServices.textMeasurer, + .utilityWindowRequester = this, + .requestUtilityWindow = RequestEditorContextUtilityWindow, + }; +} + UIEditorShellInteractionDefinition EditorContext::BuildShellDefinition( const UIEditorWorkspaceController& workspaceController, std::string_view captureText, diff --git a/editor/app/Composition/EditorContext.h b/editor/app/Composition/EditorContext.h index 8adae4e9..bfc52763 100644 --- a/editor/app/Composition/EditorContext.h +++ b/editor/app/Composition/EditorContext.h @@ -1,6 +1,7 @@ #pragma once #include "Composition/EditorShellVariant.h" +#include "Core/Panels/EditorPanelServices.h" #include "Scene/EditorSceneRuntime.h" #include "Services/Project/EditorProjectRuntime.h" #include "Core/UtilityWindows/EditorUtilityWindowRuntime.h" @@ -66,6 +67,7 @@ public: UIEditorWorkspaceController BuildWorkspaceController() const; const UIEditorShellInteractionServices& GetShellServices() const; + EditorPanelServices BuildPanelServices(); UIEditorShellInteractionDefinition BuildShellDefinition( const UIEditorWorkspaceController& workspaceController, diff --git a/editor/app/Composition/EditorShellHostedPanelCoordinator.cpp b/editor/app/Composition/EditorShellHostedPanelCoordinator.cpp index 73ed069f..9ce56cb3 100644 --- a/editor/app/Composition/EditorShellHostedPanelCoordinator.cpp +++ b/editor/app/Composition/EditorShellHostedPanelCoordinator.cpp @@ -1,5 +1,6 @@ #include "Composition/EditorShellHostedPanelCoordinator.h" +#include "Composition/EditorContext.h" #include "Core/WorkspacePanels/EditorWorkspacePanelRuntime.h" #include @@ -19,13 +20,21 @@ void EditorShellHostedPanelCoordinator::Update( context.inputEvents, shellOwnsHostedContentPointerStream); - context.workspacePanels.Update( - EditorWorkspacePanelUpdateContext{ - .context = context.context, - .shellFrame = context.shellFrame, - .shellInteractionState = context.shellInteractionState, - .hostedContentEvents = hostedContentEvents, - }); + EditorPanelServices services = context.context.BuildPanelServices(); + const EditorWorkspacePanelUpdateContext updateContext{ + .services = services, + .shellFrame = context.shellFrame, + .shellInteractionState = context.shellInteractionState, + .hostedContentEvents = hostedContentEvents, + }; + + context.workspacePanels.UpdatePhase( + updateContext, + EditorWorkspacePanelUpdatePhase::Main); + context.context.SyncSessionFromCommandFocusService(); + context.workspacePanels.UpdatePhase( + updateContext, + EditorWorkspacePanelUpdatePhase::AfterCommandFocusSync); } } // namespace XCEngine::UI::Editor::App diff --git a/editor/app/Composition/EditorShellSessionCoordinator.cpp b/editor/app/Composition/EditorShellSessionCoordinator.cpp index d4be764a..ec3b6b95 100644 --- a/editor/app/Composition/EditorShellSessionCoordinator.cpp +++ b/editor/app/Composition/EditorShellSessionCoordinator.cpp @@ -7,8 +7,9 @@ namespace XCEngine::UI::Editor::App { UIEditorShellInteractionDefinition EditorShellSessionCoordinator::PrepareShellDefinition( const EditorShellSessionCoordinatorContext& context) const { + EditorPanelServices services = context.context.BuildPanelServices(); context.workspacePanels.PrepareForShellDefinition( - context.context, + services, context.workspaceController); context.context.BindEditCommandRoutes( context.workspacePanels.FindCommandRoute(EditorActionRoute::Hierarchy), diff --git a/editor/app/Core/Panels/EditorPanelServices.h b/editor/app/Core/Panels/EditorPanelServices.h new file mode 100644 index 00000000..2f75bc12 --- /dev/null +++ b/editor/app/Core/Panels/EditorPanelServices.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +namespace XCEngine::UI::Editor { + +class UIEditorTextMeasurer; + +} // namespace XCEngine::UI::Editor + +namespace XCEngine::UI::Editor::System { + +class SystemInteractionService; + +} // namespace XCEngine::UI::Editor::System + +namespace XCEngine::UI::Editor::App { + +class EditorCommandFocusService; +class EditorProjectRuntime; +class EditorSceneRuntime; +enum class EditorUtilityWindowKind : std::uint8_t; +struct EditorColorPickerToolState; +struct EditorSession; + +struct EditorPanelServices { + using UtilityWindowRequestFn = void (*)(void*, EditorUtilityWindowKind); + + EditorSession& session; + EditorProjectRuntime& projectRuntime; + EditorSceneRuntime& sceneRuntime; + EditorCommandFocusService& commandFocusService; + EditorColorPickerToolState& colorPickerToolState; + System::SystemInteractionService* systemInteractionHost = nullptr; + const UIEditorTextMeasurer* textMeasurer = nullptr; + void* utilityWindowRequester = nullptr; + UtilityWindowRequestFn requestUtilityWindow = nullptr; + + void RequestOpenUtilityWindow(EditorUtilityWindowKind kind) const { + if (requestUtilityWindow != nullptr) { + requestUtilityWindow(utilityWindowRequester, kind); + } + } +}; + +} // namespace XCEngine::UI::Editor::App diff --git a/editor/app/Core/UtilityWindows/EditorUtilityWindowRuntime.h b/editor/app/Core/UtilityWindows/EditorUtilityWindowRuntime.h index 4e734d60..d8672864 100644 --- a/editor/app/Core/UtilityWindows/EditorUtilityWindowRuntime.h +++ b/editor/app/Core/UtilityWindows/EditorUtilityWindowRuntime.h @@ -1,5 +1,6 @@ #pragma once +#include "Core/Panels/EditorPanelServices.h" #include "Core/Windowing/EditorWindowTypes.h" #include @@ -13,8 +14,6 @@ namespace XCEngine::UI::Editor::App { -class EditorContext; - enum class EditorUtilityWindowKind : std::uint8_t { None = 0, ColorPicker, @@ -53,7 +52,7 @@ public: virtual std::string_view GetDrawListId() const = 0; virtual void ResetInteractionState() = 0; virtual void Update( - EditorContext& context, + EditorPanelServices& services, const EditorUtilityWindowHostContext& hostContext, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) = 0; virtual void Append(::XCEngine::UI::UIDrawList& drawList) const = 0; diff --git a/editor/app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h b/editor/app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h index 5dfc2f9d..08b321dd 100644 --- a/editor/app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h +++ b/editor/app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h @@ -1,6 +1,7 @@ #pragma once #include "Commands/EditorEditCommandRoute.h" +#include "Core/Panels/EditorPanelServices.h" #include "State/EditorSession.h" #include @@ -33,7 +34,6 @@ class UiTextureHost; namespace XCEngine::UI::Editor::App { class BuiltInIcons; -class EditorContext; class ViewportHostService; enum class EditorWorkspacePanelCursorKind : std::uint8_t { @@ -66,7 +66,7 @@ struct EditorWorkspacePanelShutdownContext { }; struct EditorWorkspacePanelUpdateContext { - EditorContext& context; + EditorPanelServices& services; UIEditorShellInteractionFrame& shellFrame; UIEditorShellInteractionState& shellInteractionState; const std::vector<::XCEngine::UI::UIInputEvent>& hostedContentEvents; @@ -84,9 +84,9 @@ public: virtual void Shutdown(const EditorWorkspacePanelShutdownContext&) {} virtual void ResetInteractionState() {} virtual void PrepareForShellDefinition( - EditorContext& context, + EditorPanelServices& services, UIEditorWorkspaceController& workspaceController) { - (void)context; + (void)services; (void)workspaceController; } virtual EditorWorkspacePanelUpdatePhase GetUpdatePhase() const { @@ -124,9 +124,11 @@ public: void Shutdown(const EditorWorkspacePanelShutdownContext& context); void ResetInteractionState(); void PrepareForShellDefinition( - EditorContext& context, + EditorPanelServices& services, UIEditorWorkspaceController& workspaceController); - void Update(const EditorWorkspacePanelUpdateContext& context); + void UpdatePhase( + const EditorWorkspacePanelUpdateContext& context, + EditorWorkspacePanelUpdatePhase phase); void AppendDrawPackets(::XCEngine::UI::UIDrawData& drawData) const; bool HasActivePointerCapture() const; diff --git a/editor/app/Features/ColorPicker/ColorPickerPanel.cpp b/editor/app/Features/ColorPicker/ColorPickerPanel.cpp index d4a92ff0..c66fbbb4 100644 --- a/editor/app/Features/ColorPicker/ColorPickerPanel.cpp +++ b/editor/app/Features/ColorPicker/ColorPickerPanel.cpp @@ -1,6 +1,6 @@ #include "ColorPickerPanel.h" -#include "Composition/EditorContext.h" +#include "Core/Panels/EditorPanelServices.h" #include "State/EditorColorPickerToolState.h" #include @@ -88,7 +88,7 @@ void ColorPickerPanel::ResetInteractionState() { } void ColorPickerPanel::Update( - EditorContext& context, + EditorPanelServices& services, const EditorUtilityWindowHostContext& hostContext, const std::vector& inputEvents) { if (!hostContext.mounted) { @@ -101,7 +101,7 @@ void ColorPickerPanel::Update( m_metrics = BuildColorPickerPanelMetrics(m_bounds); m_palette = BuildColorPickerPanelPalette(); - EditorColorPickerToolState& toolState = context.GetColorPickerToolState(); + EditorColorPickerToolState& toolState = services.colorPickerToolState; m_hasActiveTarget = toolState.active && !toolState.inspectorTarget.subjectKey.empty() && diff --git a/editor/app/Features/ColorPicker/ColorPickerPanel.h b/editor/app/Features/ColorPicker/ColorPickerPanel.h index 2303908a..74c323ad 100644 --- a/editor/app/Features/ColorPicker/ColorPickerPanel.h +++ b/editor/app/Features/ColorPicker/ColorPickerPanel.h @@ -15,7 +15,7 @@ public: } void ResetInteractionState() override; void Update( - EditorContext& context, + EditorPanelServices& services, const EditorUtilityWindowHostContext& hostContext, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override; void Append(::XCEngine::UI::UIDrawList& drawList) const override; diff --git a/editor/app/Features/EditorWorkspacePanelRegistry.cpp b/editor/app/Features/EditorWorkspacePanelRegistry.cpp index 0b651362..1f879ccd 100644 --- a/editor/app/Features/EditorWorkspacePanelRegistry.cpp +++ b/editor/app/Features/EditorWorkspacePanelRegistry.cpp @@ -9,7 +9,6 @@ #include "Features/Scene/SceneViewportFeature.h" #include "Rendering/Assets/BuiltInIcons.h" #include "Rendering/Viewport/ViewportHostService.h" -#include "Composition/EditorContext.h" #include @@ -201,7 +200,7 @@ public: void Update(const EditorWorkspacePanelUpdateContext& context) override { m_panel.Update( - context.context.GetSession(), + context.services.session, ResolveHostedPanelDispatchEntry( context.shellFrame.hostedPanelDispatchFrame, GetPanelId())); @@ -244,10 +243,10 @@ public: } void PrepareForShellDefinition( - EditorContext& context, + EditorPanelServices& services, UIEditorWorkspaceController&) override { - m_panel.SetSceneRuntime(&context.GetSceneRuntime()); - m_panel.SetCommandFocusService(&context.GetCommandFocusService()); + m_panel.SetSceneRuntime(&services.sceneRuntime); + m_panel.SetCommandFocusService(&services.commandFocusService); } void Update(const EditorWorkspacePanelUpdateContext& context) override { @@ -305,9 +304,9 @@ public: } void Update(const EditorWorkspacePanelUpdateContext& context) override { - m_panel.SetCommandFocusService(&context.context.GetCommandFocusService()); + m_panel.SetCommandFocusService(&context.services.commandFocusService); m_panel.Update( - context.context, + context.services, ResolveHostedPanelDispatchEntry( context.shellFrame.hostedPanelDispatchFrame, GetPanelId()), @@ -354,9 +353,9 @@ public: } void Update(const EditorWorkspacePanelUpdateContext& context) override { - m_panel.SetProjectRuntime(&context.context.GetProjectRuntime()); - m_panel.SetCommandFocusService(&context.context.GetCommandFocusService()); - m_panel.SetSystemInteractionHost(context.context.GetSystemInteractionHost()); + m_panel.SetProjectRuntime(&context.services.projectRuntime); + m_panel.SetCommandFocusService(&context.services.commandFocusService); + m_panel.SetSystemInteractionHost(context.services.systemInteractionHost); m_panel.Update( ResolveHostedPanelDispatchEntry( context.shellFrame.hostedPanelDispatchFrame, @@ -438,16 +437,16 @@ public: } void PrepareForShellDefinition( - EditorContext& context, + EditorPanelServices& services, UIEditorWorkspaceController&) override { - m_commandRoute.BindSceneRuntime(&context.GetSceneRuntime()); - m_feature.SetCommandFocusService(&context.GetCommandFocusService()); - m_feature.SyncRenderRequest(context.GetSceneRuntime()); + m_commandRoute.BindSceneRuntime(&services.sceneRuntime); + m_feature.SetCommandFocusService(&services.commandFocusService); + m_feature.SyncRenderRequest(services.sceneRuntime); } void Update(const EditorWorkspacePanelUpdateContext& context) override { m_feature.Update( - context.context.GetSceneRuntime(), + context.services.sceneRuntime, context.shellInteractionState.workspaceInteractionState.composeState, context.shellFrame.workspaceInteractionFrame.composeFrame); } @@ -495,26 +494,19 @@ void EditorWorkspacePanelRuntimeSet::ResetInteractionState() { } void EditorWorkspacePanelRuntimeSet::PrepareForShellDefinition( - EditorContext& context, + EditorPanelServices& services, UIEditorWorkspaceController& workspaceController) { for (const std::unique_ptr& panel : m_panels) { - panel->PrepareForShellDefinition(context, workspaceController); + panel->PrepareForShellDefinition(services, workspaceController); } } -void EditorWorkspacePanelRuntimeSet::Update( - const EditorWorkspacePanelUpdateContext& context) { - const std::vector mainPanels = - BuildUpdateOrder(EditorWorkspacePanelUpdatePhase::Main); - for (EditorWorkspacePanel* panel : mainPanels) { - panel->Update(context); - } - - context.context.SyncSessionFromCommandFocusService(); - - const std::vector afterFocusSyncPanels = - BuildUpdateOrder(EditorWorkspacePanelUpdatePhase::AfterCommandFocusSync); - for (EditorWorkspacePanel* panel : afterFocusSyncPanels) { +void EditorWorkspacePanelRuntimeSet::UpdatePhase( + const EditorWorkspacePanelUpdateContext& context, + EditorWorkspacePanelUpdatePhase phase) { + const std::vector phasePanels = + BuildUpdateOrder(phase); + for (EditorWorkspacePanel* panel : phasePanels) { panel->Update(context); } } diff --git a/editor/app/Features/Inspector/AddComponentPanel.cpp b/editor/app/Features/Inspector/AddComponentPanel.cpp index 811afb78..19aa1360 100644 --- a/editor/app/Features/Inspector/AddComponentPanel.cpp +++ b/editor/app/Features/Inspector/AddComponentPanel.cpp @@ -1,6 +1,6 @@ #include "Features/Inspector/AddComponentPanel.h" -#include "Composition/EditorContext.h" +#include "Core/Panels/EditorPanelServices.h" #include "Features/Inspector/Components/IInspectorComponentEditor.h" #include "Features/Inspector/Components/InspectorComponentEditorRegistry.h" @@ -122,7 +122,7 @@ void AddComponentPanel::RebuildEntries( } bool AddComponentPanel::TryActivateEntry( - EditorContext& context, + EditorPanelServices& services, std::size_t entryIndex) { if (entryIndex >= m_entries.size()) { return false; @@ -133,13 +133,13 @@ bool AddComponentPanel::TryActivateEntry( return false; } - if (!context.GetSceneRuntime().AddComponentToSelectedGameObject(entry.componentTypeName)) { + if (!services.sceneRuntime.AddComponentToSelectedGameObject(entry.componentTypeName)) { return false; } - m_hasTarget = context.GetSceneRuntime().GetSelectedGameObject() != nullptr; - m_targetDisplayName = context.GetSceneRuntime().GetSelectedDisplayName(); - RebuildEntries(context.GetSceneRuntime().GetSelectedGameObject()); + m_hasTarget = services.sceneRuntime.GetSelectedGameObject() != nullptr; + m_targetDisplayName = services.sceneRuntime.GetSelectedDisplayName(); + RebuildEntries(services.sceneRuntime.GetSelectedGameObject()); return true; } @@ -154,7 +154,7 @@ std::size_t AddComponentPanel::HitTestEntry(const UIPoint& point) const { } void AddComponentPanel::Update( - EditorContext& context, + EditorPanelServices& services, const EditorUtilityWindowHostContext& hostContext, const std::vector& inputEvents) { if (!hostContext.mounted) { @@ -164,9 +164,9 @@ void AddComponentPanel::Update( m_visible = true; m_bounds = hostContext.bounds; - m_hasTarget = context.GetSceneRuntime().GetSelectedGameObject() != nullptr; - m_targetDisplayName = context.GetSceneRuntime().GetSelectedDisplayName(); - RebuildEntries(context.GetSceneRuntime().GetSelectedGameObject()); + m_hasTarget = services.sceneRuntime.GetSelectedGameObject() != nullptr; + m_targetDisplayName = services.sceneRuntime.GetSelectedDisplayName(); + RebuildEntries(services.sceneRuntime.GetSelectedGameObject()); if (hostContext.focusLost) { ResetInteractionState(); @@ -204,7 +204,7 @@ void AddComponentPanel::Update( m_hoveredEntryIndex = HitTestEntry(event.position); if (m_pressedEntryIndex != kInvalidEntryIndex && m_pressedEntryIndex == m_hoveredEntryIndex) { - TryActivateEntry(context, m_pressedEntryIndex); + TryActivateEntry(services, m_pressedEntryIndex); } m_pressedEntryIndex = kInvalidEntryIndex; break; diff --git a/editor/app/Features/Inspector/AddComponentPanel.h b/editor/app/Features/Inspector/AddComponentPanel.h index ba002571..a17701ea 100644 --- a/editor/app/Features/Inspector/AddComponentPanel.h +++ b/editor/app/Features/Inspector/AddComponentPanel.h @@ -19,7 +19,7 @@ public: } void ResetInteractionState() override; void Update( - EditorContext& context, + EditorPanelServices& services, const EditorUtilityWindowHostContext& hostContext, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override; void Append(::XCEngine::UI::UIDrawList& drawList) const override; @@ -35,7 +35,7 @@ private: void ResetPanelState(); void RebuildEntries(const ::XCEngine::Components::GameObject* gameObject); - bool TryActivateEntry(EditorContext& context, std::size_t entryIndex); + bool TryActivateEntry(EditorPanelServices& services, std::size_t entryIndex); std::size_t HitTestEntry(const ::XCEngine::UI::UIPoint& point) const; bool m_visible = false; diff --git a/editor/app/Features/Inspector/InspectorPanel.cpp b/editor/app/Features/Inspector/InspectorPanel.cpp index 1f337e62..82ddeb00 100644 --- a/editor/app/Features/Inspector/InspectorPanel.cpp +++ b/editor/app/Features/Inspector/InspectorPanel.cpp @@ -1,6 +1,7 @@ #include "InspectorPanel.h" -#include "Composition/EditorContext.h" +#include "Core/Panels/EditorPanelServices.h" +#include "Core/UtilityWindows/EditorUtilityWindowRuntime.h" #include "State/EditorColorPickerToolState.h" #include #include @@ -10,6 +11,7 @@ #include "Features/Inspector/Components/IInspectorComponentEditor.h" #include "Features/Inspector/Components/InspectorComponentEditorRegistry.h" #include "Scene/EditorSceneRuntime.h" +#include "Services/Project/EditorProjectRuntime.h" #include "State/EditorCommandFocusService.h" #include @@ -446,36 +448,37 @@ Widgets::UIEditorPropertyGridField* InspectorPanel::FindMutableField( return &m_presentation.sections[location.sectionIndex].fields[location.fieldIndex]; } -void InspectorPanel::CapturePresentationStamps(const EditorContext& context) { - m_lastSceneSelectionStamp = context.GetSceneRuntime().GetSelectionStamp(); - m_lastProjectSelectionStamp = context.GetProjectRuntime().GetSelectionStamp(); - m_lastSceneInspectorRevision = context.GetSceneRuntime().GetInspectorRevision(); +void InspectorPanel::CapturePresentationStamps( + const EditorPanelServices& services) { + m_lastSceneSelectionStamp = services.sceneRuntime.GetSelectionStamp(); + m_lastProjectSelectionStamp = services.projectRuntime.GetSelectionStamp(); + m_lastSceneInspectorRevision = services.sceneRuntime.GetInspectorRevision(); } void InspectorPanel::RebuildPresentation( - EditorContext& context, + EditorPanelServices& services, bool subjectChanged) { m_presentation = BuildInspectorPresentationModel( m_subject, - context.GetSceneRuntime(), + services.sceneRuntime, InspectorComponentEditorRegistry::Get()); - CapturePresentationStamps(context); + CapturePresentationStamps(services); SyncExpansionState(subjectChanged); SyncSelectionState(); } -void InspectorPanel::ForceResyncPresentation(EditorContext& context) { +void InspectorPanel::ForceResyncPresentation(EditorPanelServices& services) { if (m_subject.kind != InspectorSubjectKind::SceneObject) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } const std::string structureSignature = BuildInspectorStructureSignature( m_subject, - context.GetSceneRuntime(), + services.sceneRuntime, InspectorComponentEditorRegistry::Get()); if (structureSignature != m_presentation.structureSignature) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } @@ -483,38 +486,38 @@ void InspectorPanel::ForceResyncPresentation(EditorContext& context) { SyncInspectorPresentationModelValues( m_presentation, m_subject, - context.GetSceneRuntime(), + services.sceneRuntime, InspectorComponentEditorRegistry::Get()); if (!syncResult.success) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } m_presentation.structureSignature = structureSignature; - CapturePresentationStamps(context); + CapturePresentationStamps(services); SyncSelectionState(); } void InspectorPanel::RefreshPresentation( - EditorContext& context, + EditorPanelServices& services, bool subjectChanged) { if (subjectChanged) { - RebuildPresentation(context, true); + RebuildPresentation(services, true); return; } switch (m_subject.kind) { case InspectorSubjectKind::ProjectAsset: if (m_lastProjectSelectionStamp != - context.GetProjectRuntime().GetSelectionStamp()) { - RebuildPresentation(context, false); + services.projectRuntime.GetSelectionStamp()) { + RebuildPresentation(services, false); } return; case InspectorSubjectKind::SceneObject: { - const EditorSceneRuntime& sceneRuntime = context.GetSceneRuntime(); + const EditorSceneRuntime& sceneRuntime = services.sceneRuntime; if (m_lastSceneSelectionStamp != sceneRuntime.GetSelectionStamp()) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } @@ -527,7 +530,7 @@ void InspectorPanel::RefreshPresentation( sceneRuntime, InspectorComponentEditorRegistry::Get()); if (structureSignature != m_presentation.structureSignature) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } @@ -538,12 +541,12 @@ void InspectorPanel::RefreshPresentation( sceneRuntime, InspectorComponentEditorRegistry::Get()); if (!syncResult.success) { - RebuildPresentation(context, false); + RebuildPresentation(services, false); return; } m_presentation.structureSignature = structureSignature; - CapturePresentationStamps(context); + CapturePresentationStamps(services); SyncSelectionState(); return; } @@ -554,8 +557,8 @@ void InspectorPanel::RefreshPresentation( } } -bool InspectorPanel::ApplyColorPickerToolValue(EditorContext& context) { - EditorColorPickerToolState& toolState = context.GetColorPickerToolState(); +bool InspectorPanel::ApplyColorPickerToolValue(EditorPanelServices& services) { + EditorColorPickerToolState& toolState = services.colorPickerToolState; if (m_sceneRuntime == nullptr || !toolState.active || toolState.revision == m_lastAppliedColorPickerRevision || @@ -581,16 +584,16 @@ bool InspectorPanel::ApplyColorPickerToolValue(EditorContext& context) { const bool applied = ApplyChangedField(field->fieldId); m_lastAppliedColorPickerRevision = toolState.revision; if (!applied) { - ForceResyncPresentation(context); + ForceResyncPresentation(services); return false; } - RefreshPresentation(context, false); + RefreshPresentation(services, false); return true; } void InspectorPanel::RequestColorPicker( - EditorContext& context, + EditorPanelServices& services, std::string_view fieldId) { const Widgets::UIEditorPropertyGridField* field = FindField(fieldId); if (field == nullptr || @@ -600,12 +603,12 @@ void InspectorPanel::RequestColorPicker( } OpenEditorColorPickerToolForInspectorField( - context.GetColorPickerToolState(), + services.colorPickerToolState, m_subjectKey, field->fieldId, field->colorValue.value, field->colorValue.showAlpha); - context.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker); + services.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker); } void InspectorPanel::ResetAddComponentButtonState() { @@ -614,7 +617,7 @@ void InspectorPanel::ResetAddComponentButtonState() { } void InspectorPanel::UpdateAddComponentButton( - EditorContext& context, + EditorPanelServices& services, const std::vector& inputEvents) { if (!ShouldShowAddComponentButton()) { ResetAddComponentButtonState(); @@ -655,7 +658,7 @@ void InspectorPanel::UpdateAddComponentButton( if (m_addComponentButtonPressed && ContainsPoint(buttonRect, event.position)) { - context.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent); + services.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent); } m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position); @@ -723,7 +726,7 @@ bool InspectorPanel::ApplyChangedField(std::string_view fieldId) { } void InspectorPanel::Update( - EditorContext& context, + EditorPanelServices& services, const UIEditorHostedPanelDispatchEntry& dispatchEntry, const std::vector& inputEvents) { if (!dispatchEntry.mounted) { @@ -733,9 +736,9 @@ void InspectorPanel::Update( m_visible = true; m_bounds = dispatchEntry.bounds; - m_sceneRuntime = &context.GetSceneRuntime(); - m_textMeasurer = context.GetShellServices().textMeasurer; - m_subject = BuildInspectorSubject(context.GetSession(), context.GetSceneRuntime()); + m_sceneRuntime = &services.sceneRuntime; + m_textMeasurer = services.textMeasurer; + m_subject = BuildInspectorSubject(services.session, services.sceneRuntime); const std::string nextSubjectKey = BuildSubjectKey(); const bool subjectChanged = m_subjectKey != nextSubjectKey; @@ -744,8 +747,8 @@ void InspectorPanel::Update( ResetInteractionState(); } - RefreshPresentation(context, subjectChanged); - ApplyColorPickerToolValue(context); + RefreshPresentation(services, subjectChanged); + ApplyColorPickerToolValue(services); const std::vector filteredEvents = BuildUIEditorPanelInputEvents( @@ -814,21 +817,21 @@ void InspectorPanel::Update( m_gridFrame.result = interactionFrame.result; if (interactionFrame.result.pickerRequested && !interactionFrame.result.requestedFieldId.empty()) { - RequestColorPicker(context, interactionFrame.result.requestedFieldId); + RequestColorPicker(services, interactionFrame.result.requestedFieldId); } if (interactionFrame.result.fieldValueChanged && !interactionFrame.result.changedFieldId.empty()) { if (ApplyChangedField(interactionFrame.result.changedFieldId)) { - RefreshPresentation(context, false); + RefreshPresentation(services, false); } else { - ForceResyncPresentation(context); + ForceResyncPresentation(services); } } } RebuildScrollableLayout(); - UpdateAddComponentButton(context, filteredEvents); + UpdateAddComponentButton(services, filteredEvents); } void InspectorPanel::Append(UIDrawList& drawList) const { diff --git a/editor/app/Features/Inspector/InspectorPanel.h b/editor/app/Features/Inspector/InspectorPanel.h index 6bce7cbc..68b24197 100644 --- a/editor/app/Features/Inspector/InspectorPanel.h +++ b/editor/app/Features/Inspector/InspectorPanel.h @@ -22,14 +22,14 @@ namespace XCEngine::UI::Editor::App { class EditorCommandFocusService; -class EditorContext; class EditorSceneRuntime; +struct EditorPanelServices; class InspectorPanel final : public EditorEditCommandRoute { public: void SetCommandFocusService(EditorCommandFocusService* commandFocusService); void Update( - EditorContext& context, + EditorPanelServices& services, const UIEditorHostedPanelDispatchEntry& dispatchEntry, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents); void Append(::XCEngine::UI::UIDrawList& drawList) const; @@ -58,15 +58,15 @@ private: const InspectorPresentationComponentBinding* FindSelectedComponentBinding() const; const Widgets::UIEditorPropertyGridField* FindField(std::string_view fieldId) const; Widgets::UIEditorPropertyGridField* FindMutableField(std::string_view fieldId); - void CapturePresentationStamps(const EditorContext& context); - void RebuildPresentation(EditorContext& context, bool subjectChanged); - void RefreshPresentation(EditorContext& context, bool subjectChanged); - void ForceResyncPresentation(EditorContext& context); - bool ApplyColorPickerToolValue(EditorContext& context); - void RequestColorPicker(EditorContext& context, std::string_view fieldId); + void CapturePresentationStamps(const EditorPanelServices& services); + void RebuildPresentation(EditorPanelServices& services, bool subjectChanged); + void RefreshPresentation(EditorPanelServices& services, bool subjectChanged); + void ForceResyncPresentation(EditorPanelServices& services); + bool ApplyColorPickerToolValue(EditorPanelServices& services); + void RequestColorPicker(EditorPanelServices& services, std::string_view fieldId); void ResetAddComponentButtonState(); void UpdateAddComponentButton( - EditorContext& context, + EditorPanelServices& services, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents); bool ApplyChangedField(std::string_view fieldId); diff --git a/editor/app/Windowing/Content/EditorUtilityWindowContentController.cpp b/editor/app/Windowing/Content/EditorUtilityWindowContentController.cpp index ddaf61c5..8f7db0a3 100644 --- a/editor/app/Windowing/Content/EditorUtilityWindowContentController.cpp +++ b/editor/app/Windowing/Content/EditorUtilityWindowContentController.cpp @@ -1,5 +1,6 @@ #include "Windowing/Content/EditorUtilityWindowContentController.h" +#include "Composition/EditorContext.h" #include "Core/UtilityWindows/EditorUtilityWindowRuntime.h" #include @@ -67,8 +68,9 @@ EditorUtilityWindowContentController::UpdateAndAppend( return {}; } + EditorPanelServices services = context.editorContext.BuildPanelServices(); m_panel->Update( - context.editorContext, + services, EditorUtilityWindowHostContext{ .mounted = true, .bounds = context.bounds,