editor: remove shared panel services bag

This commit is contained in:
2026-04-29 13:10:03 +08:00
parent a3a80dff8f
commit a8e1a2b097
18 changed files with 202 additions and 206 deletions

View File

@@ -66,16 +66,22 @@ Rules:
owns scene document state: current path/name, dirty flag, new/open/save
routing, and runtime-mode transitions.
- `ProjectPanel` may identify an openable scene asset, but scene document loading
must go through `EditorPanelServices::RequestOpenSceneAsset` and the
must go through `EditorFrameServices::RequestOpenSceneAsset` and the
coordinator. Do not reintroduce `ProjectRuntime` pending-open queues.
- `scripts.rebuild` has a bound coordinator owner, but no in-process script
assembly builder is currently wired. Keep it disabled and explicit until that
builder exists.
- the old shared `EditorPanelServices` dependency bag is gone. Workspace and
utility panels now receive explicit bindings or panel-local contexts; do not
recreate a catch-all mutable panel service bundle under a new name
## Working Rules
- prefer explicit owner/coordinator/runtime-service seams over direct panel to
engine hookups
- keep panel dependencies explicit. If a panel needs more data or actions, add a
narrow panel-local context or binding instead of routing everything through a
generic shared services struct
- when changing runtime or document flow, inspect `EditorSession`,
`EditorRuntimeCoordinator`, `EditorHostCommandBridge`, the relevant feature,
and the matching tests
@@ -90,6 +96,8 @@ Rules:
- no new low-level render pass dependency on scene backend creation or lifecycle
- no silent fallback where a command should fail honestly
- no panel-local shortcut that bypasses the intended runtime owner
- no new shared mutable panel-services bag or service-locator style panel
dependency bundle
- no scene-open side channel in `EditorProjectRuntime`; project UI must call the
panel service request hook
- no play-mode path that mutates the editable scene in place or skips

View File

