From af5690395ddd2f97a8b3a06b7729eb8008aacb4a Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Thu, 23 Apr 2026 14:11:33 +0800 Subject: [PATCH] Refactor new_editor window architecture and routing --- ...abilityRefactorPlan_完成归档_2026-04-23.md | 168 +++++++ new_editor/CMakeLists.txt | 42 +- new_editor/app/Bootstrap/Application.cpp | 12 +- new_editor/app/Bootstrap/Application.h | 6 +- new_editor/app/Composition/EditorContext.cpp | 6 +- new_editor/app/Composition/EditorContext.h | 13 +- .../app/Composition/EditorShellRuntime.cpp | 8 +- .../app/Composition/EditorShellRuntime.h | 14 +- .../EditorWindowWorkspaceStore.cpp | 188 +------- .../Composition/EditorWindowWorkspaceStore.h | 28 -- .../Features/ColorPicker/ColorPickerPanel.cpp | 2 +- .../Features/ColorPicker/ColorPickerPanel.h | 29 +- .../Features/Inspector/AddComponentPanel.cpp | 2 +- .../Features/Inspector/AddComponentPanel.h | 25 +- .../InspectorBindingComponentEditor.cpp | 1 + .../InspectorBindingComponentEditor.h | 1 + .../InspectorComponentEditorUtils.h | 11 + .../TransformInspectorComponentEditor.cpp | 6 +- .../Inspector/InspectorPresentationModel.cpp | 1 + .../app/Features/Project/ProjectPanel.cpp | 75 ++- .../app/Features/Project/ProjectPanel.h | 10 +- .../Scene/SceneViewportController.cpp | 4 +- .../Features/Scene/SceneViewportController.h | 10 +- .../Features/Scene/SceneViewportFeature.cpp | 6 +- .../app/Features/Scene/SceneViewportFeature.h | 10 +- .../Scene/SceneViewportToolOverlay.cpp | 6 +- .../Features/Scene/SceneViewportToolOverlay.h | 6 +- .../Chrome/EditorWindowChromeController.cpp | 57 +-- .../Chrome/EditorWindowChromeController.h | 4 +- ...omponentUtilityWindowContentController.cpp | 51 --- ...dComponentUtilityWindowContentController.h | 31 -- ...orPickerUtilityWindowContentController.cpp | 52 --- ...olorPickerUtilityWindowContentController.h | 31 -- ...andaloneUtilityWindowContentController.cpp | 81 ---- .../EditorUtilityWindowContentController.cpp | 103 +++++ ...=> EditorUtilityWindowContentController.h} | 34 +- .../Content/EditorWindowContentController.h | 118 ++--- ...EditorWorkspaceWindowContentController.cpp | 40 +- .../EditorWorkspaceWindowContentController.h | 20 +- .../Win32/Runtime/EditorWindowFrameDriver.cpp | 6 +- .../Win32/Runtime/EditorWindowFrameDriver.h | 2 +- .../Runtime/EditorWindowFrameOrchestrator.cpp | 4 +- .../Runtime/EditorWindowFrameOrchestrator.h | 2 +- .../Runtime/EditorWindowInputController.cpp | 2 +- .../Runtime/EditorWindowInputController.h | 4 +- .../Runtime/EditorWindowRuntimeController.cpp | 127 ++---- .../Runtime/EditorWindowRuntimeController.h | 35 +- .../EditorWindowScreenshotController.cpp | 2 +- .../System/Win32SystemInteractionHost.cpp | 2 +- .../Win32/System/Win32SystemInteractionHost.h | 4 +- .../EditorFloatingWindowPlacement.cpp | 2 +- .../EditorUtilityWindowCoordinator.cpp | 17 +- .../EditorUtilityWindowCoordinator.h | 2 +- .../Platform/Win32/Windowing/EditorWindow.cpp | 340 +++----------- .../Platform/Win32/Windowing/EditorWindow.h | 85 +--- .../Windowing/EditorWindowHostRuntime.cpp | 16 +- .../Win32/Windowing/EditorWindowHostRuntime.h | 2 +- .../EditorWindowLifecycleCoordinator.cpp | 8 +- .../Win32/Windowing/EditorWindowManager.cpp | 16 +- .../EditorWindowMessageDispatcher.cpp | 159 ++++--- .../Windowing/EditorWindowMessageDispatcher.h | 4 +- .../Windowing/EditorWindowTransferRequests.h | 2 +- .../EditorWindowWorkspaceCoordinator.cpp | 29 +- .../EditorWindowWorkspaceCoordinator.h | 2 +- new_editor/app/Ports/PortFwd.h | 10 - .../ShaderResourceDescriptorAllocatorPort.h | 31 -- .../app/Rendering/Assets/BuiltInIcons.cpp | 6 +- .../app/Rendering/Assets/BuiltInIcons.h | 6 +- .../D3D12ShaderResourceDescriptorAllocator.h | 15 +- .../app/Rendering/D3D12/D3D12UiTextSystem.cpp | 38 ++ .../app/Rendering/D3D12/D3D12UiTextSystem.h | 2 + .../app/Rendering/D3D12/D3D12UiTextureHost.h | 4 +- .../app/Rendering/D3D12/D3D12WindowRenderer.h | 4 +- new_editor/app/Rendering/Host/HostFwd.h | 8 + .../Host/UiTextureHost.h} | 8 +- .../Host/ViewportRenderHost.h} | 12 +- .../Viewport/ViewportHostService.cpp | 76 +++- .../Rendering/Viewport/ViewportHostService.h | 11 +- .../Viewport/ViewportRenderTargets.cpp | 11 +- .../Viewport/ViewportRenderTargets.h | 8 +- .../State/EditorUtilityWindowRequestState.h | 2 +- new_editor/app/Support/EmbeddedPngLoader.cpp | 4 +- new_editor/app/Support/EmbeddedPngLoader.h | 4 +- .../SystemInteractionService.h} | 8 +- .../EditorUtilityWindowKind.h | 0 .../UtilityWindows/EditorUtilityWindowPanel.h | 34 ++ .../EditorUtilityWindowRegistry.cpp | 22 +- .../EditorUtilityWindowRegistry.h | 7 +- .../XCEditor/Fields/UIEditorAssetField.h | 2 +- .../XCEditor/Fields/UIEditorBoolField.h | 2 +- .../XCEditor/Fields/UIEditorColorField.h | 2 +- .../Fields/UIEditorEditableFieldCore.h | 3 + .../XCEditor/Fields/UIEditorEnumField.h | 2 +- .../XCEditor/Fields/UIEditorNumberField.h | 2 +- .../XCEditor/Fields/UIEditorObjectField.h | 2 +- .../XCEditor/Fields/UIEditorPropertyGrid.h | 2 +- .../XCEditor/Fields/UIEditorTextField.h | 2 +- .../XCEditor/Fields/UIEditorVector2Field.h | 2 +- .../XCEditor/Fields/UIEditorVector3Field.h | 2 +- .../XCEditor/Fields/UIEditorVector4Field.h | 2 +- .../Foundation/UIEditorTextMeasurement.h | 4 + .../XCEditor/Widgets/UIEditorFieldRowLayout.h | 2 +- .../XCEditor/Widgets/UIEditorTextLayout.h | 14 +- .../UIEditorFilterableTreeHost.cpp | 10 +- new_editor/src/Fields/ColorFieldRendering.cpp | 40 +- .../Fields/PropertyGridInteractionInternal.h | 28 ++ new_editor/src/Fields/UIEditorAssetField.cpp | 2 +- new_editor/src/Fields/UIEditorBoolField.cpp | 2 +- new_editor/src/Fields/UIEditorColorField.cpp | 2 +- .../src/Fields/UIEditorEditableFieldCore.cpp | 5 + new_editor/src/Fields/UIEditorEnumField.cpp | 18 +- new_editor/src/Fields/UIEditorFieldStyle.cpp | 12 +- new_editor/src/Fields/UIEditorNumberField.cpp | 9 +- .../Fields/UIEditorNumberFieldInteraction.cpp | 2 +- new_editor/src/Fields/UIEditorObjectField.cpp | 2 +- .../src/Fields/UIEditorPropertyGrid.cpp | 91 +++- .../UIEditorPropertyGridInteraction.cpp | 427 +++++++++++++++--- new_editor/src/Fields/UIEditorTextField.cpp | 9 +- .../Fields/UIEditorTextFieldInteraction.cpp | 6 + .../src/Fields/UIEditorVectorFieldShared.h | 8 +- .../src/Widgets/UIEditorFieldRowLayout.cpp | 4 +- 121 files changed, 1647 insertions(+), 1592 deletions(-) create mode 100644 docs/used/NewEditor_ContentCapabilityRefactorPlan_完成归档_2026-04-23.md delete mode 100644 new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.cpp delete mode 100644 new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.h delete mode 100644 new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.cpp delete mode 100644 new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.h delete mode 100644 new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.cpp create mode 100644 new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp rename new_editor/app/Platform/Win32/Content/{EditorStandaloneUtilityWindowContentController.h => EditorUtilityWindowContentController.h} (52%) delete mode 100644 new_editor/app/Ports/PortFwd.h delete mode 100644 new_editor/app/Ports/ShaderResourceDescriptorAllocatorPort.h create mode 100644 new_editor/app/Rendering/Host/HostFwd.h rename new_editor/app/{Ports/TexturePort.h => Rendering/Host/UiTextureHost.h} (82%) rename new_editor/app/{Ports/ViewportRenderPort.h => Rendering/Host/ViewportRenderHost.h} (57%) rename new_editor/app/{Ports/SystemInteractionPort.h => System/SystemInteractionService.h} (60%) rename new_editor/app/{Platform/Win32/Content => UtilityWindows}/EditorUtilityWindowKind.h (100%) create mode 100644 new_editor/app/UtilityWindows/EditorUtilityWindowPanel.h rename new_editor/app/{Platform/Win32/Content => UtilityWindows}/EditorUtilityWindowRegistry.cpp (66%) rename new_editor/app/{Platform/Win32/Content => UtilityWindows}/EditorUtilityWindowRegistry.h (76%) diff --git a/docs/used/NewEditor_ContentCapabilityRefactorPlan_完成归档_2026-04-23.md b/docs/used/NewEditor_ContentCapabilityRefactorPlan_完成归档_2026-04-23.md new file mode 100644 index 00000000..41416216 --- /dev/null +++ b/docs/used/NewEditor_ContentCapabilityRefactorPlan_完成归档_2026-04-23.md @@ -0,0 +1,168 @@ +# NewEditor Content Capability Refactor Plan + +Date: 2026-04-23 +Status: Completed + +## 1. Objective + +Refactor the `new_editor/app/Platform/Win32` window-content boundary so that optional behaviors are expressed as explicit capabilities instead of being stuffed into one fat `EditorWindowContentController` interface. + +This plan targets the most severe remaining architecture issue in Win32: + +1. `EditorWindowContentController` currently mixes base rendering lifecycle, workspace mutation, dock-host interaction, capture/cursor feedback, and title-bar policy in one interface. +2. `EditorWindowRuntimeController` mirrors that bloated surface almost one-to-one, so every optional behavior is forwarded twice before it reaches real implementation. +3. Workspace content implements nearly the entire interface, while utility content implements only a thin subset and inherits a large set of meaningless default methods. + +The goal is to stop capability sprawl at the root instead of continuing to delete wrappers one file at a time. + +## 2. Confirmed Root Cause + +The current layering drift is: + +1. `EditorWindowContentController` acts as both: + - mandatory window-content contract + - optional capability registry +2. `EditorWindowRuntimeController` repeats those same optional operations as direct forwarding methods. +3. Callers such as: + - `EditorWindow` + - `EditorWindowMessageDispatcher` + - `EditorWindowWorkspaceCoordinator` + - `EditorWindowChromeController` + consume the mirrored runtime API instead of consuming small, explicit capability contracts. + +That creates two kinds of redundancy: + +1. interface redundancy: + optional methods live on a base type that many implementations do not meaningfully support +2. forwarding redundancy: + runtime methods exist only to forward a single optional call to content + +## 3. Target End State + +After the refactor: + +1. `EditorWindowContentController` keeps only mandatory content lifecycle and frame responsibilities. +2. Optional behaviors become explicit capability interfaces: + - workspace binding + - dock-host interaction + - input/capture feedback + - title-bar presentation policy +3. `EditorWindowRuntimeController` exposes capability lookup, not one forwarding method per optional behavior. +4. Win32 callers use those capability interfaces directly and apply local fallback behavior when a capability is absent. + +## 4. Capability Split + +### 4.1 Mandatory base contract + +Keep in `EditorWindowContentController` only behavior that every content implementation must provide: + +1. initialize / shutdown / reset +2. viewport presentation enablement +3. frame update and viewport render +4. shell frame and shell interaction state +5. minimum outer size + +### 4.2 Optional capability contracts + +Introduce explicit optional interfaces: + +1. `EditorWindowWorkspaceBinding` + - already exists +2. `EditorWindowDockHostBinding` + - external dock preview + - dock tab drag hotspot + - dock drop target resolution +3. `EditorWindowInputFeedbackBinding` + - hosted content capture + - shell capture + - generic interactive capture + - hosted content cursor + - dock cursor +4. `EditorWindowTitleBarBinding` + - detached title-bar tab strip policy + - detached tab title resolution + - detached window title resolution + +## 5. Execution Phases + +### Phase A. Introduce capability interfaces + +1. Extend `EditorWindowContentController.h` with the new capability types. +2. Replace optional default methods on the base class with `TryGet...Binding()` queries. + +### Phase B. Move workspace content onto explicit capabilities + +1. Make `EditorWorkspaceWindowContentController` implement: + - `EditorWindowDockHostBinding` + - `EditorWindowInputFeedbackBinding` + - `EditorWindowTitleBarBinding` +2. Keep utility-window content minimal; it should not implement capabilities it does not need. + +### Phase C. Shrink runtime surface + +1. Delete mirrored forwarding methods from `EditorWindowRuntimeController` for: + - dock preview / hotspot / drop target + - capture feedback / cursor feedback + - title-bar policy helpers +2. Replace them with capability accessors. + +### Phase D. Update Win32 callers + +Update callers to query the capability they actually need: + +1. `EditorWindow` +2. `EditorWindowMessageDispatcher` +3. `EditorWindowWorkspaceCoordinator` +4. `EditorWindowChromeController` + +Each caller must own its fallback behavior instead of assuming every content type supports everything. + +### Phase E. Validate + +1. build `XCUIEditorApp` +2. confirm no stale content/runtime forwarding methods remain +3. confirm utility-window content still compiles without fake overrides + +## 6. Concrete File Plan + +### Files to update + +1. `new_editor/app/Platform/Win32/Content/EditorWindowContentController.h` +2. `new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.h` +3. `new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp` +4. `new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.h` +5. `new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp` +6. `new_editor/app/Platform/Win32/Windowing/EditorWindow.cpp` +7. `new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp` +8. `new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp` +9. `new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp` + +## 7. Validation Criteria + +The refactor is only considered correct if all of the following are true: + +1. optional content behaviors are no longer declared as default no-op methods on the main base class +2. runtime no longer mirrors those same optional methods one-by-one +3. callers consume explicit capability types +4. the editor build still reaches at least the same link stage as before the refactor + +## 8. Non-Goals + +This plan does not include: + +1. removing `EditorWindowManager` +2. splitting `EditorWindowWorkspaceCoordinator` +3. merging steady-state and immediate frame finalization flows +4. changing utility-window feature behavior + +## 9. Completion Notes + +Completed on: 2026-04-23 + +Validation result: + +1. `EditorWindowContentController` no longer carries the old default no-op optional behavior surface. +2. `EditorWindowRuntimeController` no longer mirrors those optional behaviors as one-by-one forwarding methods. +3. Win32 callers now consume capability bindings instead of the old mirrored runtime helpers. +4. `XCUIEditorApp` builds successfully with: + `cmake --build D:\Xuanchi\Main\XCEngine\build\new_editor --config Debug --target XCUIEditorApp` diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index 048d9f67..26531e8e 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -150,12 +150,12 @@ set(XCUI_EDITOR_SHARED_SOURCES ) set(XCUI_EDITOR_HOST_PLATFORM_SOURCES - app/Platform/Win32/BorderlessWindowChrome.cpp - app/Platform/Win32/BorderlessWindowFrame.cpp + app/Platform/Win32/Chrome/BorderlessWindowChrome.cpp + app/Platform/Win32/Chrome/BorderlessWindowFrame.cpp ) set(XCUI_EDITOR_HOST_RENDERING_SOURCES - app/Platform/Win32/EditorWindowScreenshotController.cpp + app/Platform/Win32/Runtime/EditorWindowScreenshotController.cpp app/Rendering/D3D12/D3D12HostDevice.cpp app/Rendering/D3D12/D3D12WindowCapture.cpp app/Rendering/D3D12/D3D12UiRenderer.cpp @@ -217,6 +217,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) app/Features/Scene/SceneViewportFeature.cpp app/Features/Scene/SceneViewportToolOverlay.cpp app/Features/Scene/SceneViewportController.cpp + app/UtilityWindows/EditorUtilityWindowRegistry.cpp ) set(XCUI_EDITOR_APP_RENDERING_SOURCES @@ -239,25 +240,22 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) ) set(XCUI_EDITOR_APP_PLATFORM_SOURCES - app/Platform/Win32/EditorWindow.cpp - app/Platform/Win32/EditorAddComponentUtilityWindowContentController.cpp - app/Platform/Win32/EditorColorPickerUtilityWindowContentController.cpp - app/Platform/Win32/EditorFloatingWindowPlacement.cpp - app/Platform/Win32/EditorStandaloneUtilityWindowContentController.cpp - app/Platform/Win32/EditorWindowChromeController.cpp - app/Platform/Win32/EditorWindowFrameDriver.cpp - app/Platform/Win32/EditorWindowFrameOrchestrator.cpp - app/Platform/Win32/EditorWindowInputController.cpp - app/Platform/Win32/EditorWindowRuntimeController.cpp - app/Platform/Win32/EditorUtilityWindowRegistry.cpp - app/Platform/Win32/EditorWorkspaceWindowContentController.cpp - app/Platform/Win32/Win32SystemInteractionHost.cpp - app/Platform/Win32/WindowManager/EditorWindowHostRuntime.cpp - app/Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.cpp - app/Platform/Win32/WindowManager/EditorWindowManager.cpp - app/Platform/Win32/WindowManager/EditorWindowMessageDispatcher.cpp - app/Platform/Win32/WindowManager/EditorUtilityWindowCoordinator.cpp - app/Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.cpp + app/Platform/Win32/Windowing/EditorWindow.cpp + app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp + app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp + app/Platform/Win32/Chrome/EditorWindowChromeController.cpp + app/Platform/Win32/Runtime/EditorWindowFrameDriver.cpp + app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.cpp + app/Platform/Win32/Runtime/EditorWindowInputController.cpp + app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp + app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp + app/Platform/Win32/System/Win32SystemInteractionHost.cpp + app/Platform/Win32/Windowing/EditorWindowHostRuntime.cpp + app/Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.cpp + app/Platform/Win32/Windowing/EditorWindowManager.cpp + app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp + app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.cpp + app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp ) set(XCUI_EDITOR_APP_CORE_SOURCES diff --git a/new_editor/app/Bootstrap/Application.cpp b/new_editor/app/Bootstrap/Application.cpp index 345712f4..6ebfdbbe 100644 --- a/new_editor/app/Bootstrap/Application.cpp +++ b/new_editor/app/Bootstrap/Application.cpp @@ -1,11 +1,11 @@ -#include "Bootstrap/Application.h" +#include "Bootstrap/Application.h" #include "Bootstrap/EditorResources.h" -#include "Ports/SystemInteractionPort.h" +#include "System/SystemInteractionService.h" #include "Composition/EditorContext.h" -#include "Platform/Win32/EditorWindowManager.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWorkspaceWindowContentController.h" -#include "Platform/Win32/Win32SystemInteractionHost.h" +#include "Platform/Win32/Windowing/EditorWindowManager.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Content/EditorWorkspaceWindowContentController.h" +#include "Platform/Win32/System/Win32SystemInteractionHost.h" #include "Support/EnvironmentFlags.h" #include "Support/ExecutablePath.h" diff --git a/new_editor/app/Bootstrap/Application.h b/new_editor/app/Bootstrap/Application.h index ceae9d71..f9eed748 100644 --- a/new_editor/app/Bootstrap/Application.h +++ b/new_editor/app/Bootstrap/Application.h @@ -15,8 +15,8 @@ class EditorContext; class EditorWindowManager; } -namespace Ports { -class SystemInteractionPort; +namespace System { +class SystemInteractionService; } } @@ -48,7 +48,7 @@ private: std::filesystem::path m_repoRoot = {}; std::unique_ptr m_editorContext = {}; std::unique_ptr m_windowManager = {}; - std::unique_ptr m_systemInteractionHost = {}; + std::unique_ptr m_systemInteractionHost = {}; }; int RunXCUIEditorApp(HINSTANCE hInstance, int nCmdShow); diff --git a/new_editor/app/Composition/EditorContext.cpp b/new_editor/app/Composition/EditorContext.cpp index 43112a47..843b7a5e 100644 --- a/new_editor/app/Composition/EditorContext.cpp +++ b/new_editor/app/Composition/EditorContext.cpp @@ -93,7 +93,7 @@ void EditorContext::AttachTextMeasurer( m_shellServices.textMeasurer = &textMeasurer; } -void EditorContext::SetSystemInteractionHost(Ports::SystemInteractionPort* systemInteractionHost) { +void EditorContext::SetSystemInteractionHost(System::SystemInteractionService* systemInteractionHost) { m_systemInteractionHost = systemInteractionHost; } @@ -194,11 +194,11 @@ void EditorContext::SyncSessionFromCommandFocusService() { ResolveEditorActionRoute(m_session.activePanelId)); } -Ports::SystemInteractionPort* EditorContext::GetSystemInteractionHost() { +System::SystemInteractionService* EditorContext::GetSystemInteractionHost() { return m_systemInteractionHost; } -const Ports::SystemInteractionPort* EditorContext::GetSystemInteractionHost() const { +const System::SystemInteractionService* EditorContext::GetSystemInteractionHost() const { return m_systemInteractionHost; } diff --git a/new_editor/app/Composition/EditorContext.h b/new_editor/app/Composition/EditorContext.h index c178256d..14b5e1ec 100644 --- a/new_editor/app/Composition/EditorContext.h +++ b/new_editor/app/Composition/EditorContext.h @@ -3,6 +3,7 @@ #include "Composition/EditorShellVariant.h" #include "Project/EditorProjectRuntime.h" #include "Scene/EditorSceneRuntime.h" +#include "UtilityWindows/EditorUtilityWindowKind.h" #include "Commands/EditorHostCommandBridge.h" #include "State/EditorColorPickerToolState.h" @@ -21,8 +22,8 @@ #include #include -namespace XCEngine::UI::Editor::Ports { -class SystemInteractionPort; +namespace XCEngine::UI::Editor::System { +class SystemInteractionService; } namespace XCEngine::UI::Editor::App { @@ -33,7 +34,7 @@ class EditorContext { public: bool Initialize(const std::filesystem::path& repoRoot); void AttachTextMeasurer(const UIEditorTextMeasurer& textMeasurer); - void SetSystemInteractionHost(Ports::SystemInteractionPort* systemInteractionHost); + void SetSystemInteractionHost(System::SystemInteractionService* systemInteractionHost); void BindEditCommandRoutes( EditorEditCommandRoute* hierarchyRoute, EditorEditCommandRoute* projectRoute, @@ -60,8 +61,8 @@ public: void ClearSelection(); void SyncSessionFromSelectionService(); void SyncSessionFromCommandFocusService(); - Ports::SystemInteractionPort* GetSystemInteractionHost(); - const Ports::SystemInteractionPort* GetSystemInteractionHost() const; + System::SystemInteractionService* GetSystemInteractionHost(); + const System::SystemInteractionService* GetSystemInteractionHost() const; UIEditorWorkspaceController BuildWorkspaceController() const; const UIEditorShellInteractionServices& GetShellServices() const; @@ -95,7 +96,7 @@ private: EditorColorPickerToolState m_colorPickerToolState = {}; EditorUtilityWindowRequestState m_utilityWindowRequestState = {}; EditorHostCommandBridge m_hostCommandBridge = {}; - Ports::SystemInteractionPort* m_systemInteractionHost = nullptr; + System::SystemInteractionService* m_systemInteractionHost = nullptr; std::string m_lastStatus = {}; std::string m_lastMessage = {}; }; diff --git a/new_editor/app/Composition/EditorShellRuntime.cpp b/new_editor/app/Composition/EditorShellRuntime.cpp index f7594dfe..1504459f 100644 --- a/new_editor/app/Composition/EditorShellRuntime.cpp +++ b/new_editor/app/Composition/EditorShellRuntime.cpp @@ -1,6 +1,6 @@ #include "Composition/EditorShellRuntime.h" -#include "Ports/TexturePort.h" -#include "Ports/ViewportRenderPort.h" +#include "Rendering/Host/UiTextureHost.h" +#include "Rendering/Host/ViewportRenderHost.h" #include "Composition/EditorContext.h" #include "Composition/EditorPanelIds.h" #include @@ -10,7 +10,7 @@ namespace XCEngine::UI::Editor::App { void EditorShellRuntime::Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, UIEditorTextMeasurer& textMeasurer) { m_textureHost = &textureHost; m_builtInIcons.Initialize(textureHost); @@ -26,7 +26,7 @@ void EditorShellRuntime::Initialize( m_hierarchyPanel.Initialize(); } -void EditorShellRuntime::AttachViewportWindowRenderer(Ports::ViewportRenderPort& renderer) { +void EditorShellRuntime::AttachViewportWindowRenderer(Rendering::Host::ViewportRenderHost& renderer) { m_viewportHostService.AttachWindowRenderer(renderer); } diff --git a/new_editor/app/Composition/EditorShellRuntime.h b/new_editor/app/Composition/EditorShellRuntime.h index 53434a54..2f198fbe 100644 --- a/new_editor/app/Composition/EditorShellRuntime.h +++ b/new_editor/app/Composition/EditorShellRuntime.h @@ -33,12 +33,12 @@ class EditorContext; } // namespace XCEngine::UI::Editor::App -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::Rendering::Host { -class TexturePort; -class ViewportRenderPort; +class UiTextureHost; +class ViewportRenderHost; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host namespace XCEngine::Rendering { @@ -52,11 +52,11 @@ class EditorShellRuntime { public: void Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, UIEditorTextMeasurer& textMeasurer); void Shutdown(); void ResetInteractionState(); - void AttachViewportWindowRenderer(Ports::ViewportRenderPort& renderer); + void AttachViewportWindowRenderer(Rendering::Host::ViewportRenderHost& renderer); void DetachViewportWindowRenderer(); void SetViewportSurfacePresentationEnabled(bool enabled); @@ -99,7 +99,7 @@ private: ViewportHostService m_viewportHostService = {}; SceneViewportFeature m_sceneViewportFeature = {}; BuiltInIcons m_builtInIcons = {}; - Ports::TexturePort* m_textureHost = nullptr; + Rendering::Host::UiTextureHost* m_textureHost = nullptr; ConsolePanel m_consolePanel = {}; HierarchyPanel m_hierarchyPanel = {}; InspectorPanel m_inspectorPanel = {}; diff --git a/new_editor/app/Composition/EditorWindowWorkspaceStore.cpp b/new_editor/app/Composition/EditorWindowWorkspaceStore.cpp index 22152b18..95116b0c 100644 --- a/new_editor/app/Composition/EditorWindowWorkspaceStore.cpp +++ b/new_editor/app/Composition/EditorWindowWorkspaceStore.cpp @@ -1,140 +1,12 @@ -#include "Composition/EditorWindowWorkspaceStore.h" +#include "Composition/EditorWindowWorkspaceStore.h" -#include - -#include -#include #include namespace XCEngine::UI::Editor::App { -namespace { - -UIEditorWindowWorkspaceState BuildWindowState( - std::string_view windowId, - const UIEditorWorkspaceController& workspaceController) { - UIEditorWindowWorkspaceState state = {}; - state.windowId = std::string(windowId); - state.workspace = workspaceController.GetWorkspace(); - state.session = workspaceController.GetSession(); - return state; -} - -std::string ResolveFallbackWindowId(const UIEditorWindowWorkspaceSet& windowSet) { - if (!windowSet.primaryWindowId.empty() && - FindUIEditorWindowWorkspaceState(windowSet, windowSet.primaryWindowId) != nullptr) { - return windowSet.primaryWindowId; - } - - return windowSet.windows.empty() ? std::string() : windowSet.windows.front().windowId; -} - -void UpsertWindowState( - UIEditorWindowWorkspaceSet& windowSet, - UIEditorWindowWorkspaceState windowState) { - if (UIEditorWindowWorkspaceState* existing = - FindMutableUIEditorWindowWorkspaceState(windowSet, windowState.windowId); - existing != nullptr) { - *existing = std::move(windowState); - return; - } - - windowSet.windows.push_back(std::move(windowState)); -} - -std::string DescribeWindowSetState(const UIEditorWindowWorkspaceSet& windowSet) { - std::ostringstream stream = {}; - stream << "primary='" << windowSet.primaryWindowId - << "' active='" << windowSet.activeWindowId - << "' count=" << windowSet.windows.size() - << " windows=["; - bool first = true; - for (const UIEditorWindowWorkspaceState& state : windowSet.windows) { - if (!first) { - stream << ','; - } - first = false; - stream << state.windowId; - } - stream << ']'; - return stream.str(); -} - -} // namespace - EditorWindowWorkspaceStore::EditorWindowWorkspaceStore(UIEditorPanelRegistry panelRegistry) : m_panelRegistry(std::move(panelRegistry)) {} -UIEditorWindowWorkspaceController EditorWindowWorkspaceStore::BuildMutationController() const { - return UIEditorWindowWorkspaceController(m_panelRegistry, m_windowSet); -} - -bool EditorWindowWorkspaceStore::RegisterWindowProjection( - std::string_view windowId, - bool primary, - const UIEditorWorkspaceController& workspaceController, - std::string& outError) { - UIEditorWindowWorkspaceSet nextWindowSet = m_windowSet; - UpsertWindowState(nextWindowSet, BuildWindowState(windowId, workspaceController)); - - if (primary) { - if (!nextWindowSet.primaryWindowId.empty() && nextWindowSet.primaryWindowId != windowId) { - outError = - "Cannot register a second primary window '" + std::string(windowId) + - "' while '" + nextWindowSet.primaryWindowId + "' is still primary."; - return false; - } - nextWindowSet.primaryWindowId = std::string(windowId); - } else if (nextWindowSet.primaryWindowId.empty()) { - outError = - "Cannot register detached window '" + std::string(windowId) + - "' before the primary window exists."; - return false; - } - - if (nextWindowSet.activeWindowId.empty() || - FindUIEditorWindowWorkspaceState(nextWindowSet, nextWindowSet.activeWindowId) == nullptr) { - nextWindowSet.activeWindowId = ResolveFallbackWindowId(nextWindowSet); - } - - if (!ValidateWindowSet(nextWindowSet, outError)) { - return false; - } - - ReplaceWindowSet(std::move(nextWindowSet)); - outError.clear(); - return true; -} - -bool EditorWindowWorkspaceStore::CommitWindowProjection( - std::string_view windowId, - const UIEditorWorkspaceController& workspaceController, - std::string& outError) { - UIEditorWindowWorkspaceSet nextWindowSet = m_windowSet; - UIEditorWindowWorkspaceState* existingWindow = - FindMutableUIEditorWindowWorkspaceState(nextWindowSet, windowId); - if (existingWindow == nullptr) { - outError = "Window '" + std::string(windowId) + "' is not registered in the workspace store."; - return false; - } - - existingWindow->workspace = workspaceController.GetWorkspace(); - existingWindow->session = workspaceController.GetSession(); - - if (nextWindowSet.activeWindowId.empty() || - FindUIEditorWindowWorkspaceState(nextWindowSet, nextWindowSet.activeWindowId) == nullptr) { - nextWindowSet.activeWindowId = ResolveFallbackWindowId(nextWindowSet); - } - - if (!ValidateWindowSet(nextWindowSet, outError)) { - return false; - } - - ReplaceWindowSet(std::move(nextWindowSet)); - outError.clear(); - return true; -} - bool EditorWindowWorkspaceStore::ValidateWindowSet( const UIEditorWindowWorkspaceSet& windowSet, std::string& outError) const { @@ -149,62 +21,4 @@ bool EditorWindowWorkspaceStore::ValidateWindowSet( return true; } -void EditorWindowWorkspaceStore::ReplaceWindowSet(UIEditorWindowWorkspaceSet windowSet) { - m_windowSet = std::move(windowSet); -} - -void EditorWindowWorkspaceStore::RemoveWindow(std::string_view windowId, bool primary) { - const std::string beforeState = DescribeWindowSetState(m_windowSet); - if (m_windowSet.windows.empty()) { - AppendUIEditorRuntimeTrace( - "window-close", - "store remove skipped windowId='" + std::string(windowId) + - "' primaryArg=" + (primary ? "1" : "0") + - " stateBefore=" + beforeState); - return; - } - - if (primary || m_windowSet.primaryWindowId == windowId) { - m_windowSet = {}; - AppendUIEditorRuntimeTrace( - "window-close", - "store remove cleared all windows windowId='" + std::string(windowId) + - "' primaryArg=" + (primary ? "1" : "0") + - " stateBefore=" + beforeState + - " stateAfter=" + DescribeWindowSetState(m_windowSet)); - return; - } - - m_windowSet.windows.erase( - std::remove_if( - m_windowSet.windows.begin(), - m_windowSet.windows.end(), - [windowId](const UIEditorWindowWorkspaceState& state) { - return state.windowId == windowId; - }), - m_windowSet.windows.end()); - - if (m_windowSet.windows.empty()) { - m_windowSet = {}; - return; - } - - if (FindUIEditorWindowWorkspaceState(m_windowSet, m_windowSet.primaryWindowId) == nullptr) { - m_windowSet.primaryWindowId = ResolveFallbackWindowId(m_windowSet); - } - - if (m_windowSet.activeWindowId == windowId || - FindUIEditorWindowWorkspaceState(m_windowSet, m_windowSet.activeWindowId) == nullptr) { - m_windowSet.activeWindowId = ResolveFallbackWindowId(m_windowSet); - } - - AppendUIEditorRuntimeTrace( - "window-close", - "store remove completed windowId='" + std::string(windowId) + - "' primaryArg=" + (primary ? "1" : "0") + - " stateBefore=" + beforeState + - " stateAfter=" + DescribeWindowSetState(m_windowSet)); -} - } // namespace XCEngine::UI::Editor::App - diff --git a/new_editor/app/Composition/EditorWindowWorkspaceStore.h b/new_editor/app/Composition/EditorWindowWorkspaceStore.h index adc1ff65..5b58c8fc 100644 --- a/new_editor/app/Composition/EditorWindowWorkspaceStore.h +++ b/new_editor/app/Composition/EditorWindowWorkspaceStore.h @@ -1,10 +1,8 @@ #pragma once #include -#include #include -#include namespace XCEngine::UI::Editor::App { @@ -16,38 +14,12 @@ public: return m_panelRegistry; } - bool HasState() const { - return !m_windowSet.windows.empty(); - } - - const UIEditorWindowWorkspaceSet& GetWindowSet() const { - return m_windowSet; - } - - UIEditorWindowWorkspaceController BuildMutationController() const; - - bool RegisterWindowProjection( - std::string_view windowId, - bool primary, - const UIEditorWorkspaceController& workspaceController, - std::string& outError); - - bool CommitWindowProjection( - std::string_view windowId, - const UIEditorWorkspaceController& workspaceController, - std::string& outError); - bool ValidateWindowSet( const UIEditorWindowWorkspaceSet& windowSet, std::string& outError) const; - void ReplaceWindowSet(UIEditorWindowWorkspaceSet windowSet); - - void RemoveWindow(std::string_view windowId, bool primary); - private: UIEditorPanelRegistry m_panelRegistry = {}; - UIEditorWindowWorkspaceSet m_windowSet = {}; }; } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Features/ColorPicker/ColorPickerPanel.cpp b/new_editor/app/Features/ColorPicker/ColorPickerPanel.cpp index 46c318cf..d4a92ff0 100644 --- a/new_editor/app/Features/ColorPicker/ColorPickerPanel.cpp +++ b/new_editor/app/Features/ColorPicker/ColorPickerPanel.cpp @@ -89,7 +89,7 @@ void ColorPickerPanel::ResetInteractionState() { void ColorPickerPanel::Update( EditorContext& context, - const ColorPickerPanelHostContext& hostContext, + const EditorUtilityWindowHostContext& hostContext, const std::vector& inputEvents) { if (!hostContext.mounted) { ResetPanelState(); diff --git a/new_editor/app/Features/ColorPicker/ColorPickerPanel.h b/new_editor/app/Features/ColorPicker/ColorPickerPanel.h index 2b99eb98..f9bb93fe 100644 --- a/new_editor/app/Features/ColorPicker/ColorPickerPanel.h +++ b/new_editor/app/Features/ColorPicker/ColorPickerPanel.h @@ -1,33 +1,24 @@ #pragma once +#include "UtilityWindows/EditorUtilityWindowPanel.h" + #include -#include - #include -#include namespace XCEngine::UI::Editor::App { -class EditorContext; - -struct ColorPickerPanelHostContext { - bool mounted = false; - ::XCEngine::UI::UIRect bounds = {}; - bool allowInteraction = false; - bool focused = false; - bool focusGained = false; - bool focusLost = false; -}; - -class ColorPickerPanel { +class ColorPickerPanel final : public EditorUtilityWindowPanel { public: - void ResetInteractionState(); + std::string_view GetDrawListId() const override { + return "XCEditorUtility.ColorPicker"; + } + void ResetInteractionState() override; void Update( EditorContext& context, - const ColorPickerPanelHostContext& hostContext, - const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents); - void Append(::XCEngine::UI::UIDrawList& drawList) const; + const EditorUtilityWindowHostContext& hostContext, + const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override; + void Append(::XCEngine::UI::UIDrawList& drawList) const override; private: void ResetPanelState(); diff --git a/new_editor/app/Features/Inspector/AddComponentPanel.cpp b/new_editor/app/Features/Inspector/AddComponentPanel.cpp index feb19981..811afb78 100644 --- a/new_editor/app/Features/Inspector/AddComponentPanel.cpp +++ b/new_editor/app/Features/Inspector/AddComponentPanel.cpp @@ -155,7 +155,7 @@ std::size_t AddComponentPanel::HitTestEntry(const UIPoint& point) const { void AddComponentPanel::Update( EditorContext& context, - const AddComponentPanelHostContext& hostContext, + const EditorUtilityWindowHostContext& hostContext, const std::vector& inputEvents) { if (!hostContext.mounted) { ResetPanelState(); diff --git a/new_editor/app/Features/Inspector/AddComponentPanel.h b/new_editor/app/Features/Inspector/AddComponentPanel.h index 79d6a24e..e21bcd27 100644 --- a/new_editor/app/Features/Inspector/AddComponentPanel.h +++ b/new_editor/app/Features/Inspector/AddComponentPanel.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "UtilityWindows/EditorUtilityWindowPanel.h" #include #include @@ -12,24 +12,17 @@ class GameObject; namespace XCEngine::UI::Editor::App { -class EditorContext; - -struct AddComponentPanelHostContext { - bool mounted = false; - ::XCEngine::UI::UIRect bounds = {}; - bool focused = false; - bool focusGained = false; - bool focusLost = false; -}; - -class AddComponentPanel { +class AddComponentPanel final : public EditorUtilityWindowPanel { public: - void ResetInteractionState(); + std::string_view GetDrawListId() const override { + return "XCEditorUtility.AddComponent"; + } + void ResetInteractionState() override; void Update( EditorContext& context, - const AddComponentPanelHostContext& hostContext, - const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents); - void Append(::XCEngine::UI::UIDrawList& drawList) const; + const EditorUtilityWindowHostContext& hostContext, + const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override; + void Append(::XCEngine::UI::UIDrawList& drawList) const override; private: struct EntryPresentation { diff --git a/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.cpp b/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.cpp index 8bb4f250..65548575 100644 --- a/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.cpp +++ b/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.cpp @@ -324,6 +324,7 @@ InspectorFieldBinding BuildInspectorVector3FieldBinding( label, getter(), options.step, + options.controlMinWidth, options.integerMode, options.minValue, options.maxValue); diff --git a/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.h b/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.h index cdd343bf..dc7760c2 100644 --- a/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.h +++ b/new_editor/app/Features/Inspector/Components/InspectorBindingComponentEditor.h @@ -27,6 +27,7 @@ struct InspectorColorFieldBindingOptions { struct InspectorVector3FieldBindingOptions { double step = 0.1; + float controlMinWidth = kDefaultInspectorFieldControlMinWidth; bool integerMode = false; double minValue = -1000000.0; double maxValue = 1000000.0; diff --git a/new_editor/app/Features/Inspector/Components/InspectorComponentEditorUtils.h b/new_editor/app/Features/Inspector/Components/InspectorComponentEditorUtils.h index a5b0f668..db0510dd 100644 --- a/new_editor/app/Features/Inspector/Components/InspectorComponentEditorUtils.h +++ b/new_editor/app/Features/Inspector/Components/InspectorComponentEditorUtils.h @@ -18,6 +18,8 @@ namespace XCEngine::UI::Editor::App { +inline constexpr float kDefaultInspectorFieldControlMinWidth = 160.0f; + inline std::string BuildInspectorComponentSectionId( std::string_view componentId, std::string_view sectionSuffix = {}) { @@ -50,6 +52,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorReadOnlyTextField( field.kind = Widgets::UIEditorPropertyGridFieldKind::Text; field.valueText = std::move(value); field.readOnly = true; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -64,6 +67,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorTextField( field.kind = Widgets::UIEditorPropertyGridFieldKind::Text; field.valueText = std::move(value); field.readOnly = readOnly; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -76,6 +80,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorBoolField( field.label = std::move(label); field.kind = Widgets::UIEditorPropertyGridFieldKind::Bool; field.boolValue = value; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -107,6 +112,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorNumberField( field.numberValue.minValue = minValue; field.numberValue.maxValue = maxValue; field.numberValue.integerMode = integerMode; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -132,6 +138,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorEnumField( field.kind = Widgets::UIEditorPropertyGridFieldKind::Enum; field.enumValue.options = std::move(options); field.enumValue.selectedIndex = selectedIndex; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -184,6 +191,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorAssetField( field.assetValue.emptyText = std::move(emptyText); field.assetValue.showPickerButton = showPickerButton; field.assetValue.showStatusBadge = !field.assetValue.statusText.empty(); + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -227,6 +235,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorColorField( field.kind = Widgets::UIEditorPropertyGridFieldKind::Color; field.colorValue.value = ToUIEditorColor(value); field.colorValue.showAlpha = showAlpha; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } @@ -265,6 +274,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorVector3Field( std::string label, const ::XCEngine::Math::Vector3& value, double step, + float controlMinWidth = kDefaultInspectorFieldControlMinWidth, bool integerMode = false, double minValue = -1000000.0, double maxValue = 1000000.0) { @@ -277,6 +287,7 @@ inline Widgets::UIEditorPropertyGridField BuildInspectorVector3Field( field.vector3Value.minValue = minValue; field.vector3Value.maxValue = maxValue; field.vector3Value.integerMode = integerMode; + field.controlMinWidth = controlMinWidth; return field; } diff --git a/new_editor/app/Features/Inspector/Components/TransformInspectorComponentEditor.cpp b/new_editor/app/Features/Inspector/Components/TransformInspectorComponentEditor.cpp index a29f5fc7..f6cebca6 100644 --- a/new_editor/app/Features/Inspector/Components/TransformInspectorComponentEditor.cpp +++ b/new_editor/app/Features/Inspector/Components/TransformInspectorComponentEditor.cpp @@ -36,7 +36,7 @@ void TransformInspectorComponentEditor::BuildBindingSections( section.fields.push_back(BuildInspectorVector3FieldBinding( "position", "Position", - InspectorVector3FieldBindingOptions{ .step = 0.1 }, + InspectorVector3FieldBindingOptions{ .step = 0.1, .controlMinWidth = 240.0f }, [transform]() { return transform->GetLocalPosition(); }, [](EditorSceneRuntime& sceneRuntime, const InspectorComponentEditorContext& bindingContext, @@ -48,7 +48,7 @@ void TransformInspectorComponentEditor::BuildBindingSections( section.fields.push_back(BuildInspectorVector3FieldBinding( "rotation", "Rotation", - InspectorVector3FieldBindingOptions{ .step = 1.0 }, + InspectorVector3FieldBindingOptions{ .step = 1.0, .controlMinWidth = 240.0f }, [transform]() { return transform->GetLocalEulerAngles(); }, [](EditorSceneRuntime& sceneRuntime, const InspectorComponentEditorContext& bindingContext, @@ -60,7 +60,7 @@ void TransformInspectorComponentEditor::BuildBindingSections( section.fields.push_back(BuildInspectorVector3FieldBinding( "scale", "Scale", - InspectorVector3FieldBindingOptions{ .step = 0.1 }, + InspectorVector3FieldBindingOptions{ .step = 0.1, .controlMinWidth = 240.0f }, [transform]() { return transform->GetLocalScale(); }, [](EditorSceneRuntime& sceneRuntime, const InspectorComponentEditorContext& bindingContext, diff --git a/new_editor/app/Features/Inspector/InspectorPresentationModel.cpp b/new_editor/app/Features/Inspector/InspectorPresentationModel.cpp index e21e1bea..9292a4f7 100644 --- a/new_editor/app/Features/Inspector/InspectorPresentationModel.cpp +++ b/new_editor/app/Features/Inspector/InspectorPresentationModel.cpp @@ -60,6 +60,7 @@ UIEditorPropertyGridField BuildReadOnlyTextField( field.kind = UIEditorPropertyGridFieldKind::Text; field.valueText = std::move(value); field.readOnly = true; + field.controlMinWidth = kDefaultInspectorFieldControlMinWidth; return field; } diff --git a/new_editor/app/Features/Project/ProjectPanel.cpp b/new_editor/app/Features/Project/ProjectPanel.cpp index 46da5d63..013387a4 100644 --- a/new_editor/app/Features/Project/ProjectPanel.cpp +++ b/new_editor/app/Features/Project/ProjectPanel.cpp @@ -6,7 +6,7 @@ #include #include #include -#include "Ports/SystemInteractionPort.h" +#include "System/SystemInteractionService.h" #include "Project/EditorProjectRuntime.h" #include "State/EditorCommandFocusService.h" #include @@ -46,8 +46,8 @@ inline constexpr float kGridTileWidth = 92.0f; inline constexpr float kGridTileHeight = 92.0f; inline constexpr float kGridTileGapX = 12.0f; inline constexpr float kGridTileGapY = 12.0f; -inline constexpr float kGridPreviewWidth = 68.0f; -inline constexpr float kGridPreviewHeight = 54.0f; +inline constexpr float kGridPreviewWidth = 80.0f; +inline constexpr float kGridPreviewHeight = 64.0f; inline constexpr float kHeaderFontSize = 12.0f; inline constexpr float kTileLabelFontSize = 11.0f; @@ -298,6 +298,48 @@ void AppendContextMenuSeparator( items.push_back(BuildContextMenuSeparatorItem(std::move(itemId))); } +std::size_t FindContextMenuItemIndexById( + const std::vector& items, + std::string_view itemId) { + for (std::size_t index = 0u; index < items.size(); ++index) { + if (items[index].itemId == itemId) { + return index; + } + } + + return Widgets::UIEditorMenuPopupInvalidIndex; +} + +Widgets::UIEditorMenuPopupState PreserveContextMenuWidgetState( + const std::vector& previousItems, + const Widgets::UIEditorMenuPopupState& previousState, + const std::vector& rebuiltItems) { + Widgets::UIEditorMenuPopupState preserved = {}; + preserved.focused = previousState.focused; + + if (previousState.hoveredIndex < previousItems.size()) { + const std::size_t hoveredIndex = + FindContextMenuItemIndexById( + rebuiltItems, + previousItems[previousState.hoveredIndex].itemId); + if (hoveredIndex < rebuiltItems.size() && rebuiltItems[hoveredIndex].enabled) { + preserved.hoveredIndex = hoveredIndex; + } + } + + if (previousState.submenuOpenIndex < previousItems.size()) { + const std::size_t submenuOpenIndex = + FindContextMenuItemIndexById( + rebuiltItems, + previousItems[previousState.submenuOpenIndex].itemId); + if (submenuOpenIndex < rebuiltItems.size() && rebuiltItems[submenuOpenIndex].enabled) { + preserved.submenuOpenIndex = submenuOpenIndex; + } + } + + return preserved; +} + } // namespace EditorProjectRuntime* ProjectPanel::ResolveProjectRuntime() { @@ -371,7 +413,7 @@ void ProjectPanel::SetCommandFocusService( } void ProjectPanel::SetSystemInteractionHost( - Ports::SystemInteractionPort* systemInteractionHost) { + System::SystemInteractionService* systemInteractionHost) { m_systemInteractionHost = systemInteractionHost; } @@ -883,6 +925,11 @@ void ProjectPanel::RebuildContextMenu() { return; } + const std::vector previousItems = + m_contextMenu.items; + const Widgets::UIEditorMenuPopupState previousWidgetState = + m_contextMenu.widgetState; + const AssetCommandTarget assetTarget = ResolveAssetCommandTarget( m_contextMenu.targetItemId, @@ -1008,7 +1055,11 @@ void ProjectPanel::RebuildContextMenu() { placement.rect, m_contextMenu.items, popupMetrics); - m_contextMenu.widgetState = {}; + m_contextMenu.widgetState = + PreserveContextMenuWidgetState( + previousItems, + previousWidgetState, + m_contextMenu.items); m_contextMenu.widgetState.focused = true; } @@ -1057,8 +1108,8 @@ bool ProjectPanel::HandleContextMenuEvent(const UIInputEvent& event) { hitTarget.index < m_contextMenu.items.size() && m_contextMenu.items[hitTarget.index].enabled) { const std::string itemId = m_contextMenu.items[hitTarget.index].itemId; - DispatchContextMenuItem(itemId); CloseContextMenu(); + DispatchContextMenuItem(itemId); return true; } @@ -1539,6 +1590,14 @@ UIEditorHostCommandDispatchResult ProjectPanel::DispatchEditCommand( m_hoveredAssetItemId.clear(); m_lastPrimaryClickedAssetId.clear(); m_lastPrimaryClickTime = {}; + if (HasValidBounds(m_layout.bounds)) { + RebuildPanelLayout(m_layout.bounds); + RebuildBrowserScrollLayout(); + ApplyBrowserLayout( + m_layout.bounds, + m_browserScrollFrame.layout.contentRect, + m_browserVerticalOffset); + } if (hadAssetSelection && !ResolveProjectRuntime()->HasSelection()) { EmitSelectionClearedEvent(EventSource::GridPrimary); } @@ -2218,12 +2277,12 @@ ProjectPanel::Layout ProjectPanel::BuildLayout( tile.tileRect = UIRect(tileX, tileY, kGridTileWidth, kGridTileHeight); tile.previewRect = UIRect( tile.tileRect.x + (tile.tileRect.width - kGridPreviewWidth) * 0.5f, - tile.tileRect.y + 6.0f, + tile.tileRect.y + 4.0f, kGridPreviewWidth, kGridPreviewHeight); tile.labelRect = UIRect( tile.tileRect.x + 4.0f, - tile.previewRect.y + tile.previewRect.height + 8.0f, + tile.previewRect.y + tile.previewRect.height + 6.0f, tile.tileRect.width - 8.0f, 18.0f); layout.assetTiles.push_back(tile); diff --git a/new_editor/app/Features/Project/ProjectPanel.h b/new_editor/app/Features/Project/ProjectPanel.h index 9d0a5a9c..730bff61 100644 --- a/new_editor/app/Features/Project/ProjectPanel.h +++ b/new_editor/app/Features/Project/ProjectPanel.h @@ -34,11 +34,11 @@ class EditorCommandFocusService; } // namespace XCEngine::UI::Editor::App -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::System { -class SystemInteractionPort; +class SystemInteractionService; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::System namespace XCEngine::UI::Editor::App { @@ -85,7 +85,7 @@ public: void Initialize(const std::filesystem::path& repoRoot); void SetProjectRuntime(EditorProjectRuntime* projectRuntime); void SetCommandFocusService(EditorCommandFocusService* commandFocusService); - void SetSystemInteractionHost(Ports::SystemInteractionPort* systemInteractionHost); + void SetSystemInteractionHost(System::SystemInteractionService* systemInteractionHost); void SetBuiltInIcons(BuiltInIcons* icons); void SetTextMeasurer(const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer); void ResetInteractionState(); @@ -253,7 +253,7 @@ private: std::unique_ptr m_ownedProjectRuntime = {}; EditorProjectRuntime* m_projectRuntime = nullptr; EditorCommandFocusService* m_commandFocusService = nullptr; - Ports::SystemInteractionPort* m_systemInteractionHost = nullptr; + System::SystemInteractionService* m_systemInteractionHost = nullptr; BuiltInIcons* m_icons = nullptr; const ::XCEngine::UI::Editor::UIEditorTextMeasurer* m_textMeasurer = nullptr; std::vector m_windowTreeItems = {}; diff --git a/new_editor/app/Features/Scene/SceneViewportController.cpp b/new_editor/app/Features/Scene/SceneViewportController.cpp index 5344d17f..7553168e 100644 --- a/new_editor/app/Features/Scene/SceneViewportController.cpp +++ b/new_editor/app/Features/Scene/SceneViewportController.cpp @@ -138,14 +138,14 @@ void ApplySceneViewportToggleButton( void SceneViewportController::Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& renderer, + Rendering::Host::UiTextureHost& renderer, const BuiltInIcons* builtInIcons) { m_toolOverlay.Initialize(repoRoot, renderer); m_sceneOverlay.SetBuiltInIcons(builtInIcons); ResetInteractionState(); } -void SceneViewportController::Shutdown(Ports::TexturePort& renderer) { +void SceneViewportController::Shutdown(Rendering::Host::UiTextureHost& renderer) { m_toolOverlay.Shutdown(renderer); ResetInteractionState(); } diff --git a/new_editor/app/Features/Scene/SceneViewportController.h b/new_editor/app/Features/Scene/SceneViewportController.h index e507b3ac..8301e687 100644 --- a/new_editor/app/Features/Scene/SceneViewportController.h +++ b/new_editor/app/Features/Scene/SceneViewportController.h @@ -21,11 +21,11 @@ class IViewportObjectPickerService; } // namespace XCEngine::UI::Editor::App -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::Rendering::Host { -class TexturePort; +class UiTextureHost; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host namespace XCEngine::UI::Editor::App { @@ -33,9 +33,9 @@ class SceneViewportController { public: void Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& renderer, + Rendering::Host::UiTextureHost& renderer, const BuiltInIcons* builtInIcons); - void Shutdown(Ports::TexturePort& renderer); + void Shutdown(Rendering::Host::UiTextureHost& renderer); void ResetInteractionState(); void SetCommandFocusService(EditorCommandFocusService* commandFocusService); diff --git a/new_editor/app/Features/Scene/SceneViewportFeature.cpp b/new_editor/app/Features/Scene/SceneViewportFeature.cpp index 60ec73d7..f899b1c2 100644 --- a/new_editor/app/Features/Scene/SceneViewportFeature.cpp +++ b/new_editor/app/Features/Scene/SceneViewportFeature.cpp @@ -1,7 +1,7 @@ #include "Features/Scene/SceneViewportFeature.h" #include "Composition/EditorPanelIds.h" -#include "Ports/TexturePort.h" +#include "Rendering/Host/UiTextureHost.h" #include "Rendering/Viewport/ViewportHostService.h" #include "Scene/EditorSceneRuntime.h" #include "State/EditorCommandFocusService.h" @@ -10,7 +10,7 @@ namespace XCEngine::UI::Editor::App { void SceneViewportFeature::Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, const BuiltInIcons* builtInIcons, ViewportHostService& viewportHostService) { viewportHostService.SetContentRenderer( @@ -21,7 +21,7 @@ void SceneViewportFeature::Initialize( } void SceneViewportFeature::Shutdown( - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, ViewportHostService& viewportHostService) { viewportHostService.SetContentRenderer(kScenePanelId, nullptr, {}); m_controller.Shutdown(textureHost); diff --git a/new_editor/app/Features/Scene/SceneViewportFeature.h b/new_editor/app/Features/Scene/SceneViewportFeature.h index ec43f7c8..b5bb0781 100644 --- a/new_editor/app/Features/Scene/SceneViewportFeature.h +++ b/new_editor/app/Features/Scene/SceneViewportFeature.h @@ -17,11 +17,11 @@ class EditorSceneRuntime; } // namespace XCEngine::UI::Editor::App -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::Rendering::Host { -class TexturePort; +class UiTextureHost; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host namespace XCEngine::UI::Editor::App { @@ -31,11 +31,11 @@ class SceneViewportFeature { public: void Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, const BuiltInIcons* builtInIcons, ViewportHostService& viewportHostService); void Shutdown( - Ports::TexturePort& textureHost, + Rendering::Host::UiTextureHost& textureHost, ViewportHostService& viewportHostService); void ResetInteractionState(); void SetCommandFocusService(EditorCommandFocusService* commandFocusService); diff --git a/new_editor/app/Features/Scene/SceneViewportToolOverlay.cpp b/new_editor/app/Features/Scene/SceneViewportToolOverlay.cpp index 4eb91fbf..8654eecf 100644 --- a/new_editor/app/Features/Scene/SceneViewportToolOverlay.cpp +++ b/new_editor/app/Features/Scene/SceneViewportToolOverlay.cpp @@ -1,6 +1,6 @@ #include "Features/Scene/SceneViewportToolOverlay.h" -#include "Ports/TexturePort.h" +#include "Rendering/Host/UiTextureHost.h" #include @@ -202,7 +202,7 @@ UIRect BuildToggleButtonRect( bool SceneViewportToolOverlay::Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& renderer) { + Rendering::Host::UiTextureHost& renderer) { Shutdown(renderer); const std::filesystem::path iconRoot = @@ -232,7 +232,7 @@ bool SceneViewportToolOverlay::Initialize( return loadedAnyTexture; } -void SceneViewportToolOverlay::Shutdown(Ports::TexturePort& renderer) { +void SceneViewportToolOverlay::Shutdown(Rendering::Host::UiTextureHost& renderer) { for (ToolTextureSet& textureSet : m_toolTextures) { renderer.ReleaseTexture(textureSet.inactiveTexture); renderer.ReleaseTexture(textureSet.activeTexture); diff --git a/new_editor/app/Features/Scene/SceneViewportToolOverlay.h b/new_editor/app/Features/Scene/SceneViewportToolOverlay.h index 6f1094fc..b6445d05 100644 --- a/new_editor/app/Features/Scene/SceneViewportToolOverlay.h +++ b/new_editor/app/Features/Scene/SceneViewportToolOverlay.h @@ -1,7 +1,7 @@ #pragma once #include "Scene/SceneToolState.h" -#include "Ports/PortFwd.h" +#include "Rendering/Host/HostFwd.h" #include #include @@ -59,8 +59,8 @@ class SceneViewportToolOverlay { public: bool Initialize( const std::filesystem::path& repoRoot, - Ports::TexturePort& renderer); - void Shutdown(Ports::TexturePort& renderer); + Rendering::Host::UiTextureHost& renderer); + void Shutdown(Rendering::Host::UiTextureHost& renderer); void ResetFrame(); void BuildFrame( diff --git a/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp b/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp index 3e44d9f6..103ea46f 100644 --- a/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp +++ b/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.cpp @@ -1,10 +1,10 @@ -#include "Platform/Win32/EditorWindowChromeController.h" +#include "Platform/Win32/Chrome/EditorWindowChromeController.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWindowFrameDriver.h" -#include "Platform/Win32/EditorWindowRuntimeController.h" -#include "Platform/Win32/EditorWindowState.h" -#include "Platform/Win32/EditorWindowSupport.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h" +#include "Platform/Win32/Runtime/EditorWindowRuntimeController.h" +#include "Platform/Win32/Windowing/EditorWindowState.h" +#include "Platform/Win32/Windowing/EditorWindowSupport.h" #include #include @@ -233,10 +233,6 @@ bool EditorWindowChromeController::HandleSystemCommand( EditorContext& editorContext, bool globalTabDragActive, WPARAM wParam) { - if (!window.IsBorderlessWindowEnabled()) { - return false; - } - switch (wParam & 0xFFF0u) { case SC_MAXIMIZE: ToggleMaximizeRestore(window, editorContext, globalTabDragActive); @@ -438,9 +434,7 @@ void EditorWindowChromeController::ForceClearResizeState(EditorWindow& window) { Host::BorderlessWindowResizeEdge EditorWindowChromeController::HitTestResizeEdge( const EditorWindow& window, LPARAM lParam) const { - if (!window.IsBorderlessWindowEnabled() || - window.m_state->window.hwnd == nullptr || - window.IsBorderlessWindowMaximized()) { + if (window.m_state->window.hwnd == nullptr || IsBorderlessWindowMaximized()) { return Host::BorderlessWindowResizeEdge::None; } @@ -499,7 +493,7 @@ bool EditorWindowChromeController::HandleChromeButtonDown(EditorWindow& window, return true; case Host::BorderlessWindowChromeHitTarget::DragRegion: if (window.m_state->window.hwnd != nullptr) { - if (window.IsBorderlessWindowMaximized()) { + if (IsBorderlessWindowMaximized()) { POINT screenPoint = {}; if (GetCursorPos(&screenPoint)) { BeginBorderlessWindowDragRestore(screenPoint); @@ -661,7 +655,7 @@ void EditorWindowChromeController::ClearChromeState(EditorWindow& window) { Host::BorderlessWindowChromeHitTarget EditorWindowChromeController::HitTestChrome( const EditorWindow& window, LPARAM lParam) const { - if (!window.IsBorderlessWindowEnabled() || window.m_state->window.hwnd == nullptr) { + if (window.m_state->window.hwnd == nullptr) { return Host::BorderlessWindowChromeHitTarget::None; } @@ -684,8 +678,12 @@ Host::BorderlessWindowChromeLayout EditorWindowChromeController::ResolveChromeLa float clientWidthDips) const { float leadingOccupiedRight = 0.0f; if (ShouldUseDetachedTitleBarTabStrip(window)) { + const EditorWindowTitleBarBinding* titleBarBinding = + window.m_runtime->TryGetTitleBarBinding(); leadingOccupiedRight = ResolveDetachedTabWidth( - window.m_runtime->ResolveTabStripTitleText("Panel"), + titleBarBinding != nullptr + ? titleBarBinding->ResolveTabStripTitleText("Panel") + : std::string("Panel"), &window.m_runtime->GetTextMeasurer()); } @@ -696,18 +694,16 @@ Host::BorderlessWindowChromeLayout EditorWindowChromeController::ResolveChromeLa bool EditorWindowChromeController::ShouldUseDetachedTitleBarTabStrip( const EditorWindow& window) const { + const EditorWindowTitleBarBinding* titleBarBinding = window.m_runtime->TryGetTitleBarBinding(); return !window.m_state->window.primary && - window.m_runtime->ShouldUseDetachedTitleBarTabStrip(); + titleBarBinding != nullptr && + titleBarBinding->ShouldUseDetachedTitleBarTabStrip(); } void EditorWindowChromeController::AppendChrome( const EditorWindow& window, UIDrawList& drawList, float clientWidthDips) const { - if (!window.IsBorderlessWindowEnabled()) { - return; - } - const Host::BorderlessWindowChromeLayout layout = ResolveChromeLayout(window, clientWidthDips); const bool useDetachedTitleBarTabStrip = ShouldUseDetachedTitleBarTabStrip(window); @@ -753,10 +749,17 @@ void EditorWindowChromeController::AppendChrome( 0.0f, (layout.titleBarRect.height - kBorderlessTitleBarFontSize) * 0.5f - 1.0f)), - window.m_runtime->ResolveDetachedWindowTitleText( - window.m_state->window.titleText.empty() - ? std::string_view("XCEngine Editor") - : std::string_view(window.m_state->window.titleText)), + [&window]() { + const std::string_view fallbackWindowTitle = + window.m_state->window.titleText.empty() + ? std::string_view("XCEngine Editor") + : std::string_view(window.m_state->window.titleText); + const EditorWindowTitleBarBinding* titleBarBinding = + window.m_runtime->TryGetTitleBarBinding(); + return titleBarBinding != nullptr + ? titleBarBinding->ResolveDetachedWindowTitleText(fallbackWindowTitle) + : std::string(fallbackWindowTitle); + }(), kShellTextColor, kBorderlessTitleBarFontSize); } @@ -817,7 +820,7 @@ void EditorWindowChromeController::AppendChrome( drawList, layout, GetChromeState(), - window.IsBorderlessWindowMaximized()); + IsBorderlessWindowMaximized()); } void EditorWindowChromeController::ApplyResizeCursorHoverPriority() { @@ -903,7 +906,7 @@ void EditorWindowChromeController::ToggleMaximizeRestore( return; } - if (!window.IsBorderlessWindowMaximized()) { + if (!IsBorderlessWindowMaximized()) { RECT currentRect = {}; RECT workAreaRect = {}; if (!QueryCurrentWindowRect(window, currentRect) || diff --git a/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.h b/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.h index a2207817..74b4807d 100644 --- a/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.h +++ b/new_editor/app/Platform/Win32/Chrome/EditorWindowChromeController.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include namespace XCEngine::UI { diff --git a/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.cpp b/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.cpp deleted file mode 100644 index 4d1d8a8f..00000000 --- a/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "Platform/Win32/EditorAddComponentUtilityWindowContentController.h" - -#include - -namespace XCEngine::UI::Editor::App { - -EditorAddComponentUtilityWindowContentController:: - EditorAddComponentUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize) - : EditorStandaloneUtilityWindowContentController(minimumOuterSize) {} - -EditorAddComponentUtilityWindowContentController:: - ~EditorAddComponentUtilityWindowContentController() = default; - -void EditorAddComponentUtilityWindowContentController::OnShutdown() { - m_addComponentPanel.ResetInteractionState(); -} - -void EditorAddComponentUtilityWindowContentController::OnResetInteractionState() { - m_addComponentPanel.ResetInteractionState(); -} - -EditorWindowFrameTransferRequests -EditorAddComponentUtilityWindowContentController::UpdateStandaloneContent( - const EditorStandaloneUtilityWindowFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) { - m_addComponentPanel.Update( - context.editorContext, - AddComponentPanelHostContext{ - .mounted = true, - .bounds = context.bounds, - .focused = context.focused, - .focusGained = context.focusGained, - .focusLost = context.focusLost, - }, - context.inputEvents); - - ::XCEngine::UI::UIDrawList& drawList = - drawData.EmplaceDrawList("XCEditorUtility.AddComponent"); - m_addComponentPanel.Append(drawList); - return {}; -} - -std::unique_ptr -CreateEditorAddComponentUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize) { - return std::make_unique( - minimumOuterSize); -} - -} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.h b/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.h deleted file mode 100644 index 582b4d1d..00000000 --- a/new_editor/app/Platform/Win32/Content/EditorAddComponentUtilityWindowContentController.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "Features/Inspector/AddComponentPanel.h" -#include "Platform/Win32/EditorStandaloneUtilityWindowContentController.h" - -#include - -namespace XCEngine::UI::Editor::App { - -class EditorAddComponentUtilityWindowContentController final - : public EditorStandaloneUtilityWindowContentController { -public: - explicit EditorAddComponentUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize); - ~EditorAddComponentUtilityWindowContentController() override; - -private: - void OnShutdown() override; - void OnResetInteractionState() override; - EditorWindowFrameTransferRequests UpdateStandaloneContent( - const EditorStandaloneUtilityWindowFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) override; - - AddComponentPanel m_addComponentPanel = {}; -}; - -std::unique_ptr -CreateEditorAddComponentUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize); - -} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.cpp b/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.cpp deleted file mode 100644 index ed65b7e7..00000000 --- a/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "Platform/Win32/EditorColorPickerUtilityWindowContentController.h" - -#include - -namespace XCEngine::UI::Editor::App { - -EditorColorPickerUtilityWindowContentController:: - EditorColorPickerUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize) - : EditorStandaloneUtilityWindowContentController(minimumOuterSize) {} - -EditorColorPickerUtilityWindowContentController:: - ~EditorColorPickerUtilityWindowContentController() = default; - -void EditorColorPickerUtilityWindowContentController::OnShutdown() { - m_colorPickerPanel.ResetInteractionState(); -} - -void EditorColorPickerUtilityWindowContentController::OnResetInteractionState() { - m_colorPickerPanel.ResetInteractionState(); -} - -EditorWindowFrameTransferRequests -EditorColorPickerUtilityWindowContentController::UpdateStandaloneContent( - const EditorStandaloneUtilityWindowFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) { - m_colorPickerPanel.Update( - context.editorContext, - ColorPickerPanelHostContext{ - .mounted = true, - .bounds = context.bounds, - .allowInteraction = true, - .focused = context.focused, - .focusGained = context.focusGained, - .focusLost = context.focusLost, - }, - context.inputEvents); - - ::XCEngine::UI::UIDrawList& drawList = - drawData.EmplaceDrawList("XCEditorUtility.ColorPicker"); - m_colorPickerPanel.Append(drawList); - return {}; -} - -std::unique_ptr -CreateEditorColorPickerUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize) { - return std::make_unique( - minimumOuterSize); -} - -} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.h b/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.h deleted file mode 100644 index 3793666b..00000000 --- a/new_editor/app/Platform/Win32/Content/EditorColorPickerUtilityWindowContentController.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "Features/ColorPicker/ColorPickerPanel.h" -#include "Platform/Win32/EditorStandaloneUtilityWindowContentController.h" - -#include - -namespace XCEngine::UI::Editor::App { - -class EditorColorPickerUtilityWindowContentController final - : public EditorStandaloneUtilityWindowContentController { -public: - explicit EditorColorPickerUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize); - ~EditorColorPickerUtilityWindowContentController() override; - -private: - void OnShutdown() override; - void OnResetInteractionState() override; - EditorWindowFrameTransferRequests UpdateStandaloneContent( - const EditorStandaloneUtilityWindowFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) override; - - ColorPickerPanel m_colorPickerPanel = {}; -}; - -std::unique_ptr -CreateEditorColorPickerUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize); - -} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.cpp b/new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.cpp deleted file mode 100644 index 281b9b69..00000000 --- a/new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "Platform/Win32/EditorStandaloneUtilityWindowContentController.h" - -#include - -namespace XCEngine::UI::Editor::App { - -using ::XCEngine::UI::UIInputEvent; -using ::XCEngine::UI::UIInputEventType; - -EditorStandaloneUtilityWindowContentController:: - EditorStandaloneUtilityWindowContentController( - const ::XCEngine::UI::UISize& minimumOuterSize) - : m_minimumOuterSize(minimumOuterSize) {} - -EditorStandaloneUtilityWindowContentController:: - ~EditorStandaloneUtilityWindowContentController() = default; - -void EditorStandaloneUtilityWindowContentController::ReplaceWorkspaceController( - UIEditorWorkspaceController) {} - -void EditorStandaloneUtilityWindowContentController::Shutdown() { - OnShutdown(); - m_shellInteractionState = {}; - m_shellFrame = {}; - m_windowFocused = false; -} - -void EditorStandaloneUtilityWindowContentController::ResetInteractionState() { - OnResetInteractionState(); -} - -EditorWindowFrameTransferRequests -EditorStandaloneUtilityWindowContentController::UpdateAndAppend( - const EditorWindowContentFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) { - bool focusGained = false; - bool focusLost = false; - for (const UIInputEvent& event : context.inputEvents) { - if (event.type == UIInputEventType::FocusGained) { - m_windowFocused = true; - focusGained = true; - } else if (event.type == UIInputEventType::FocusLost) { - m_windowFocused = false; - focusLost = true; - } - } - - m_shellInteractionState.focused = m_windowFocused; - m_shellFrame.focused = m_windowFocused; - return UpdateStandaloneContent( - EditorStandaloneUtilityWindowFrameContext{ - .editorContext = context.editorContext, - .bounds = context.bounds, - .inputEvents = context.inputEvents, - .focused = m_windowFocused, - .focusGained = focusGained, - .focusLost = focusLost, - }, - drawData); -} - -const UIEditorShellInteractionFrame& -EditorStandaloneUtilityWindowContentController::GetShellFrame() const { - return m_shellFrame; -} - -const UIEditorShellInteractionState& -EditorStandaloneUtilityWindowContentController::GetShellInteractionState() const { - return m_shellInteractionState; -} - -::XCEngine::UI::UISize -EditorStandaloneUtilityWindowContentController::ResolveMinimumOuterSize() const { - return m_minimumOuterSize; -} - -void EditorStandaloneUtilityWindowContentController::OnShutdown() {} - -void EditorStandaloneUtilityWindowContentController::OnResetInteractionState() {} - -} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp b/new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp new file mode 100644 index 00000000..da51ebca --- /dev/null +++ b/new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp @@ -0,0 +1,103 @@ +#include "Platform/Win32/Content/EditorUtilityWindowContentController.h" + +#include "UtilityWindows/EditorUtilityWindowPanel.h" +#include "UtilityWindows/EditorUtilityWindowRegistry.h" + +#include + +namespace XCEngine::UI::Editor::App { + +using ::XCEngine::UI::UIInputEvent; +using ::XCEngine::UI::UIInputEventType; + +EditorUtilityWindowContentController::EditorUtilityWindowContentController( + std::unique_ptr panel, + const ::XCEngine::UI::UISize& minimumOuterSize) + : m_panel(std::move(panel)), + m_minimumOuterSize(minimumOuterSize) {} + +EditorUtilityWindowContentController::~EditorUtilityWindowContentController() = default; + +void EditorUtilityWindowContentController::Shutdown() { + if (m_panel != nullptr) { + m_panel->ResetInteractionState(); + } + m_shellInteractionState = {}; + m_shellFrame = {}; + m_windowFocused = false; +} + +void EditorUtilityWindowContentController::ResetInteractionState() { + if (m_panel != nullptr) { + m_panel->ResetInteractionState(); + } +} + +EditorWindowFrameTransferRequests +EditorUtilityWindowContentController::UpdateAndAppend( + const EditorWindowContentFrameContext& context, + ::XCEngine::UI::UIDrawData& drawData) { + bool focusGained = false; + bool focusLost = false; + for (const UIInputEvent& event : context.inputEvents) { + if (event.type == UIInputEventType::FocusGained) { + m_windowFocused = true; + focusGained = true; + } else if (event.type == UIInputEventType::FocusLost) { + m_windowFocused = false; + focusLost = true; + } + } + + m_shellInteractionState.focused = m_windowFocused; + m_shellFrame.focused = m_windowFocused; + + if (m_panel == nullptr) { + return {}; + } + + m_panel->Update( + context.editorContext, + EditorUtilityWindowHostContext{ + .mounted = true, + .bounds = context.bounds, + .allowInteraction = true, + .focused = m_windowFocused, + .focusGained = focusGained, + .focusLost = focusLost, + }, + context.inputEvents); + + ::XCEngine::UI::UIDrawList& drawList = + drawData.EmplaceDrawList(std::string(m_panel->GetDrawListId())); + m_panel->Append(drawList); + return {}; +} + +const UIEditorShellInteractionFrame& EditorUtilityWindowContentController::GetShellFrame() const { + return m_shellFrame; +} + +const UIEditorShellInteractionState& +EditorUtilityWindowContentController::GetShellInteractionState() const { + return m_shellInteractionState; +} + +::XCEngine::UI::UISize EditorUtilityWindowContentController::ResolveMinimumOuterSize() const { + return m_minimumOuterSize; +} + +std::unique_ptr CreateEditorUtilityWindowContentController( + const EditorUtilityWindowDescriptor& descriptor) { + std::unique_ptr panel = + CreateEditorUtilityWindowPanel(descriptor.kind); + if (panel == nullptr) { + return nullptr; + } + + return std::make_unique( + std::move(panel), + descriptor.minimumOuterSize); +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.h b/new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.h similarity index 52% rename from new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.h rename to new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.h index d964b7f9..2b31125d 100644 --- a/new_editor/app/Platform/Win32/Content/EditorStandaloneUtilityWindowContentController.h +++ b/new_editor/app/Platform/Win32/Content/EditorUtilityWindowContentController.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowContentController.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" #include @@ -10,47 +10,35 @@ namespace XCEngine::UI::Editor::App { -struct EditorStandaloneUtilityWindowFrameContext { - EditorContext& editorContext; - const ::XCEngine::UI::UIRect& bounds; - const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents; - bool focused = false; - bool focusGained = false; - bool focusLost = false; -}; +class EditorUtilityWindowPanel; +struct EditorUtilityWindowDescriptor; -class EditorStandaloneUtilityWindowContentController +class EditorUtilityWindowContentController final : public EditorWindowContentController { public: - explicit EditorStandaloneUtilityWindowContentController( + EditorUtilityWindowContentController( + std::unique_ptr panel, const ::XCEngine::UI::UISize& minimumOuterSize); - ~EditorStandaloneUtilityWindowContentController() override; + ~EditorUtilityWindowContentController() override; - void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) override; void Shutdown() override; void ResetInteractionState() override; - EditorWindowFrameTransferRequests UpdateAndAppend( const EditorWindowContentFrameContext& context, ::XCEngine::UI::UIDrawData& drawData) override; - const UIEditorShellInteractionFrame& GetShellFrame() const override; const UIEditorShellInteractionState& GetShellInteractionState() const override; - ::XCEngine::UI::UISize ResolveMinimumOuterSize() const override; -protected: - virtual void OnShutdown(); - virtual void OnResetInteractionState(); - virtual EditorWindowFrameTransferRequests UpdateStandaloneContent( - const EditorStandaloneUtilityWindowFrameContext& context, - ::XCEngine::UI::UIDrawData& drawData) = 0; - private: + std::unique_ptr m_panel = {}; ::XCEngine::UI::UISize m_minimumOuterSize = {}; UIEditorShellInteractionState m_shellInteractionState = {}; UIEditorShellInteractionFrame m_shellFrame = {}; bool m_windowFocused = true; }; +std::unique_ptr CreateEditorUtilityWindowContentController( + const EditorUtilityWindowDescriptor& descriptor); + } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorWindowContentController.h b/new_editor/app/Platform/Win32/Content/EditorWindowContentController.h index 1e975500..5a883f9b 100644 --- a/new_editor/app/Platform/Win32/Content/EditorWindowContentController.h +++ b/new_editor/app/Platform/Win32/Content/EditorWindowContentController.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include #include @@ -41,12 +41,12 @@ struct UIEditorDockHostDropPreviewState; } // namespace XCEngine::UI::Editor -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::Rendering::Host { -class TexturePort; -class ViewportRenderPort; +class UiTextureHost; +class ViewportRenderHost; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host namespace XCEngine::UI::Editor::App { @@ -58,12 +58,57 @@ enum class EditorWindowContentCursorKind : std::uint8_t { ResizeNS, }; +class EditorWindowWorkspaceBinding { +public: + virtual ~EditorWindowWorkspaceBinding() = default; + + virtual const UIEditorWorkspaceController* TryGetWorkspaceController() const = 0; + virtual void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) = 0; +}; + +class EditorWindowDockHostBinding { +public: + virtual ~EditorWindowDockHostBinding() = default; + + virtual void SetExternalDockHostDropPreview( + const Widgets::UIEditorDockHostDropPreviewState& preview) = 0; + virtual void ClearExternalDockHostDropPreview() = 0; + virtual bool TryResolveDockTabDragHotspot( + std::string_view nodeId, + std::string_view panelId, + const ::XCEngine::UI::UIPoint& point, + ::XCEngine::UI::UIPoint& outHotspot) const = 0; + virtual UIEditorDockHostTabDropTarget ResolveDockTabDropTarget( + const ::XCEngine::UI::UIPoint& point) const = 0; +}; + +class EditorWindowInputFeedbackBinding { +public: + virtual ~EditorWindowInputFeedbackBinding() = default; + + virtual bool HasHostedContentCapture() const = 0; + virtual bool HasShellInteractiveCapture() const = 0; + virtual bool HasInteractiveCapture() const = 0; + virtual EditorWindowContentCursorKind GetHostedContentCursorKind() const = 0; + virtual EditorWindowContentCursorKind GetDockCursorKind() const = 0; +}; + +class EditorWindowTitleBarBinding { +public: + virtual ~EditorWindowTitleBarBinding() = default; + + virtual bool ShouldUseDetachedTitleBarTabStrip() const = 0; + virtual std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const = 0; + virtual std::string ResolveDetachedWindowTitleText( + std::string_view fallbackWindowTitle) const = 0; +}; + struct EditorWindowContentInitializationContext { const std::filesystem::path& repoRoot; EditorContext& editorContext; - Ports::TexturePort& textureHost; + Rendering::Host::UiTextureHost& textureHost; UIEditorTextMeasurer& textMeasurer; - Ports::ViewportRenderPort& viewportRenderer; + Rendering::Host::ViewportRenderHost& viewportRenderer; }; struct EditorWindowContentFrameContext { @@ -80,13 +125,24 @@ class EditorWindowContentController { public: virtual ~EditorWindowContentController() = default; - virtual const UIEditorWorkspaceController* TryGetWorkspaceController() const { + virtual EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() { return nullptr; } - virtual UIEditorWorkspaceController* TryGetMutableWorkspaceController() { + virtual const EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() const { + return nullptr; + } + virtual EditorWindowDockHostBinding* TryGetDockHostBinding() { + return nullptr; + } + virtual const EditorWindowDockHostBinding* TryGetDockHostBinding() const { + return nullptr; + } + virtual const EditorWindowInputFeedbackBinding* TryGetInputFeedbackBinding() const { + return nullptr; + } + virtual const EditorWindowTitleBarBinding* TryGetTitleBarBinding() const { return nullptr; } - virtual void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) = 0; virtual void Initialize(const EditorWindowContentInitializationContext&) {} virtual void Shutdown() {} @@ -101,49 +157,7 @@ public: virtual const UIEditorShellInteractionFrame& GetShellFrame() const = 0; virtual const UIEditorShellInteractionState& GetShellInteractionState() const = 0; - virtual void SetExternalDockHostDropPreview( - const Widgets::UIEditorDockHostDropPreviewState&) {} - virtual void ClearExternalDockHostDropPreview() {} - - virtual bool TryResolveDockTabDragHotspot( - std::string_view, - std::string_view, - const ::XCEngine::UI::UIPoint&, - ::XCEngine::UI::UIPoint&) const { - return false; - } - virtual UIEditorDockHostTabDropTarget ResolveDockTabDropTarget( - const ::XCEngine::UI::UIPoint&) const { - return {}; - } - - virtual bool HasHostedContentCapture() const { - return false; - } - virtual bool HasShellInteractiveCapture() const { - return false; - } - virtual bool HasInteractiveCapture() const { - return false; - } - virtual EditorWindowContentCursorKind GetHostedContentCursorKind() const { - return EditorWindowContentCursorKind::Arrow; - } - virtual EditorWindowContentCursorKind GetDockCursorKind() const { - return EditorWindowContentCursorKind::Arrow; - } - virtual ::XCEngine::UI::UISize ResolveMinimumOuterSize() const = 0; - virtual bool ShouldUseDetachedTitleBarTabStrip() const { - return false; - } - virtual std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const { - return std::string(fallbackTitle); - } - virtual std::string ResolveDetachedWindowTitleText( - std::string_view fallbackWindowTitle) const { - return std::string(fallbackWindowTitle); - } }; } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp b/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp index 539cd3cc..e901f869 100644 --- a/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp +++ b/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.cpp @@ -1,4 +1,4 @@ -#include "Platform/Win32/EditorWorkspaceWindowContentController.h" +#include "Platform/Win32/Content/EditorWorkspaceWindowContentController.h" #include @@ -37,13 +37,36 @@ EditorWorkspaceWindowContentController::EditorWorkspaceWindowContentController( EditorWorkspaceWindowContentController::~EditorWorkspaceWindowContentController() = default; -const UIEditorWorkspaceController* -EditorWorkspaceWindowContentController::TryGetWorkspaceController() const { - return &m_workspaceController; +EditorWindowWorkspaceBinding* EditorWorkspaceWindowContentController::TryGetWorkspaceBinding() { + return this; } -UIEditorWorkspaceController* -EditorWorkspaceWindowContentController::TryGetMutableWorkspaceController() { +const EditorWindowWorkspaceBinding* +EditorWorkspaceWindowContentController::TryGetWorkspaceBinding() const { + return this; +} + +EditorWindowDockHostBinding* EditorWorkspaceWindowContentController::TryGetDockHostBinding() { + return this; +} + +const EditorWindowDockHostBinding* +EditorWorkspaceWindowContentController::TryGetDockHostBinding() const { + return this; +} + +const EditorWindowInputFeedbackBinding* +EditorWorkspaceWindowContentController::TryGetInputFeedbackBinding() const { + return this; +} + +const EditorWindowTitleBarBinding* +EditorWorkspaceWindowContentController::TryGetTitleBarBinding() const { + return this; +} + +const UIEditorWorkspaceController* +EditorWorkspaceWindowContentController::TryGetWorkspaceController() const { return &m_workspaceController; } @@ -161,6 +184,11 @@ std::string EditorWorkspaceWindowContentController::ResolveTabStripTitleText( return ResolveUIEditorDetachedWorkspaceTitle(m_workspaceController, fallbackTitle); } +std::string EditorWorkspaceWindowContentController::ResolveDetachedWindowTitleText( + std::string_view fallbackWindowTitle) const { + return ResolveUIEditorDetachedWorkspaceTitle(m_workspaceController, fallbackWindowTitle); +} + std::unique_ptr CreateEditorWorkspaceWindowContentController( UIEditorWorkspaceController workspaceController) { return std::make_unique( diff --git a/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.h b/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.h index 0b9c2ec4..59465157 100644 --- a/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.h +++ b/new_editor/app/Platform/Win32/Content/EditorWorkspaceWindowContentController.h @@ -1,8 +1,8 @@ #pragma once #include "Composition/EditorShellRuntime.h" -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/EditorWindowFrameOrchestrator.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h" #include @@ -10,13 +10,23 @@ namespace XCEngine::UI::Editor::App { -class EditorWorkspaceWindowContentController final : public EditorWindowContentController { +class EditorWorkspaceWindowContentController final + : public EditorWindowContentController + , public EditorWindowWorkspaceBinding + , public EditorWindowDockHostBinding + , public EditorWindowInputFeedbackBinding + , public EditorWindowTitleBarBinding { public: explicit EditorWorkspaceWindowContentController(UIEditorWorkspaceController workspaceController); ~EditorWorkspaceWindowContentController() override; + EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() override; + const EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() const override; + EditorWindowDockHostBinding* TryGetDockHostBinding() override; + const EditorWindowDockHostBinding* TryGetDockHostBinding() const override; + const EditorWindowInputFeedbackBinding* TryGetInputFeedbackBinding() const override; + const EditorWindowTitleBarBinding* TryGetTitleBarBinding() const override; const UIEditorWorkspaceController* TryGetWorkspaceController() const override; - UIEditorWorkspaceController* TryGetMutableWorkspaceController() override; void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) override; void Initialize(const EditorWindowContentInitializationContext& context) override; @@ -54,6 +64,8 @@ public: ::XCEngine::UI::UISize ResolveMinimumOuterSize() const override; bool ShouldUseDetachedTitleBarTabStrip() const override; std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const override; + std::string ResolveDetachedWindowTitleText( + std::string_view fallbackWindowTitle) const override; private: UIEditorWorkspaceController m_workspaceController = {}; diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.cpp b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.cpp index e67bf73a..a4b2f2b5 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.cpp +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.cpp @@ -1,7 +1,7 @@ -#include "Platform/Win32/EditorWindowFrameDriver.h" +#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h" -#include "Platform/Win32/EditorWindowChromeController.h" -#include "Platform/Win32/EditorWindow.h" +#include "Platform/Win32/Chrome/EditorWindowChromeController.h" +#include "Platform/Win32/Windowing/EditorWindow.h" namespace XCEngine::UI::Editor::App { diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.h b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.h index 6cbcc05e..d005cb94 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.h +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameDriver.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" namespace XCEngine::UI::Editor::App { diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.cpp b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.cpp index c03af281..63c10bee 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.cpp +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.cpp @@ -1,9 +1,9 @@ -#include "Platform/Win32/EditorWindowFrameOrchestrator.h" +#include "Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h" #include "Composition/EditorContext.h" #include "Composition/EditorShellRuntime.h" #include "Composition/EditorShellVariant.h" -#include "Platform/Win32/EditorWindowSupport.h" +#include "Platform/Win32/Windowing/EditorWindowSupport.h" #include #include diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h index bbe7386b..eb080305 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.cpp b/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.cpp index 55a65a7f..8c8116b3 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.cpp +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.cpp @@ -1,4 +1,4 @@ -#include "Platform/Win32/EditorWindowInputController.h" +#include "Platform/Win32/Runtime/EditorWindowInputController.h" #include diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.h b/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.h index 6ac870d0..5f770201 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.h +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowInputController.h @@ -4,9 +4,9 @@ #define NOMINMAX #endif -#include "Platform/Win32/EditorWindowPointerCapture.h" +#include "Platform/Win32/Windowing/EditorWindowPointerCapture.h" -#include +#include #include diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp b/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp index e776ffff..e0daacb4 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.cpp @@ -1,8 +1,8 @@ -#include "Platform/Win32/EditorWindowRuntimeController.h" +#include "Platform/Win32/Runtime/EditorWindowRuntimeController.h" #include "Bootstrap/EditorResources.h" #include "Composition/EditorContext.h" -#include "Platform/Win32/EditorWindowSupport.h" +#include "Platform/Win32/Windowing/EditorWindowSupport.h" #include "Support/EmbeddedPngLoader.h" #include @@ -36,34 +36,41 @@ bool EditorWindowRuntimeController::IsReady() const { return m_ready; } -const UIEditorWorkspaceController* EditorWindowRuntimeController::TryGetWorkspaceController() const { +EditorWindowWorkspaceBinding* EditorWindowRuntimeController::TryGetWorkspaceBinding() { return m_contentController != nullptr - ? m_contentController->TryGetWorkspaceController() + ? m_contentController->TryGetWorkspaceBinding() : nullptr; } -UIEditorWorkspaceController* EditorWindowRuntimeController::TryGetMutableWorkspaceController() { +const EditorWindowWorkspaceBinding* EditorWindowRuntimeController::TryGetWorkspaceBinding() const { return m_contentController != nullptr - ? m_contentController->TryGetMutableWorkspaceController() + ? m_contentController->TryGetWorkspaceBinding() : nullptr; } -const UIEditorWorkspaceController& EditorWindowRuntimeController::GetWorkspaceController() const { - const UIEditorWorkspaceController* workspaceController = TryGetWorkspaceController(); - assert(workspaceController != nullptr); - return *workspaceController; +EditorWindowDockHostBinding* EditorWindowRuntimeController::TryGetDockHostBinding() { + return m_contentController != nullptr + ? m_contentController->TryGetDockHostBinding() + : nullptr; } -UIEditorWorkspaceController& EditorWindowRuntimeController::GetMutableWorkspaceController() { - UIEditorWorkspaceController* workspaceController = TryGetMutableWorkspaceController(); - assert(workspaceController != nullptr); - return *workspaceController; +const EditorWindowDockHostBinding* EditorWindowRuntimeController::TryGetDockHostBinding() const { + return m_contentController != nullptr + ? m_contentController->TryGetDockHostBinding() + : nullptr; } -void EditorWindowRuntimeController::ReplaceWorkspaceController( - UIEditorWorkspaceController workspaceController) { - assert(m_contentController != nullptr); - m_contentController->ReplaceWorkspaceController(std::move(workspaceController)); +const EditorWindowInputFeedbackBinding* +EditorWindowRuntimeController::TryGetInputFeedbackBinding() const { + return m_contentController != nullptr + ? m_contentController->TryGetInputFeedbackBinding() + : nullptr; +} + +const EditorWindowTitleBarBinding* EditorWindowRuntimeController::TryGetTitleBarBinding() const { + return m_contentController != nullptr + ? m_contentController->TryGetTitleBarBinding() + : nullptr; } const UIEditorShellInteractionFrame& EditorWindowRuntimeController::GetShellFrame() const { @@ -77,88 +84,11 @@ const UIEditorShellInteractionState& EditorWindowRuntimeController::GetShellInte return m_contentController->GetShellInteractionState(); } -void EditorWindowRuntimeController::SetExternalDockHostDropPreview( - const Widgets::UIEditorDockHostDropPreviewState& preview) { - assert(m_contentController != nullptr); - m_contentController->SetExternalDockHostDropPreview(preview); -} - -void EditorWindowRuntimeController::ClearExternalDockHostDropPreview() { - if (m_contentController != nullptr) { - m_contentController->ClearExternalDockHostDropPreview(); - } -} - -bool EditorWindowRuntimeController::TryResolveDockTabDragHotspot( - std::string_view nodeId, - std::string_view panelId, - const ::XCEngine::UI::UIPoint& point, - ::XCEngine::UI::UIPoint& outHotspot) const { - return m_contentController != nullptr && - m_contentController->TryResolveDockTabDragHotspot( - nodeId, - panelId, - point, - outHotspot); -} - -UIEditorDockHostTabDropTarget EditorWindowRuntimeController::ResolveDockTabDropTarget( - const ::XCEngine::UI::UIPoint& point) const { - assert(m_contentController != nullptr); - return m_contentController->ResolveDockTabDropTarget(point); -} - -bool EditorWindowRuntimeController::HasHostedContentCapture() const { - return m_contentController != nullptr && - m_contentController->HasHostedContentCapture(); -} - -bool EditorWindowRuntimeController::HasShellInteractiveCapture() const { - return m_contentController != nullptr && - m_contentController->HasShellInteractiveCapture(); -} - -bool EditorWindowRuntimeController::HasInteractiveCapture() const { - return m_contentController != nullptr && - m_contentController->HasInteractiveCapture(); -} - -EditorWindowContentCursorKind EditorWindowRuntimeController::GetHostedContentCursorKind() const { - return m_contentController != nullptr - ? m_contentController->GetHostedContentCursorKind() - : EditorWindowContentCursorKind::Arrow; -} - -EditorWindowContentCursorKind EditorWindowRuntimeController::GetDockCursorKind() const { - return m_contentController != nullptr - ? m_contentController->GetDockCursorKind() - : EditorWindowContentCursorKind::Arrow; -} - ::XCEngine::UI::UISize EditorWindowRuntimeController::ResolveMinimumOuterSize() const { assert(m_contentController != nullptr); return m_contentController->ResolveMinimumOuterSize(); } -bool EditorWindowRuntimeController::ShouldUseDetachedTitleBarTabStrip() const { - return m_contentController != nullptr && - m_contentController->ShouldUseDetachedTitleBarTabStrip(); -} - -std::string EditorWindowRuntimeController::ResolveTabStripTitleText( - std::string_view fallbackTitle) const { - return m_contentController != nullptr - ? m_contentController->ResolveTabStripTitleText(fallbackTitle) - : std::string(fallbackTitle); -} - -std::string EditorWindowRuntimeController::ResolveDetachedWindowTitleText( - std::string_view fallbackWindowTitle) const { - return m_contentController != nullptr - ? m_contentController->ResolveDetachedWindowTitleText(fallbackWindowTitle) - : std::string(fallbackWindowTitle); -} - void EditorWindowRuntimeController::SetDpiScale(float dpiScale) { m_dpiScale = dpiScale > 0.0f ? dpiScale : 1.0f; m_textSystem.SetDpiScale(m_dpiScale); @@ -248,8 +178,11 @@ bool EditorWindowRuntimeController::Initialize( LogRuntimeTrace("icons", "titlebar logo_icon.png: " + titleBarLogoError); } - if (const UIEditorWorkspaceController* workspaceController = TryGetWorkspaceController(); - workspaceController != nullptr) { + if (const EditorWindowWorkspaceBinding* workspaceBinding = TryGetWorkspaceBinding(); + workspaceBinding != nullptr) { + const UIEditorWorkspaceController* workspaceController = + workspaceBinding->TryGetWorkspaceController(); + assert(workspaceController != nullptr); LogRuntimeTrace( "app", "shell runtime initialized: " + diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.h b/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.h index 189d0603..881ca11e 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.h +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowRuntimeController.h @@ -4,8 +4,8 @@ #define NOMINMAX #endif -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/EditorWindowScreenshotController.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Runtime/EditorWindowScreenshotController.h" #include #include @@ -39,35 +39,16 @@ public: bool IsReady() const; - const UIEditorWorkspaceController* TryGetWorkspaceController() const; - UIEditorWorkspaceController* TryGetMutableWorkspaceController(); - const UIEditorWorkspaceController& GetWorkspaceController() const; - UIEditorWorkspaceController& GetMutableWorkspaceController(); - void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController); + EditorWindowWorkspaceBinding* TryGetWorkspaceBinding(); + const EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() const; + EditorWindowDockHostBinding* TryGetDockHostBinding(); + const EditorWindowDockHostBinding* TryGetDockHostBinding() const; + const EditorWindowInputFeedbackBinding* TryGetInputFeedbackBinding() const; + const EditorWindowTitleBarBinding* TryGetTitleBarBinding() const; const UIEditorShellInteractionFrame& GetShellFrame() const; const UIEditorShellInteractionState& GetShellInteractionState() const; - - void SetExternalDockHostDropPreview( - const Widgets::UIEditorDockHostDropPreviewState& preview); - void ClearExternalDockHostDropPreview(); - bool TryResolveDockTabDragHotspot( - std::string_view nodeId, - std::string_view panelId, - const ::XCEngine::UI::UIPoint& point, - ::XCEngine::UI::UIPoint& outHotspot) const; - UIEditorDockHostTabDropTarget ResolveDockTabDropTarget( - const ::XCEngine::UI::UIPoint& point) const; - bool HasHostedContentCapture() const; - bool HasShellInteractiveCapture() const; - bool HasInteractiveCapture() const; - EditorWindowContentCursorKind GetHostedContentCursorKind() const; - EditorWindowContentCursorKind GetDockCursorKind() const; ::XCEngine::UI::UISize ResolveMinimumOuterSize() const; - bool ShouldUseDetachedTitleBarTabStrip() const; - std::string ResolveTabStripTitleText(std::string_view fallbackTitle) const; - std::string ResolveDetachedWindowTitleText( - std::string_view fallbackWindowTitle) const; void SetDpiScale(float dpiScale); ::XCEngine::UI::Editor::UIEditorTextMeasurer& GetTextMeasurer(); diff --git a/new_editor/app/Platform/Win32/Runtime/EditorWindowScreenshotController.cpp b/new_editor/app/Platform/Win32/Runtime/EditorWindowScreenshotController.cpp index 7d0e1171..99fafa75 100644 --- a/new_editor/app/Platform/Win32/Runtime/EditorWindowScreenshotController.cpp +++ b/new_editor/app/Platform/Win32/Runtime/EditorWindowScreenshotController.cpp @@ -1,4 +1,4 @@ -#include "Platform/Win32/EditorWindowScreenshotController.h" +#include "Platform/Win32/Runtime/EditorWindowScreenshotController.h" #include "Support/ExecutablePath.h" diff --git a/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.cpp b/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.cpp index 5ec0cab8..37665df8 100644 --- a/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.cpp +++ b/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.cpp @@ -1,4 +1,4 @@ -#include "Platform/Win32/Win32SystemInteractionHost.h" +#include "Platform/Win32/System/Win32SystemInteractionHost.h" #include "Support/StringEncoding.h" diff --git a/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.h b/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.h index 263e5d69..1f2e9133 100644 --- a/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.h +++ b/new_editor/app/Platform/Win32/System/Win32SystemInteractionHost.h @@ -1,10 +1,10 @@ #pragma once -#include "Ports/SystemInteractionPort.h" +#include "System/SystemInteractionService.h" namespace XCEngine::UI::Editor::Host { -class Win32SystemInteractionHost final : public Ports::SystemInteractionPort { +class Win32SystemInteractionHost final : public System::SystemInteractionService { public: bool CopyTextToClipboard(std::string_view text) override; bool RevealPathInFileBrowser( diff --git a/new_editor/app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp b/new_editor/app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp index 475051c1..a271b019 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp @@ -1,4 +1,4 @@ -#include "Platform/Win32/EditorFloatingWindowPlacement.h" +#include "Platform/Win32/Windowing/EditorFloatingWindowPlacement.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.cpp b/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.cpp index ff50b22c..5c9beac1 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.cpp @@ -1,11 +1,12 @@ -#include "Platform/Win32/WindowManager/EditorUtilityWindowCoordinator.h" +#include "Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h" -#include "Platform/Win32/EditorFloatingWindowPlacement.h" -#include "Platform/Win32/EditorUtilityWindowRegistry.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" +#include "UtilityWindows/EditorUtilityWindowRegistry.h" +#include "Platform/Win32/Windowing/EditorFloatingWindowPlacement.h" +#include "Platform/Win32/Content/EditorUtilityWindowContentController.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" #include @@ -88,7 +89,7 @@ bool EditorUtilityWindowCoordinator::TryProcessOpenUtilityWindowRequest( } std::unique_ptr contentController = - CreateEditorUtilityWindowContentController(request.kind); + CreateEditorUtilityWindowContentController(*descriptor); if (contentController == nullptr) { LogRuntimeTrace( "utility", diff --git a/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h b/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h index b40aacf3..1b2ebe5e 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindow.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindow.cpp index bdb3fc49..fbbe80b1 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindow.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindow.cpp @@ -1,18 +1,19 @@ -#include "Platform/Win32/EditorWindow.h" +#include "Platform/Win32/Windowing/EditorWindow.h" #include "Bootstrap/EditorResources.h" -#include "Platform/Win32/EditorWindowChromeController.h" -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/EditorWindowFrameDriver.h" -#include "Platform/Win32/EditorWindowSupport.h" -#include "Platform/Win32/EditorWindowFrameOrchestrator.h" -#include "Platform/Win32/EditorWindowInputController.h" -#include "Platform/Win32/EditorWindowState.h" -#include "Platform/Win32/EditorWindowRuntimeController.h" +#include "Platform/Win32/Chrome/EditorWindowChromeController.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h" +#include "Platform/Win32/Windowing/EditorWindowSupport.h" +#include "Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h" +#include "Platform/Win32/Runtime/EditorWindowInputController.h" +#include "Platform/Win32/Windowing/EditorWindowState.h" +#include "Platform/Win32/Runtime/EditorWindowRuntimeController.h" #include "Composition/EditorContext.h" #include #include #include #include +#include #include #include #include @@ -124,46 +125,21 @@ bool EditorWindow::IsRenderReady() const { return m_runtime->IsReady(); } -bool EditorWindow::IsTrackingMouseLeave() const { - return m_inputController->IsTrackingMouseLeave(); -} - -bool EditorWindow::HasHoveredBorderlessResizeEdge() const { - return m_chromeController->GetHoveredBorderlessResizeEdge() != - Host::BorderlessWindowResizeEdge::None; -} - const std::wstring& EditorWindow::GetTitle() const { return m_state->window.title; } const UIEditorWorkspaceController* EditorWindow::TryGetWorkspaceController() const { - return m_runtime->TryGetWorkspaceController(); + const EditorWindowWorkspaceBinding* workspaceBinding = m_runtime->TryGetWorkspaceBinding(); + return workspaceBinding != nullptr + ? workspaceBinding->TryGetWorkspaceController() + : nullptr; } const UIEditorWorkspaceController& EditorWindow::GetWorkspaceController() const { - return m_runtime->GetWorkspaceController(); -} - -UIEditorWorkspaceController& EditorWindow::GetMutableWorkspaceController() { - return m_runtime->GetMutableWorkspaceController(); -} - -bool EditorWindow::HasHostedContentCapture() const { - return m_runtime->HasHostedContentCapture(); -} - -bool EditorWindow::HasShellInteractiveCapture() const { - return m_runtime->HasShellInteractiveCapture(); -} - -void EditorWindow::SetExternalDockHostDropPreview( - const Widgets::UIEditorDockHostDropPreviewState& preview) { - m_runtime->SetExternalDockHostDropPreview(preview); -} - -void EditorWindow::ClearExternalDockHostDropPreview() { - m_runtime->ClearExternalDockHostDropPreview(); + const UIEditorWorkspaceController* workspaceController = TryGetWorkspaceController(); + assert(workspaceController != nullptr); + return *workspaceController; } void EditorWindow::AttachHwnd(HWND hwnd) { @@ -193,17 +169,15 @@ void EditorWindow::SetPrimary(bool primary) { m_state->window.primary = primary; } -void EditorWindow::SetTrackingMouseLeave(bool trackingMouseLeave) { - m_inputController->SetTrackingMouseLeave(trackingMouseLeave); -} - void EditorWindow::SetTitle(std::wstring title) { m_state->window.title = std::move(title); UpdateCachedTitleText(); } void EditorWindow::ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) { - m_runtime->ReplaceWorkspaceController(std::move(workspaceController)); + EditorWindowWorkspaceBinding* workspaceBinding = m_runtime->TryGetWorkspaceBinding(); + assert(workspaceBinding != nullptr); + workspaceBinding->ReplaceWorkspaceController(std::move(workspaceController)); } void EditorWindow::InvalidateHostWindow() const { @@ -357,9 +331,15 @@ bool EditorWindow::TryResolveDockTabDragHotspot( std::string_view panelId, const POINT& screenPoint, POINT& outHotspot) const { + const EditorWindowDockHostBinding* dockHostBinding = m_runtime->TryGetDockHostBinding(); + if (dockHostBinding == nullptr) { + outHotspot = {}; + return false; + } + const UIPoint clientPointDips = ConvertScreenPixelsToClientDips(screenPoint); UIPoint hotspotDips = {}; - if (!m_runtime->TryResolveDockTabDragHotspot( + if (!dockHostBinding->TryResolveDockTabDragHotspot( nodeId, panelId, clientPointDips, @@ -377,7 +357,13 @@ bool EditorWindow::TryResolveDockTabDragHotspot( bool EditorWindow::TryResolveDockTabDropTarget( const POINT& screenPoint, UIEditorDockHostTabDropTarget& outTarget) const { - outTarget = m_runtime->ResolveDockTabDropTarget( + const EditorWindowDockHostBinding* dockHostBinding = m_runtime->TryGetDockHostBinding(); + if (dockHostBinding == nullptr) { + outTarget = {}; + return false; + } + + outTarget = dockHostBinding->ResolveDockTabDropTarget( ConvertScreenPixelsToClientDips(screenPoint)); return outTarget.valid; } @@ -388,7 +374,7 @@ bool EditorWindow::OnResize(UINT width, UINT height) { if (!matchedPresentedPrediction) { m_chromeController->ClearPredictedClientPixelSize(); } - if (IsBorderlessWindowEnabled() && m_state->window.hwnd != nullptr) { + if (m_state->window.hwnd != nullptr) { Host::RefreshBorderlessWindowDwmDecorations(m_state->window.hwnd); } @@ -457,106 +443,6 @@ void EditorWindow::UpdateCachedTitleText() { namespace XCEngine::UI::Editor::App { -bool EditorWindow::IsBorderlessWindowEnabled() const { - return true; -} - -bool EditorWindow::IsBorderlessWindowMaximized() const { - return m_chromeController->IsBorderlessWindowMaximized(); -} - -bool EditorWindow::HandleBorderlessWindowSystemCommand( - EditorContext& editorContext, - bool globalTabDragActive, - WPARAM wParam) { - return m_chromeController->HandleSystemCommand( - *this, - editorContext, - globalTabDragActive, - wParam); -} - -bool EditorWindow::HandleBorderlessWindowGetMinMaxInfo(LPARAM lParam) const { - return m_chromeController->HandleGetMinMaxInfo(*this, lParam); -} - -LRESULT EditorWindow::HandleBorderlessWindowNcCalcSize(WPARAM wParam, LPARAM lParam) const { - return m_chromeController->HandleNcCalcSize(*this, wParam, lParam); -} - -bool EditorWindow::QueryCurrentWindowRect(RECT& outRect) const { - return m_chromeController->QueryCurrentWindowRect(*this, outRect); -} - -bool EditorWindow::QueryBorderlessWindowWorkAreaRect(RECT& outRect) const { - return m_chromeController->QueryBorderlessWindowWorkAreaRect(*this, outRect); -} - -bool EditorWindow::ApplyPredictedWindowRectTransition( - EditorContext& editorContext, - bool globalTabDragActive, - const RECT& targetRect) { - return m_chromeController->ApplyPredictedWindowRectTransition( - *this, - editorContext, - globalTabDragActive, - targetRect); -} - -void EditorWindow::ToggleBorderlessWindowMaximizeRestore( - EditorContext& editorContext, - bool globalTabDragActive) { - m_chromeController->ToggleMaximizeRestore(*this, editorContext, globalTabDragActive); -} - -} // namespace XCEngine::UI::Editor::App - -namespace XCEngine::UI::Editor::App { - -using ::XCEngine::UI::UIRect; - -bool EditorWindow::UpdateBorderlessWindowResizeHover(LPARAM lParam) { - return m_chromeController->UpdateResizeHover(*this, lParam); -} - -bool EditorWindow::HandleBorderlessWindowResizeButtonDown(LPARAM lParam) { - return m_chromeController->HandleResizeButtonDown(*this, lParam); -} - -bool EditorWindow::HandleBorderlessWindowResizeButtonUp() { - return m_chromeController->HandleResizeButtonUp(*this); -} - -bool EditorWindow::HandleBorderlessWindowResizePointerMove( - EditorContext& editorContext, - bool globalTabDragActive) { - return m_chromeController->HandleResizePointerMove( - *this, - editorContext, - globalTabDragActive); -} - -void EditorWindow::ClearBorderlessWindowResizeState() { - m_chromeController->ClearResizeState(*this); -} - -void EditorWindow::ForceClearBorderlessWindowResizeState() { - m_chromeController->ForceClearResizeState(*this); -} - -Host::BorderlessWindowResizeEdge EditorWindow::HitTestBorderlessWindowResizeEdge( - LPARAM lParam) const { - return m_chromeController->HitTestResizeEdge(*this, lParam); -} - -void EditorWindow::ApplyBorderlessWindowResizeCursorHoverPriority() { - m_chromeController->ApplyResizeCursorHoverPriority(); -} - -} // namespace XCEngine::UI::Editor::App - -namespace XCEngine::UI::Editor::App { - using namespace EditorWindowSupport; using ::XCEngine::UI::UIDrawData; using ::XCEngine::UI::UIDrawList; @@ -656,7 +542,7 @@ EditorWindowFrameTransferRequests EditorWindow::RenderFrame( } UIDrawList& windowChromeDrawList = drawData.EmplaceDrawList("XCEditorWindow.Chrome"); - AppendBorderlessWindowChrome(windowChromeDrawList, width); + m_chromeController->AppendChrome(*this, windowChromeDrawList, width); const Host::D3D12WindowRenderLoopPresentResult presentResult = m_runtime->Present(drawData); if (!presentResult.warning.empty()) { @@ -714,11 +600,7 @@ EditorWindow::ConsumeQueuedCompletedImmediateFrameTransferRequests() { } UIRect EditorWindow::ResolveWorkspaceBounds(float clientWidthDips, float clientHeightDips) const { - if (!IsBorderlessWindowEnabled()) { - return UIRect(0.0f, 0.0f, clientWidthDips, clientHeightDips); - } - - if (ShouldUseDetachedTitleBarTabStrip()) { + if (m_chromeController->ShouldUseDetachedTitleBarTabStrip(*this)) { return UIRect(0.0f, 0.0f, clientWidthDips, clientHeightDips); } @@ -737,7 +619,8 @@ EditorWindowFrameTransferRequests EditorWindow::RenderRuntimeFrame( UIDrawData& drawData) { SyncShellCapturedPointerButtonsFromSystemState(); std::vector frameEvents = m_inputController->TakePendingEvents(); - const bool useDetachedTitleBarTabStrip = ShouldUseDetachedTitleBarTabStrip(); + const bool useDetachedTitleBarTabStrip = + m_chromeController->ShouldUseDetachedTitleBarTabStrip(*this); editorContext.AttachTextMeasurer(m_runtime->GetTextMeasurer()); const Host::D3D12WindowRenderLoopFrameContext frameContext = m_runtime->BeginFrame(); if (!frameContext.warning.empty()) { @@ -784,12 +667,16 @@ void EditorWindow::SyncShellCapturedPointerButtonsFromSystemState() { } void EditorWindow::ApplyShellRuntimePointerCapture() { - if (m_runtime->HasShellInteractiveCapture()) { + const EditorWindowInputFeedbackBinding* inputFeedbackBinding = + m_runtime->TryGetInputFeedbackBinding(); + if (inputFeedbackBinding != nullptr && + inputFeedbackBinding->HasShellInteractiveCapture()) { AcquirePointerCapture(EditorWindowPointerCaptureOwner::Shell); return; } - if (m_runtime->HasHostedContentCapture()) { + if (inputFeedbackBinding != nullptr && + inputFeedbackBinding->HasHostedContentCapture()) { AcquirePointerCapture(EditorWindowPointerCaptureOwner::HostedContent); return; } @@ -807,7 +694,6 @@ void EditorWindow::ApplyShellRuntimePointerCapture() { namespace XCEngine::UI::Editor::App { -using ::XCEngine::UI::UIInputEvent; using ::XCEngine::UI::UIInputEventType; using ::XCEngine::UI::UIPointerButton; @@ -849,16 +735,14 @@ bool EditorWindow::ApplyCurrentCursor() const { bool EditorWindow::HasInteractiveCaptureState() const { - return m_runtime->HasInteractiveCapture() || + const EditorWindowInputFeedbackBinding* inputFeedbackBinding = + m_runtime->TryGetInputFeedbackBinding(); + return (inputFeedbackBinding != nullptr && inputFeedbackBinding->HasInteractiveCapture()) || m_chromeController->IsBorderlessWindowDragRestoreArmed() || m_chromeController->IsBorderlessResizeActive() || m_inputController->HasPointerCaptureOwner(); } -EditorWindowPointerCaptureOwner EditorWindow::GetPointerCaptureOwner() const { - return m_inputController->GetPointerCaptureOwner(); -} - bool EditorWindow::OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const { return m_inputController->OwnsPointerCapture(owner); } @@ -875,10 +759,6 @@ void EditorWindow::ForceReleasePointerCapture() { m_inputController->ForceReleasePointerCapture(m_state->window.hwnd); } -void EditorWindow::ClearPointerCaptureOwner() { - m_inputController->ClearPointerCaptureOwner(); -} - void EditorWindow::TryStartImmediateShellPointerCapture(LPARAM lParam) { if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd) || @@ -904,7 +784,6 @@ void EditorWindow::QueuePointerEvent( WPARAM wParam, LPARAM lParam, bool doubleClick) { - UIInputEvent event = {}; m_inputController->QueuePointerEvent( type, button, @@ -960,30 +839,6 @@ void EditorWindow::QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARA wParam); } -void EditorWindow::QueueKeyEvent(UIInputEventType type, WPARAM wParam, LPARAM lParam) { - m_inputController->QueueKeyEvent(type, wParam, lParam); -} - -void EditorWindow::QueueCharacterEvent(WPARAM wParam, LPARAM) { - m_inputController->QueueCharacterEvent(wParam); -} - -void EditorWindow::QueueWindowFocusEvent(UIInputEventType type) { - m_inputController->QueueWindowFocusEvent(type); -} - -void EditorWindow::SyncInputModifiersFromSystemState() { - m_inputController->SyncInputModifiersFromSystemState(); -} - -void EditorWindow::ResetInputModifiers() { - m_inputController->ResetInputModifiers(); -} - -void EditorWindow::RequestManualScreenshot() { - m_runtime->RequestManualScreenshot("manual_f12"); -} - bool EditorWindow::IsPointerInsideClientArea() const { if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) { return false; @@ -1005,6 +860,8 @@ bool EditorWindow::IsPointerInsideClientArea() const { } LPCWSTR EditorWindow::ResolveCurrentCursorResource() const { + const EditorWindowInputFeedbackBinding* inputFeedbackBinding = + m_runtime->TryGetInputFeedbackBinding(); const Host::BorderlessWindowResizeEdge borderlessResizeEdge = m_chromeController->IsBorderlessResizeActive() ? m_chromeController->GetBorderlessResizeEdge() @@ -1013,7 +870,11 @@ LPCWSTR EditorWindow::ResolveCurrentCursorResource() const { return Host::ResolveBorderlessWindowResizeCursor(borderlessResizeEdge); } - switch (m_runtime->GetHostedContentCursorKind()) { + const EditorWindowContentCursorKind hostedContentCursorKind = + inputFeedbackBinding != nullptr + ? inputFeedbackBinding->GetHostedContentCursorKind() + : EditorWindowContentCursorKind::Arrow; + switch (hostedContentCursorKind) { case EditorWindowContentCursorKind::ResizeEW: return IDC_SIZEWE; case EditorWindowContentCursorKind::ResizeNS: @@ -1023,7 +884,11 @@ LPCWSTR EditorWindow::ResolveCurrentCursorResource() const { break; } - switch (m_runtime->GetDockCursorKind()) { + const EditorWindowContentCursorKind dockCursorKind = + inputFeedbackBinding != nullptr + ? inputFeedbackBinding->GetDockCursorKind() + : EditorWindowContentCursorKind::Arrow; + switch (dockCursorKind) { case EditorWindowContentCursorKind::ResizeEW: return IDC_SIZEWE; case EditorWindowContentCursorKind::ResizeNS: @@ -1037,88 +902,3 @@ LPCWSTR EditorWindow::ResolveCurrentCursorResource() const { } // namespace XCEngine::UI::Editor::App -namespace XCEngine::UI::Editor::App { - -using namespace EditorWindowSupport; - -bool EditorWindow::UpdateBorderlessWindowChromeHover(LPARAM lParam) { - return m_chromeController->UpdateChromeHover(*this, lParam); -} - -bool EditorWindow::HandleBorderlessWindowChromeButtonDown(LPARAM lParam) { - return m_chromeController->HandleChromeButtonDown(*this, lParam); -} - -bool EditorWindow::HandleBorderlessWindowChromeButtonUp( - EditorContext& editorContext, - bool globalTabDragActive, - LPARAM lParam) { - return m_chromeController->HandleChromeButtonUp( - *this, - editorContext, - globalTabDragActive, - lParam); -} - -bool EditorWindow::HandleBorderlessWindowChromeDoubleClick( - EditorContext& editorContext, - bool globalTabDragActive, - LPARAM lParam) { - return m_chromeController->HandleChromeDoubleClick( - *this, - editorContext, - globalTabDragActive, - lParam); -} - -bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove( - EditorContext& editorContext, - bool globalTabDragActive) { - return m_chromeController->HandleChromeDragRestorePointerMove( - *this, - editorContext, - globalTabDragActive); -} - -void EditorWindow::ClearBorderlessWindowChromeDragRestoreState() { - m_chromeController->ClearChromeDragRestoreState(*this); -} - -void EditorWindow::ClearBorderlessWindowChromeState() { - m_chromeController->ClearChromeState(*this); -} - -void EditorWindow::ExecuteBorderlessWindowChromeAction( - EditorContext& editorContext, - bool globalTabDragActive, - Host::BorderlessWindowChromeHitTarget target) { - m_chromeController->ExecuteChromeAction(*this, editorContext, globalTabDragActive, target); -} - -} // namespace XCEngine::UI::Editor::App - -namespace XCEngine::UI::Editor::App { - -bool EditorWindow::ShouldUseDetachedTitleBarTabStrip() const { - return m_chromeController->ShouldUseDetachedTitleBarTabStrip(*this); -} - -Host::BorderlessWindowChromeHitTarget EditorWindow::HitTestBorderlessWindowChrome( - LPARAM lParam) const { - return m_chromeController->HitTestChrome(*this, lParam); -} - -Host::BorderlessWindowChromeLayout EditorWindow::ResolveBorderlessWindowChromeLayout( - float clientWidthDips) const { - return m_chromeController->ResolveChromeLayout(*this, clientWidthDips); -} - -void EditorWindow::AppendBorderlessWindowChrome( - ::XCEngine::UI::UIDrawList& drawList, - float clientWidthDips) const { - m_chromeController->AppendChrome(*this, drawList, clientWidthDips); -} - -} // namespace XCEngine::UI::Editor::App - - diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindow.h b/new_editor/app/Platform/Win32/Windowing/EditorWindow.h index c5928272..e82d4f5a 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindow.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindow.h @@ -4,9 +4,9 @@ #define NOMINMAX #endif -#include "Platform/Win32/EditorWindowPointerCapture.h" -#include "Platform/Win32/EditorWindowState.h" -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowPointerCapture.h" +#include "Platform/Win32/Windowing/EditorWindowState.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include @@ -48,15 +48,6 @@ struct UIEditorDockHostDropPreviewState; } // namespace XCEngine::UI::Editor -namespace XCEngine::UI::Editor::Host { - -enum class BorderlessWindowChromeHitTarget : std::uint8_t; -enum class BorderlessWindowResizeEdge : std::uint8_t; - -struct BorderlessWindowChromeLayout; - -} // namespace XCEngine::UI::Editor::Host - namespace XCEngine::UI::Editor::App { class EditorContext; @@ -107,10 +98,6 @@ private: friend class EditorWindowWorkspaceCoordinator; bool IsRenderReady() const; - bool IsTrackingMouseLeave() const; - bool HasHoveredBorderlessResizeEdge() const; - bool HasHostedContentCapture() const; - bool HasShellInteractiveCapture() const; bool TryResolveDockTabDragHotspot( std::string_view nodeId, std::string_view panelId, @@ -120,9 +107,6 @@ private: const POINT& screenPoint, UIEditorDockHostTabDropTarget& outTarget) const; void InvalidateHostWindow() const; - void SetExternalDockHostDropPreview( - const Widgets::UIEditorDockHostDropPreviewState& preview); - void ClearExternalDockHostDropPreview(); void AttachHwnd(HWND hwnd); void MarkInitializing(); @@ -130,10 +114,8 @@ private: void MarkDestroyed(); void MarkClosing(); void SetPrimary(bool primary); - void SetTrackingMouseLeave(bool trackingMouseLeave); void SetTitle(std::wstring title); void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController); - UIEditorWorkspaceController& GetMutableWorkspaceController(); bool Initialize( const std::filesystem::path& repoRoot, @@ -158,46 +140,12 @@ private: bool OnExitSizeMove(); void OnDpiChanged(UINT dpi, const RECT& suggestedRect); - bool IsBorderlessWindowEnabled() const; - bool IsBorderlessWindowMaximized() const; - bool HandleBorderlessWindowSystemCommand( - EditorContext& editorContext, - bool globalTabDragActive, - WPARAM wParam); - bool HandleBorderlessWindowGetMinMaxInfo(LPARAM lParam) const; - LRESULT HandleBorderlessWindowNcCalcSize(WPARAM wParam, LPARAM lParam) const; bool ApplyCurrentCursor() const; - bool UpdateBorderlessWindowResizeHover(LPARAM lParam); - bool HandleBorderlessWindowResizeButtonDown(LPARAM lParam); - bool HandleBorderlessWindowResizeButtonUp(); - bool HandleBorderlessWindowResizePointerMove( - EditorContext& editorContext, - bool globalTabDragActive); - void ClearBorderlessWindowResizeState(); - void ForceClearBorderlessWindowResizeState(); - Host::BorderlessWindowChromeHitTarget HitTestBorderlessWindowChrome(LPARAM lParam) const; - bool UpdateBorderlessWindowChromeHover(LPARAM lParam); - bool HandleBorderlessWindowChromeButtonDown(LPARAM lParam); - bool HandleBorderlessWindowChromeButtonUp( - EditorContext& editorContext, - bool globalTabDragActive, - LPARAM lParam); - bool HandleBorderlessWindowChromeDoubleClick( - EditorContext& editorContext, - bool globalTabDragActive, - LPARAM lParam); - bool HandleBorderlessWindowChromeDragRestorePointerMove( - EditorContext& editorContext, - bool globalTabDragActive); - void ClearBorderlessWindowChromeDragRestoreState(); - void ClearBorderlessWindowChromeState(); bool HasInteractiveCaptureState() const; - EditorWindowPointerCaptureOwner GetPointerCaptureOwner() const; bool OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const; void AcquirePointerCapture(EditorWindowPointerCaptureOwner owner); void ReleasePointerCapture(EditorWindowPointerCaptureOwner owner); void ForceReleasePointerCapture(); - void ClearPointerCaptureOwner(); void TryStartImmediateShellPointerCapture(LPARAM lParam); void QueuePointerEvent( @@ -210,13 +158,7 @@ private: const ::XCEngine::UI::UIInputModifiers& modifiers); void QueuePointerLeaveEvent(); void QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARAM lParam); - void QueueKeyEvent(::XCEngine::UI::UIInputEventType type, WPARAM wParam, LPARAM lParam); - void QueueCharacterEvent(WPARAM wParam, LPARAM lParam); - void QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType type); - void SyncInputModifiersFromSystemState(); void SyncShellCapturedPointerButtonsFromSystemState(); - void ResetInputModifiers(); - void RequestManualScreenshot(); bool ApplyWindowResize(UINT width, UINT height); bool QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const; @@ -235,27 +177,6 @@ private: float PixelsToDips(float pixels) const; ::XCEngine::UI::UIPoint ConvertClientPixelsToDips(LONG x, LONG y) const; void ApplyShellRuntimePointerCapture(); - Host::BorderlessWindowResizeEdge HitTestBorderlessWindowResizeEdge(LPARAM lParam) const; - void ApplyBorderlessWindowResizeCursorHoverPriority(); - Host::BorderlessWindowChromeLayout ResolveBorderlessWindowChromeLayout( - float clientWidthDips) const; - bool QueryCurrentWindowRect(RECT& outRect) const; - bool QueryBorderlessWindowWorkAreaRect(RECT& outRect) const; - bool ApplyPredictedWindowRectTransition( - EditorContext& editorContext, - bool globalTabDragActive, - const RECT& targetRect); - bool ShouldUseDetachedTitleBarTabStrip() const; - void ToggleBorderlessWindowMaximizeRestore( - EditorContext& editorContext, - bool globalTabDragActive); - void AppendBorderlessWindowChrome( - ::XCEngine::UI::UIDrawList& drawList, - float clientWidthDips) const; - void ExecuteBorderlessWindowChromeAction( - EditorContext& editorContext, - bool globalTabDragActive, - Host::BorderlessWindowChromeHitTarget target); void UpdateCachedTitleText(); static bool IsVerboseRuntimeTraceEnabled(); diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.cpp index 5c7a6ce2..6460bd1a 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.cpp @@ -1,14 +1,14 @@ -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" #include "Bootstrap/EditorResources.h" #include "Composition/EditorContext.h" -#include "Platform/Win32/EditorWindowChromeController.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/EditorWindowFrameDriver.h" -#include "Platform/Win32/WindowManager/EditorUtilityWindowCoordinator.h" -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" -#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" +#include "Platform/Win32/Chrome/EditorWindowChromeController.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h" +#include "Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.h b/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.h index ad8d52d2..a7ded4f2 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorWindowManager.h" +#include "Platform/Win32/Windowing/EditorWindowManager.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.cpp index a74b86c7..55fa32f5 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.cpp @@ -1,8 +1,8 @@ -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" -#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h" #include #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowManager.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindowManager.cpp index 6bf9500e..83add784 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowManager.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowManager.cpp @@ -1,12 +1,12 @@ -#include "Platform/Win32/EditorWindowManager.h" +#include "Platform/Win32/Windowing/EditorWindowManager.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWindowContentController.h" -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" -#include "Platform/Win32/WindowManager/EditorUtilityWindowCoordinator.h" -#include "Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h" -#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Content/EditorWindowContentController.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" +#include "Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowMessageDispatcher.h" +#include "Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp index 90bce9c0..2e40e78b 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.cpp @@ -1,13 +1,16 @@ -#include "Platform/Win32/WindowManager/EditorWindowMessageDispatcher.h" +#include "Platform/Win32/Windowing/EditorWindowMessageDispatcher.h" -#include "Platform/Win32/BorderlessWindowChrome.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorWindowFrameDriver.h" -#include "Platform/Win32/EditorWindowPointerCapture.h" -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" -#include "Platform/Win32/WindowManager/EditorUtilityWindowCoordinator.h" -#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" +#include "Platform/Win32/Chrome/BorderlessWindowChrome.h" +#include "Platform/Win32/Chrome/EditorWindowChromeController.h" +#include "Platform/Win32/Runtime/EditorWindowInputController.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h" +#include "Platform/Win32/Runtime/EditorWindowRuntimeController.h" +#include "Platform/Win32/Windowing/EditorWindowPointerCapture.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" +#include "Platform/Win32/Windowing/EditorUtilityWindowCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h" #include #include @@ -106,7 +109,7 @@ void EditorWindowMessageDispatcher::RenderAndHandleWindowFrame(const DispatchCon } bool EditorWindowMessageDispatcher::EnsureTrackingMouseLeave(const DispatchContext& context) { - if (context.window.IsTrackingMouseLeave()) { + if (context.window.m_inputController->IsTrackingMouseLeave()) { return true; } @@ -118,7 +121,7 @@ bool EditorWindowMessageDispatcher::EnsureTrackingMouseLeave(const DispatchConte return false; } - context.window.SetTrackingMouseLeave(true); + context.window.m_inputController->SetTrackingMouseLeave(true); return true; } @@ -126,15 +129,22 @@ bool EditorWindowMessageDispatcher::TryHandleChromeHoverConsumption( const DispatchContext& context, LPARAM lParam, LRESULT& outResult) { + EditorWindowInputController& inputController = *context.window.m_inputController; + EditorWindowChromeController& chromeController = *context.window.m_chromeController; + const EditorWindowInputFeedbackBinding* inputFeedbackBinding = + context.window.m_runtime->TryGetInputFeedbackBinding(); + if (!CanConsumeEditorWindowChromeHover( - context.window.GetPointerCaptureOwner(), - context.window.HasShellInteractiveCapture(), - context.window.HasHostedContentCapture())) { + inputController.GetPointerCaptureOwner(), + inputFeedbackBinding != nullptr && + inputFeedbackBinding->HasShellInteractiveCapture(), + inputFeedbackBinding != nullptr && + inputFeedbackBinding->HasHostedContentCapture())) { return false; } - const bool resizeHoverChanged = context.window.UpdateBorderlessWindowResizeHover(lParam); - if (context.window.UpdateBorderlessWindowChromeHover(lParam)) { + const bool resizeHoverChanged = chromeController.UpdateResizeHover(context.window, lParam); + if (chromeController.UpdateChromeHover(context.window, lParam)) { context.window.InvalidateHostWindow(); } if (resizeHoverChanged) { @@ -142,13 +152,14 @@ bool EditorWindowMessageDispatcher::TryHandleChromeHoverConsumption( } EnsureTrackingMouseLeave(context); - if (context.window.HasHoveredBorderlessResizeEdge()) { + if (chromeController.GetHoveredBorderlessResizeEdge() != + Host::BorderlessWindowResizeEdge::None) { outResult = 0; return true; } const Host::BorderlessWindowChromeHitTarget chromeHitTarget = - context.window.HitTestBorderlessWindowChrome(lParam); + chromeController.HitTestChrome(context.window, lParam); if (chromeHitTarget == Host::BorderlessWindowChromeHitTarget::MinimizeButton || chromeHitTarget == Host::BorderlessWindowChromeHitTarget::MaximizeRestoreButton || chromeHitTarget == Host::BorderlessWindowChromeHitTarget::CloseButton) { @@ -165,26 +176,31 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowPointerMessage( WPARAM wParam, LPARAM lParam, LRESULT& outResult) { + EditorWindowInputController& inputController = *context.window.m_inputController; + EditorWindowChromeController& chromeController = *context.window.m_chromeController; + switch (message) { case WM_MOUSEMOVE: if (CanRouteEditorWindowGlobalTabDragPointerMessages( - context.window.GetPointerCaptureOwner(), + inputController.GetPointerCaptureOwner(), context.workspaceCoordinator.OwnsActiveGlobalTabDrag(context.window.GetWindowId())) && context.workspaceCoordinator.HandleGlobalTabDragPointerMove(context.hwnd)) { outResult = 0; return true; } if (CanRouteEditorWindowBorderlessResizePointerMessages( - context.window.GetPointerCaptureOwner()) && - context.window.HandleBorderlessWindowResizePointerMove( + inputController.GetPointerCaptureOwner()) && + chromeController.HandleResizePointerMove( + context.window, context.hostRuntime.GetEditorContext(), context.workspaceCoordinator.IsGlobalTabDragActive())) { outResult = 0; return true; } if (CanRouteEditorWindowBorderlessChromePointerMessages( - context.window.GetPointerCaptureOwner()) && - context.window.HandleBorderlessWindowChromeDragRestorePointerMove( + inputController.GetPointerCaptureOwner()) && + chromeController.HandleChromeDragRestorePointerMove( + context.window, context.hostRuntime.GetEditorContext(), context.workspaceCoordinator.IsGlobalTabDragActive())) { outResult = 0; @@ -202,10 +218,10 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowPointerMessage( outResult = 0; return true; case WM_MOUSELEAVE: - context.window.SetTrackingMouseLeave(false); - context.window.ClearBorderlessWindowResizeState(); - context.window.ClearBorderlessWindowChromeDragRestoreState(); - context.window.ClearBorderlessWindowChromeState(); + inputController.SetTrackingMouseLeave(false); + chromeController.ClearResizeState(context.window); + chromeController.ClearChromeDragRestoreState(context.window); + chromeController.ClearChromeState(context.window); context.window.QueuePointerLeaveEvent(); outResult = 0; return true; @@ -213,11 +229,11 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowPointerMessage( if (context.workspaceCoordinator.OwnsActiveGlobalTabDrag(context.window.GetWindowId())) { context.workspaceCoordinator.EndGlobalTabDragSession(); } - if (context.window.HandleBorderlessWindowResizeButtonDown(lParam)) { + if (chromeController.HandleResizeButtonDown(context.window, lParam)) { outResult = 0; return true; } - if (context.window.HandleBorderlessWindowChromeButtonDown(lParam)) { + if (chromeController.HandleChromeButtonDown(context.window, lParam)) { outResult = 0; return true; } @@ -255,21 +271,22 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowPointerMessage( return true; case WM_LBUTTONUP: if (CanRouteEditorWindowGlobalTabDragPointerMessages( - context.window.GetPointerCaptureOwner(), + inputController.GetPointerCaptureOwner(), context.workspaceCoordinator.OwnsActiveGlobalTabDrag(context.window.GetWindowId())) && context.workspaceCoordinator.HandleGlobalTabDragPointerButtonUp(context.hwnd)) { outResult = 0; return true; } if (CanRouteEditorWindowBorderlessResizePointerMessages( - context.window.GetPointerCaptureOwner()) && - context.window.HandleBorderlessWindowResizeButtonUp()) { + inputController.GetPointerCaptureOwner()) && + chromeController.HandleResizeButtonUp(context.window)) { outResult = 0; return true; } if (CanRouteEditorWindowBorderlessChromePointerMessages( - context.window.GetPointerCaptureOwner()) && - context.window.HandleBorderlessWindowChromeButtonUp( + inputController.GetPointerCaptureOwner()) && + chromeController.HandleChromeButtonUp( + context.window, context.hostRuntime.GetEditorContext(), context.workspaceCoordinator.IsGlobalTabDragActive(), lParam)) { @@ -300,7 +317,8 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowPointerMessage( outResult = 0; return true; case WM_LBUTTONDBLCLK: - if (context.window.HandleBorderlessWindowChromeDoubleClick( + if (chromeController.HandleChromeDoubleClick( + context.window, context.hostRuntime.GetEditorContext(), context.workspaceCoordinator.IsGlobalTabDragActive(), lParam)) { @@ -351,24 +369,27 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowInputMessage( WPARAM wParam, LPARAM lParam, LRESULT& outResult) { + EditorWindowInputController& inputController = *context.window.m_inputController; + EditorWindowChromeController& chromeController = *context.window.m_chromeController; + if (TryDispatchWindowPointerMessage(context, message, wParam, lParam, outResult)) { return true; } switch (message) { case WM_SETFOCUS: - context.window.SyncInputModifiersFromSystemState(); - context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusGained); + inputController.SyncInputModifiersFromSystemState(); + inputController.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusGained); outResult = 0; return true; case WM_KILLFOCUS: - context.window.ResetInputModifiers(); - context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost); + inputController.ResetInputModifiers(); + inputController.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost); outResult = 0; return true; case WM_CAPTURECHANGED: if (reinterpret_cast(lParam) != context.hwnd) { - context.window.ClearPointerCaptureOwner(); + inputController.ClearPointerCaptureOwner(); } if (context.workspaceCoordinator.OwnsActiveGlobalTabDrag(context.window.GetWindowId()) && reinterpret_cast(lParam) != context.hwnd) { @@ -378,34 +399,34 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowInputMessage( } if (reinterpret_cast(lParam) != context.hwnd && context.window.HasInteractiveCaptureState()) { - context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost); - context.window.ForceClearBorderlessWindowResizeState(); - context.window.ClearBorderlessWindowChromeDragRestoreState(); - context.window.ClearBorderlessWindowChromeState(); + inputController.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost); + chromeController.ForceClearResizeState(context.window); + chromeController.ClearChromeDragRestoreState(context.window); + chromeController.ClearChromeState(context.window); outResult = 0; return true; } if (reinterpret_cast(lParam) != context.hwnd) { - context.window.ForceClearBorderlessWindowResizeState(); - context.window.ClearBorderlessWindowChromeDragRestoreState(); - context.window.ClearBorderlessWindowChromeState(); + chromeController.ForceClearResizeState(context.window); + chromeController.ClearChromeDragRestoreState(context.window); + chromeController.ClearChromeState(context.window); } return false; case WM_KEYDOWN: case WM_SYSKEYDOWN: if (wParam == VK_F12) { - context.window.RequestManualScreenshot(); + context.window.m_runtime->RequestManualScreenshot("manual_f12"); } - context.window.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyDown, wParam, lParam); + inputController.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyDown, wParam, lParam); outResult = 0; return true; case WM_KEYUP: case WM_SYSKEYUP: - context.window.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyUp, wParam, lParam); + inputController.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyUp, wParam, lParam); outResult = 0; return true; case WM_CHAR: - context.window.QueueCharacterEvent(wParam, lParam); + inputController.QueueCharacterEvent(wParam); outResult = 0; return true; default: @@ -481,42 +502,32 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowChromeMessage( WPARAM wParam, LPARAM lParam, LRESULT& outResult) { + EditorWindowChromeController& chromeController = *context.window.m_chromeController; + switch (message) { case WM_GETMINMAXINFO: - if (context.window.IsBorderlessWindowEnabled() && - context.window.HandleBorderlessWindowGetMinMaxInfo(lParam)) { + if (chromeController.HandleGetMinMaxInfo(context.window, lParam)) { outResult = 0; return true; } return false; case WM_NCCALCSIZE: - if (context.window.IsBorderlessWindowEnabled()) { - outResult = context.window.HandleBorderlessWindowNcCalcSize(wParam, lParam); - return true; - } - return false; + outResult = chromeController.HandleNcCalcSize(context.window, wParam, lParam); + return true; case WM_NCACTIVATE: - if (context.window.IsBorderlessWindowEnabled()) { - outResult = TRUE; - return true; - } - return false; + outResult = TRUE; + return true; case WM_NCHITTEST: - if (context.window.IsBorderlessWindowEnabled()) { - outResult = HTCLIENT; - return true; - } - return false; + outResult = HTCLIENT; + return true; case WM_NCPAINT: case kMessageNcUaDrawCaption: case kMessageNcUaDrawFrame: - if (context.window.IsBorderlessWindowEnabled()) { - outResult = 0; - return true; - } - return false; + outResult = 0; + return true; case WM_SYSCOMMAND: - if (context.window.HandleBorderlessWindowSystemCommand( + if (chromeController.HandleSystemCommand( + context.window, context.hostRuntime.GetEditorContext(), context.workspaceCoordinator.IsGlobalTabDragActive(), wParam)) { diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.h b/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.h index 2bf60349..d506a727 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.h @@ -1,10 +1,10 @@ -#pragma once +#pragma once #ifndef NOMINMAX #define NOMINMAX #endif -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowTransferRequests.h b/new_editor/app/Platform/Win32/Windowing/EditorWindowTransferRequests.h index 185685b5..363cad23 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowTransferRequests.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowTransferRequests.h @@ -4,7 +4,7 @@ #define NOMINMAX #endif -#include "Platform/Win32/EditorUtilityWindowKind.h" +#include "UtilityWindows/EditorUtilityWindowKind.h" #include diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp b/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp index 31872b58..e924b001 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.cpp @@ -1,11 +1,12 @@ -#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h" #include "Composition/EditorContext.h" -#include "Platform/Win32/EditorWindow.h" -#include "Platform/Win32/EditorFloatingWindowPlacement.h" -#include "Platform/Win32/EditorWorkspaceWindowContentController.h" -#include "Platform/Win32/WindowManager/EditorWindowHostRuntime.h" -#include "Platform/Win32/WindowManager/EditorWindowLifecycleCoordinator.h" +#include "Platform/Win32/Windowing/EditorWindow.h" +#include "Platform/Win32/Windowing/EditorFloatingWindowPlacement.h" +#include "Platform/Win32/Content/EditorWorkspaceWindowContentController.h" +#include "Platform/Win32/Runtime/EditorWindowRuntimeController.h" +#include "Platform/Win32/Windowing/EditorWindowHostRuntime.h" +#include "Platform/Win32/Windowing/EditorWindowLifecycleCoordinator.h" #include #include @@ -469,8 +470,12 @@ void EditorWindowWorkspaceCoordinator::ClearGlobalTabDragDropPreview() { if (EditorWindow* previewWindow = m_hostRuntime.FindWindow(m_globalTabDragSession.previewWindowId); IsLiveInteractiveWindow(previewWindow)) { - previewWindow->ClearExternalDockHostDropPreview(); - previewWindow->InvalidateHostWindow(); + if (EditorWindowDockHostBinding* dockHostBinding = + previewWindow->m_runtime->TryGetDockHostBinding(); + dockHostBinding != nullptr) { + dockHostBinding->ClearExternalDockHostDropPreview(); + previewWindow->InvalidateHostWindow(); + } } m_globalTabDragSession.previewWindowId.clear(); } @@ -508,8 +513,12 @@ void EditorWindowWorkspaceCoordinator::UpdateGlobalTabDragDropPreview() { preview.targetNodeId = dropTarget.nodeId; preview.placement = dropTarget.placement; preview.insertionIndex = dropTarget.insertionIndex; - targetWindow->SetExternalDockHostDropPreview(preview); - targetWindow->InvalidateHostWindow(); + if (EditorWindowDockHostBinding* dockHostBinding = + targetWindow->m_runtime->TryGetDockHostBinding(); + dockHostBinding != nullptr) { + dockHostBinding->SetExternalDockHostDropPreview(preview); + targetWindow->InvalidateHostWindow(); + } m_globalTabDragSession.previewWindowId = std::string(targetWindow->GetWindowId()); } diff --git a/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h b/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h index 40f954f6..d61ffc78 100644 --- a/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h +++ b/new_editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.h @@ -5,7 +5,7 @@ #endif #include "Composition/EditorWindowWorkspaceStore.h" -#include "Platform/Win32/EditorWindowTransferRequests.h" +#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h" #include diff --git a/new_editor/app/Ports/PortFwd.h b/new_editor/app/Ports/PortFwd.h deleted file mode 100644 index f659d2c4..00000000 --- a/new_editor/app/Ports/PortFwd.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace XCEngine::UI::Editor::Ports { - -class ShaderResourceDescriptorAllocatorPort; -class SystemInteractionPort; -class TexturePort; -class ViewportRenderPort; - -} // namespace XCEngine::UI::Editor::Ports diff --git a/new_editor/app/Ports/ShaderResourceDescriptorAllocatorPort.h b/new_editor/app/Ports/ShaderResourceDescriptorAllocatorPort.h deleted file mode 100644 index caaf8310..00000000 --- a/new_editor/app/Ports/ShaderResourceDescriptorAllocatorPort.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#include -#include - -#include - -namespace XCEngine::UI::Editor::Ports { - -class ShaderResourceDescriptorAllocatorPort { -public: - virtual ~ShaderResourceDescriptorAllocatorPort() = default; - - virtual bool Initialize(::XCEngine::RHI::RHIDevice& device, UINT descriptorCount = 64u) = 0; - virtual void Shutdown() = 0; - - [[nodiscard]] virtual bool IsInitialized() const = 0; - virtual bool CreateTextureDescriptor( - ::XCEngine::RHI::RHITexture* texture, - D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle, - D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) = 0; - virtual void Free( - D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle, - D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle) = 0; -}; - -} // namespace XCEngine::UI::Editor::Ports diff --git a/new_editor/app/Rendering/Assets/BuiltInIcons.cpp b/new_editor/app/Rendering/Assets/BuiltInIcons.cpp index 7b9d80a8..5624e0c1 100644 --- a/new_editor/app/Rendering/Assets/BuiltInIcons.cpp +++ b/new_editor/app/Rendering/Assets/BuiltInIcons.cpp @@ -1,7 +1,7 @@ #include "BuiltInIcons.h" #include "Bootstrap/EditorResources.h" -#include "Ports/TexturePort.h" +#include "Rendering/Host/UiTextureHost.h" #include "Support/EmbeddedPngLoader.h" #include "Support/StringEncoding.h" @@ -63,7 +63,7 @@ void AppendLoadError( } void LoadEmbeddedIconTexture( - Ports::TexturePort& renderer, + Rendering::Host::UiTextureHost& renderer, UINT resourceId, std::string_view label, ::XCEngine::UI::UITextureHandle& outTexture, @@ -494,7 +494,7 @@ bool DecodeTextureFromFile( } // namespace -void BuiltInIcons::Initialize(Ports::TexturePort& renderer) { +void BuiltInIcons::Initialize(Rendering::Host::UiTextureHost& renderer) { Shutdown(); m_renderer = &renderer; diff --git a/new_editor/app/Rendering/Assets/BuiltInIcons.h b/new_editor/app/Rendering/Assets/BuiltInIcons.h index 08c0563e..39bf145f 100644 --- a/new_editor/app/Rendering/Assets/BuiltInIcons.h +++ b/new_editor/app/Rendering/Assets/BuiltInIcons.h @@ -1,6 +1,6 @@ #pragma once -#include "Ports/PortFwd.h" +#include "Rendering/Host/HostFwd.h" #include @@ -32,7 +32,7 @@ enum class BuiltInIconKind : std::uint8_t { class BuiltInIcons { public: - void Initialize(Ports::TexturePort& renderer); + void Initialize(Rendering::Host::UiTextureHost& renderer); void Shutdown(); void BeginFrame(); @@ -108,7 +108,7 @@ private: const std::filesystem::path& projectRoot); void PruneAssetPreviewCache(); - Ports::TexturePort* m_renderer = nullptr; + Rendering::Host::UiTextureHost* m_renderer = nullptr; ::XCEngine::UI::UITextureHandle m_folderIcon = {}; ::XCEngine::UI::UITextureHandle m_gameObjectIcon = {}; ::XCEngine::UI::UITextureHandle m_sceneIcon = {}; diff --git a/new_editor/app/Rendering/D3D12/D3D12ShaderResourceDescriptorAllocator.h b/new_editor/app/Rendering/D3D12/D3D12ShaderResourceDescriptorAllocator.h index 253bc616..e0bf9e83 100644 --- a/new_editor/app/Rendering/D3D12/D3D12ShaderResourceDescriptorAllocator.h +++ b/new_editor/app/Rendering/D3D12/D3D12ShaderResourceDescriptorAllocator.h @@ -4,8 +4,6 @@ #define NOMINMAX #endif -#include "Ports/ShaderResourceDescriptorAllocatorPort.h" - #include #include #include @@ -20,13 +18,12 @@ namespace XCEngine::UI::Editor::Host { -class D3D12ShaderResourceDescriptorAllocator - : public Ports::ShaderResourceDescriptorAllocatorPort { +class D3D12ShaderResourceDescriptorAllocator { public: - bool Initialize(::XCEngine::RHI::RHIDevice& device, UINT descriptorCount = 64u) override; - void Shutdown() override; + bool Initialize(::XCEngine::RHI::RHIDevice& device, UINT descriptorCount = 64u); + void Shutdown(); - bool IsInitialized() const override; + bool IsInitialized() const; ID3D12DescriptorHeap* GetDescriptorHeap() const; UINT GetDescriptorSize() const; UINT GetDescriptorCount() const; @@ -37,10 +34,10 @@ public: bool CreateTextureDescriptor( ::XCEngine::RHI::RHITexture* texture, D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle, - D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) override; + D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle); void Free( D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle, - D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle) override; + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle); private: void AllocateInternal( diff --git a/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.cpp b/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.cpp index 25e6d709..c68b595a 100644 --- a/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.cpp +++ b/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.cpp @@ -651,6 +651,44 @@ float D3D12UiTextSystem::MeasureTextWidth( return std::ceil(width * dpiScale) / dpiScale; } +float D3D12UiTextSystem::MeasureTextAdvance( + const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const { + if (!m_dwriteFactory || request.text.empty()) { + return 0.0f; + } + + const std::wstring text = Utf8ToWide(request.text); + if (text.empty()) { + return 0.0f; + } + + const float dpiScale = ClampDpiScale(m_dpiScale); + const float resolvedFontSize = ResolveDisplayFontSize(request.fontSize); + IDWriteTextFormat* textFormat = GetTextFormat(resolvedFontSize); + if (textFormat == nullptr) { + return 0.0f; + } + + Microsoft::WRL::ComPtr textLayout = {}; + const HRESULT hr = m_dwriteFactory->CreateTextLayout( + text.c_str(), + static_cast(text.size()), + textFormat, + 4096.0f, + resolvedFontSize * 2.0f, + textLayout.ReleaseAndGetAddressOf()); + if (FAILED(hr) || textLayout == nullptr) { + return 0.0f; + } + + DWRITE_TEXT_METRICS textMetrics = {}; + if (FAILED(textLayout->GetMetrics(&textMetrics))) { + return 0.0f; + } + + return std::ceil(textMetrics.widthIncludingTrailingWhitespace * dpiScale) / dpiScale; +} + bool D3D12UiTextSystem::RasterizeTextMask( std::string_view text, float fontSize, diff --git a/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.h b/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.h index 2d292c20..707d9765 100644 --- a/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.h +++ b/new_editor/app/Rendering/D3D12/D3D12UiTextSystem.h @@ -63,6 +63,8 @@ public: float MeasureTextWidth( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; + float MeasureTextAdvance( + const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; bool ShapeTextRun( std::string_view text, float fontSize, diff --git a/new_editor/app/Rendering/D3D12/D3D12UiTextureHost.h b/new_editor/app/Rendering/D3D12/D3D12UiTextureHost.h index dec353d2..af5412de 100644 --- a/new_editor/app/Rendering/D3D12/D3D12UiTextureHost.h +++ b/new_editor/app/Rendering/D3D12/D3D12UiTextureHost.h @@ -4,7 +4,7 @@ #define NOMINMAX #endif -#include "Ports/TexturePort.h" +#include "Rendering/Host/UiTextureHost.h" #include @@ -24,7 +24,7 @@ namespace XCEngine::UI::Editor::Host { -class D3D12UiTextureHost final : public Ports::TexturePort { +class D3D12UiTextureHost final : public Rendering::Host::UiTextureHost { public: bool Initialize(D3D12WindowRenderer& windowRenderer); void Shutdown(); diff --git a/new_editor/app/Rendering/D3D12/D3D12WindowRenderer.h b/new_editor/app/Rendering/D3D12/D3D12WindowRenderer.h index 530c88f6..7e1bfeae 100644 --- a/new_editor/app/Rendering/D3D12/D3D12WindowRenderer.h +++ b/new_editor/app/Rendering/D3D12/D3D12WindowRenderer.h @@ -4,7 +4,7 @@ #define NOMINMAX #endif -#include "Ports/ViewportRenderPort.h" +#include "Rendering/Host/ViewportRenderHost.h" #include "D3D12HostDevice.h" #include "D3D12ShaderResourceDescriptorAllocator.h" #include "D3D12WindowCapture.h" @@ -23,7 +23,7 @@ namespace XCEngine::UI::Editor::Host { -class D3D12WindowRenderer : public Ports::ViewportRenderPort { +class D3D12WindowRenderer : public Rendering::Host::ViewportRenderHost { public: static constexpr std::uint32_t kFrameContextCount = D3D12HostDevice::kFrameContextCount; diff --git a/new_editor/app/Rendering/Host/HostFwd.h b/new_editor/app/Rendering/Host/HostFwd.h new file mode 100644 index 00000000..17fea4e2 --- /dev/null +++ b/new_editor/app/Rendering/Host/HostFwd.h @@ -0,0 +1,8 @@ +#pragma once + +namespace XCEngine::UI::Editor::Rendering::Host { + +class UiTextureHost; +class ViewportRenderHost; + +} // namespace XCEngine::UI::Editor::Rendering::Host diff --git a/new_editor/app/Ports/TexturePort.h b/new_editor/app/Rendering/Host/UiTextureHost.h similarity index 82% rename from new_editor/app/Ports/TexturePort.h rename to new_editor/app/Rendering/Host/UiTextureHost.h index eed382f9..1b527d34 100644 --- a/new_editor/app/Ports/TexturePort.h +++ b/new_editor/app/Rendering/Host/UiTextureHost.h @@ -7,11 +7,11 @@ #include #include -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::Rendering::Host { -class TexturePort { +class UiTextureHost { public: - virtual ~TexturePort() = default; + virtual ~UiTextureHost() = default; virtual bool LoadTextureFromFile( const std::filesystem::path& path, @@ -31,4 +31,4 @@ public: virtual void ReleaseTexture(::XCEngine::UI::UITextureHandle& texture) = 0; }; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host diff --git a/new_editor/app/Ports/ViewportRenderPort.h b/new_editor/app/Rendering/Host/ViewportRenderHost.h similarity index 57% rename from new_editor/app/Ports/ViewportRenderPort.h rename to new_editor/app/Rendering/Host/ViewportRenderHost.h index 30a5680b..753b1124 100644 --- a/new_editor/app/Ports/ViewportRenderPort.h +++ b/new_editor/app/Rendering/Host/ViewportRenderHost.h @@ -4,13 +4,17 @@ #include #include -namespace XCEngine::UI::Editor::Ports { +#include -class ViewportRenderPort { +namespace XCEngine::UI::Editor::Rendering::Host { + +class ViewportRenderHost { public: - virtual ~ViewportRenderPort() = default; + virtual ~ViewportRenderHost() = default; [[nodiscard]] virtual ::XCEngine::RHI::RHIDevice* GetRHIDevice() const = 0; + [[nodiscard]] virtual std::uint32_t GetViewportResourceRetirementSlotCount() const = 0; + virtual bool TryGetActiveViewportResourceRetirementSlot(std::uint32_t& outSlot) const = 0; virtual bool CreateViewportTextureHandle( ::XCEngine::RHI::RHITexture& texture, std::uint32_t width, @@ -20,4 +24,4 @@ public: ::XCEngine::UI::UITextureHandle& texture) = 0; }; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::Rendering::Host diff --git a/new_editor/app/Rendering/Viewport/ViewportHostService.cpp b/new_editor/app/Rendering/Viewport/ViewportHostService.cpp index a02ebcc4..269b8424 100644 --- a/new_editor/app/Rendering/Viewport/ViewportHostService.cpp +++ b/new_editor/app/Rendering/Viewport/ViewportHostService.cpp @@ -1,6 +1,6 @@ #include "ViewportHostService.h" -#include "Ports/ViewportRenderPort.h" +#include "Rendering/Host/ViewportRenderHost.h" #include @@ -19,15 +19,17 @@ ViewportHostService::ViewportHostService() = default; ViewportHostService::~ViewportHostService() = default; void ViewportHostService::AttachWindowRenderer( - Ports::ViewportRenderPort& windowRenderer) { + Rendering::Host::ViewportRenderHost& windowRenderer) { if (m_windowRenderer == &windowRenderer) { m_device = windowRenderer.GetRHIDevice(); + m_retiredTargetsBySlot.resize(windowRenderer.GetViewportResourceRetirementSlotCount()); return; } ReleaseWindowResources(); m_windowRenderer = &windowRenderer; m_device = windowRenderer.GetRHIDevice(); + m_retiredTargetsBySlot.resize(windowRenderer.GetViewportResourceRetirementSlotCount()); } void ViewportHostService::DetachWindowRenderer() { @@ -51,14 +53,17 @@ void ViewportHostService::Shutdown() { for (auto& [viewportId, entry] : m_entries) { DestroyViewportEntry(entry); } + DestroyRetiredTargets(); m_windowRenderer = nullptr; m_device = nullptr; m_surfacePresentationEnabled = false; m_entries.clear(); + m_retiredTargetsBySlot.clear(); } void ViewportHostService::BeginFrame() { + ReclaimRetiredTargetsForCurrentSlot(); for (auto& [viewportId, entry] : m_entries) { entry.requestedWidth = 0; entry.requestedHeight = 0; @@ -71,10 +76,12 @@ void ViewportHostService::ReleaseWindowResources() { for (auto& [viewportId, entry] : m_entries) { DestroyViewportEntry(entry); } + DestroyRetiredTargets(); m_windowRenderer = nullptr; m_device = nullptr; m_surfacePresentationEnabled = false; + m_retiredTargetsBySlot.clear(); } ViewportHostService::ViewportEntry& ViewportHostService::GetOrCreateEntry( @@ -96,6 +103,58 @@ void ViewportHostService::DestroyViewportEntry(ViewportEntry& entry) { entry.statusText.clear(); } +void ViewportHostService::DestroyRetiredTargets() { + for (auto& retiredTargets : m_retiredTargetsBySlot) { + for (ViewportRenderTargets& targets : retiredTargets) { + m_renderTargetManager.DestroyTargets(m_windowRenderer, targets); + } + retiredTargets.clear(); + } +} + +void ViewportHostService::ReclaimRetiredTargetsForCurrentSlot() { + if (m_windowRenderer == nullptr || m_retiredTargetsBySlot.empty()) { + return; + } + + std::uint32_t activeSlot = 0u; + if (!m_windowRenderer->TryGetActiveViewportResourceRetirementSlot(activeSlot) || + activeSlot >= m_retiredTargetsBySlot.size()) { + return; + } + + for (ViewportRenderTargets& targets : m_retiredTargetsBySlot[activeSlot]) { + m_renderTargetManager.DestroyTargets(m_windowRenderer, targets); + } + m_retiredTargetsBySlot[activeSlot].clear(); +} + +void ViewportHostService::RetireViewportTargets(ViewportRenderTargets& targets) { + if (targets.colorTexture == nullptr && + targets.colorView == nullptr && + targets.depthTexture == nullptr && + targets.depthView == nullptr && + !targets.textureHandle.IsValid()) { + targets = {}; + return; + } + + if (m_windowRenderer == nullptr || m_retiredTargetsBySlot.empty()) { + m_renderTargetManager.DestroyTargets(nullptr, targets); + return; + } + + std::uint32_t activeSlot = 0u; + if (!m_windowRenderer->TryGetActiveViewportResourceRetirementSlot(activeSlot) || + activeSlot >= m_retiredTargetsBySlot.size()) { + m_renderTargetManager.DestroyTargets(m_windowRenderer, targets); + return; + } + + m_retiredTargetsBySlot[activeSlot].push_back({}); + std::swap(m_retiredTargetsBySlot[activeSlot].back(), targets); +} + ViewportFrame ViewportHostService::RequestViewport( std::string_view viewportId, const ::XCEngine::UI::UISize& requestedSize) { @@ -175,13 +234,22 @@ bool ViewportHostService::EnsureViewportResources(ViewportEntry& entry) { return false; } - return m_renderTargetManager.EnsureTargets( + ViewportRenderTargets nextTargets = {}; + if (!m_renderTargetManager.CreateTargets( entry.requirements, entry.requestedWidth, entry.requestedHeight, *m_device, *m_windowRenderer, - entry.renderTargets); + nextTargets)) { + return false; + } + + ViewportRenderTargets retiredTargets = {}; + std::swap(retiredTargets, entry.renderTargets); + std::swap(entry.renderTargets, nextTargets); + RetireViewportTargets(retiredTargets); + return true; } void ViewportHostService::ApplyViewportFallback( diff --git a/new_editor/app/Rendering/Viewport/ViewportHostService.h b/new_editor/app/Rendering/Viewport/ViewportHostService.h index 49c06fac..6e3f06c5 100644 --- a/new_editor/app/Rendering/Viewport/ViewportHostService.h +++ b/new_editor/app/Rendering/Viewport/ViewportHostService.h @@ -1,6 +1,6 @@ #pragma once -#include "Ports/PortFwd.h" +#include "Rendering/Host/HostFwd.h" #include "Rendering/Viewport/ViewportContentRenderer.h" #include "ViewportRenderTargets.h" @@ -11,6 +11,7 @@ #include #include #include +#include namespace XCEngine::UI::Editor::App { @@ -19,7 +20,7 @@ public: ViewportHostService(); ~ViewportHostService(); - void AttachWindowRenderer(Ports::ViewportRenderPort& windowRenderer); + void AttachWindowRenderer(Rendering::Host::ViewportRenderHost& windowRenderer); void DetachWindowRenderer(); void SetSurfacePresentationEnabled(bool enabled); void SetContentRenderer( @@ -52,6 +53,9 @@ private: void ReleaseWindowResources(); ViewportEntry& GetOrCreateEntry(std::string_view viewportId); void DestroyViewportEntry(ViewportEntry& entry); + void DestroyRetiredTargets(); + void ReclaimRetiredTargetsForCurrentSlot(); + void RetireViewportTargets(ViewportRenderTargets& targets); bool EnsureViewportResources(ViewportEntry& entry); void ApplyViewportFallback( ViewportEntry& entry, @@ -68,11 +72,12 @@ private: const ViewportEntry& entry, const ::XCEngine::UI::UISize& requestedSize) const; - Ports::ViewportRenderPort* m_windowRenderer = nullptr; + Rendering::Host::ViewportRenderHost* m_windowRenderer = nullptr; ::XCEngine::RHI::RHIDevice* m_device = nullptr; ViewportRenderTargetManager m_renderTargetManager = {}; bool m_surfacePresentationEnabled = false; std::unordered_map m_entries = {}; + std::vector> m_retiredTargetsBySlot = {}; }; } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Rendering/Viewport/ViewportRenderTargets.cpp b/new_editor/app/Rendering/Viewport/ViewportRenderTargets.cpp index cd524b48..54495507 100644 --- a/new_editor/app/Rendering/Viewport/ViewportRenderTargets.cpp +++ b/new_editor/app/Rendering/Viewport/ViewportRenderTargets.cpp @@ -1,6 +1,6 @@ #include "Rendering/Viewport/ViewportRenderTargets.h" -#include "Ports/ViewportRenderPort.h" +#include "Rendering/Host/ViewportRenderHost.h" namespace XCEngine::UI::Editor::App { @@ -118,7 +118,7 @@ bool CreateViewportSelectionMaskResources( } bool CreateViewportTextureHandle( - Ports::ViewportRenderPort& renderHost, + Rendering::Host::ViewportRenderHost& renderHost, ViewportRenderTargets& targets) { if (targets.colorTexture == nullptr) { return false; @@ -213,18 +213,17 @@ ViewportResourceReuseQuery BuildViewportRenderTargetsReuseQuery( targets.selectionMaskState); } -bool ViewportRenderTargetManager::EnsureTargets( +bool ViewportRenderTargetManager::CreateTargets( const ViewportResourceRequirements& requirements, std::uint32_t width, std::uint32_t height, ::XCEngine::RHI::RHIDevice& device, - Ports::ViewportRenderPort& renderHost, + Rendering::Host::ViewportRenderHost& renderHost, ViewportRenderTargets& targets) const { if (width == 0u || height == 0u) { return false; } - DestroyTargets(&renderHost, targets); targets.width = width; targets.height = height; @@ -251,7 +250,7 @@ bool ViewportRenderTargetManager::EnsureTargets( } void ViewportRenderTargetManager::DestroyTargets( - Ports::ViewportRenderPort* renderHost, + Rendering::Host::ViewportRenderHost* renderHost, ViewportRenderTargets& targets) const { if (renderHost != nullptr && targets.textureHandle.IsValid()) { renderHost->ReleaseViewportTextureHandle(targets.textureHandle); diff --git a/new_editor/app/Rendering/Viewport/ViewportRenderTargets.h b/new_editor/app/Rendering/Viewport/ViewportRenderTargets.h index 10abec98..9e575178 100644 --- a/new_editor/app/Rendering/Viewport/ViewportRenderTargets.h +++ b/new_editor/app/Rendering/Viewport/ViewportRenderTargets.h @@ -1,6 +1,6 @@ #pragma once -#include "Ports/PortFwd.h" +#include "Rendering/Host/HostFwd.h" #include "ViewportRenderTargetUtils.h" #include @@ -49,15 +49,15 @@ ViewportResourceReuseQuery BuildViewportRenderTargetsReuseQuery( class ViewportRenderTargetManager { public: - bool EnsureTargets( + bool CreateTargets( const ViewportResourceRequirements& requirements, std::uint32_t width, std::uint32_t height, ::XCEngine::RHI::RHIDevice& device, - Ports::ViewportRenderPort& renderHost, + Rendering::Host::ViewportRenderHost& renderHost, ViewportRenderTargets& targets) const; void DestroyTargets( - Ports::ViewportRenderPort* renderHost, + Rendering::Host::ViewportRenderHost* renderHost, ViewportRenderTargets& targets) const; }; diff --git a/new_editor/app/State/EditorUtilityWindowRequestState.h b/new_editor/app/State/EditorUtilityWindowRequestState.h index a55398af..b2059dcf 100644 --- a/new_editor/app/State/EditorUtilityWindowRequestState.h +++ b/new_editor/app/State/EditorUtilityWindowRequestState.h @@ -1,6 +1,6 @@ #pragma once -#include "Platform/Win32/EditorUtilityWindowKind.h" +#include "UtilityWindows/EditorUtilityWindowKind.h" #include diff --git a/new_editor/app/Support/EmbeddedPngLoader.cpp b/new_editor/app/Support/EmbeddedPngLoader.cpp index 8dbcaa91..f7d1c2d8 100644 --- a/new_editor/app/Support/EmbeddedPngLoader.cpp +++ b/new_editor/app/Support/EmbeddedPngLoader.cpp @@ -1,6 +1,6 @@ #include "Support/EmbeddedPngLoader.h" -#include "Ports/TexturePort.h" +#include "Rendering/Host/UiTextureHost.h" namespace XCEngine::UI::Editor::App { @@ -49,7 +49,7 @@ bool LoadEmbeddedPngBytes( } bool LoadEmbeddedPngTexture( - Ports::TexturePort& renderer, + Rendering::Host::UiTextureHost& renderer, UINT resourceId, ::XCEngine::UI::UITextureHandle& outTexture, std::string& outError) { diff --git a/new_editor/app/Support/EmbeddedPngLoader.h b/new_editor/app/Support/EmbeddedPngLoader.h index 34422e9b..775b2761 100644 --- a/new_editor/app/Support/EmbeddedPngLoader.h +++ b/new_editor/app/Support/EmbeddedPngLoader.h @@ -1,6 +1,6 @@ #pragma once -#include "Ports/PortFwd.h" +#include "Rendering/Host/HostFwd.h" #include @@ -23,7 +23,7 @@ bool LoadEmbeddedPngBytes( std::string& outError); bool LoadEmbeddedPngTexture( - Ports::TexturePort& renderer, + Rendering::Host::UiTextureHost& renderer, UINT resourceId, ::XCEngine::UI::UITextureHandle& outTexture, std::string& outError); diff --git a/new_editor/app/Ports/SystemInteractionPort.h b/new_editor/app/System/SystemInteractionService.h similarity index 60% rename from new_editor/app/Ports/SystemInteractionPort.h rename to new_editor/app/System/SystemInteractionService.h index 8806d840..5b49573c 100644 --- a/new_editor/app/Ports/SystemInteractionPort.h +++ b/new_editor/app/System/SystemInteractionService.h @@ -3,11 +3,11 @@ #include #include -namespace XCEngine::UI::Editor::Ports { +namespace XCEngine::UI::Editor::System { -class SystemInteractionPort { +class SystemInteractionService { public: - virtual ~SystemInteractionPort() = default; + virtual ~SystemInteractionService() = default; virtual bool CopyTextToClipboard(std::string_view text) = 0; virtual bool RevealPathInFileBrowser( @@ -15,4 +15,4 @@ public: bool selectTarget) = 0; }; -} // namespace XCEngine::UI::Editor::Ports +} // namespace XCEngine::UI::Editor::System diff --git a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowKind.h b/new_editor/app/UtilityWindows/EditorUtilityWindowKind.h similarity index 100% rename from new_editor/app/Platform/Win32/Content/EditorUtilityWindowKind.h rename to new_editor/app/UtilityWindows/EditorUtilityWindowKind.h diff --git a/new_editor/app/UtilityWindows/EditorUtilityWindowPanel.h b/new_editor/app/UtilityWindows/EditorUtilityWindowPanel.h new file mode 100644 index 00000000..5042f7d6 --- /dev/null +++ b/new_editor/app/UtilityWindows/EditorUtilityWindowPanel.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include + +namespace XCEngine::UI::Editor::App { + +class EditorContext; + +struct EditorUtilityWindowHostContext { + bool mounted = false; + ::XCEngine::UI::UIRect bounds = {}; + bool allowInteraction = false; + bool focused = false; + bool focusGained = false; + bool focusLost = false; +}; + +class EditorUtilityWindowPanel { +public: + virtual ~EditorUtilityWindowPanel() = default; + + virtual std::string_view GetDrawListId() const = 0; + virtual void ResetInteractionState() = 0; + virtual void Update( + EditorContext& context, + const EditorUtilityWindowHostContext& hostContext, + const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) = 0; + virtual void Append(::XCEngine::UI::UIDrawList& drawList) const = 0; +}; + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.cpp b/new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.cpp similarity index 66% rename from new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.cpp rename to new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.cpp index 3f92c2e5..b317167e 100644 --- a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.cpp +++ b/new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.cpp @@ -1,7 +1,7 @@ -#include "Platform/Win32/EditorUtilityWindowRegistry.h" +#include "UtilityWindows/EditorUtilityWindowRegistry.h" -#include "Platform/Win32/EditorAddComponentUtilityWindowContentController.h" -#include "Platform/Win32/EditorColorPickerUtilityWindowContentController.h" +#include "Features/ColorPicker/ColorPickerPanel.h" +#include "Features/Inspector/AddComponentPanel.h" namespace XCEngine::UI::Editor::App { @@ -25,7 +25,7 @@ constexpr EditorUtilityWindowDescriptor kAddComponentUtilityWindowDescriptor = { .minimumOuterSize = UISize(320.0f, 460.0f), }; -} +} // namespace const EditorUtilityWindowDescriptor* ResolveEditorUtilityWindowDescriptor( EditorUtilityWindowKind kind) { @@ -40,21 +40,13 @@ const EditorUtilityWindowDescriptor* ResolveEditorUtilityWindowDescriptor( } } -std::unique_ptr CreateEditorUtilityWindowContentController( +std::unique_ptr CreateEditorUtilityWindowPanel( EditorUtilityWindowKind kind) { - const EditorUtilityWindowDescriptor* descriptor = - ResolveEditorUtilityWindowDescriptor(kind); - if (descriptor == nullptr) { - return nullptr; - } - switch (kind) { case EditorUtilityWindowKind::ColorPicker: - return CreateEditorColorPickerUtilityWindowContentController( - descriptor->minimumOuterSize); + return std::make_unique(); case EditorUtilityWindowKind::AddComponent: - return CreateEditorAddComponentUtilityWindowContentController( - descriptor->minimumOuterSize); + return std::make_unique(); case EditorUtilityWindowKind::None: default: return nullptr; diff --git a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.h b/new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.h similarity index 76% rename from new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.h rename to new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.h index a65faf88..50a8c776 100644 --- a/new_editor/app/Platform/Win32/Content/EditorUtilityWindowRegistry.h +++ b/new_editor/app/UtilityWindows/EditorUtilityWindowRegistry.h @@ -1,6 +1,7 @@ #pragma once -#include "Platform/Win32/EditorUtilityWindowKind.h" +#include "UtilityWindows/EditorUtilityWindowKind.h" +#include "UtilityWindows/EditorUtilityWindowPanel.h" #include @@ -9,8 +10,6 @@ namespace XCEngine::UI::Editor::App { -class EditorWindowContentController; - struct EditorUtilityWindowDescriptor { EditorUtilityWindowKind kind = EditorUtilityWindowKind::None; std::string_view windowId = {}; @@ -22,7 +21,7 @@ struct EditorUtilityWindowDescriptor { const EditorUtilityWindowDescriptor* ResolveEditorUtilityWindowDescriptor( EditorUtilityWindowKind kind); -std::unique_ptr CreateEditorUtilityWindowContentController( +std::unique_ptr CreateEditorUtilityWindowPanel( EditorUtilityWindowKind kind); } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/include/XCEditor/Fields/UIEditorAssetField.h b/new_editor/include/XCEditor/Fields/UIEditorAssetField.h index 82bde529..d4eca80a 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorAssetField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorAssetField.h @@ -40,7 +40,7 @@ struct UIEditorAssetFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float valueBoxMinWidth = 116.0f; float controlInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorBoolField.h b/new_editor/include/XCEditor/Fields/UIEditorBoolField.h index 9daa1cd1..adcfcfe4 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorBoolField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorBoolField.h @@ -31,7 +31,7 @@ struct UIEditorBoolFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float checkboxSize = 18.0f; float labelTextInsetY = 0.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorColorField.h b/new_editor/include/XCEditor/Fields/UIEditorColorField.h index a0c6b653..76a7c836 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorColorField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorColorField.h @@ -44,7 +44,7 @@ struct UIEditorColorFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float swatchWidth = 54.0f; float swatchInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorEditableFieldCore.h b/new_editor/include/XCEditor/Fields/UIEditorEditableFieldCore.h index 04d084cd..ad0c38df 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorEditableFieldCore.h +++ b/new_editor/include/XCEditor/Fields/UIEditorEditableFieldCore.h @@ -100,6 +100,9 @@ void RecordUIEditorEditableFieldClick( std::int32_t keyCode, const ::XCEngine::UI::UIInputModifiers& modifiers); +bool IsUIEditorEditableFieldCharacterInsertable( + std::uint32_t character); + bool InsertUIEditorEditableFieldCharacter( UIEditorEditableFieldSession& session, std::uint32_t character); diff --git a/new_editor/include/XCEditor/Fields/UIEditorEnumField.h b/new_editor/include/XCEditor/Fields/UIEditorEnumField.h index 739a1ac7..0d6464bb 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorEnumField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorEnumField.h @@ -36,7 +36,7 @@ struct UIEditorEnumFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float valueBoxMinWidth = 96.0f; float controlInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorNumberField.h b/new_editor/include/XCEditor/Fields/UIEditorNumberField.h index c72febf2..44d3c318 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorNumberField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorNumberField.h @@ -43,7 +43,7 @@ struct UIEditorNumberFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float valueBoxMinWidth = 96.0f; float controlInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorObjectField.h b/new_editor/include/XCEditor/Fields/UIEditorObjectField.h index f0f60e85..47ae57f4 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorObjectField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorObjectField.h @@ -38,7 +38,7 @@ struct UIEditorObjectFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float valueBoxMinWidth = 96.0f; float controlInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorPropertyGrid.h b/new_editor/include/XCEditor/Fields/UIEditorPropertyGrid.h index f00df3f6..977a468b 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorPropertyGrid.h +++ b/new_editor/include/XCEditor/Fields/UIEditorPropertyGrid.h @@ -126,6 +126,7 @@ struct UIEditorPropertyGridField { std::string valueText = {}; bool readOnly = false; float desiredHeight = 0.0f; + float controlMinWidth = 0.0f; UIEditorPropertyGridFieldKind kind = UIEditorPropertyGridFieldKind::Text; bool boolValue = false; UIEditorPropertyGridNumberFieldValue numberValue = {}; @@ -199,7 +200,6 @@ struct UIEditorPropertyGridMetrics { float horizontalPadding = 12.0f; float sectionHeaderHorizontalPadding = 6.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; float labelControlGap = 20.0f; float disclosureExtent = 12.0f; float disclosureLabelGap = 8.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorTextField.h b/new_editor/include/XCEditor/Fields/UIEditorTextField.h index 15947cff..4a23e685 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorTextField.h +++ b/new_editor/include/XCEditor/Fields/UIEditorTextField.h @@ -38,7 +38,7 @@ struct UIEditorTextFieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float valueBoxMinWidth = 96.0f; float controlInsetY = 1.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorVector2Field.h b/new_editor/include/XCEditor/Fields/UIEditorVector2Field.h index b0603be9..29d1dd37 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorVector2Field.h +++ b/new_editor/include/XCEditor/Fields/UIEditorVector2Field.h @@ -49,7 +49,7 @@ struct UIEditorVector2FieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float controlInsetY = 1.0f; float componentGap = 6.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorVector3Field.h b/new_editor/include/XCEditor/Fields/UIEditorVector3Field.h index 7f47eda9..df24fc1e 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorVector3Field.h +++ b/new_editor/include/XCEditor/Fields/UIEditorVector3Field.h @@ -49,7 +49,7 @@ struct UIEditorVector3FieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float controlInsetY = 1.0f; float componentGap = 6.0f; diff --git a/new_editor/include/XCEditor/Fields/UIEditorVector4Field.h b/new_editor/include/XCEditor/Fields/UIEditorVector4Field.h index c99a85c9..321aa29c 100644 --- a/new_editor/include/XCEditor/Fields/UIEditorVector4Field.h +++ b/new_editor/include/XCEditor/Fields/UIEditorVector4Field.h @@ -60,7 +60,7 @@ struct UIEditorVector4FieldMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float controlInsetY = 1.0f; float componentGap = 6.0f; diff --git a/new_editor/include/XCEditor/Foundation/UIEditorTextMeasurement.h b/new_editor/include/XCEditor/Foundation/UIEditorTextMeasurement.h index a28f2068..a5933cff 100644 --- a/new_editor/include/XCEditor/Foundation/UIEditorTextMeasurement.h +++ b/new_editor/include/XCEditor/Foundation/UIEditorTextMeasurement.h @@ -14,6 +14,10 @@ public: virtual ~UIEditorTextMeasurer() = default; virtual float MeasureTextWidth(const UIEditorTextMeasureRequest& request) const = 0; + + virtual float MeasureTextAdvance(const UIEditorTextMeasureRequest& request) const { + return MeasureTextWidth(request); + } }; } // namespace XCEngine::UI::Editor diff --git a/new_editor/include/XCEditor/Widgets/UIEditorFieldRowLayout.h b/new_editor/include/XCEditor/Widgets/UIEditorFieldRowLayout.h index f78af830..c5c5aa9f 100644 --- a/new_editor/include/XCEditor/Widgets/UIEditorFieldRowLayout.h +++ b/new_editor/include/XCEditor/Widgets/UIEditorFieldRowLayout.h @@ -98,7 +98,7 @@ struct UIEditorFieldRowLayoutMetrics { float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; - float sharedControlColumnMinWidth = 0.0f; + float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float controlInsetY = 1.0f; }; diff --git a/new_editor/include/XCEditor/Widgets/UIEditorTextLayout.h b/new_editor/include/XCEditor/Widgets/UIEditorTextLayout.h index 2e31031a..265a5d36 100644 --- a/new_editor/include/XCEditor/Widgets/UIEditorTextLayout.h +++ b/new_editor/include/XCEditor/Widgets/UIEditorTextLayout.h @@ -26,6 +26,16 @@ inline float ResolveUIEditorTextTop( return centeredTop - 1.0f + offsetY; } +inline float ResolveUIEditorControlTextTop( + const ::XCEngine::UI::UIRect& rect, + float fontSize, + float offsetY = 0.0f) { + const float textHeight = MeasureUIEditorTextLayoutHeight(fontSize); + const float centeredTop = + rect.y + (std::max)(0.0f, std::floor((rect.height - textHeight) * 0.5f)); + return centeredTop + offsetY; +} + inline ::XCEngine::UI::UIRect ResolveUIEditorTextClipRect( const ::XCEngine::UI::UIRect& rect, float fontSize) { @@ -64,7 +74,7 @@ inline float MeasureUIEditorTextWidthToCaret( if (textMeasurer != nullptr && clampedCaretOffset > 0u && fontSize > 0.0f) { - return textMeasurer->MeasureTextWidth( + return textMeasurer->MeasureTextAdvance( ::XCEngine::UI::Editor::UIEditorTextMeasureRequest{ std::string_view(text.data(), clampedCaretOffset), fontSize @@ -132,7 +142,7 @@ inline void AppendUIEditorTextCaret( caretOffset, fontSize, textMeasurer)); - const float top = ResolveUIEditorTextTop(rect, fontSize, insetY); + const float top = ResolveUIEditorControlTextTop(rect, fontSize, insetY); const float bottom = top + MeasureUIEditorTextLayoutHeight(fontSize); drawList.AddLine( ::XCEngine::UI::UIPoint(caretX, top), diff --git a/new_editor/src/Collections/UIEditorFilterableTreeHost.cpp b/new_editor/src/Collections/UIEditorFilterableTreeHost.cpp index 21b0f519..6a1dfa76 100644 --- a/new_editor/src/Collections/UIEditorFilterableTreeHost.cpp +++ b/new_editor/src/Collections/UIEditorFilterableTreeHost.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -58,7 +59,7 @@ Widgets::UIEditorFilterableTreeHostMetrics ResolveMetrics( resolved.searchFieldMetrics.valueBoxMinWidth = 0.0f; resolved.searchFieldMetrics.controlInsetY = 1.0f; resolved.searchFieldMetrics.valueTextInsetX = 8.0f; - resolved.searchFieldMetrics.valueTextInsetY = -1.0f; + resolved.searchFieldMetrics.valueTextInsetY = 0.0f; resolved.searchFieldMetrics.valueFontSize = 12.0f; resolved.searchFieldMetrics.valueBoxRounding = 4.0f; resolved.searchFieldMetrics.cornerRounding = 0.0f; @@ -165,11 +166,6 @@ void BuildFilteredItems( } } -float ResolveTextTop(const UIRect& rect, float fontSize, float insetY) { - const float lineHeight = fontSize * 1.6f; - return rect.y + std::floor((rect.height - lineHeight) * 0.5f) + insetY; -} - } // namespace UIEditorFilterableTreeHostFrame UpdateUIEditorFilterableTreeHost( @@ -263,7 +259,7 @@ void AppendUIEditorFilterableTreeHostSearchField( drawList.AddText( UIPoint( valueRect.x + resolvedMetrics.searchFieldMetrics.valueTextInsetX, - ResolveTextTop( + Widgets::ResolveUIEditorControlTextTop( valueRect, resolvedMetrics.searchFieldMetrics.valueFontSize, resolvedMetrics.searchFieldMetrics.valueTextInsetY)), diff --git a/new_editor/src/Fields/ColorFieldRendering.cpp b/new_editor/src/Fields/ColorFieldRendering.cpp index 65e9df27..fb63b6a5 100644 --- a/new_editor/src/Fields/ColorFieldRendering.cpp +++ b/new_editor/src/Fields/ColorFieldRendering.cpp @@ -35,10 +35,10 @@ UIEditorColorFieldPalette ResolvePalette(const UIEditorColorFieldPalette& palett const auto& tokens = GetUIEditorInspectorFieldStyleTokens(); UIEditorColorFieldPalette resolved = palette; - if (AreUIEditorFieldColorsEqual(palette.swatchBorderColor, UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.swatchBorderColor, UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.swatchBorderColor = tokens.swatchBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.swatchHoverBorderColor, UIColor(0.34f, 0.34f, 0.34f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.swatchHoverBorderColor, UIColor(0.19f, 0.19f, 0.19f, 1.0f))) { resolved.swatchHoverBorderColor = tokens.swatchHoverBorderColor; } if (AreUIEditorFieldColorsEqual( @@ -46,64 +46,64 @@ UIEditorColorFieldPalette ResolvePalette(const UIEditorColorFieldPalette& palett UIColor(0.08f, 0.08f, 0.08f, 0.18f))) { resolved.swatchReadOnlyOverlayColor = tokens.swatchReadOnlyOverlayColor; } - if (AreUIEditorFieldColorsEqual(palette.popupColor, UIColor(0.24f, 0.24f, 0.24f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.popupColor, UIColor(0.10f, 0.10f, 0.10f, 1.0f))) { resolved.popupColor = tokens.popupColor; } if (AreUIEditorFieldColorsEqual(palette.popupBorderColor, UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.popupBorderColor = tokens.popupBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.popupHeaderColor, UIColor(0.43f, 0.24f, 0.05f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.popupHeaderColor, UIColor(0.11f, 0.11f, 0.11f, 1.0f))) { resolved.popupHeaderColor = tokens.popupHeaderColor; } - if (AreUIEditorFieldColorsEqual(palette.popupTitleColor, UIColor(0.95f, 0.95f, 0.95f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.popupTitleColor, UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.popupTitleColor = tokens.popupTitleColor; } - if (AreUIEditorFieldColorsEqual(palette.closeButtonColor, UIColor(0.76f, 0.35f, 0.34f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.closeButtonColor, UIColor(0.20f, 0.10f, 0.10f, 1.0f))) { resolved.closeButtonColor = tokens.closeButtonColor; } - if (AreUIEditorFieldColorsEqual(palette.closeButtonHoverColor, UIColor(0.82f, 0.40f, 0.39f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.closeButtonHoverColor, UIColor(0.28f, 0.14f, 0.14f, 1.0f))) { resolved.closeButtonHoverColor = tokens.closeButtonHoverColor; } - if (AreUIEditorFieldColorsEqual(palette.closeGlyphColor, UIColor(0.95f, 0.95f, 0.95f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.closeGlyphColor, UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.closeGlyphColor = tokens.closeGlyphColor; } - if (AreUIEditorFieldColorsEqual(palette.labelColor, UIColor(0.88f, 0.88f, 0.88f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.labelColor, UIColor(0.72f, 0.72f, 0.72f, 1.0f))) { resolved.labelColor = tokens.labelColor; } - if (AreUIEditorFieldColorsEqual(palette.popupTextColor, UIColor(0.86f, 0.86f, 0.86f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.popupTextColor, UIColor(0.88f, 0.88f, 0.88f, 1.0f))) { resolved.popupTextColor = tokens.popupTextColor; } - if (AreUIEditorFieldColorsEqual(palette.popupTextMutedColor, UIColor(0.72f, 0.72f, 0.72f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.popupTextMutedColor, UIColor(0.66f, 0.66f, 0.66f, 1.0f))) { resolved.popupTextMutedColor = tokens.popupTextMutedColor; } - if (AreUIEditorFieldColorsEqual(palette.previewBorderColor, UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.previewBorderColor, UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.previewBorderColor = tokens.previewBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.previewBaseColor, UIColor(0.19f, 0.19f, 0.19f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.previewBaseColor, UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { resolved.previewBaseColor = tokens.previewBaseColor; } - if (AreUIEditorFieldColorsEqual(palette.checkerLightColor, UIColor(0.84f, 0.84f, 0.84f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.checkerLightColor, UIColor(0.24f, 0.24f, 0.24f, 1.0f))) { resolved.checkerLightColor = tokens.checkerLightColor; } - if (AreUIEditorFieldColorsEqual(palette.checkerDarkColor, UIColor(0.55f, 0.55f, 0.55f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.checkerDarkColor, UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { resolved.checkerDarkColor = tokens.checkerDarkColor; } - if (AreUIEditorFieldColorsEqual(palette.sliderBorderColor, UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.sliderBorderColor, UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.sliderBorderColor = tokens.sliderBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.numericBoxColor, UIColor(0.19f, 0.19f, 0.19f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.numericBoxColor, UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { resolved.numericBoxColor = tokens.numericBoxColor; } - if (AreUIEditorFieldColorsEqual(palette.numericBoxBorderColor, UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.numericBoxBorderColor, UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.numericBoxBorderColor = tokens.numericBoxBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.numericBoxTextColor, UIColor(0.90f, 0.90f, 0.90f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.numericBoxTextColor, UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.numericBoxTextColor = tokens.numericBoxTextColor; } if (AreUIEditorFieldColorsEqual(palette.handleFillColor, UIColor(1.0f, 1.0f, 1.0f, 1.0f))) { resolved.handleFillColor = tokens.handleFillColor; } - if (AreUIEditorFieldColorsEqual(palette.handleStrokeColor, UIColor(0.0f, 0.0f, 0.0f, 0.4f))) { + if (AreUIEditorFieldColorsEqual(palette.handleStrokeColor, UIColor(0.10f, 0.10f, 0.10f, 0.5f))) { resolved.handleStrokeColor = tokens.handleStrokeColor; } diff --git a/new_editor/src/Fields/PropertyGridInteractionInternal.h b/new_editor/src/Fields/PropertyGridInteractionInternal.h index e2e08982..e5df6e14 100644 --- a/new_editor/src/Fields/PropertyGridInteractionInternal.h +++ b/new_editor/src/Fields/PropertyGridInteractionInternal.h @@ -3,8 +3,29 @@ #include "Fields/PropertyGridInternal.h" #include +#include + namespace XCEngine::UI::Editor::Internal { +struct UIEditorPropertyGridRoutedFields { + std::array fieldIds = {}; + std::size_t count = 0u; + + [[nodiscard]] bool Empty() const { + return count == 0u; + } + + [[nodiscard]] bool Contains(std::string_view fieldId) const { + for (std::size_t index = 0u; index < count; ++index) { + if (fieldIds[index] == fieldId) { + return true; + } + } + + return false; + } +}; + bool ShouldUsePropertyGridPointerPosition(const ::XCEngine::UI::UIInputEvent& event); bool HasSystemModifiers(const ::XCEngine::UI::UIInputModifiers& modifiers); bool ApplyKeyboardNavigation( @@ -117,6 +138,7 @@ bool ProcessColorFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); bool ProcessNumberFieldEvent( UIEditorPropertyGridInteractionState& state, @@ -126,6 +148,7 @@ bool ProcessNumberFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); bool ProcessTextFieldEvent( UIEditorPropertyGridInteractionState& state, @@ -135,6 +158,7 @@ bool ProcessTextFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); bool ProcessAssetFieldEvent( UIEditorPropertyGridInteractionState& state, @@ -144,6 +168,7 @@ bool ProcessAssetFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); void PruneVectorFieldVisualStates( UIEditorPropertyGridInteractionState& state, @@ -157,6 +182,7 @@ bool ProcessVector2FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); bool ProcessVector3FieldEvent( UIEditorPropertyGridInteractionState& state, @@ -166,6 +192,7 @@ bool ProcessVector3FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); bool ProcessVector4FieldEvent( UIEditorPropertyGridInteractionState& state, @@ -175,6 +202,7 @@ bool ProcessVector4FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result); } // namespace XCEngine::UI::Editor::Internal diff --git a/new_editor/src/Fields/UIEditorAssetField.cpp b/new_editor/src/Fields/UIEditorAssetField.cpp index 2c72cafd..fb00ab06 100644 --- a/new_editor/src/Fields/UIEditorAssetField.cpp +++ b/new_editor/src/Fields/UIEditorAssetField.cpp @@ -130,7 +130,7 @@ UIEditorAssetFieldLayout BuildUIEditorAssetFieldLayout( metrics.horizontalPadding, metrics.labelControlGap, metrics.controlColumnStart, - metrics.sharedControlColumnMinWidth, + metrics.controlMinWidth, metrics.controlTrailingInset, metrics.controlInsetY, }); diff --git a/new_editor/src/Fields/UIEditorBoolField.cpp b/new_editor/src/Fields/UIEditorBoolField.cpp index f9870a08..20c29db3 100644 --- a/new_editor/src/Fields/UIEditorBoolField.cpp +++ b/new_editor/src/Fields/UIEditorBoolField.cpp @@ -46,7 +46,7 @@ UIEditorBoolFieldLayout BuildUIEditorBoolFieldLayout( metrics.horizontalPadding, metrics.labelControlGap, metrics.controlColumnStart, - metrics.sharedControlColumnMinWidth, + metrics.controlMinWidth, metrics.controlTrailingInset, 0.0f, }); diff --git a/new_editor/src/Fields/UIEditorColorField.cpp b/new_editor/src/Fields/UIEditorColorField.cpp index 5e3e65ce..b5824988 100644 --- a/new_editor/src/Fields/UIEditorColorField.cpp +++ b/new_editor/src/Fields/UIEditorColorField.cpp @@ -120,7 +120,7 @@ UIEditorColorFieldLayout BuildUIEditorColorFieldLayout( resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, - resolvedMetrics.sharedControlColumnMinWidth, + resolvedMetrics.controlMinWidth, resolvedMetrics.controlTrailingInset, resolvedMetrics.swatchInsetY, }); diff --git a/new_editor/src/Fields/UIEditorEditableFieldCore.cpp b/new_editor/src/Fields/UIEditorEditableFieldCore.cpp index aa150923..252dbf8a 100644 --- a/new_editor/src/Fields/UIEditorEditableFieldCore.cpp +++ b/new_editor/src/Fields/UIEditorEditableFieldCore.cpp @@ -169,6 +169,11 @@ void RecordUIEditorEditableFieldClick( return result; } +bool IsUIEditorEditableFieldCharacterInsertable(std::uint32_t character) { + ::XCEngine::UI::Text::UITextInputState probeState = {}; + return ::XCEngine::UI::Text::InsertCharacter(probeState, character); +} + bool InsertUIEditorEditableFieldCharacter( UIEditorEditableFieldSession& session, std::uint32_t character) { diff --git a/new_editor/src/Fields/UIEditorEnumField.cpp b/new_editor/src/Fields/UIEditorEnumField.cpp index 546abd2a..d558859d 100644 --- a/new_editor/src/Fields/UIEditorEnumField.cpp +++ b/new_editor/src/Fields/UIEditorEnumField.cpp @@ -34,28 +34,28 @@ UIEditorEnumFieldPalette ResolvePalette(const UIEditorEnumFieldPalette& palette) const auto& tokens = GetUIEditorInspectorFieldStyleTokens(); UIEditorEnumFieldPalette resolved = palette; - if (AreUIEditorFieldColorsEqual(palette.focusedBorderColor, ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.focusedBorderColor, ::XCEngine::UI::UIColor(0.19f, 0.19f, 0.19f, 1.0f))) { resolved.focusedBorderColor = tokens.controlFocusedBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.valueBoxColor, ::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.valueBoxColor, ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f))) { resolved.valueBoxColor = tokens.controlColor; } - if (AreUIEditorFieldColorsEqual(palette.valueBoxHoverColor, ::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.valueBoxHoverColor, ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { resolved.valueBoxHoverColor = tokens.controlHoverColor; } - if (AreUIEditorFieldColorsEqual(palette.readOnlyColor, ::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.readOnlyColor, ::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f))) { resolved.readOnlyColor = tokens.controlReadOnlyColor; } - if (AreUIEditorFieldColorsEqual(palette.controlBorderColor, ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.controlBorderColor, ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f))) { resolved.controlBorderColor = tokens.controlBorderColor; } - if (AreUIEditorFieldColorsEqual(palette.labelColor, ::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.labelColor, ::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 1.0f))) { resolved.labelColor = tokens.labelColor; } - if (AreUIEditorFieldColorsEqual(palette.valueColor, ::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.valueColor, ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.valueColor = tokens.valueColor; } - if (AreUIEditorFieldColorsEqual(palette.arrowColor, ::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f))) { + if (AreUIEditorFieldColorsEqual(palette.arrowColor, ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.arrowColor = tokens.arrowColor; } @@ -115,7 +115,7 @@ UIEditorEnumFieldLayout BuildUIEditorEnumFieldLayout( resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, - resolvedMetrics.sharedControlColumnMinWidth, + resolvedMetrics.controlMinWidth, resolvedMetrics.controlTrailingInset, resolvedMetrics.controlInsetY, }); diff --git a/new_editor/src/Fields/UIEditorFieldStyle.cpp b/new_editor/src/Fields/UIEditorFieldStyle.cpp index 85c6b40c..17682ed1 100644 --- a/new_editor/src/Fields/UIEditorFieldStyle.cpp +++ b/new_editor/src/Fields/UIEditorFieldStyle.cpp @@ -24,14 +24,13 @@ const Widgets::UIEditorPropertyGridMetrics& GetUIEditorFixedPropertyGridMetrics( metrics.horizontalPadding = 12.0f; metrics.sectionHeaderHorizontalPadding = 6.0f; metrics.controlColumnStart = 236.0f; - metrics.sharedControlColumnMinWidth = 160.0f; metrics.labelControlGap = 20.0f; metrics.disclosureExtent = treeMetrics.disclosureExtent; metrics.disclosureLabelGap = treeMetrics.disclosureLabelGap; metrics.sectionTextInsetY = 0.0f; metrics.sectionFontSize = 12.0f; metrics.labelTextInsetY = 0.0f; - metrics.labelFontSize = 11.0f; + metrics.labelFontSize = 12.0f; metrics.valueTextInsetY = 0.0f; metrics.valueFontSize = 12.0f; metrics.valueBoxInsetY = 1.0f; @@ -66,7 +65,7 @@ const Widgets::UIEditorPropertyGridPalette& GetUIEditorFixedPropertyGridPalette( palette.valueBoxEditingBorderColor = UIColor(0.19f, 0.19f, 0.19f, 1.0f); palette.disclosureColor = UIColor(0.44f, 0.44f, 0.44f, 1.0f); palette.sectionTextColor = UIColor(0.88f, 0.88f, 0.88f, 1.0f); - palette.labelTextColor = UIColor(0.72f, 0.72f, 0.72f, 1.0f); + palette.labelTextColor = UIColor(0.88f, 0.88f, 0.88f, 1.0f); palette.valueTextColor = UIColor(0.88f, 0.88f, 0.88f, 1.0f); palette.readOnlyValueTextColor = UIColor(0.62f, 0.62f, 0.62f, 1.0f); palette.editTagColor = UIColor(0.80f, 0.80f, 0.80f, 1.0f); @@ -83,7 +82,6 @@ Widgets::UIEditorBoolFieldMetrics BuildUIEditorPropertyGridBoolFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; hosted.labelFontSize = propertyGridMetrics.labelFontSize; @@ -121,7 +119,6 @@ Widgets::UIEditorNumberFieldMetrics BuildUIEditorPropertyGridNumberFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.controlInsetY = propertyGridMetrics.valueBoxInsetY; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; @@ -165,7 +162,6 @@ Widgets::UIEditorTextFieldMetrics BuildUIEditorPropertyGridTextFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.controlInsetY = propertyGridMetrics.valueBoxInsetY; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; @@ -210,7 +206,6 @@ Metrics BuildUIEditorPropertyGridVectorFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.controlInsetY = propertyGridMetrics.valueBoxInsetY; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; @@ -305,7 +300,6 @@ Widgets::UIEditorEnumFieldMetrics BuildUIEditorPropertyGridEnumFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.controlInsetY = propertyGridMetrics.valueBoxInsetY; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; @@ -350,7 +344,6 @@ Widgets::UIEditorColorFieldMetrics BuildUIEditorPropertyGridColorFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.swatchWidth = boolMetrics.checkboxSize; hosted.swatchInsetY = @@ -394,7 +387,6 @@ Widgets::UIEditorObjectFieldMetrics BuildUIEditorPropertyGridObjectFieldMetrics( hosted.horizontalPadding = propertyGridMetrics.horizontalPadding; hosted.labelControlGap = propertyGridMetrics.labelControlGap; hosted.controlColumnStart = propertyGridMetrics.controlColumnStart; - hosted.sharedControlColumnMinWidth = propertyGridMetrics.sharedControlColumnMinWidth; hosted.controlTrailingInset = propertyGridMetrics.valueBoxInsetX; hosted.controlInsetY = propertyGridMetrics.valueBoxInsetY; hosted.labelTextInsetY = propertyGridMetrics.labelTextInsetY; diff --git a/new_editor/src/Fields/UIEditorNumberField.cpp b/new_editor/src/Fields/UIEditorNumberField.cpp index 0cb85ac7..e68ae6df 100644 --- a/new_editor/src/Fields/UIEditorNumberField.cpp +++ b/new_editor/src/Fields/UIEditorNumberField.cpp @@ -111,7 +111,7 @@ std::string FormatNumberValue(double value, bool integerMode) { return palette.readOnlyColor; } if (state.editing) { - return palette.valueBoxEditingColor; + return palette.valueBoxColor; } if (state.hoveredTarget == UIEditorNumberFieldHitTargetKind::ValueBox) { return palette.valueBoxHoverColor; @@ -153,7 +153,10 @@ void AppendValueText( drawList.AddText( UIPoint( layout.valueRect.x + resolvedMetrics.valueTextInsetX, - ResolveUIEditorTextTop(layout.valueRect, resolvedMetrics.valueFontSize, resolvedMetrics.valueTextInsetY)), + ResolveUIEditorControlTextTop( + layout.valueRect, + resolvedMetrics.valueFontSize, + resolvedMetrics.valueTextInsetY)), std::string(text), spec.readOnly ? resolvedPalette.readOnlyValueColor : resolvedPalette.valueColor, resolvedMetrics.valueFontSize); @@ -236,7 +239,7 @@ UIEditorNumberFieldLayout BuildUIEditorNumberFieldLayout( resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, - resolvedMetrics.sharedControlColumnMinWidth, + resolvedMetrics.controlMinWidth, resolvedMetrics.controlTrailingInset, resolvedMetrics.controlInsetY, }); diff --git a/new_editor/src/Fields/UIEditorNumberFieldInteraction.cpp b/new_editor/src/Fields/UIEditorNumberFieldInteraction.cpp index a5c1b497..2ea09469 100644 --- a/new_editor/src/Fields/UIEditorNumberFieldInteraction.cpp +++ b/new_editor/src/Fields/UIEditorNumberFieldInteraction.cpp @@ -369,7 +369,7 @@ UIEditorNumberFieldInteractionFrame UpdateUIEditorNumberFieldInteraction( spec.fieldId, event, UIEditorEditableFieldInvalidComponentIndex)) { - eventResult.editStarted = BeginEdit(state, spec, true); + eventResult.editStarted = BeginEdit(state, spec, false); eventResult.consumed = true; } else { RecordUIEditorEditableFieldClick( diff --git a/new_editor/src/Fields/UIEditorObjectField.cpp b/new_editor/src/Fields/UIEditorObjectField.cpp index 1e368f8b..c92ab5dc 100644 --- a/new_editor/src/Fields/UIEditorObjectField.cpp +++ b/new_editor/src/Fields/UIEditorObjectField.cpp @@ -119,7 +119,7 @@ UIEditorObjectFieldLayout BuildUIEditorObjectFieldLayout( metrics.horizontalPadding, metrics.labelControlGap, metrics.controlColumnStart, - metrics.sharedControlColumnMinWidth, + metrics.controlMinWidth, metrics.controlTrailingInset, metrics.controlInsetY, }); diff --git a/new_editor/src/Fields/UIEditorPropertyGrid.cpp b/new_editor/src/Fields/UIEditorPropertyGrid.cpp index 3bf6d750..b3163be5 100644 --- a/new_editor/src/Fields/UIEditorPropertyGrid.cpp +++ b/new_editor/src/Fields/UIEditorPropertyGrid.cpp @@ -398,6 +398,14 @@ Spec BuildVectorFieldSpec( return spec; } +template +Metrics ApplyFieldControlMinWidth( + Metrics metrics, + const UIEditorPropertyGridField& field) { + metrics.controlMinWidth = field.controlMinWidth; + return metrics; +} + UIEditorVector2FieldSpec BuildVector2FieldSpec(const UIEditorPropertyGridField& field) { return BuildVectorFieldSpec(field, field.vector2Value); } @@ -416,75 +424,102 @@ UIEditorPropertyGridFieldRects ResolveFieldRects( const UIEditorPropertyGridMetrics& metrics) { switch (field.kind) { case UIEditorPropertyGridFieldKind::Bool: { + const UIEditorBoolFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridBoolFieldMetrics(metrics), + field); const UIEditorBoolFieldLayout fieldLayout = BuildUIEditorBoolFieldLayout( rowRect, BuildBoolFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridBoolFieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.checkboxRect }; } case UIEditorPropertyGridFieldKind::Number: { + const UIEditorNumberFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridNumberFieldMetrics(metrics), + field); const UIEditorNumberFieldLayout fieldLayout = BuildUIEditorNumberFieldLayout( rowRect, BuildNumberFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridNumberFieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.valueRect }; } case UIEditorPropertyGridFieldKind::Enum: { + const UIEditorEnumFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridEnumFieldMetrics(metrics), + field); const UIEditorEnumFieldLayout fieldLayout = BuildUIEditorEnumFieldLayout( rowRect, BuildEnumFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridEnumFieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.valueRect }; } case UIEditorPropertyGridFieldKind::Asset: { + const UIEditorAssetFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridAssetFieldMetrics(metrics), + field); const UIEditorAssetFieldLayout fieldLayout = BuildUIEditorAssetFieldLayout( rowRect, BuildAssetFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridAssetFieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.controlRect }; } case UIEditorPropertyGridFieldKind::Color: { + const UIEditorColorFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridColorFieldMetrics(metrics), + field); const UIEditorColorFieldLayout fieldLayout = BuildUIEditorColorFieldLayout( rowRect, BuildColorFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridColorFieldMetrics(metrics)); - return { fieldLayout.labelRect, fieldLayout.swatchRect }; + fieldMetrics); + return { fieldLayout.labelRect, fieldLayout.controlRect }; } case UIEditorPropertyGridFieldKind::Vector2: { + const UIEditorVector2FieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector2FieldMetrics(metrics), + field); const UIEditorVector2FieldLayout fieldLayout = BuildUIEditorVector2FieldLayout( rowRect, BuildVector2FieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector2FieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.controlRect }; } case UIEditorPropertyGridFieldKind::Vector3: { + const UIEditorVector3FieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector3FieldMetrics(metrics), + field); const UIEditorVector3FieldLayout fieldLayout = BuildUIEditorVector3FieldLayout( rowRect, BuildVector3FieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector3FieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.controlRect }; } case UIEditorPropertyGridFieldKind::Vector4: { + const UIEditorVector4FieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector4FieldMetrics(metrics), + field); const UIEditorVector4FieldLayout fieldLayout = BuildUIEditorVector4FieldLayout( rowRect, BuildVector4FieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridVector4FieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.controlRect }; } case UIEditorPropertyGridFieldKind::Text: default: { + const UIEditorTextFieldMetrics fieldMetrics = ApplyFieldControlMinWidth( + ::XCEngine::UI::Editor::BuildUIEditorPropertyGridTextFieldMetrics(metrics), + field); const UIEditorTextFieldLayout fieldLayout = BuildUIEditorTextFieldLayout( rowRect, BuildTextFieldSpec(field), - ::XCEngine::UI::Editor::BuildUIEditorPropertyGridTextFieldMetrics(metrics)); + fieldMetrics); return { fieldLayout.labelRect, fieldLayout.valueRect }; } } @@ -940,6 +975,8 @@ void AppendUIEditorPropertyGridForeground( switch (field.kind) { case UIEditorPropertyGridFieldKind::Bool: { + const UIEditorBoolFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(boolMetrics, field); UIEditorBoolFieldState fieldState = {}; fieldState.hoveredTarget = Internal::ResolveBoolHoveredTarget(state, field); fieldState.focused = state.focused; @@ -950,11 +987,13 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildBoolFieldSpec(field), fieldState, boolPalette, - boolMetrics); + fieldMetrics); break; } case UIEditorPropertyGridFieldKind::Number: { + const UIEditorNumberFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(numberMetrics, field); UIEditorNumberFieldState fieldState = {}; if (const auto* visualState = Internal::FindNumberFieldVisualState(state, field.fieldId); @@ -976,12 +1015,14 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildNumberFieldSpec(field), fieldState, numberPalette, - numberMetrics, + fieldMetrics, textMeasurer); break; } case UIEditorPropertyGridFieldKind::Enum: { + const UIEditorEnumFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(enumMetrics, field); UIEditorEnumFieldState fieldState = {}; fieldState.hoveredTarget = Internal::ResolveEnumHoveredTarget(state, field); fieldState.focused = state.focused; @@ -993,11 +1034,13 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildEnumFieldSpec(field), fieldState, enumPalette, - enumMetrics); + fieldMetrics); break; } case UIEditorPropertyGridFieldKind::Asset: { + const UIEditorAssetFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(assetMetrics, field); UIEditorAssetFieldState fieldState = {}; if (const auto* visualState = Internal::FindAssetFieldVisualState(state, field.fieldId); @@ -1018,11 +1061,13 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildAssetFieldSpec(field), fieldState, assetPalette, - assetMetrics); + fieldMetrics); break; } case UIEditorPropertyGridFieldKind::Color: { + const UIEditorColorFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(colorMetrics, field); UIEditorColorFieldState fieldState = {}; fieldState.hoveredTarget = Internal::ResolveColorHoveredTarget(state, field); fieldState.activeTarget = @@ -1044,12 +1089,14 @@ void AppendUIEditorPropertyGridForeground( fieldSpec, fieldState, colorPalette, - colorMetrics, + fieldMetrics, popupViewportRect); break; } case UIEditorPropertyGridFieldKind::Vector2: { + const UIEditorVector2FieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(vector2Metrics, field); UIEditorVector2FieldState fieldState = {}; if (const auto* visualState = Internal::FindVector2FieldVisualState(state, field.fieldId); @@ -1069,12 +1116,14 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildVector2FieldSpec(field), fieldState, vector2Palette, - vector2Metrics, + fieldMetrics, textMeasurer); break; } case UIEditorPropertyGridFieldKind::Vector3: { + const UIEditorVector3FieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(vector3Metrics, field); UIEditorVector3FieldState fieldState = {}; if (const auto* visualState = Internal::FindVector3FieldVisualState(state, field.fieldId); @@ -1094,12 +1143,14 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildVector3FieldSpec(field), fieldState, vector3Palette, - vector3Metrics, + fieldMetrics, textMeasurer); break; } case UIEditorPropertyGridFieldKind::Vector4: { + const UIEditorVector4FieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(vector4Metrics, field); UIEditorVector4FieldState fieldState = {}; if (const auto* visualState = Internal::FindVector4FieldVisualState(state, field.fieldId); @@ -1119,13 +1170,15 @@ void AppendUIEditorPropertyGridForeground( Internal::BuildVector4FieldSpec(field), fieldState, vector4Palette, - vector4Metrics, + fieldMetrics, textMeasurer); break; } case UIEditorPropertyGridFieldKind::Text: default: { + const UIEditorTextFieldMetrics fieldMetrics = + Internal::ApplyFieldControlMinWidth(textMetrics, field); UIEditorTextFieldState fieldState = {}; if (const auto* visualState = Internal::FindTextFieldVisualState(state, field.fieldId); @@ -1153,7 +1206,7 @@ void AppendUIEditorPropertyGridForeground( fieldSpec, fieldState, textPalette, - textMetrics, + fieldMetrics, textMeasurer); if (fieldState.editing) { diff --git a/new_editor/src/Fields/UIEditorPropertyGridInteraction.cpp b/new_editor/src/Fields/UIEditorPropertyGridInteraction.cpp index 25bfb823..4fac3fba 100644 --- a/new_editor/src/Fields/UIEditorPropertyGridInteraction.cpp +++ b/new_editor/src/Fields/UIEditorPropertyGridInteraction.cpp @@ -42,6 +42,199 @@ bool IsSharedEditableFieldKind(UIEditorPropertyGridFieldKind kind) { } } +const UIEditorPropertyGridField* ResolveHitField( + const UIEditorPropertyGridHitTarget& hitTarget, + const std::vector& sections) { + if ((hitTarget.kind != UIEditorPropertyGridHitTargetKind::FieldRow && + hitTarget.kind != UIEditorPropertyGridHitTargetKind::ValueBox) || + hitTarget.sectionIndex >= sections.size() || + hitTarget.fieldIndex >= sections[hitTarget.sectionIndex].fields.size()) { + return nullptr; + } + + return §ions[hitTarget.sectionIndex].fields[hitTarget.fieldIndex]; +} + +std::string_view ResolveHitFieldId( + const UIEditorPropertyGridHitTarget& hitTarget, + const std::vector& sections) { + if (const UIEditorPropertyGridField* field = ResolveHitField(hitTarget, sections); + field != nullptr) { + return field->fieldId; + } + + return {}; +} + +bool DoesFieldIdMatchKind( + std::string_view fieldId, + const std::vector& sections, + UIEditorPropertyGridFieldKind kind) { + if (fieldId.empty()) { + return false; + } + + const auto location = Widgets::FindUIEditorPropertyGridFieldLocation(sections, fieldId); + return location.IsValid() && + location.sectionIndex < sections.size() && + location.fieldIndex < sections[location.sectionIndex].fields.size() && + sections[location.sectionIndex].fields[location.fieldIndex].kind == kind; +} + +bool DoesFieldIdMatchSharedEditableKind( + std::string_view fieldId, + const std::vector& sections) { + if (fieldId.empty()) { + return false; + } + + const auto location = Widgets::FindUIEditorPropertyGridFieldLocation(sections, fieldId); + return location.IsValid() && + location.sectionIndex < sections.size() && + location.fieldIndex < sections[location.sectionIndex].fields.size() && + IsSharedEditableFieldKind( + sections[location.sectionIndex].fields[location.fieldIndex].kind); +} + +void PushRoutedFieldId( + Internal::UIEditorPropertyGridRoutedFields& routedFields, + std::string_view fieldId) { + if (fieldId.empty() || routedFields.count >= routedFields.fieldIds.size()) { + return; + } + + if (routedFields.Contains(fieldId)) { + return; + } + + routedFields.fieldIds[routedFields.count++] = fieldId; +} + +Internal::UIEditorPropertyGridRoutedFields ResolveSharedEditableRouteFields( + const UIEditorPropertyGridInteractionState& state, + const ::XCEngine::UI::Widgets::UIPropertyEditModel& propertyEditModel, + const ::XCEngine::UI::Widgets::UISelectionModel& selectionModel, + const std::vector& sections, + const UIInputEvent& event, + std::string_view hitFieldId) { + Internal::UIEditorPropertyGridRoutedFields routedFields = {}; + const auto pushIfMatch = [&routedFields, §ions](std::string_view fieldId) { + if (DoesFieldIdMatchSharedEditableKind(fieldId, sections)) { + PushRoutedFieldId(routedFields, fieldId); + } + }; + + switch (event.type) { + case UIInputEventType::PointerButtonDown: + pushIfMatch(hitFieldId); + break; + + case UIInputEventType::PointerButtonUp: + case UIInputEventType::PointerMove: + case UIInputEventType::PointerEnter: + case UIInputEventType::PointerLeave: + pushIfMatch(state.propertyGridState.pressedFieldId); + pushIfMatch(state.propertyGridState.hoveredFieldId); + pushIfMatch(state.editableFieldSession.activeFieldId); + pushIfMatch(hitFieldId); + break; + + case UIInputEventType::KeyDown: + case UIInputEventType::Character: + if (propertyEditModel.HasActiveEdit()) { + pushIfMatch(propertyEditModel.GetActiveFieldId()); + } + pushIfMatch(state.editableFieldSession.activeFieldId); + if (selectionModel.HasSelection()) { + pushIfMatch(selectionModel.GetSelectedId()); + } + break; + + case UIInputEventType::FocusGained: + case UIInputEventType::FocusLost: + if (propertyEditModel.HasActiveEdit()) { + pushIfMatch(propertyEditModel.GetActiveFieldId()); + } + pushIfMatch(state.propertyGridState.pressedFieldId); + pushIfMatch(state.propertyGridState.hoveredFieldId); + pushIfMatch(state.editableFieldSession.activeFieldId); + if (selectionModel.HasSelection()) { + pushIfMatch(selectionModel.GetSelectedId()); + } + break; + + default: + break; + } + + return routedFields; +} + +Internal::UIEditorPropertyGridRoutedFields ResolveSingleKindRouteFields( + const UIEditorPropertyGridInteractionState& state, + const ::XCEngine::UI::Widgets::UISelectionModel& selectionModel, + const ::XCEngine::UI::Widgets::UIPropertyEditModel& propertyEditModel, + const std::vector& sections, + const UIInputEvent& event, + std::string_view hitFieldId, + UIEditorPropertyGridFieldKind kind) { + Internal::UIEditorPropertyGridRoutedFields routedFields = {}; + const auto pushIfMatch = [&routedFields, §ions, kind](std::string_view fieldId) { + if (DoesFieldIdMatchKind(fieldId, sections, kind)) { + PushRoutedFieldId(routedFields, fieldId); + } + }; + + switch (event.type) { + case UIInputEventType::PointerButtonDown: + pushIfMatch(hitFieldId); + break; + + case UIInputEventType::PointerButtonUp: + case UIInputEventType::PointerMove: + case UIInputEventType::PointerEnter: + case UIInputEventType::PointerLeave: + pushIfMatch(state.propertyGridState.pressedFieldId); + pushIfMatch(state.propertyGridState.hoveredFieldId); + if (propertyEditModel.HasActiveEdit()) { + pushIfMatch(propertyEditModel.GetActiveFieldId()); + } + pushIfMatch(state.editableFieldSession.activeFieldId); + pushIfMatch(hitFieldId); + break; + + case UIInputEventType::KeyDown: + case UIInputEventType::Character: + if (propertyEditModel.HasActiveEdit()) { + pushIfMatch(propertyEditModel.GetActiveFieldId()); + } + pushIfMatch(state.editableFieldSession.activeFieldId); + if (selectionModel.HasSelection() && + DoesFieldIdMatchKind(selectionModel.GetSelectedId(), sections, kind)) { + pushIfMatch(selectionModel.GetSelectedId()); + } + break; + + case UIInputEventType::FocusGained: + case UIInputEventType::FocusLost: + if (propertyEditModel.HasActiveEdit()) { + pushIfMatch(propertyEditModel.GetActiveFieldId()); + } + pushIfMatch(state.propertyGridState.pressedFieldId); + pushIfMatch(state.propertyGridState.hoveredFieldId); + pushIfMatch(state.editableFieldSession.activeFieldId); + if (selectionModel.HasSelection()) { + pushIfMatch(selectionModel.GetSelectedId()); + } + break; + + default: + break; + } + + return routedFields; +} + } // namespace UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( @@ -83,6 +276,75 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( ? HitTestUIEditorPropertyGrid(layout, state.pointerPosition) : UIEditorPropertyGridHitTarget {}; eventResult.hitTarget = hitTarget; + const std::string_view hitFieldId = ResolveHitFieldId(hitTarget, sections); + + if (event.type == UIInputEventType::PointerButtonDown && + event.pointerButton == UIPointerButton::Left && + popupHit.kind == UIEditorMenuPopupHitTargetKind::None) { + const bool insideGrid = + state.hasPointerPosition && + Widgets::IsUIEditorPropertyGridPointInside( + layout.bounds, + state.pointerPosition); + if (hitTarget.kind == UIEditorPropertyGridHitTargetKind::FieldRow || + hitTarget.kind == UIEditorPropertyGridHitTargetKind::ValueBox) { + state.propertyGridState.focused = true; + state.propertyGridState.pressedFieldId = std::string(hitFieldId); + } else if (hitTarget.kind == + UIEditorPropertyGridHitTargetKind::SectionHeader || + insideGrid) { + state.propertyGridState.focused = true; + state.propertyGridState.pressedFieldId.clear(); + } else { + state.propertyGridState.focused = false; + state.propertyGridState.pressedFieldId.clear(); + } + } + + const Internal::UIEditorPropertyGridRoutedFields numberRoutes = + ResolveSingleKindRouteFields( + state, + selectionModel, + propertyEditModel, + sections, + event, + hitFieldId, + UIEditorPropertyGridFieldKind::Number); + const Internal::UIEditorPropertyGridRoutedFields textRoutes = + ResolveSingleKindRouteFields( + state, + selectionModel, + propertyEditModel, + sections, + event, + hitFieldId, + UIEditorPropertyGridFieldKind::Text); + const Internal::UIEditorPropertyGridRoutedFields colorRoutes = + ResolveSingleKindRouteFields( + state, + selectionModel, + propertyEditModel, + sections, + event, + hitFieldId, + UIEditorPropertyGridFieldKind::Color); + const Internal::UIEditorPropertyGridRoutedFields assetRoutes = + ResolveSingleKindRouteFields( + state, + selectionModel, + propertyEditModel, + sections, + event, + hitFieldId, + UIEditorPropertyGridFieldKind::Asset); + const Internal::UIEditorPropertyGridRoutedFields sharedEditableRoutes = + ResolveSharedEditableRouteFields( + state, + propertyEditModel, + selectionModel, + sections, + event, + hitFieldId); UIEditorPropertyGridInteractionResult numberEventResult = {}; if (Internal::ProcessNumberFieldEvent( @@ -93,6 +355,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + numberRoutes, numberEventResult)) { Internal::MergeInteractionResult(eventResult, numberEventResult); refreshInteractionLayout(); @@ -114,6 +377,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + textRoutes, textEventResult)) { Internal::MergeInteractionResult(eventResult, textEventResult); refreshInteractionLayout(); @@ -134,6 +398,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + colorRoutes, eventResult)) { Internal::MergeInteractionResult(interactionResult, eventResult); refreshInteractionLayout(); @@ -150,6 +415,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + sharedEditableRoutes, vectorEventResult) || Internal::ProcessVector3FieldEvent( state, @@ -159,6 +425,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + sharedEditableRoutes, vectorEventResult) || Internal::ProcessVector4FieldEvent( state, @@ -168,6 +435,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + sharedEditableRoutes, vectorEventResult); if (vectorHandled) { Internal::MergeInteractionResult(eventResult, vectorEventResult); @@ -191,6 +459,7 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( sections, metrics, event, + assetRoutes, assetEventResult)) { Internal::MergeInteractionResult(eventResult, assetEventResult); refreshInteractionLayout(); @@ -212,7 +481,14 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction( break; case UIInputEventType::FocusLost: - Internal::CommitActiveEdit(state, propertyEditModel, sections, eventResult); + if (!Internal::CommitActiveEdit( + state, + propertyEditModel, + sections, + eventResult) && + eventResult.editCommitRejected) { + Internal::CancelActiveEdit(state, propertyEditModel, eventResult); + } Internal::ClosePopup(state, eventResult); state.propertyGridState.focused = false; state.propertyGridState.pressedFieldId.clear(); @@ -1234,9 +1510,7 @@ template bool HasMeaningfulResult( const typename Traits::InteractionResult& result, const typename Traits::FieldStateType& previousFieldState, - const typename Traits::InteractionState& interactionState, - bool hadFocus, - bool hadEditing) { + const typename Traits::InteractionState& interactionState) { return result.consumed || result.focusChanged || Traits::HasValueChange(result) || @@ -1248,8 +1522,6 @@ bool HasMeaningfulResult( previousFieldState, Traits::FieldState(interactionState)) || result.hitTarget.kind != Traits::kNoneHitTargetKind || - hadFocus || - hadEditing || Traits::FieldState(interactionState).focused || Traits::FieldState(interactionState).editing; } @@ -1308,8 +1580,12 @@ bool ProcessFieldEventImpl( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { - const typename Traits::Metrics fieldMetrics = Traits::BuildMetrics(metrics); + if (routedFields.Empty()) { + return false; + } + bool handled = false; for (std::size_t visibleFieldIndex = 0u; @@ -1323,7 +1599,10 @@ bool ProcessFieldEventImpl( } UIEditorPropertyGridField& field = sections[sectionIndex].fields[fieldIndex]; - if (field.kind != Traits::kFieldKind) { + typename Traits::Metrics fieldMetrics = Traits::BuildMetrics(metrics); + fieldMetrics.controlMinWidth = field.controlMinWidth; + if (field.kind != Traits::kFieldKind || + !routedFields.Contains(field.fieldId)) { continue; } @@ -1331,8 +1610,6 @@ bool ProcessFieldEventImpl( state.editableFieldSession; typename Traits::InteractionState interactionState = BuildInteractionState(state, field.fieldId); - const bool hadFocus = Traits::FieldState(interactionState).focused; - const bool hadEditing = Traits::FieldState(interactionState).editing; const typename Traits::FieldStateType previousFieldState = Traits::FieldState(interactionState); typename Traits::Spec spec = Traits::BuildSpec(field); @@ -1347,9 +1624,7 @@ bool ProcessFieldEventImpl( if (!HasMeaningfulResult( frame.result, previousFieldState, - interactionState, - hadFocus, - hadEditing)) { + interactionState)) { continue; } @@ -1358,13 +1633,12 @@ bool ProcessFieldEventImpl( if (frame.result.consumed || frame.result.focusChanged || + frame.result.hitTarget.kind != Traits::kNoneHitTargetKind || frame.result.editStarted || frame.result.editCommitted || Traits::HasEditCommitRejected(frame.result) || frame.result.editCanceled || - Traits::HasValueChange(frame.result) || - hadFocus || - Traits::FieldState(interactionState).focused) { + Traits::HasValueChange(frame.result)) { result.selectionChanged = selectionModel.SetSelection(field.fieldId) || result.selectionChanged; result.selectedFieldId = field.fieldId; @@ -1381,8 +1655,7 @@ bool ProcessFieldEventImpl( propertyEditModel.GetActiveFieldId() != field.fieldId && (frame.result.hitTarget.kind != Traits::kNoneHitTargetKind || frame.result.editStarted || - hadFocus || - Traits::FieldState(interactionState).focused)) { + frame.result.consumed)) { CommitActiveEdit(state, propertyEditModel, sections, result); } @@ -1402,9 +1675,11 @@ bool ProcessFieldEventImpl( field.fieldId, interactionState, storeSharedSession); - state.propertyGridState.focused = - Traits::FieldState(interactionState).focused; - state.propertyGridState.pressedFieldId.clear(); + if (event.type == UIInputEventType::PointerButtonUp && + event.pointerButton == UIPointerButton::Left && + state.propertyGridState.pressedFieldId == field.fieldId) { + state.propertyGridState.pressedFieldId.clear(); + } if (Traits::FieldState(interactionState).editing) { propertyEditModel.BeginEdit( field.fieldId, @@ -1636,6 +1911,7 @@ bool ProcessNumberFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { return SingleValueFieldInteractionLocal::ProcessFieldEventImpl< SingleValueFieldInteractionLocal::NumberTraits>( @@ -1646,6 +1922,7 @@ bool ProcessNumberFieldEvent( sections, metrics, event, + routedFields, result); } @@ -1657,6 +1934,7 @@ bool ProcessTextFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { return SingleValueFieldInteractionLocal::ProcessFieldEventImpl< SingleValueFieldInteractionLocal::TextTraits>( @@ -1667,6 +1945,7 @@ bool ProcessTextFieldEvent( sections, metrics, event, + routedFields, result); } @@ -2003,8 +2282,7 @@ void CopySpecToField( bool HasMeaningfulResult( const UIEditorAssetFieldInteractionResult& result, - const UIEditorAssetFieldInteractionState& interactionState, - bool hadFocus) { + const UIEditorAssetFieldInteractionState& interactionState) { return result.consumed || result.focusChanged || result.valueChanged || @@ -2012,7 +2290,6 @@ bool HasMeaningfulResult( result.pickerRequested || result.clearRequested || result.hitTarget.kind != Widgets::UIEditorAssetFieldHitTargetKind::None || - hadFocus || interactionState.fieldState.focused; } @@ -2091,7 +2368,12 @@ bool ProcessAssetFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { + if (routedFields.Empty()) { + return false; + } + const Widgets::UIEditorAssetFieldMetrics assetMetrics = BuildUIEditorPropertyGridAssetFieldMetrics(metrics); bool handled = false; @@ -2107,13 +2389,13 @@ bool ProcessAssetFieldEvent( } UIEditorPropertyGridField& field = sections[sectionIndex].fields[fieldIndex]; - if (field.kind != UIEditorPropertyGridFieldKind::Asset) { + if (field.kind != UIEditorPropertyGridFieldKind::Asset || + !routedFields.Contains(field.fieldId)) { continue; } UIEditorAssetFieldInteractionState assetState = AssetFieldInteractionLocal::BuildInteractionState(state, field.fieldId); - const bool hadFocus = assetState.fieldState.focused; Widgets::UIEditorAssetFieldSpec spec = Widgets::Internal::BuildAssetFieldSpec(field); const UIEditorAssetFieldInteractionFrame frame = @@ -2126,24 +2408,26 @@ bool ProcessAssetFieldEvent( if (!AssetFieldInteractionLocal::HasMeaningfulResult( frame.result, - assetState, - hadFocus)) { + assetState)) { continue; } handled = true; AssetFieldInteractionLocal::CopySpecToField(field, spec); AssetFieldInteractionLocal::StoreInteractionState(state, field.fieldId, assetState); - state.propertyGridState.focused = assetState.fieldState.focused; - state.propertyGridState.pressedFieldId.clear(); + if (event.type == UIInputEventType::PointerButtonUp && + event.pointerButton == UIPointerButton::Left && + state.propertyGridState.pressedFieldId == field.fieldId) { + state.propertyGridState.pressedFieldId.clear(); + } if (frame.result.consumed || frame.result.focusChanged || + frame.result.hitTarget.kind != + Widgets::UIEditorAssetFieldHitTargetKind::None || frame.result.valueChanged || frame.result.activateRequested || - frame.result.pickerRequested || - hadFocus || - assetState.fieldState.focused) { + frame.result.pickerRequested) { result.selectionChanged = selectionModel.SetSelection(field.fieldId) || result.selectionChanged; result.selectedFieldId = field.fieldId; @@ -2158,8 +2442,7 @@ bool ProcessAssetFieldEvent( frame.result.valueChanged || frame.result.activateRequested || frame.result.pickerRequested || - hadFocus || - assetState.fieldState.focused)) { + frame.result.consumed)) { CommitActiveEdit(state, propertyEditModel, sections, result); } @@ -2208,7 +2491,12 @@ bool ProcessColorFieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { + if (routedFields.Empty()) { + return false; + } + const Widgets::UIEditorColorFieldMetrics colorMetrics = BuildUIEditorPropertyGridColorFieldMetrics(metrics); @@ -2223,7 +2511,8 @@ bool ProcessColorFieldEvent( } UIEditorPropertyGridField& field = sections[sectionIndex].fields[fieldIndex]; - if (field.kind != UIEditorPropertyGridFieldKind::Color) { + if (field.kind != UIEditorPropertyGridFieldKind::Color || + !routedFields.Contains(field.fieldId)) { continue; } @@ -2250,11 +2539,15 @@ bool ProcessColorFieldEvent( static_cast(::XCEngine::Input::KeyCode::Enter) || event.keyCode == static_cast(::XCEngine::Input::KeyCode::Space)); - const bool swatchHit = - fieldHitTarget.kind == Widgets::UIEditorColorFieldHitTargetKind::Swatch; + const bool valueBoxHit = + state.hasPointerPosition && + visibleFieldIndex < layout.fieldValueRects.size() && + Widgets::IsUIEditorPropertyGridPointInside( + layout.fieldValueRects[visibleFieldIndex], + state.pointerPosition); if (!pressedField && - !swatchHit && + !valueBoxHit && !keyboardActivate) { continue; } @@ -2268,10 +2561,11 @@ bool ProcessColorFieldEvent( }; auto assignHitTarget = [&]() { - if (fieldHitTarget.kind == Widgets::UIEditorColorFieldHitTargetKind::Row) { - result.hitTarget.kind = UIEditorPropertyGridHitTargetKind::FieldRow; - } else if (fieldHitTarget.kind == Widgets::UIEditorColorFieldHitTargetKind::Swatch) { + if (valueBoxHit || + fieldHitTarget.kind == Widgets::UIEditorColorFieldHitTargetKind::Swatch) { result.hitTarget.kind = UIEditorPropertyGridHitTargetKind::ValueBox; + } else if (fieldHitTarget.kind == Widgets::UIEditorColorFieldHitTargetKind::Row) { + result.hitTarget.kind = UIEditorPropertyGridHitTargetKind::FieldRow; } else { return; } @@ -2284,7 +2578,7 @@ bool ProcessColorFieldEvent( switch (event.type) { case ::XCEngine::UI::UIInputEventType::PointerButtonDown: if (event.pointerButton == ::XCEngine::UI::UIPointerButton::Left && - swatchHit) { + valueBoxHit) { state.propertyGridState.focused = true; state.propertyGridState.pressedFieldId = field.fieldId; result.consumed = true; @@ -2298,8 +2592,8 @@ bool ProcessColorFieldEvent( pressedField) { state.propertyGridState.pressedFieldId.clear(); state.propertyGridState.focused = true; - if (!swatchHit) { - return true; + if (!valueBoxHit) { + return false; } if (propertyEditModel.HasActiveEdit() && @@ -2515,9 +2809,7 @@ template bool HasMeaningfulResult( const typename Traits::InteractionResult& result, const typename Traits::FieldStateType& previousFieldState, - const typename Traits::InteractionState& interactionState, - bool hadFocus, - bool hadEditing) { + const typename Traits::InteractionState& interactionState) { return result.consumed || result.focusChanged || result.valueChanged || @@ -2531,8 +2823,6 @@ bool HasMeaningfulResult( previousFieldState, Traits::FieldState(interactionState)) || result.hitTarget.kind != Traits::kNoneHitTargetKind || - hadFocus || - hadEditing || Traits::FieldState(interactionState).focused || Traits::FieldState(interactionState).editing; } @@ -2564,9 +2854,12 @@ bool ProcessVectorFieldEventImpl( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { - const typename Traits::Metrics vectorMetrics = - Traits::BuildMetrics(metrics); + if (routedFields.Empty()) { + return false; + } + bool handled = false; for (std::size_t visibleFieldIndex = 0u; @@ -2580,7 +2873,10 @@ bool ProcessVectorFieldEventImpl( } UIEditorPropertyGridField& field = sections[sectionIndex].fields[fieldIndex]; - if (field.kind != Traits::kFieldKind) { + typename Traits::Metrics vectorMetrics = Traits::BuildMetrics(metrics); + vectorMetrics.controlMinWidth = field.controlMinWidth; + if (field.kind != Traits::kFieldKind || + !routedFields.Contains(field.fieldId)) { continue; } @@ -2588,8 +2884,6 @@ bool ProcessVectorFieldEventImpl( state.editableFieldSession; typename Traits::InteractionState vectorState = BuildInteractionState(state, field.fieldId); - const bool hadFocus = Traits::FieldState(vectorState).focused; - const bool hadEditing = Traits::FieldState(vectorState).editing; const typename Traits::FieldStateType previousFieldState = Traits::FieldState(vectorState); typename Traits::Spec spec = Traits::BuildSpec(field); @@ -2604,9 +2898,7 @@ bool ProcessVectorFieldEventImpl( if (!HasMeaningfulResult( frame.result, previousFieldState, - vectorState, - hadFocus, - hadEditing)) { + vectorState)) { continue; } @@ -2615,13 +2907,12 @@ bool ProcessVectorFieldEventImpl( if (frame.result.consumed || frame.result.selectionChanged || + frame.result.hitTarget.kind != Traits::kNoneHitTargetKind || frame.result.editStarted || frame.result.valueChanged || frame.result.stepApplied || frame.result.editCommitted || - frame.result.editCanceled || - hadFocus || - Traits::FieldState(vectorState).focused) { + frame.result.editCanceled) { result.selectionChanged = selectionModel.SetSelection(field.fieldId) || result.selectionChanged; result.selectedFieldId = field.fieldId; @@ -2654,9 +2945,11 @@ bool ProcessVectorFieldEventImpl( field.fieldId, vectorState, storeSharedSession); - state.propertyGridState.focused = - Traits::FieldState(vectorState).focused; - state.propertyGridState.pressedFieldId.clear(); + if (event.type == UIInputEventType::PointerButtonUp && + event.pointerButton == UIPointerButton::Left && + state.propertyGridState.pressedFieldId == field.fieldId) { + state.propertyGridState.pressedFieldId.clear(); + } if (Traits::FieldState(vectorState).editing) { propertyEditModel.BeginEdit( field.fieldId, @@ -2930,6 +3223,7 @@ bool ProcessVector2FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { return VectorFieldInteractionLocal::ProcessVectorFieldEventImpl< VectorFieldInteractionLocal::Vector2Traits>( @@ -2940,6 +3234,7 @@ bool ProcessVector2FieldEvent( sections, metrics, event, + routedFields, result); } @@ -2951,6 +3246,7 @@ bool ProcessVector3FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { return VectorFieldInteractionLocal::ProcessVectorFieldEventImpl< VectorFieldInteractionLocal::Vector3Traits>( @@ -2961,6 +3257,7 @@ bool ProcessVector3FieldEvent( sections, metrics, event, + routedFields, result); } @@ -2972,6 +3269,7 @@ bool ProcessVector4FieldEvent( std::vector& sections, const Widgets::UIEditorPropertyGridMetrics& metrics, const ::XCEngine::UI::UIInputEvent& event, + const Internal::UIEditorPropertyGridRoutedFields& routedFields, UIEditorPropertyGridInteractionResult& result) { return VectorFieldInteractionLocal::ProcessVectorFieldEventImpl< VectorFieldInteractionLocal::Vector4Traits>( @@ -2982,6 +3280,7 @@ bool ProcessVector4FieldEvent( sections, metrics, event, + routedFields, result); } diff --git a/new_editor/src/Fields/UIEditorTextField.cpp b/new_editor/src/Fields/UIEditorTextField.cpp index 9df3f8d2..324f7c0b 100644 --- a/new_editor/src/Fields/UIEditorTextField.cpp +++ b/new_editor/src/Fields/UIEditorTextField.cpp @@ -85,7 +85,7 @@ UIEditorTextFieldPalette ResolvePalette(const UIEditorTextFieldPalette& palette) return palette.readOnlyColor; } if (state.editing) { - return palette.valueBoxEditingColor; + return palette.valueBoxColor; } if (state.hoveredTarget == UIEditorTextFieldHitTargetKind::ValueBox) { return palette.valueBoxHoverColor; @@ -117,7 +117,7 @@ UIEditorTextFieldLayout BuildUIEditorTextFieldLayout( resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, - resolvedMetrics.sharedControlColumnMinWidth, + resolvedMetrics.controlMinWidth, resolvedMetrics.controlTrailingInset, resolvedMetrics.controlInsetY, }); @@ -199,7 +199,10 @@ void AppendUIEditorTextFieldForeground( drawList.AddText( UIPoint( layout.valueRect.x + resolvedMetrics.valueTextInsetX, - ResolveUIEditorTextTop(layout.valueRect, resolvedMetrics.valueFontSize, resolvedMetrics.valueTextInsetY)), + ResolveUIEditorControlTextTop( + layout.valueRect, + resolvedMetrics.valueFontSize, + resolvedMetrics.valueTextInsetY)), state.editing ? state.displayText : spec.value, spec.readOnly ? resolvedPalette.readOnlyValueColor : resolvedPalette.valueColor, resolvedMetrics.valueFontSize); diff --git a/new_editor/src/Fields/UIEditorTextFieldInteraction.cpp b/new_editor/src/Fields/UIEditorTextFieldInteraction.cpp index 89b98f80..9eb19901 100644 --- a/new_editor/src/Fields/UIEditorTextFieldInteraction.cpp +++ b/new_editor/src/Fields/UIEditorTextFieldInteraction.cpp @@ -255,6 +255,12 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction( break; } + if (!state.session.editing && + !IsUIEditorEditableFieldCharacterInsertable( + event.character)) { + break; + } + if (!state.session.editing) { eventResult.editStarted = BeginEdit(state, spec, true); } diff --git a/new_editor/src/Fields/UIEditorVectorFieldShared.h b/new_editor/src/Fields/UIEditorVectorFieldShared.h index f75932f5..f75df787 100644 --- a/new_editor/src/Fields/UIEditorVectorFieldShared.h +++ b/new_editor/src/Fields/UIEditorVectorFieldShared.h @@ -190,7 +190,7 @@ template return palette.readOnlyColor; } if (state.editing && state.selectedComponentIndex == componentIndex) { - return palette.componentEditingColor; + return palette.componentColor; } if (state.hoveredComponentIndex == componentIndex) { return palette.componentHoverColor; @@ -265,7 +265,7 @@ typename Traits::Layout BuildLayout( resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, - resolvedMetrics.sharedControlColumnMinWidth, + resolvedMetrics.controlMinWidth, resolvedMetrics.controlTrailingInset, resolvedMetrics.controlInsetY, }); @@ -428,7 +428,7 @@ void AppendForeground( drawList.AddText( UIPoint( prefixTextX, - Widgets::ResolveUIEditorTextTop( + Widgets::ResolveUIEditorControlTextTop( layout.componentPrefixRects[componentIndex], resolvedMetrics.prefixFontSize, resolvedMetrics.prefixTextInsetY)), @@ -445,7 +445,7 @@ void AppendForeground( UIPoint( layout.componentValueRects[componentIndex].x + resolvedMetrics.valueTextInsetX, - Widgets::ResolveUIEditorTextTop( + Widgets::ResolveUIEditorControlTextTop( layout.componentValueRects[componentIndex], resolvedMetrics.valueFontSize, resolvedMetrics.valueTextInsetY)), diff --git a/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp b/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp index f0b3c846..62b039db 100644 --- a/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp +++ b/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp @@ -82,8 +82,8 @@ UIEditorFieldRowLayout BuildUIEditorFieldRowLayout( rowBounds.x + ClampNonNegative(rowBounds.width) - trailingInset; const float contentWidth = ClampNonNegative(contentRight - contentLeft); const float requestedReservedControlWidth = ClampNonNegative( - metrics.sharedControlColumnMinWidth > 0.0f - ? metrics.sharedControlColumnMinWidth + metrics.controlMinWidth > 0.0f + ? metrics.controlMinWidth : minimumControlWidth); const float reservedControlWidth = ClampNonNegative((std::min)(requestedReservedControlWidth, contentWidth));