@@ -17,22 +17,6 @@ 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<EditorContext*>(requester);
if (context != nullptr) {
context->RequestOpenUtilityWindow(kind);
}
}
bool RequestEditorContextOpenSceneAsset(
void* requester,
const std::filesystem::path& scenePath) {
auto* context = static_cast<EditorContext*>(requester);
return context != nullptr && context->RequestOpenSceneAsset(scenePath);
}
std::string ComposeStatusText(
std::string_view status,
std::string_view message) {
@@ -260,20 +244,8 @@ 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,
.sceneAssetOpenRequester = this,
.requestOpenSceneAsset = RequestEditorContextOpenSceneAsset,
};
const UIEditorTextMeasurer* EditorContext::GetTextMeasurer() const {
return m_shellServices.textMeasurer;
}
bool EditorContext::RequestOpenSceneAsset(const std::filesystem::path& scenePath) {

View File

@@ -1,6 +1,5 @@
#pragma once
#include "Panels/EditorPanelServices.h"
#include "Environment/EditorRuntimePaths.h"
#include "Windowing/EditorFrameServices.h"
#include "Scene/EditorSceneRuntime.h"
@@ -47,6 +46,20 @@ public:
EditorEditCommandRoute* sceneRoute,
EditorEditCommandRoute* inspectorRoute = nullptr) override;
void SetExitRequestHandler(std::function<void()> handler);
const EditorSession& GetSession() const override;
EditorCommandFocusService& GetCommandFocusService() override;
const EditorCommandFocusService& GetCommandFocusService() const override;
EditorProjectRuntime& GetProjectRuntime() override;
const EditorProjectRuntime& GetProjectRuntime() const override;
EditorSceneRuntime& GetSceneRuntime() override;
const EditorSceneRuntime& GetSceneRuntime() const override;
EditorColorPickerToolState& GetColorPickerToolState() override;
const EditorColorPickerToolState& GetColorPickerToolState() const override;
void RequestOpenUtilityWindow(EditorUtilityWindowKind kind) override;
System::SystemInteractionService* GetSystemInteractionHost() override;
const System::SystemInteractionService* GetSystemInteractionHost() const override;
const UIEditorTextMeasurer* GetTextMeasurer() const override;
bool RequestOpenSceneAsset(const std::filesystem::path& scenePath) override;
void SyncSessionFromWorkspace(
const UIEditorWorkspaceController& workspaceController) override;
void TickEditorRuntime() override;
@@ -54,30 +67,16 @@ public:
bool IsValid() const override;
const std::string& GetValidationMessage() const override;
const EditorShellAsset& GetShellAsset() const;
const EditorSession& GetSession() const;
EditorCommandFocusService& GetCommandFocusService();
const EditorCommandFocusService& GetCommandFocusService() const;
EditorProjectRuntime& GetProjectRuntime();
const EditorProjectRuntime& GetProjectRuntime() const;
EditorSceneRuntime& GetSceneRuntime();
const EditorSceneRuntime& GetSceneRuntime() const;
EditorRuntimeCoordinator& GetRuntimeCoordinator();
const EditorRuntimeCoordinator& GetRuntimeCoordinator() const;
EditorColorPickerToolState& GetColorPickerToolState();
const EditorColorPickerToolState& GetColorPickerToolState() const;
void RequestOpenUtilityWindow(EditorUtilityWindowKind kind);
std::optional<EditorUtilityWindowKind> ConsumeOpenUtilityWindowRequest() override;
void SetSelection(EditorSelectionState selection);
void ClearSelection();
void SyncSessionFromSelectionService();
void SyncSessionFromCommandFocusService() override;
System::SystemInteractionService* GetSystemInteractionHost();
const System::SystemInteractionService* GetSystemInteractionHost() const;
UIEditorWorkspaceController BuildWorkspaceController() const;
const UIEditorShellInteractionServices& GetShellServices() const override;
EditorPanelServices BuildPanelServices() override;
bool RequestOpenSceneAsset(const std::filesystem::path& scenePath);
UIEditorShellInteractionDefinition BuildShellDefinition(
const UIEditorWorkspaceController& workspaceController,

View File

@@ -20,9 +20,8 @@ void EditorShellHostedPanelCoordinator::Update(
context.inputEvents,
shellOwnsHostedContentPointerStream);
EditorPanelServices services = context.frameServices.BuildPanelServices();
const EditorWorkspacePanelUpdateContext updateContext{
.services = services,
.frameServices = context.frameServices,
.shellFrame = context.shellFrame,
.shellInteractionState = context.shellInteractionState,
.hostedContentEvents = hostedContentEvents,

View File

@@ -6,9 +6,8 @@ namespace XCEngine::UI::Editor::App {
UIEditorShellInteractionDefinition EditorShellSessionCoordinator::PrepareShellDefinition(
const EditorShellSessionCoordinatorContext& context) const {
EditorPanelServices services = context.frameServices.BuildPanelServices();
context.workspacePanels.PrepareForShellDefinition(
services,
context.frameServices,
context.workspaceController);
context.frameServices.BindEditCommandRoutes(
context.workspacePanels.FindCommandRoute(EditorActionRoute::Hierarchy),

View File

@@ -1,57 +0,0 @@
#pragma once
#include <cstdint>
#include <filesystem>
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);
using SceneAssetOpenRequestFn = bool (*)(
void*,
const std::filesystem::path&);
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* sceneAssetOpenRequester = nullptr;
SceneAssetOpenRequestFn requestOpenSceneAsset = nullptr;
void RequestOpenUtilityWindow(EditorUtilityWindowKind kind) const {
if (requestUtilityWindow != nullptr) {
requestUtilityWindow(utilityWindowRequester, kind);
}
}
bool RequestOpenSceneAsset(const std::filesystem::path& scenePath) const {
return requestOpenSceneAsset != nullptr &&
requestOpenSceneAsset(sceneAssetOpenRequester, scenePath);
}
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,5 @@
#pragma once
#include "Panels/EditorPanelServices.h"
#include "Windowing/EditorWindowTypes.h"
#include <XCEngine/UI/DrawData.h>
@@ -14,6 +13,8 @@
namespace XCEngine::UI::Editor::App {
class EditorFrameServices;
enum class EditorUtilityWindowKind : std::uint8_t {
None = 0,
ColorPicker,
@@ -52,7 +53,7 @@ public:
virtual std::string_view GetDrawListId() const = 0;
virtual void ResetInteractionState() = 0;
virtual void Update(
EditorPanelServices& services,
EditorFrameServices& frameServices,
const EditorUtilityWindowHostContext& hostContext,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) = 0;
virtual void Append(::XCEngine::UI::UIDrawList& drawList) const = 0;

View File

@@ -1,6 +1,5 @@
#pragma once
#include "Panels/EditorPanelServices.h"
#include "UtilityWindows/EditorUtilityWindowRuntime.h"
#include "Windowing/EditorShellVariant.h"
#include "WorkspacePanels/EditorWorkspacePanelRuntime.h"
@@ -10,14 +9,26 @@
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <optional>
#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor::System {
class SystemInteractionService;
} // namespace XCEngine::UI::Editor::System
namespace XCEngine::UI::Editor::App {
class EditorEditCommandRoute;
class EditorCommandFocusService;
class EditorProjectRuntime;
class EditorSceneRuntime;
class EditorSceneViewportRuntime;
struct EditorColorPickerToolState;
struct EditorSession;
struct WorkspaceTraceEntry {
std::string channel = {};
@@ -37,13 +48,26 @@ public:
EditorEditCommandRoute* projectRoute,
EditorEditCommandRoute* sceneRoute,
EditorEditCommandRoute* inspectorRoute) = 0;
virtual const EditorSession& GetSession() const = 0;
virtual EditorCommandFocusService& GetCommandFocusService() = 0;
virtual const EditorCommandFocusService& GetCommandFocusService() const = 0;
virtual EditorProjectRuntime& GetProjectRuntime() = 0;
virtual const EditorProjectRuntime& GetProjectRuntime() const = 0;
virtual EditorSceneRuntime& GetSceneRuntime() = 0;
virtual const EditorSceneRuntime& GetSceneRuntime() const = 0;
virtual EditorColorPickerToolState& GetColorPickerToolState() = 0;
virtual const EditorColorPickerToolState& GetColorPickerToolState() const = 0;
virtual System::SystemInteractionService* GetSystemInteractionHost() = 0;
virtual const System::SystemInteractionService* GetSystemInteractionHost() const = 0;
virtual const UIEditorTextMeasurer* GetTextMeasurer() const = 0;
virtual void RequestOpenUtilityWindow(EditorUtilityWindowKind kind) = 0;
virtual bool RequestOpenSceneAsset(const std::filesystem::path& scenePath) = 0;
virtual void SyncSessionFromWorkspace(
const UIEditorWorkspaceController& workspaceController) = 0;
virtual void SyncSessionFromCommandFocusService() = 0;
virtual void TickEditorRuntime() = 0;
virtual const UIEditorShellInteractionServices& GetShellServices() const = 0;
virtual EditorPanelServices BuildPanelServices() = 0;
virtual UIEditorShellInteractionDefinition BuildShellDefinition(
const UIEditorWorkspaceController& workspaceController,
std::string_view captureText,

View File

@@ -51,10 +51,10 @@ void EditorWorkspacePanelRuntimeSet::ResetInteractionState() {
}
void EditorWorkspacePanelRuntimeSet::PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController& workspaceController) {
for (const std::unique_ptr<EditorWorkspacePanel>& panel : m_panels) {
panel->PrepareForShellDefinition(services, workspaceController);
panel->PrepareForShellDefinition(frameServices, workspaceController);
}
}

View File

@@ -3,9 +3,8 @@
#include "Assets/EditorIconService.h"
#include "Commands/EditorEditCommandRoute.h"
#include "Environment/EditorRuntimePaths.h"
#include "State/EditorSession.h"
#include "Panels/EditorPanelServices.h"
#include "Viewport/EditorViewportRuntimeServices.h"
#include "State/EditorSession.h"
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEditor/Panels/UIEditorHostedPanelDispatch.h>
@@ -29,6 +28,8 @@ struct UIInputEvent;
namespace XCEngine::UI::Editor::App {
class EditorFrameServices;
enum class EditorWorkspacePanelCursorKind : std::uint8_t {
Arrow = 0,
ResizeEW
@@ -55,7 +56,7 @@ struct EditorWorkspacePanelInitializationContext {
struct EditorWorkspacePanelShutdownContext {};
struct EditorWorkspacePanelUpdateContext {
EditorPanelServices& services;
EditorFrameServices& frameServices;
UIEditorShellInteractionFrame& shellFrame;
UIEditorShellInteractionState& shellInteractionState;
const std::vector<::XCEngine::UI::UIInputEvent>& hostedContentEvents;
@@ -73,9 +74,9 @@ public:
virtual void Shutdown(const EditorWorkspacePanelShutdownContext&) {}
virtual void ResetInteractionState() {}
virtual void PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController& workspaceController) {
(void)services;
(void)frameServices;
(void)workspaceController;
}
virtual EditorWorkspacePanelUpdatePhase GetUpdatePhase() const {
@@ -113,7 +114,7 @@ public:
void Shutdown(const EditorWorkspacePanelShutdownContext& context);
void ResetInteractionState();
void PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController& workspaceController);
void UpdatePhase(
const EditorWorkspacePanelUpdateContext& context,

View File

@@ -1,6 +1,6 @@
#include "ColorPickerPanel.h"
#include "Panels/EditorPanelServices.h"
#include "Windowing/EditorFrameServices.h"
#include "State/EditorColorPickerToolState.h"
#include <XCEditor/Fields/UIEditorFieldStyle.h>
@@ -88,7 +88,7 @@ void ColorPickerPanel::ResetInteractionState() {
}
void ColorPickerPanel::Update(
EditorPanelServices& services,
EditorFrameServices& frameServices,
const EditorUtilityWindowHostContext& hostContext,
const std::vector<UIInputEvent>& inputEvents) {
if (!hostContext.mounted) {
@@ -101,7 +101,7 @@ void ColorPickerPanel::Update(
m_metrics = BuildColorPickerPanelMetrics(m_bounds);
m_palette = BuildColorPickerPanelPalette();
EditorColorPickerToolState& toolState = services.colorPickerToolState;
EditorColorPickerToolState& toolState = frameServices.GetColorPickerToolState();
m_hasActiveTarget =
toolState.active &&
!toolState.inspectorTarget.subjectKey.empty() &&

View File

@@ -15,7 +15,7 @@ public:
}
void ResetInteractionState() override;
void Update(
EditorPanelServices& services,
EditorFrameServices& frameServices,
const EditorUtilityWindowHostContext& hostContext,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override;
void Append(::XCEngine::UI::UIDrawList& drawList) const override;

View File

@@ -9,9 +9,11 @@
#include "Scene/SceneEditCommandRoute.h"
#include "Scene/SceneViewportFeature.h"
#include "Product/EditorProductManifest.h"
#include "Windowing/EditorFrameServices.h"
#include <XCEditor/Panels/UIEditorHostedPanelDispatch.h>
#include <filesystem>
#include <memory>
#include <sstream>
@@ -26,6 +28,22 @@ constexpr int kProjectUpdatePriority = 20;
constexpr int kInspectorUpdatePriority = 30;
constexpr int kConsoleUpdatePriority = 40;
void RequestUtilityWindowFromFrameServices(
void* requester,
EditorUtilityWindowKind kind) {
auto* frameServices = static_cast<EditorFrameServices*>(requester);
if (frameServices != nullptr) {
frameServices->RequestOpenUtilityWindow(kind);
}
}
bool RequestSceneAssetFromFrameServices(
void* requester,
const std::filesystem::path& scenePath) {
auto* frameServices = static_cast<EditorFrameServices*>(requester);
return frameServices != nullptr && frameServices->RequestOpenSceneAsset(scenePath);
}
const UIEditorHostedPanelDispatchEntry& ResolveHostedPanelDispatchEntry(
const UIEditorHostedPanelDispatchFrame& dispatchFrame,
std::string_view panelId) {
@@ -187,7 +205,7 @@ public:
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.Update(
context.services.session,
context.frameServices.GetSession(),
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()));
@@ -230,10 +248,10 @@ public:
}
void PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController&) override {
m_panel.SetSceneRuntime(&services.sceneRuntime);
m_panel.SetCommandFocusService(&services.commandFocusService);
m_panel.SetSceneRuntime(&frameServices.GetSceneRuntime());
m_panel.SetCommandFocusService(&frameServices.GetCommandFocusService());
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
@@ -291,9 +309,18 @@ public:
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.SetCommandFocusService(&context.services.commandFocusService);
m_panel.SetCommandFocusService(&context.frameServices.GetCommandFocusService());
InspectorPanelContext panelContext{
.session = context.frameServices.GetSession(),
.projectRuntime = context.frameServices.GetProjectRuntime(),
.sceneRuntime = context.frameServices.GetSceneRuntime(),
.colorPickerToolState = context.frameServices.GetColorPickerToolState(),
.textMeasurer = context.frameServices.GetTextMeasurer(),
.utilityWindowRequester = &context.frameServices,
.requestUtilityWindow = RequestUtilityWindowFromFrameServices,
};
m_panel.Update(
context.services,
panelContext,
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()),
@@ -340,12 +367,12 @@ public:
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.SetProjectRuntime(&context.services.projectRuntime);
m_panel.SetCommandFocusService(&context.services.commandFocusService);
m_panel.SetSystemInteractionHost(context.services.systemInteractionHost);
m_panel.SetProjectRuntime(&context.frameServices.GetProjectRuntime());
m_panel.SetCommandFocusService(&context.frameServices.GetCommandFocusService());
m_panel.SetSystemInteractionHost(context.frameServices.GetSystemInteractionHost());
m_panel.SetSceneAssetOpenRequestHandler(
context.services.sceneAssetOpenRequester,
context.services.requestOpenSceneAsset);
&context.frameServices,
RequestSceneAssetFromFrameServices);
m_panel.Update(
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
@@ -428,16 +455,16 @@ public:
}
void PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController&) override {
m_commandRoute.BindSceneRuntime(&services.sceneRuntime);
m_feature.SetCommandFocusService(&services.commandFocusService);
m_feature.SyncRenderRequest(services.sceneRuntime);
m_commandRoute.BindSceneRuntime(&frameServices.GetSceneRuntime());
m_feature.SetCommandFocusService(&frameServices.GetCommandFocusService());
m_feature.SyncRenderRequest(frameServices.GetSceneRuntime());
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_feature.Update(
context.services.sceneRuntime,
context.frameServices.GetSceneRuntime(),
context.shellInteractionState.workspaceInteractionState.composeState,
context.shellFrame.workspaceInteractionFrame.composeFrame);
}
@@ -483,9 +510,9 @@ public:
}
void PrepareForShellDefinition(
EditorPanelServices& services,
EditorFrameServices& frameServices,
UIEditorWorkspaceController&) override {
m_feature.SetCommandFocusService(&services.commandFocusService);
m_feature.SetCommandFocusService(&frameServices.GetCommandFocusService());
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {

View File

@@ -1,8 +1,9 @@
#include "Inspector/AddComponentPanel.h"
#include "Panels/EditorPanelServices.h"
#include "Inspector/Components/IInspectorComponentEditor.h"
#include "Inspector/Components/InspectorComponentEditorRegistry.h"
#include "Scene/EditorSceneRuntime.h"
#include "Windowing/EditorFrameServices.h"
#include <XCEditor/Fields/UIEditorFieldStyle.h>
@@ -123,7 +124,7 @@ void AddComponentPanel::RebuildEntries(
}
bool AddComponentPanel::TryActivateEntry(
EditorPanelServices& services,
EditorSceneRuntime& sceneRuntime,
std::size_t entryIndex) {
if (entryIndex >= m_entries.size()) {
return false;
@@ -134,14 +135,14 @@ bool AddComponentPanel::TryActivateEntry(
return false;
}
if (!services.sceneRuntime.AddComponentToSelectedGameObject(entry.componentTypeName)) {
if (!sceneRuntime.AddComponentToSelectedGameObject(entry.componentTypeName)) {
return false;
}
const std::optional<EditorSceneObjectSnapshot> selectedObject =
services.sceneRuntime.GetSelectedObjectSnapshot();
sceneRuntime.GetSelectedObjectSnapshot();
m_hasTarget = selectedObject.has_value();
m_targetDisplayName = services.sceneRuntime.GetSelectedDisplayName();
m_targetDisplayName = sceneRuntime.GetSelectedDisplayName();
RebuildEntries(selectedObject.has_value() ? &selectedObject.value() : nullptr);
return true;
}
@@ -157,7 +158,7 @@ std::size_t AddComponentPanel::HitTestEntry(const UIPoint& point) const {
}
void AddComponentPanel::Update(
EditorPanelServices& services,
EditorFrameServices& frameServices,
const EditorUtilityWindowHostContext& hostContext,
const std::vector<UIInputEvent>& inputEvents) {
if (!hostContext.mounted) {
@@ -165,12 +166,13 @@ void AddComponentPanel::Update(
return;
}
EditorSceneRuntime& sceneRuntime = frameServices.GetSceneRuntime();
m_visible = true;
m_bounds = hostContext.bounds;
const std::optional<EditorSceneObjectSnapshot> selectedObject =
services.sceneRuntime.GetSelectedObjectSnapshot();
sceneRuntime.GetSelectedObjectSnapshot();
m_hasTarget = selectedObject.has_value();
m_targetDisplayName = services.sceneRuntime.GetSelectedDisplayName();
m_targetDisplayName = sceneRuntime.GetSelectedDisplayName();
RebuildEntries(selectedObject.has_value() ? &selectedObject.value() : nullptr);
if (hostContext.focusLost) {
@@ -209,7 +211,7 @@ void AddComponentPanel::Update(
m_hoveredEntryIndex = HitTestEntry(event.position);
if (m_pressedEntryIndex != kInvalidEntryIndex &&
m_pressedEntryIndex == m_hoveredEntryIndex) {
TryActivateEntry(services, m_pressedEntryIndex);
TryActivateEntry(sceneRuntime, m_pressedEntryIndex);
}
m_pressedEntryIndex = kInvalidEntryIndex;
break;

View File

@@ -9,6 +9,8 @@
namespace XCEngine::UI::Editor::App {
class EditorSceneRuntime;
class AddComponentPanel final : public EditorUtilityWindowPanel {
public:
std::string_view GetDrawListId() const override {
@@ -16,7 +18,7 @@ public:
}
void ResetInteractionState() override;
void Update(
EditorPanelServices& services,
EditorFrameServices& frameServices,
const EditorUtilityWindowHostContext& hostContext,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override;
void Append(::XCEngine::UI::UIDrawList& drawList) const override;
@@ -32,7 +34,7 @@ private:
void ResetPanelState();
void RebuildEntries(const EditorSceneObjectSnapshot* gameObject);
bool TryActivateEntry(EditorPanelServices& services, std::size_t entryIndex);
bool TryActivateEntry(EditorSceneRuntime& sceneRuntime, std::size_t entryIndex);
std::size_t HitTestEntry(const ::XCEngine::UI::UIPoint& point) const;
bool m_visible = false;

View File

@@ -1,6 +1,5 @@
#include "InspectorPanel.h"
#include "Panels/EditorPanelServices.h"
#include "UtilityWindows/EditorUtilityWindowRuntime.h"
#include "State/EditorColorPickerToolState.h"
#include "Inspector/InspectorFieldValueApplier.h"
@@ -450,36 +449,36 @@ Widgets::UIEditorPropertyGridField* InspectorPanel::FindMutableField(
}
void InspectorPanel::CapturePresentationStamps(
const EditorPanelServices& services) {
m_lastSceneSelectionStamp = services.sceneRuntime.GetSelectionStamp();
m_lastProjectSelectionStamp = services.projectRuntime.GetSelectionStamp();
m_lastSceneInspectorRevision = services.sceneRuntime.GetInspectorRevision();
const InspectorPanelContext& context) {
m_lastSceneSelectionStamp = context.sceneRuntime.GetSelectionStamp();
m_lastProjectSelectionStamp = context.projectRuntime.GetSelectionStamp();
m_lastSceneInspectorRevision = context.sceneRuntime.GetInspectorRevision();
}
void InspectorPanel::RebuildPresentation(
EditorPanelServices& services,
InspectorPanelContext& context,
bool subjectChanged) {
m_presentation = BuildInspectorPresentationModel(
m_subject,
services.sceneRuntime,
context.sceneRuntime,
InspectorComponentEditorRegistry::Get());
CapturePresentationStamps(services);
CapturePresentationStamps(context);
SyncExpansionState(subjectChanged);
SyncSelectionState();
}
void InspectorPanel::ForceResyncPresentation(EditorPanelServices& services) {
void InspectorPanel::ForceResyncPresentation(InspectorPanelContext& context) {
if (m_subject.kind != InspectorSubjectKind::SceneObject) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
const std::string structureSignature = BuildInspectorStructureSignature(
m_subject,
services.sceneRuntime,
context.sceneRuntime,
InspectorComponentEditorRegistry::Get());
if (structureSignature != m_presentation.structureSignature) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
@@ -487,38 +486,38 @@ void InspectorPanel::ForceResyncPresentation(EditorPanelServices& services) {
SyncInspectorPresentationModelValues(
m_presentation,
m_subject,
services.sceneRuntime,
context.sceneRuntime,
InspectorComponentEditorRegistry::Get());
if (!syncResult.success) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
m_presentation.structureSignature = structureSignature;
CapturePresentationStamps(services);
CapturePresentationStamps(context);
SyncSelectionState();
}
void InspectorPanel::RefreshPresentation(
EditorPanelServices& services,
InspectorPanelContext& context,
bool subjectChanged) {
if (subjectChanged) {
RebuildPresentation(services, true);
RebuildPresentation(context, true);
return;
}
switch (m_subject.kind) {
case InspectorSubjectKind::ProjectAsset:
if (m_lastProjectSelectionStamp !=
services.projectRuntime.GetSelectionStamp()) {
RebuildPresentation(services, false);
context.projectRuntime.GetSelectionStamp()) {
RebuildPresentation(context, false);
}
return;
case InspectorSubjectKind::SceneObject: {
const EditorSceneRuntime& sceneRuntime = services.sceneRuntime;
const EditorSceneRuntime& sceneRuntime = context.sceneRuntime;
if (m_lastSceneSelectionStamp != sceneRuntime.GetSelectionStamp()) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
@@ -531,7 +530,7 @@ void InspectorPanel::RefreshPresentation(
sceneRuntime,
InspectorComponentEditorRegistry::Get());
if (structureSignature != m_presentation.structureSignature) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
@@ -542,12 +541,12 @@ void InspectorPanel::RefreshPresentation(
sceneRuntime,
InspectorComponentEditorRegistry::Get());
if (!syncResult.success) {
RebuildPresentation(services, false);
RebuildPresentation(context, false);
return;
}
m_presentation.structureSignature = structureSignature;
CapturePresentationStamps(services);
CapturePresentationStamps(context);
SyncSelectionState();
return;
}
@@ -558,8 +557,8 @@ void InspectorPanel::RefreshPresentation(
}
}
bool InspectorPanel::ApplyColorPickerToolValue(EditorPanelServices& services) {
EditorColorPickerToolState& toolState = services.colorPickerToolState;
bool InspectorPanel::ApplyColorPickerToolValue(InspectorPanelContext& context) {
EditorColorPickerToolState& toolState = context.colorPickerToolState;
if (m_sceneRuntime == nullptr ||
!toolState.active ||
toolState.revision == m_lastAppliedColorPickerRevision ||
@@ -585,16 +584,16 @@ bool InspectorPanel::ApplyColorPickerToolValue(EditorPanelServices& services) {
const bool applied = ApplyChangedField(field->fieldId);
m_lastAppliedColorPickerRevision = toolState.revision;
if (!applied) {
ForceResyncPresentation(services);
ForceResyncPresentation(context);
return false;
}
RefreshPresentation(services, false);
RefreshPresentation(context, false);
return true;
}
void InspectorPanel::RequestColorPicker(
EditorPanelServices& services,
InspectorPanelContext& context,
std::string_view fieldId) {
const Widgets::UIEditorPropertyGridField* field = FindField(fieldId);
if (field == nullptr ||
@@ -604,12 +603,12 @@ void InspectorPanel::RequestColorPicker(
}
OpenEditorColorPickerToolForInspectorField(
services.colorPickerToolState,
context.colorPickerToolState,
m_subjectKey,
field->fieldId,
field->colorValue.value,
field->colorValue.showAlpha);
services.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker);
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker);
}
void InspectorPanel::ResetAddComponentButtonState() {
@@ -618,7 +617,7 @@ void InspectorPanel::ResetAddComponentButtonState() {
}
void InspectorPanel::UpdateAddComponentButton(
EditorPanelServices& services,
InspectorPanelContext& context,
const std::vector<UIInputEvent>& inputEvents) {
if (!ShouldShowAddComponentButton()) {
ResetAddComponentButtonState();
@@ -659,7 +658,7 @@ void InspectorPanel::UpdateAddComponentButton(
if (m_addComponentButtonPressed &&
ContainsPoint(buttonRect, event.position)) {
services.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent);
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent);
}
m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position);
@@ -711,7 +710,7 @@ bool InspectorPanel::ApplyChangedField(std::string_view fieldId) {
}
void InspectorPanel::Update(
EditorPanelServices& services,
InspectorPanelContext& context,
const UIEditorHostedPanelDispatchEntry& dispatchEntry,
const std::vector<UIInputEvent>& inputEvents) {
if (!dispatchEntry.mounted) {
@@ -721,9 +720,9 @@ void InspectorPanel::Update(
m_visible = true;
m_bounds = dispatchEntry.bounds;
m_sceneRuntime = &services.sceneRuntime;
m_textMeasurer = services.textMeasurer;
m_subject = BuildInspectorSubject(services.session, services.sceneRuntime);
m_sceneRuntime = &context.sceneRuntime;
m_textMeasurer = context.textMeasurer;
m_subject = BuildInspectorSubject(context.session, context.sceneRuntime);
const std::string nextSubjectKey = BuildSubjectKey();
const bool subjectChanged = m_subjectKey != nextSubjectKey;
@@ -732,8 +731,8 @@ void InspectorPanel::Update(
ResetInteractionState();
}
RefreshPresentation(services, subjectChanged);
ApplyColorPickerToolValue(services);
RefreshPresentation(context, subjectChanged);
ApplyColorPickerToolValue(context);
const std::vector<UIInputEvent> filteredEvents =
BuildUIEditorPanelInputEvents(
@@ -802,21 +801,21 @@ void InspectorPanel::Update(
m_gridFrame.result = interactionFrame.result;
if (interactionFrame.result.pickerRequested &&
!interactionFrame.result.requestedFieldId.empty()) {
RequestColorPicker(services, interactionFrame.result.requestedFieldId);
RequestColorPicker(context, interactionFrame.result.requestedFieldId);
}
if (interactionFrame.result.fieldValueChanged &&
!interactionFrame.result.changedFieldId.empty()) {
if (ApplyChangedField(interactionFrame.result.changedFieldId)) {
RefreshPresentation(services, false);
RefreshPresentation(context, false);
} else {
ForceResyncPresentation(services);
ForceResyncPresentation(context);
}
}
}
RebuildScrollableLayout();
UpdateAddComponentButton(services, filteredEvents);
UpdateAddComponentButton(context, filteredEvents);
}
void InspectorPanel::Append(UIDrawList& drawList) const {

View File

@@ -22,14 +22,35 @@
namespace XCEngine::UI::Editor::App {
class EditorCommandFocusService;
struct EditorColorPickerToolState;
class EditorProjectRuntime;
class EditorSceneRuntime;
struct EditorPanelServices;
struct EditorSession;
enum class EditorUtilityWindowKind : std::uint8_t;
struct InspectorPanelContext {
using UtilityWindowRequestFn = void (*)(void*, EditorUtilityWindowKind);
const EditorSession& session;
EditorProjectRuntime& projectRuntime;
EditorSceneRuntime& sceneRuntime;
EditorColorPickerToolState& colorPickerToolState;
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr;
void* utilityWindowRequester = nullptr;
UtilityWindowRequestFn requestUtilityWindow = nullptr;
void RequestOpenUtilityWindow(EditorUtilityWindowKind kind) const {
if (requestUtilityWindow != nullptr) {
requestUtilityWindow(utilityWindowRequester, kind);
}
}
};
class InspectorPanel final : public EditorEditCommandRoute {
public:
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);
void Update(
EditorPanelServices& services,
InspectorPanelContext& context,
const UIEditorHostedPanelDispatchEntry& dispatchEntry,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents);
void Append(::XCEngine::UI::UIDrawList& drawList) const;
@@ -58,15 +79,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 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 CapturePresentationStamps(const InspectorPanelContext& context);
void RebuildPresentation(InspectorPanelContext& context, bool subjectChanged);
void RefreshPresentation(InspectorPanelContext& context, bool subjectChanged);
void ForceResyncPresentation(InspectorPanelContext& context);
bool ApplyColorPickerToolValue(InspectorPanelContext& context);
void RequestColorPicker(InspectorPanelContext& context, std::string_view fieldId);
void ResetAddComponentButtonState();
void UpdateAddComponentButton(
EditorPanelServices& services,
InspectorPanelContext& context,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents);
bool ApplyChangedField(std::string_view fieldId);

View File

@@ -67,9 +67,8 @@ EditorUtilityWindowContentController::UpdateAndAppend(
return {};
}
EditorPanelServices services = context.frameServices.BuildPanelServices();
m_panel->Update(
services,
context.frameServices,
EditorUtilityWindowHostContext{
.mounted = true,
.bounds = context.bounds,