关键节点

This commit is contained in:
2026-04-25 16:46:01 +08:00
parent 6002d86a7e
commit ef41c44464
516 changed files with 6175 additions and 12401 deletions

View File

@@ -242,9 +242,6 @@ endif()
add_subdirectory(engine)
add_subdirectory(managed)
if(EXISTS "${CMAKE_SOURCE_DIR}/editor/CMakeLists.txt")
add_subdirectory(editor)
endif()
add_subdirectory(new_editor)
add_subdirectory(editor)
add_subdirectory(mvs/RenderDoc)
add_subdirectory(tests)

View File

@@ -117,6 +117,7 @@ set(XCUI_EDITOR_VIEWPORT_SOURCES
set(XCUI_EDITOR_WORKSPACE_SOURCES
src/Workspace/UIEditorWorkspaceCompose.cpp
src/Workspace/UIEditorWorkspaceController.cpp
src/Workspace/UIEditorDetachedWindowPolicy.cpp
src/Workspace/UIEditorWorkspaceInteraction.cpp
src/Workspace/UIEditorWorkspaceInputOwner.cpp
src/Workspace/UIEditorWorkspaceLayoutPersistence.cpp
@@ -125,6 +126,8 @@ set(XCUI_EDITOR_WORKSPACE_SOURCES
src/Workspace/SplitterDragCorrection/Correction.cpp
src/Workspace/UIEditorWorkspaceSession.cpp
src/Workspace/UIEditorWorkspaceTransfer.cpp
src/Workspace/UIEditorWindowWorkspaceController.cpp
src/Workspace/UIEditorWindowWorkspaceModel.cpp
)
set(XCUI_EDITOR_WIDGET_SUPPORT_SOURCES
@@ -172,6 +175,8 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
)
set(XCUI_EDITOR_APP_STATE_SOURCES
app/State/EditorColorPickerToolState.cpp
app/State/EditorUtilityWindowRequestState.cpp
app/State/EditorSession.cpp
)
@@ -187,9 +192,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
app/Composition/EditorShellInteractionEngine.cpp
app/Composition/EditorShellRuntime.cpp
app/Composition/EditorShellSessionCoordinator.cpp
app/Composition/EditorWindowApplicationComposition.cpp
app/Composition/EditorWindowWorkspaceStore.cpp
app/Composition/EditorUtilityWindowPanelComposition.cpp
app/Composition/WorkspaceEventSync.cpp
)
@@ -214,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
@@ -235,48 +239,24 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
app/Scene/EditorSceneBridge.cpp
)
set(XCUI_EDITOR_APP_WINDOWING_SOURCES
app/Windowing/Application/EditorWindowApplicationRuntime.cpp
app/Windowing/Application/EditorWindowApplicationStateRuntime.cpp
app/Windowing/Application/EditorWindowGeometry.cpp
app/Windowing/Application/EditorWindowLifecycleRelay.cpp
app/Windowing/Application/EditorWindowPostFrameRuntime.cpp
app/Windowing/Application/FrameScheduler.cpp
app/Windowing/Application/WindowSession.cpp
app/Windowing/Content/EditorWindowContentRuntime.cpp
app/Windowing/Content/EditorWindowFrameOrchestrator.cpp
app/Windowing/Utility/EditorUtilityWindowCatalog.cpp
app/Windowing/Utility/EditorUtilityWindowFrameWorkflow.cpp
app/Windowing/Utility/EditorUtilityWindowRequestSink.cpp
app/Windowing/Utility/EditorUtilityWindowSession.cpp
app/Windowing/Utility/EditorWindowUtilityRuntime.cpp
app/Windowing/Workspace/EditorWindowWorkspaceInteractionRuntime.cpp
app/Windowing/Workspace/EditorWindowWorkspaceMutationRuntime.cpp
app/Windowing/Workspace/EditorWindowWorkspaceProjectionRuntime.cpp
app/Windowing/Workspace/UIEditorDetachedWindowPolicy.cpp
app/Windowing/Workspace/UIEditorWindowWorkspaceController.cpp
app/Windowing/Workspace/UIEditorWindowWorkspaceModel.cpp
)
set(XCUI_EDITOR_APP_PLATFORM_SOURCES
app/Platform/Win32/Windowing/EditorWindow.cpp
app/Platform/Win32/Windowing/EditorFloatingWindowPlacement.cpp
app/Platform/Win32/Windowing/EditorWindowSession.cpp
app/Platform/Win32/Content/EditorUtilityWindowContentController.cpp
app/Platform/Win32/Chrome/EditorWindowChromeController.cpp
app/Platform/Win32/Rendering/D3D12WindowRenderHost.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/Backend/Win32NativeWindowBackend.cpp
app/Platform/Win32/Projection/Win32WindowCommandProjector.cpp
app/Platform/Win32/Windowing/EditorWindowFramePumpRuntime.cpp
app/Platform/Win32/Windowing/EditorWindowRegistryRuntime.cpp
app/Platform/Win32/Windowing/EditorWindowInputMessageExecutor.cpp
app/Platform/Win32/Windowing/EditorWindowLifecycleEventRuntime.cpp
app/Platform/Win32/Windowing/EditorWindowLifecycleFinalizationRuntime.cpp
app/Platform/Win32/Windowing/EditorWindowMessagePumpRuntime.cpp
app/Platform/Win32/Windowing/EditorWindowPlatformRuntime.cpp
app/Platform/Win32/Windowing/Win32WindowApplicationRuntime.cpp
app/Platform/Win32/Windowing/Win32WindowRuntimeGraph.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
@@ -286,7 +266,6 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
${XCUI_EDITOR_APP_FEATURE_SOURCES}
${XCUI_EDITOR_APP_RENDERING_SOURCES}
${XCUI_EDITOR_APP_SUPPORT_SOURCES}
${XCUI_EDITOR_APP_WINDOWING_SOURCES}
)
set(XCUI_EDITOR_APP_INTERNAL_SOURCES
@@ -354,9 +333,3 @@ endif()

View File

@@ -2,12 +2,12 @@
#include "Bootstrap/EditorResources.h"
#include "System/SystemInteractionService.h"
#include "Composition/EditorContext.h"
#include "Composition/EditorWindowApplicationComposition.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"
#include "Platform/Win32/Windowing/EditorWindowPlatformRuntime.h"
#include "Platform/Win32/Windowing/Win32WindowApplicationRuntime.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
@@ -123,46 +123,35 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
hostConfig.windowStyle = kBorderlessWindowStyle;
hostConfig.primaryWindowTitle = kWindowTitle;
hostConfig.windowUserData = this;
auto platformRuntime = std::make_unique<App::EditorWindowPlatformRuntime>(
m_windowManager = std::make_unique<App::EditorWindowManager>(
hostConfig,
m_repoRoot,
*m_editorContext);
App::EditorWindowHostAdapters hostAdapters =
platformRuntime->CreateWindowHostAdapters();
m_windowApplicationComposition =
std::make_unique<App::EditorWindowApplicationComposition>(
kWindowTitle,
hostAdapters,
*m_editorContext);
m_windowRuntime = std::make_unique<App::Win32WindowApplicationRuntime>(
std::move(platformRuntime),
m_windowApplicationComposition->GetRuntime(),
*m_editorContext);
m_editorContext->SetExitRequestHandler([this]() {
if (m_windowRuntime == nullptr) {
if (m_windowManager == nullptr) {
return;
}
m_windowRuntime->RequestClosePrimaryWindow();
if (App::EditorWindow* primaryWindow = m_windowManager->FindPrimaryWindow();
primaryWindow != nullptr &&
primaryWindow->GetHwnd() != nullptr) {
PostMessageW(primaryWindow->GetHwnd(), WM_CLOSE, 0, 0);
}
});
m_editorContext->SetReadyStatus();
App::EditorWindowCreateParams createParams = {};
App::EditorWindowManager::CreateParams createParams = {};
createParams.windowId = "main";
createParams.windowType =
::XCEngine::UI::Editor::Windowing::Domain::WindowType::PrimaryWorkspace;
createParams.title = kWindowTitle;
createParams.showCommand = nCmdShow;
createParams.primary = true;
createParams.autoCaptureOnStartup =
App::IsEnvironmentFlagEnabled("XCUI_AUTO_CAPTURE_ON_STARTUP");
if (!m_windowRuntime->CreateWindowHost(
App::EditorWorkspaceWindowContentSpec{
.workspaceController = m_editorContext->BuildWorkspaceController(),
},
createParams)) {
if (m_windowManager->CreateEditorWindow(
App::CreateEditorWorkspaceWindowContentController(
m_editorContext->BuildWorkspaceController()),
createParams) == nullptr) {
AppendUIEditorRuntimeTrace("app", "primary window creation failed");
return false;
}
@@ -174,36 +163,21 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
void Application::Shutdown() {
AppendUIEditorRuntimeTrace("app", "shutdown begin");
if (m_windowRuntime != nullptr) {
AppendUIEditorRuntimeTrace("app", "shutdown stage=WindowManager begin");
m_windowRuntime->Shutdown();
m_windowRuntime.reset();
AppendUIEditorRuntimeTrace("app", "shutdown stage=WindowManager end");
}
if (m_windowApplicationComposition != nullptr) {
AppendUIEditorRuntimeTrace("app", "shutdown stage=WindowApplicationComposition begin");
m_windowApplicationComposition.reset();
AppendUIEditorRuntimeTrace("app", "shutdown stage=WindowApplicationComposition end");
if (m_windowManager != nullptr) {
m_windowManager->Shutdown();
m_windowManager.reset();
}
if (m_editorContext != nullptr) {
AppendUIEditorRuntimeTrace("app", "shutdown stage=EditorContext begin");
m_editorContext->SetSystemInteractionHost(nullptr);
AppendUIEditorRuntimeTrace("app", "shutdown stage=EditorContext end");
}
AppendUIEditorRuntimeTrace("app", "shutdown stage=SystemInteractionHost begin");
m_systemInteractionHost.reset();
AppendUIEditorRuntimeTrace("app", "shutdown stage=SystemInteractionHost end");
AppendUIEditorRuntimeTrace("app", "shutdown stage=ResourceManager begin");
::XCEngine::Resources::ResourceManager::Get().Shutdown();
AppendUIEditorRuntimeTrace("app", "shutdown stage=ResourceManager end");
if (m_windowClassAtom != 0 && m_hInstance != nullptr) {
AppendUIEditorRuntimeTrace("app", "shutdown stage=UnregisterClass begin");
UnregisterClassW(kWindowClassName, m_hInstance);
m_windowClassAtom = 0;
AppendUIEditorRuntimeTrace("app", "shutdown stage=UnregisterClass end");
}
AppendUIEditorRuntimeTrace("app", "shutdown end");
@@ -255,21 +229,17 @@ int Application::Run(HINSTANCE hInstance, int nCmdShow) {
TranslateMessage(&message);
DispatchMessageW(&message);
if (m_windowRuntime != nullptr) {
m_windowRuntime->PumpFrames(
App::EditorWindowFramePumpMode::AfterMessage);
}
++processedMessageCount;
}
if (m_windowRuntime != nullptr) {
if (m_windowManager != nullptr) {
::XCEngine::Resources::ResourceManager::Get().UpdateAsyncLoads();
m_windowRuntime->DestroyClosedWindows();
if (!m_windowRuntime->HasWindows()) {
m_windowManager->DestroyClosedWindows();
if (!m_windowManager->HasWindows()) {
break;
}
m_windowRuntime->PumpFrames(App::EditorWindowFramePumpMode::SteadyTick);
m_windowManager->RenderAllWindows();
} else {
break;
}
@@ -356,8 +326,8 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
? reinterpret_cast<Application*>(createStruct->lpCreateParams)
: nullptr;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(application));
if (application != nullptr && application->m_windowRuntime != nullptr) {
application->m_windowRuntime->HandlePendingNativeWindowCreated(hwnd);
if (application != nullptr && application->m_windowManager != nullptr) {
application->m_windowManager->HandlePendingNativeWindowCreated(hwnd);
}
return TRUE;
}
@@ -365,8 +335,8 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
Application* application = GetApplicationFromWindowUserData(hwnd);
LRESULT dispatcherResult = 0;
if (application != nullptr &&
application->m_windowRuntime != nullptr &&
application->m_windowRuntime->TryDispatchWindowMessage(
application->m_windowManager != nullptr &&
application->m_windowManager->TryDispatchWindowMessage(
hwnd,
message,
wParam,
@@ -380,4 +350,3 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
} // namespace XCEngine::UI::Editor

View File

@@ -12,8 +12,7 @@
namespace XCEngine::UI::Editor {
namespace App {
class EditorContext;
class EditorWindowApplicationComposition;
class Win32WindowApplicationRuntime;
class EditorWindowManager;
}
namespace System {
@@ -48,8 +47,7 @@ private:
ATOM m_windowClassAtom = 0;
std::filesystem::path m_repoRoot = {};
std::unique_ptr<App::EditorContext> m_editorContext = {};
std::unique_ptr<App::EditorWindowApplicationComposition> m_windowApplicationComposition = {};
std::unique_ptr<App::Win32WindowApplicationRuntime> m_windowRuntime = {};
std::unique_ptr<App::EditorWindowManager> m_windowManager = {};
std::unique_ptr<System::SystemInteractionService> m_systemInteractionHost = {};
};

View File

@@ -70,6 +70,8 @@ bool EditorContext::Initialize(const std::filesystem::path& repoRoot) {
m_sceneRuntime.Initialize(m_session.projectRoot);
AppendUIEditorRuntimeTrace("startup", "EditorSceneRuntime::Initialize end");
m_sceneRuntime.BindSelectionService(&m_selectionService);
ResetEditorColorPickerToolState(m_colorPickerToolState);
ResetEditorUtilityWindowRequestState(m_utilityWindowRequestState);
SyncSessionFromSelectionService();
m_hostCommandBridge.BindSession(m_session);
m_hostCommandBridge.BindCommandFocusService(m_commandFocusService);
@@ -157,6 +159,21 @@ const EditorSceneRuntime& EditorContext::GetSceneRuntime() const {
return m_sceneRuntime;
}
EditorColorPickerToolState& EditorContext::GetColorPickerToolState() {
return m_colorPickerToolState;
}
const EditorColorPickerToolState& EditorContext::GetColorPickerToolState() const {
return m_colorPickerToolState;
}
void EditorContext::RequestOpenUtilityWindow(EditorUtilityWindowKind kind) {
RequestEditorUtilityWindow(m_utilityWindowRequestState, kind);
}
std::optional<EditorUtilityWindowKind> EditorContext::ConsumeOpenUtilityWindowRequest() {
return ConsumeEditorUtilityWindowRequest(m_utilityWindowRequestState);
}
void EditorContext::SetSelection(EditorSelectionState selection) {
m_selectionService.SetSelection(std::move(selection));
@@ -366,6 +383,3 @@ void EditorContext::AppendConsoleEntry(
} // namespace XCEngine::UI::Editor::App

View File

@@ -3,11 +3,14 @@
#include "Composition/EditorShellVariant.h"
#include "Project/EditorProjectRuntime.h"
#include "Scene/EditorSceneRuntime.h"
#include "UtilityWindows/EditorUtilityWindowKind.h"
#include "Commands/EditorHostCommandBridge.h"
#include "State/EditorColorPickerToolState.h"
#include "State/EditorCommandFocusService.h"
#include "State/EditorSelectionService.h"
#include "State/EditorSession.h"
#include "State/EditorUtilityWindowRequestState.h"
#include <XCEditor/Foundation/UIEditorShortcutManager.h>
#include <XCEditor/Shell/UIEditorShellAsset.h>
#include <XCEditor/Shell/UIEditorShellInteraction.h>
@@ -18,7 +21,6 @@
#include <optional>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor::System {
class SystemInteractionService;
@@ -51,6 +53,10 @@ public:
const EditorProjectRuntime& GetProjectRuntime() const;
EditorSceneRuntime& GetSceneRuntime();
const EditorSceneRuntime& GetSceneRuntime() const;
EditorColorPickerToolState& GetColorPickerToolState();
const EditorColorPickerToolState& GetColorPickerToolState() const;
void RequestOpenUtilityWindow(EditorUtilityWindowKind kind);
std::optional<EditorUtilityWindowKind> ConsumeOpenUtilityWindowRequest();
void SetSelection(EditorSelectionState selection);
void ClearSelection();
void SyncSessionFromSelectionService();
@@ -87,6 +93,8 @@ private:
EditorSelectionService m_selectionService = {};
EditorProjectRuntime m_projectRuntime = {};
EditorSceneRuntime m_sceneRuntime = {};
EditorColorPickerToolState m_colorPickerToolState = {};
EditorUtilityWindowRequestState m_utilityWindowRequestState = {};
EditorHostCommandBridge m_hostCommandBridge = {};
System::SystemInteractionService* m_systemInteractionHost = nullptr;
std::string m_lastStatus = {};
@@ -94,6 +102,3 @@ private:
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -569,7 +569,7 @@ namespace XCEngine::UI::Editor::App {
EditorShellAsset BuildEditorApplicationShellAsset(const std::filesystem::path& repoRoot) {
EditorShellAsset asset = {};
asset.screenId = "editor.shell";
asset.captureRootPath = (repoRoot / "new_editor/captures").lexically_normal();
asset.captureRootPath = (repoRoot / "editor/captures").lexically_normal();
asset.panelRegistry = BuildEditorPanelRegistry();
asset.workspace = BuildEditorWorkspaceModel(asset.panelRegistry);
asset.workspaceSession =

View File

@@ -69,8 +69,6 @@ void EditorShellHostedPanelCoordinator::Update(
hostedContentEvents);
context.inspectorPanel.Update(
context.context,
context.utilityWindowResultState,
context.utilityRequestSink,
inspectorDispatchEntry,
hostedContentEvents);
context.context.SyncSessionFromCommandFocusService();
@@ -80,6 +78,3 @@ void EditorShellHostedPanelCoordinator::Update(
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -19,8 +19,6 @@ namespace XCEngine::UI::Editor::App {
class ConsolePanel;
class EditorContext;
class EditorUtilityWindowRequestSink;
struct EditorUtilityWindowResultState;
class HierarchyPanel;
class InspectorPanel;
class ProjectPanel;
@@ -28,8 +26,6 @@ class SceneViewportFeature;
struct EditorShellHostedPanelCoordinatorContext {
EditorContext& context;
EditorUtilityWindowResultState& utilityWindowResultState;
EditorUtilityWindowRequestSink& utilityRequestSink;
UIEditorShellInteractionFrame& shellFrame;
UIEditorShellInteractionState& shellInteractionState;
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents;
@@ -47,7 +43,3 @@ public:
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,4 +1,4 @@
#include "Composition/EditorShellRuntime.h"
#include "Composition/EditorShellRuntime.h"
#include "Rendering/Host/UiTextureHost.h"
#include "Rendering/Host/ViewportRenderHost.h"
#include "Composition/EditorContext.h"
@@ -91,11 +91,11 @@ void EditorShellRuntime::ClearExternalDockHostDropPreview() {
.dockHostState.dropPreview = {};
}
ProjectPanel::CursorKind EditorShellRuntime::GetHostedContentCursorType() const {
ProjectPanel::CursorKind EditorShellRuntime::GetHostedContentCursorKind() const {
return m_projectPanel.GetCursorKind();
}
Widgets::UIEditorDockHostCursorKind EditorShellRuntime::GetDockCursorType() const {
Widgets::UIEditorDockHostCursorKind EditorShellRuntime::GetDockCursorKind() const {
return Widgets::ResolveUIEditorDockHostCursorKind(
m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout);
}
@@ -163,8 +163,6 @@ namespace XCEngine::UI::Editor::App {
void EditorShellRuntime::Update(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
UIEditorWorkspaceController& workspaceController,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
@@ -208,8 +206,6 @@ void EditorShellRuntime::Update(
m_hostedPanelCoordinator.Update(
EditorShellHostedPanelCoordinatorContext{
.context = context,
.utilityWindowResultState = utilityWindowResultState,
.utilityRequestSink = utilityRequestSink,
.shellFrame = m_shellFrame,
.shellInteractionState = m_shellInteractionState,
.inputEvents = inputEvents,
@@ -229,6 +225,3 @@ void EditorShellRuntime::Update(
} // namespace XCEngine::UI::Editor::App

View File

@@ -30,8 +30,6 @@
namespace XCEngine::UI::Editor::App {
class EditorContext;
class EditorUtilityWindowRequestSink;
struct EditorUtilityWindowResultState;
} // namespace XCEngine::UI::Editor::App
@@ -44,7 +42,7 @@ class ViewportRenderHost;
namespace XCEngine::Rendering {
struct RenderContext;
class RenderContext;
} // namespace XCEngine::Rendering
@@ -64,8 +62,6 @@ public:
void Update(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
UIEditorWorkspaceController& workspaceController,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
@@ -86,8 +82,8 @@ public:
const Widgets::UIEditorDockHostDropPreviewState& preview);
void ClearExternalDockHostDropPreview();
ProjectPanel::CursorKind GetHostedContentCursorType() const;
Widgets::UIEditorDockHostCursorKind GetDockCursorType() const;
ProjectPanel::CursorKind GetHostedContentCursorKind() const;
Widgets::UIEditorDockHostCursorKind GetDockCursorKind() const;
bool TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
@@ -122,7 +118,3 @@ private:
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,6 @@
#pragma once
#include "Windowing/Workspace/UIEditorWindowWorkspaceController.h"
#include <XCEditor/Workspace/UIEditorWindowWorkspaceController.h>
#include <string>

View File

@@ -1,5 +1,8 @@
#include "ColorPickerPanel.h"
#include "Composition/EditorContext.h"
#include "State/EditorColorPickerToolState.h"
#include <XCEditor/Fields/UIEditorFieldStyle.h>
#include <XCEditor/Foundation/UIEditorPanelInputFilter.h>
@@ -84,14 +87,13 @@ void ColorPickerPanel::ResetInteractionState() {
m_frame = {};
}
EditorUtilityWindowPanelOutput ColorPickerPanel::Update(
EditorUtilityWindowPanelServices services,
void ColorPickerPanel::Update(
EditorContext& context,
const EditorUtilityWindowHostContext& hostContext,
const EditorUtilityWindowSession& session,
const std::vector<UIInputEvent>& inputEvents) {
if (!hostContext.mounted) {
ResetPanelState();
return {};
return;
}
m_visible = true;
@@ -99,30 +101,33 @@ EditorUtilityWindowPanelOutput ColorPickerPanel::Update(
m_metrics = BuildColorPickerPanelMetrics(m_bounds);
m_palette = BuildColorPickerPanelPalette();
const EditorUtilityWindowColorPickerPayload* payload = TryGetColorPickerPayload(session);
m_hasActiveTarget = payload != nullptr && payload->IsValid();
EditorColorPickerToolState& toolState = context.GetColorPickerToolState();
m_hasActiveTarget =
toolState.active &&
!toolState.inspectorTarget.subjectKey.empty() &&
!toolState.inspectorTarget.fieldId.empty();
if (!m_hasActiveTarget) {
m_targetSubjectKey.clear();
m_targetFieldId.clear();
m_spec = {};
m_frame = {};
m_interactionState = {};
return {};
return;
}
const bool targetChanged =
m_targetSubjectKey != payload->targetSubjectKey ||
m_targetFieldId != payload->targetFieldId;
m_targetSubjectKey != toolState.inspectorTarget.subjectKey ||
m_targetFieldId != toolState.inspectorTarget.fieldId;
if (targetChanged) {
ResetInteractionState();
m_targetSubjectKey = payload->targetSubjectKey;
m_targetFieldId = payload->targetFieldId;
m_targetSubjectKey = toolState.inspectorTarget.subjectKey;
m_targetFieldId = toolState.inspectorTarget.fieldId;
}
m_spec = {};
m_spec.fieldId = m_targetFieldId;
m_spec.value = payload->initialColor;
m_spec.showAlpha = payload->showAlpha;
m_spec.value = toolState.color;
m_spec.showAlpha = toolState.showAlpha;
m_spec.readOnly = false;
m_spec.embeddedEditor = true;
@@ -162,19 +167,7 @@ EditorUtilityWindowPanelOutput ColorPickerPanel::Update(
m_bounds);
}
if (m_frame.result.colorChanged) {
return EditorUtilityWindowPanelOutput{
.result = EditorUtilityWindowPanelResult{
.type = EditorUtilityWindowPanelResult::Type::ColorPickerValueChanged,
.targetSubjectKey = m_targetSubjectKey,
.targetFieldId = m_targetFieldId,
.color = m_spec.value,
.showAlpha = payload->showAlpha,
},
};
}
return {};
UpdateEditorColorPickerToolColor(toolState, m_spec.value);
}
void ColorPickerPanel::Append(UIDrawList& drawList) const {
@@ -213,4 +206,3 @@ void ColorPickerPanel::Append(UIDrawList& drawList) const {
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,6 @@
#pragma once
#include "Windowing/Utility/EditorUtilityWindowPanel.h"
#include "UtilityWindows/EditorUtilityWindowPanel.h"
#include <XCEditor/Fields/UIEditorColorFieldInteraction.h>
@@ -14,10 +14,9 @@ public:
return "XCEditorUtility.ColorPicker";
}
void ResetInteractionState() override;
EditorUtilityWindowPanelOutput Update(
EditorUtilityWindowPanelServices services,
void Update(
EditorContext& context,
const EditorUtilityWindowHostContext& hostContext,
const EditorUtilityWindowSession& session,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override;
void Append(::XCEngine::UI::UIDrawList& drawList) const override;
@@ -37,7 +36,3 @@ private:
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,6 @@
#include "Features/Inspector/AddComponentPanel.h"
#include "Windowing/Utility/EditorUtilityWindowFeatureCommands.h"
#include "Composition/EditorContext.h"
#include "Features/Inspector/Components/IInspectorComponentEditor.h"
#include "Features/Inspector/Components/InspectorComponentEditorRegistry.h"
@@ -122,15 +122,8 @@ void AddComponentPanel::RebuildEntries(
}
bool AddComponentPanel::TryActivateEntry(
const EditorUtilityWindowSession& session,
std::size_t entryIndex,
EditorUtilityWindowPanelResult& outResult) const {
outResult = {};
const EditorUtilityWindowAddComponentPayload* payload = TryGetAddComponentPayload(session);
if (payload == nullptr || !payload->IsValid()) {
return false;
}
EditorContext& context,
std::size_t entryIndex) {
if (entryIndex >= m_entries.size()) {
return false;
}
@@ -140,9 +133,13 @@ bool AddComponentPanel::TryActivateEntry(
return false;
}
outResult.type = EditorUtilityWindowPanelResult::Type::AddComponent;
outResult.targetItemId = payload->targetItemId;
outResult.componentTypeName = entry.componentTypeName;
if (!context.GetSceneRuntime().AddComponentToSelectedGameObject(entry.componentTypeName)) {
return false;
}
m_hasTarget = context.GetSceneRuntime().GetSelectedGameObject() != nullptr;
m_targetDisplayName = context.GetSceneRuntime().GetSelectedDisplayName();
RebuildEntries(context.GetSceneRuntime().GetSelectedGameObject());
return true;
}
@@ -156,33 +153,20 @@ std::size_t AddComponentPanel::HitTestEntry(const UIPoint& point) const {
return kInvalidEntryIndex;
}
EditorUtilityWindowPanelOutput AddComponentPanel::Update(
EditorUtilityWindowPanelServices services,
void AddComponentPanel::Update(
EditorContext& context,
const EditorUtilityWindowHostContext& hostContext,
const EditorUtilityWindowSession& session,
const std::vector<UIInputEvent>& inputEvents) {
if (!hostContext.mounted) {
ResetPanelState();
return {};
return;
}
m_visible = true;
const EditorUtilityWindowAddComponentPayload* payload = TryGetAddComponentPayload(session);
m_hasTarget = payload != nullptr && payload->IsValid();
if (!m_hasTarget) {
m_targetDisplayName.clear();
m_entries.clear();
ResetInteractionState();
return {};
}
m_bounds = hostContext.bounds;
const ::XCEngine::Components::GameObject* gameObject =
services.addComponentQueries != nullptr
? services.addComponentQueries->FindTargetGameObject(payload->targetItemId)
: nullptr;
m_hasTarget = gameObject != nullptr;
m_targetDisplayName = payload->targetDisplayName;
RebuildEntries(gameObject);
m_hasTarget = context.GetSceneRuntime().GetSelectedGameObject() != nullptr;
m_targetDisplayName = context.GetSceneRuntime().GetSelectedDisplayName();
RebuildEntries(context.GetSceneRuntime().GetSelectedGameObject());
if (hostContext.focusLost) {
ResetInteractionState();
@@ -220,13 +204,7 @@ EditorUtilityWindowPanelOutput AddComponentPanel::Update(
m_hoveredEntryIndex = HitTestEntry(event.position);
if (m_pressedEntryIndex != kInvalidEntryIndex &&
m_pressedEntryIndex == m_hoveredEntryIndex) {
EditorUtilityWindowPanelResult result = {};
if (TryActivateEntry(session, m_pressedEntryIndex, result)) {
return EditorUtilityWindowPanelOutput{
.closeRequested = true,
.result = std::move(result),
};
}
TryActivateEntry(context, m_pressedEntryIndex);
}
m_pressedEntryIndex = kInvalidEntryIndex;
break;
@@ -235,8 +213,6 @@ EditorUtilityWindowPanelOutput AddComponentPanel::Update(
break;
}
}
return {};
}
void AddComponentPanel::Append(UIDrawList& drawList) const {
@@ -326,11 +302,3 @@ void AddComponentPanel::Append(UIDrawList& drawList) const {
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,6 @@
#pragma once
#include "Windowing/Utility/EditorUtilityWindowPanel.h"
#include "UtilityWindows/EditorUtilityWindowPanel.h"
#include <cstddef>
#include <string>
@@ -18,10 +18,9 @@ public:
return "XCEditorUtility.AddComponent";
}
void ResetInteractionState() override;
EditorUtilityWindowPanelOutput Update(
EditorUtilityWindowPanelServices services,
void Update(
EditorContext& context,
const EditorUtilityWindowHostContext& hostContext,
const EditorUtilityWindowSession& session,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents) override;
void Append(::XCEngine::UI::UIDrawList& drawList) const override;
@@ -36,10 +35,7 @@ private:
void ResetPanelState();
void RebuildEntries(const ::XCEngine::Components::GameObject* gameObject);
bool TryActivateEntry(
const EditorUtilityWindowSession& session,
std::size_t entryIndex,
EditorUtilityWindowPanelResult& outResult) const;
bool TryActivateEntry(EditorContext& context, std::size_t entryIndex);
std::size_t HitTestEntry(const ::XCEngine::UI::UIPoint& point) const;
bool m_visible = false;
@@ -52,7 +48,3 @@ private:
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,8 +1,7 @@
#include "InspectorPanel.h"
#include "Composition/EditorContext.h"
#include "Windowing/Utility/EditorUtilityWindowResultState.h"
#include "Windowing/Utility/EditorUtilityWindowRequestSink.h"
#include "State/EditorColorPickerToolState.h"
#include <XCEditor/Collections/UIEditorScrollView.h>
#include <XCEditor/Fields/UIEditorFieldStyle.h>
#include <XCEditor/Foundation/UIEditorPanelInputFilter.h>
@@ -15,7 +14,6 @@
#include <algorithm>
#include <cmath>
#include <utility>
namespace XCEngine::UI::Editor::App {
@@ -241,6 +239,7 @@ void InspectorPanel::ResetInteractionState() {
m_scrollVerticalOffset = 0.0f;
m_interactionState = {};
m_gridFrame = {};
m_lastAppliedColorPickerRevision = 0u;
ResetAddComponentButtonState();
}
@@ -555,66 +554,32 @@ void InspectorPanel::RefreshPresentation(
}
}
bool InspectorPanel::ApplyColorPickerToolValue(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState) {
const EditorUtilityWindowColorPickerResult& result =
utilityWindowResultState.colorPickerResult;
if (!result.active ||
!IsEditorUtilityWindowColorPickerResultTarget(
utilityWindowResultState,
bool InspectorPanel::ApplyColorPickerToolValue(EditorContext& context) {
EditorColorPickerToolState& toolState = context.GetColorPickerToolState();
if (m_sceneRuntime == nullptr ||
!toolState.active ||
toolState.revision == m_lastAppliedColorPickerRevision ||
!IsEditorColorPickerToolTarget(
toolState,
m_subjectKey,
result.targetFieldId)) {
toolState.inspectorTarget.fieldId)) {
return false;
}
const bool applied = TryApplyColorPickerResult(
context,
result.targetSubjectKey,
result.targetFieldId,
result.color);
ClearEditorUtilityWindowColorPickerResult(utilityWindowResultState);
return applied;
}
bool InspectorPanel::TryApplyColorPickerValue(
std::string_view targetSubjectKey,
std::string_view targetFieldId,
const UIColor& color) {
if (m_sceneRuntime == nullptr) {
return false;
}
EditorContext* context = m_currentContext;
if (context == nullptr) {
return false;
}
return TryApplyColorPickerResult(
*context,
targetSubjectKey,
targetFieldId,
color);
}
bool InspectorPanel::TryApplyColorPickerResult(
EditorContext& context,
std::string_view targetSubjectKey,
std::string_view targetFieldId,
const UIColor& color) {
if (m_sceneRuntime == nullptr || targetSubjectKey != m_subjectKey) {
return false;
}
Widgets::UIEditorPropertyGridField* field = FindMutableField(targetFieldId);
Widgets::UIEditorPropertyGridField* field =
FindMutableField(toolState.inspectorTarget.fieldId);
if (field == nullptr || field->kind != Widgets::UIEditorPropertyGridFieldKind::Color) {
return false;
}
if (AreColorsEqual(field->colorValue.value, color)) {
if (AreColorsEqual(field->colorValue.value, toolState.color)) {
m_lastAppliedColorPickerRevision = toolState.revision;
return false;
}
field->colorValue.value = color;
field->colorValue.value = toolState.color;
const bool applied = ApplyChangedField(field->fieldId);
m_lastAppliedColorPickerRevision = toolState.revision;
if (!applied) {
ForceResyncPresentation(context);
return false;
@@ -625,8 +590,7 @@ bool InspectorPanel::TryApplyColorPickerResult(
}
void InspectorPanel::RequestColorPicker(
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
EditorContext& context,
std::string_view fieldId) {
const Widgets::UIEditorPropertyGridField* field = FindField(fieldId);
if (field == nullptr ||
@@ -635,15 +599,13 @@ void InspectorPanel::RequestColorPicker(
return;
}
EditorUtilityWindowSession session = {};
session.type = EditorUtilityWindowType::ColorPicker;
session.payload = EditorUtilityWindowColorPickerPayload{
.targetSubjectKey = m_subjectKey,
.targetFieldId = field->fieldId,
.initialColor = field->colorValue.value,
.showAlpha = field->colorValue.showAlpha,
};
utilityRequestSink.Request(std::move(session));
OpenEditorColorPickerToolForInspectorField(
context.GetColorPickerToolState(),
m_subjectKey,
field->fieldId,
field->colorValue.value,
field->colorValue.showAlpha);
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker);
}
void InspectorPanel::ResetAddComponentButtonState() {
@@ -653,7 +615,6 @@ void InspectorPanel::ResetAddComponentButtonState() {
void InspectorPanel::UpdateAddComponentButton(
EditorContext& context,
EditorUtilityWindowRequestSink& utilityRequestSink,
const std::vector<UIInputEvent>& inputEvents) {
if (!ShouldShowAddComponentButton()) {
ResetAddComponentButtonState();
@@ -694,13 +655,7 @@ void InspectorPanel::UpdateAddComponentButton(
if (m_addComponentButtonPressed &&
ContainsPoint(buttonRect, event.position)) {
EditorUtilityWindowSession session = {};
session.type = EditorUtilityWindowType::AddComponent;
session.payload = EditorUtilityWindowAddComponentPayload{
.targetItemId = context.GetSceneRuntime().GetSelectedItemId(),
.targetDisplayName = context.GetSceneRuntime().GetSelectedDisplayName(),
};
utilityRequestSink.Request(std::move(session));
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent);
}
m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position);
@@ -769,8 +724,6 @@ bool InspectorPanel::ApplyChangedField(std::string_view fieldId) {
void InspectorPanel::Update(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
const UIEditorHostedPanelDispatchEntry& dispatchEntry,
const std::vector<UIInputEvent>& inputEvents) {
if (!dispatchEntry.mounted) {
@@ -781,7 +734,6 @@ void InspectorPanel::Update(
m_visible = true;
m_bounds = dispatchEntry.bounds;
m_sceneRuntime = &context.GetSceneRuntime();
m_currentContext = &context;
m_textMeasurer = context.GetShellServices().textMeasurer;
m_subject = BuildInspectorSubject(context.GetSession(), context.GetSceneRuntime());
@@ -793,7 +745,7 @@ void InspectorPanel::Update(
}
RefreshPresentation(context, subjectChanged);
ApplyColorPickerToolValue(context, utilityWindowResultState);
ApplyColorPickerToolValue(context);
const std::vector<UIInputEvent> filteredEvents =
BuildUIEditorPanelInputEvents(
@@ -862,10 +814,7 @@ void InspectorPanel::Update(
m_gridFrame.result = interactionFrame.result;
if (interactionFrame.result.pickerRequested &&
!interactionFrame.result.requestedFieldId.empty()) {
RequestColorPicker(
utilityWindowResultState,
utilityRequestSink,
interactionFrame.result.requestedFieldId);
RequestColorPicker(context, interactionFrame.result.requestedFieldId);
}
if (interactionFrame.result.fieldValueChanged &&
@@ -879,7 +828,7 @@ void InspectorPanel::Update(
}
RebuildScrollableLayout();
UpdateAddComponentButton(context, utilityRequestSink, filteredEvents);
UpdateAddComponentButton(context, filteredEvents);
}
void InspectorPanel::Append(UIDrawList& drawList) const {
@@ -1047,16 +996,3 @@ UIEditorHostCommandDispatchResult InspectorPanel::DispatchEditCommand(
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -2,7 +2,6 @@
#include "Features/Inspector/InspectorPresentationModel.h"
#include "Features/Inspector/InspectorSubject.h"
#include "Windowing/Utility/EditorUtilityWindowFeatureCommands.h"
#include "Commands/EditorEditCommandRoute.h"
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
@@ -25,18 +24,12 @@ namespace XCEngine::UI::Editor::App {
class EditorCommandFocusService;
class EditorContext;
class EditorSceneRuntime;
class EditorUtilityWindowRequestSink;
struct EditorUtilityWindowResultState;
class InspectorPanel final
: public EditorEditCommandRoute
, public EditorUtilityWindowColorPickerCommandPort {
class InspectorPanel final : public EditorEditCommandRoute {
public:
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);
void Update(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
const UIEditorHostedPanelDispatchEntry& dispatchEntry,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents);
void Append(::XCEngine::UI::UIDrawList& drawList) const;
@@ -45,10 +38,6 @@ public:
std::string_view commandId) const override;
UIEditorHostCommandDispatchResult DispatchEditCommand(
std::string_view commandId) override;
bool TryApplyColorPickerValue(
std::string_view targetSubjectKey,
std::string_view targetFieldId,
const ::XCEngine::UI::UIColor& color) override;
private:
void ResetPanelState();
@@ -73,28 +62,16 @@ private:
void RebuildPresentation(EditorContext& context, bool subjectChanged);
void RefreshPresentation(EditorContext& context, bool subjectChanged);
void ForceResyncPresentation(EditorContext& context);
bool ApplyColorPickerToolValue(
EditorContext& context,
EditorUtilityWindowResultState& utilityWindowResultState);
bool TryApplyColorPickerResult(
EditorContext& context,
std::string_view targetSubjectKey,
std::string_view targetFieldId,
const ::XCEngine::UI::UIColor& color);
void RequestColorPicker(
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
std::string_view fieldId);
bool ApplyColorPickerToolValue(EditorContext& context);
void RequestColorPicker(EditorContext& context, std::string_view fieldId);
void ResetAddComponentButtonState();
void UpdateAddComponentButton(
EditorContext& context,
EditorUtilityWindowRequestSink& utilityRequestSink,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents);
bool ApplyChangedField(std::string_view fieldId);
EditorCommandFocusService* m_commandFocusService = nullptr;
EditorSceneRuntime* m_sceneRuntime = nullptr;
EditorContext* m_currentContext = nullptr;
bool m_visible = false;
::XCEngine::UI::UIRect m_bounds = {};
InspectorSubject m_subject = {};
@@ -112,17 +89,10 @@ private:
std::uint64_t m_lastSceneSelectionStamp = 0u;
std::uint64_t m_lastProjectSelectionStamp = 0u;
std::uint64_t m_lastSceneInspectorRevision = 0u;
std::uint64_t m_lastAppliedColorPickerRevision = 0u;
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* m_textMeasurer = nullptr;
bool m_addComponentButtonHovered = false;
bool m_addComponentButtonPressed = false;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,4 +1,4 @@
#include "ProjectPanel.h"
#include "ProjectPanel.h"
#include "Rendering/Assets/BuiltInIcons.h"
#include <XCEditor/Collections/UIEditorScrollView.h>
#include <XCEditor/Collections/UIEditorTreeView.h>

View File

@@ -206,7 +206,7 @@ bool SceneViewportToolOverlay::Initialize(
Shutdown(renderer);
const std::filesystem::path iconRoot =
(repoRoot / "new_editor" / "resources" / "Icons").lexically_normal();
(repoRoot / "editor" / "resources" / "Icons").lexically_normal();
bool loadedAnyTexture = false;
for (std::size_t index = 0; index < kToolButtonSpecs.size(); ++index) {
const ToolButtonSpec& path = kToolButtonSpecs[index];

View File

@@ -1,8 +1,7 @@
#pragma once
#include <Platform/Win32/Chrome/BorderlessWindowChrome.h>
#include <Platform/Win32/Chrome/BorderlessWindowFrame.h>
#include <Platform/Win32/Windowing/EditorWindowPointerCapture.h>
#include <Platform/Win32/Chrome/HostRuntimeState.h>
namespace XCEngine::UI {
@@ -14,8 +13,6 @@ namespace XCEngine::UI::Editor::App {
class EditorContext;
class EditorWindow;
class Win32NativeWindowBackend;
class Win32WindowCommandProjector;
} // namespace XCEngine::UI::Editor::App
@@ -23,9 +20,7 @@ namespace XCEngine::UI::Editor::App {
class EditorWindowChromeController final {
public:
EditorWindowChromeController(
Win32NativeWindowBackend& nativeWindowBackend,
Win32WindowCommandProjector& windowCommandProjector);
EditorWindowChromeController() = default;
~EditorWindowChromeController() = default;
EditorWindowChromeController(const EditorWindowChromeController&) = delete;
@@ -33,23 +28,52 @@ public:
EditorWindowChromeController(EditorWindowChromeController&&) = delete;
EditorWindowChromeController& operator=(EditorWindowChromeController&&) = delete;
void Reset(EditorWindow& window);
void Reset();
void BeginInteractiveResize(EditorWindow& window);
void EndInteractiveResize(EditorWindow& window);
void EndBorderlessResize(EditorWindow& window);
bool IsBorderlessResizeActive(const EditorWindow& window) const;
Host::BorderlessWindowResizeEdge GetBorderlessResizeEdge(
const EditorWindow& window) const;
void SetHoveredBorderlessResizeEdge(
EditorWindow& window,
Host::BorderlessWindowResizeEdge edge);
Host::BorderlessWindowResizeEdge GetHoveredBorderlessResizeEdge(
const EditorWindow& window) const;
void SetWindowDpi(UINT dpi);
UINT GetWindowDpi() const;
float GetDpiScale(float baseDpiScale) const;
void EndBorderlessWindowDragRestore(EditorWindow& window);
bool IsBorderlessWindowDragRestoreArmed(const EditorWindow& window) const;
void ResetChromeState(EditorWindow& window);
void BeginInteractiveResize();
void EndInteractiveResize();
void BeginBorderlessResize(
Host::BorderlessWindowResizeEdge edge,
const POINT& initialScreenPoint,
const RECT& initialWindowRect);
void EndBorderlessResize();
bool IsBorderlessResizeActive() const;
Host::BorderlessWindowResizeEdge GetBorderlessResizeEdge() const;
const POINT& GetBorderlessResizeInitialScreenPoint() const;
const RECT& GetBorderlessResizeInitialWindowRect() const;
void SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge edge);
Host::BorderlessWindowResizeEdge GetHoveredBorderlessResizeEdge() const;
void SetPredictedClientPixelSize(UINT width, UINT height);
void ClearPredictedClientPixelSize();
bool TryGetPredictedClientPixelSize(UINT& outWidth, UINT& outHeight) const;
void MarkPredictedClientPixelSizePresented();
bool ConsumePresentedPredictedClientPixelSizeMatch(UINT width, UINT height);
void RequestSkipNextSteadyStateFrame();
bool ConsumeSkipNextSteadyStateFrame();
void SetBorderlessWindowMaximized(bool maximized);
bool IsBorderlessWindowMaximized() const;
void SetBorderlessWindowRestoreRect(const RECT& rect);
bool TryGetBorderlessWindowRestoreRect(RECT& outRect) const;
void BeginBorderlessWindowDragRestore(const POINT& initialScreenPoint);
void EndBorderlessWindowDragRestore();
bool IsBorderlessWindowDragRestoreArmed() const;
const POINT& GetBorderlessWindowDragRestoreInitialScreenPoint() const;
Host::BorderlessWindowChromeHitTarget GetHoveredChromeTarget() const;
void SetHoveredChromeTarget(Host::BorderlessWindowChromeHitTarget target);
Host::BorderlessWindowChromeHitTarget GetPressedChromeTarget() const;
void SetPressedChromeTarget(Host::BorderlessWindowChromeHitTarget target);
void ResetChromeState();
bool IsChromeStateClear() const;
const Host::BorderlessWindowChromeState& GetChromeState() const;
bool HandleSystemCommand(
EditorWindow& window,
@@ -57,10 +81,7 @@ public:
bool globalTabDragActive,
WPARAM wParam);
bool HandleGetMinMaxInfo(const EditorWindow& window, LPARAM lParam) const;
LRESULT HandleNcCalcSize(
const EditorWindow& window,
WPARAM wParam,
LPARAM lParam) const;
LRESULT HandleNcCalcSize(const EditorWindow& window, WPARAM wParam, LPARAM lParam) const;
bool UpdateResizeHover(EditorWindow& window, LPARAM lParam);
bool HandleResizeButtonDown(EditorWindow& window, LPARAM lParam);
@@ -104,46 +125,9 @@ public:
const EditorWindow& window,
::XCEngine::UI::UIDrawList& drawList,
float clientWidthDips) const;
private:
void BeginBorderlessResize(
EditorWindow& window,
Host::BorderlessWindowResizeEdge edge,
const POINT& initialScreenPoint,
const RECT& initialWindowRect);
const POINT& GetBorderlessResizeInitialScreenPoint(
const EditorWindow& window) const;
const RECT& GetBorderlessResizeInitialWindowRect(
const EditorWindow& window) const;
void SetBorderlessWindowMaximized(EditorWindow& window, bool maximized);
bool IsBorderlessWindowMaximized(const EditorWindow& window) const;
void SetBorderlessWindowRestoreRect(EditorWindow& window, const RECT& rect);
bool TryGetBorderlessWindowRestoreRect(
const EditorWindow& window,
RECT& outRect) const;
void BeginBorderlessWindowDragRestore(
EditorWindow& window,
const POINT& initialScreenPoint);
const POINT& GetBorderlessWindowDragRestoreInitialScreenPoint(
const EditorWindow& window) const;
Host::BorderlessWindowChromeHitTarget GetHoveredChromeTarget(
const EditorWindow& window) const;
void SetHoveredChromeTarget(
EditorWindow& window,
Host::BorderlessWindowChromeHitTarget target);
Host::BorderlessWindowChromeHitTarget GetPressedChromeTarget(
const EditorWindow& window) const;
void SetPressedChromeTarget(
EditorWindow& window,
Host::BorderlessWindowChromeHitTarget target);
bool IsChromeStateClear(const EditorWindow& window) const;
const Host::BorderlessWindowChromeState& GetChromeState(
const EditorWindow& window) const;
void ApplyResizeCursorHoverPriority(EditorWindow& window);
void ApplyResizeCursorHoverPriority();
bool QueryCurrentWindowRect(const EditorWindow& window, RECT& outRect) const;
bool QueryBorderlessWindowWorkAreaRect(
const EditorWindow& window,
RECT& outRect) const;
bool QueryBorderlessWindowWorkAreaRect(const EditorWindow& window, RECT& outRect) const;
bool ApplyPredictedWindowRectTransition(
EditorWindow& window,
EditorContext& editorContext,
@@ -159,8 +143,9 @@ private:
bool globalTabDragActive,
Host::BorderlessWindowChromeHitTarget target);
Win32NativeWindowBackend& m_nativeWindowBackend;
Win32WindowCommandProjector& m_windowCommandProjector;
private:
Host::BorderlessWindowChromeState m_chromeState = {};
Host::HostRuntimeState m_runtimeState = {};
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -14,6 +14,13 @@ struct BorderlessWindowResizeState {
BorderlessWindowResizeEdge hoveredEdge = BorderlessWindowResizeEdge::None;
};
struct PredictedClientPixelSize {
bool active = false;
UINT width = 0u;
UINT height = 0u;
bool presented = false;
};
struct BorderlessWindowPlacementState {
bool maximized = false;
bool hasRestoreRect = false;
@@ -28,10 +35,27 @@ struct BorderlessWindowDragRestoreState {
class HostRuntimeState {
public:
void Reset() {
m_windowDpi = 96u;
m_inInteractiveResize = false;
m_borderlessResizeState = {};
m_predictedClientPixelSize = {};
m_borderlessWindowPlacementState = {};
m_borderlessWindowDragRestoreState = {};
m_skipNextSteadyStateFrame = false;
}
void SetWindowDpi(UINT dpi) {
m_windowDpi = dpi == 0u ? 96u : dpi;
}
UINT GetWindowDpi() const {
return m_windowDpi;
}
float GetDpiScale(float baseDpiScale) const {
return baseDpiScale > 0.0f
? static_cast<float>(m_windowDpi) / baseDpiScale
: 1.0f;
}
void BeginInteractiveResize() {
@@ -62,6 +86,7 @@ public:
m_borderlessResizeState.active = false;
m_borderlessResizeState.edge = BorderlessWindowResizeEdge::None;
m_inInteractiveResize = false;
m_predictedClientPixelSize = {};
}
bool IsBorderlessResizeActive() const {
@@ -88,6 +113,66 @@ public:
return m_borderlessResizeState.hoveredEdge;
}
void SetPredictedClientPixelSize(UINT width, UINT height) {
if (width == 0u || height == 0u) {
m_predictedClientPixelSize = {};
return;
}
m_predictedClientPixelSize.active = true;
m_predictedClientPixelSize.width = width;
m_predictedClientPixelSize.height = height;
m_predictedClientPixelSize.presented = false;
}
void ClearPredictedClientPixelSize() {
m_predictedClientPixelSize = {};
}
bool TryGetPredictedClientPixelSize(UINT& outWidth, UINT& outHeight) const {
outWidth = 0u;
outHeight = 0u;
if (!m_predictedClientPixelSize.active ||
m_predictedClientPixelSize.width == 0u ||
m_predictedClientPixelSize.height == 0u) {
return false;
}
outWidth = m_predictedClientPixelSize.width;
outHeight = m_predictedClientPixelSize.height;
return true;
}
void MarkPredictedClientPixelSizePresented() {
if (!m_predictedClientPixelSize.active) {
return;
}
m_predictedClientPixelSize.presented = true;
}
bool ConsumePresentedPredictedClientPixelSizeMatch(UINT width, UINT height) {
if (!m_predictedClientPixelSize.active ||
!m_predictedClientPixelSize.presented ||
m_predictedClientPixelSize.width != width ||
m_predictedClientPixelSize.height != height) {
return false;
}
m_predictedClientPixelSize = {};
return true;
}
void RequestSkipNextSteadyStateFrame() {
m_skipNextSteadyStateFrame = true;
}
bool ConsumeSkipNextSteadyStateFrame() {
const bool skipFrame = m_skipNextSteadyStateFrame;
m_skipNextSteadyStateFrame = false;
return skipFrame;
}
void SetBorderlessWindowMaximized(bool maximized) {
m_borderlessWindowPlacementState.maximized = maximized;
}
@@ -129,10 +214,13 @@ public:
}
private:
UINT m_windowDpi = 96u;
bool m_inInteractiveResize = false;
BorderlessWindowResizeState m_borderlessResizeState = {};
PredictedClientPixelSize m_predictedClientPixelSize = {};
BorderlessWindowPlacementState m_borderlessWindowPlacementState = {};
BorderlessWindowDragRestoreState m_borderlessWindowDragRestoreState = {};
bool m_skipNextSteadyStateFrame = false;
};
} // namespace XCEngine::UI::Editor::Host

View File

@@ -0,0 +1,103 @@
#include "Platform/Win32/Content/EditorUtilityWindowContentController.h"
#include "UtilityWindows/EditorUtilityWindowPanel.h"
#include "UtilityWindows/EditorUtilityWindowRegistry.h"
#include <XCEngine/UI/DrawData.h>
namespace XCEngine::UI::Editor::App {
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
EditorUtilityWindowContentController::EditorUtilityWindowContentController(
std::unique_ptr<EditorUtilityWindowPanel> 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<EditorWindowContentController> CreateEditorUtilityWindowContentController(
const EditorUtilityWindowDescriptor& descriptor) {
std::unique_ptr<EditorUtilityWindowPanel> panel =
CreateEditorUtilityWindowPanel(descriptor.kind);
if (panel == nullptr) {
return nullptr;
}
return std::make_unique<EditorUtilityWindowContentController>(
std::move(panel),
descriptor.minimumOuterSize);
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,44 @@
#pragma once
#include "Platform/Win32/Content/EditorWindowContentController.h"
#include <XCEditor/Shell/UIEditorShellInteraction.h>
#include <XCEngine/UI/Types.h>
#include <memory>
namespace XCEngine::UI::Editor::App {
class EditorUtilityWindowPanel;
struct EditorUtilityWindowDescriptor;
class EditorUtilityWindowContentController final
: public EditorWindowContentController {
public:
EditorUtilityWindowContentController(
std::unique_ptr<EditorUtilityWindowPanel> panel,
const ::XCEngine::UI::UISize& minimumOuterSize);
~EditorUtilityWindowContentController() 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;
private:
std::unique_ptr<EditorUtilityWindowPanel> m_panel = {};
::XCEngine::UI::UISize m_minimumOuterSize = {};
UIEditorShellInteractionState m_shellInteractionState = {};
UIEditorShellInteractionFrame m_shellFrame = {};
bool m_windowFocused = true;
};
std::unique_ptr<EditorWindowContentController> CreateEditorUtilityWindowContentController(
const EditorUtilityWindowDescriptor& descriptor);
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,163 @@
#pragma once
#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h"
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <cstdint>
#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::Rendering {
class RenderContext;
} // namespace XCEngine::Rendering
namespace XCEngine::UI {
class UIDrawData;
struct UIInputEvent;
struct UIPoint;
struct UIRect;
struct UISize;
} // namespace XCEngine::UI
namespace XCEngine::UI::Editor {
class UIEditorWorkspaceController;
struct UIEditorShellInteractionFrame;
struct UIEditorShellInteractionState;
namespace Widgets {
struct UIEditorDockHostDropPreviewState;
}
} // namespace XCEngine::UI::Editor
namespace XCEngine::UI::Editor::Rendering::Host {
class UiTextureHost;
class ViewportRenderHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
class EditorContext;
enum class EditorWindowContentCursorKind : std::uint8_t {
Arrow = 0,
ResizeEW,
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;
Rendering::Host::UiTextureHost& textureHost;
UIEditorTextMeasurer& textMeasurer;
Rendering::Host::ViewportRenderHost& viewportRenderer;
};
struct EditorWindowContentFrameContext {
EditorContext& editorContext;
const ::XCEngine::UI::UIRect& bounds;
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents;
std::string_view captureStatusText;
bool primary = false;
bool globalTabDragActive = false;
bool useDetachedTitleBarTabStrip = false;
};
class EditorWindowContentController {
public:
virtual ~EditorWindowContentController() = default;
virtual EditorWindowWorkspaceBinding* TryGetWorkspaceBinding() {
return nullptr;
}
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 Initialize(const EditorWindowContentInitializationContext&) {}
virtual void Shutdown() {}
virtual void ResetInteractionState() {}
virtual void SetViewportSurfacePresentationEnabled(bool) {}
virtual EditorWindowFrameTransferRequests UpdateAndAppend(
const EditorWindowContentFrameContext& context,
::XCEngine::UI::UIDrawData& drawData) = 0;
virtual void RenderRequestedViewports(const ::XCEngine::Rendering::RenderContext&) {}
virtual const UIEditorShellInteractionFrame& GetShellFrame() const = 0;
virtual const UIEditorShellInteractionState& GetShellInteractionState() const = 0;
virtual ::XCEngine::UI::UISize ResolveMinimumOuterSize() const = 0;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,198 @@
#include "Platform/Win32/Content/EditorWorkspaceWindowContentController.h"
#include <XCEditor/Workspace/UIEditorDetachedWindowPolicy.h>
namespace XCEngine::UI::Editor::App {
namespace {
EditorWindowContentCursorKind ToContentCursorKind(ProjectPanel::CursorKind cursorKind) {
switch (cursorKind) {
case ProjectPanel::CursorKind::ResizeEW:
return EditorWindowContentCursorKind::ResizeEW;
case ProjectPanel::CursorKind::Arrow:
default:
return EditorWindowContentCursorKind::Arrow;
}
}
EditorWindowContentCursorKind ToContentCursorKind(
Widgets::UIEditorDockHostCursorKind cursorKind) {
switch (cursorKind) {
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
return EditorWindowContentCursorKind::ResizeEW;
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
return EditorWindowContentCursorKind::ResizeNS;
case Widgets::UIEditorDockHostCursorKind::Arrow:
default:
return EditorWindowContentCursorKind::Arrow;
}
}
} // namespace
EditorWorkspaceWindowContentController::EditorWorkspaceWindowContentController(
UIEditorWorkspaceController workspaceController)
: m_workspaceController(std::move(workspaceController)) {}
EditorWorkspaceWindowContentController::~EditorWorkspaceWindowContentController() = default;
EditorWindowWorkspaceBinding* EditorWorkspaceWindowContentController::TryGetWorkspaceBinding() {
return this;
}
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;
}
void EditorWorkspaceWindowContentController::ReplaceWorkspaceController(
UIEditorWorkspaceController workspaceController) {
m_workspaceController = std::move(workspaceController);
}
void EditorWorkspaceWindowContentController::Initialize(
const EditorWindowContentInitializationContext& context) {
m_shellRuntime.Initialize(context.repoRoot, context.textureHost, context.textMeasurer);
m_shellRuntime.AttachViewportWindowRenderer(context.viewportRenderer);
}
void EditorWorkspaceWindowContentController::Shutdown() {
m_shellRuntime.Shutdown();
}
void EditorWorkspaceWindowContentController::ResetInteractionState() {
m_shellRuntime.ResetInteractionState();
}
void EditorWorkspaceWindowContentController::SetViewportSurfacePresentationEnabled(bool enabled) {
m_shellRuntime.SetViewportSurfacePresentationEnabled(enabled);
}
EditorWindowFrameTransferRequests EditorWorkspaceWindowContentController::UpdateAndAppend(
const EditorWindowContentFrameContext& context,
::XCEngine::UI::UIDrawData& drawData) {
return m_frameOrchestrator.UpdateAndAppend(
context.editorContext,
m_workspaceController,
m_shellRuntime,
context.bounds,
context.inputEvents,
context.captureStatusText,
context.primary,
context.globalTabDragActive,
context.useDetachedTitleBarTabStrip,
drawData);
}
void EditorWorkspaceWindowContentController::RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext) {
m_shellRuntime.RenderRequestedViewports(renderContext);
}
const UIEditorShellInteractionFrame&
EditorWorkspaceWindowContentController::GetShellFrame() const {
return m_shellRuntime.GetShellFrame();
}
const UIEditorShellInteractionState&
EditorWorkspaceWindowContentController::GetShellInteractionState() const {
return m_shellRuntime.GetShellInteractionState();
}
void EditorWorkspaceWindowContentController::SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) {
m_shellRuntime.SetExternalDockHostDropPreview(preview);
}
void EditorWorkspaceWindowContentController::ClearExternalDockHostDropPreview() {
m_shellRuntime.ClearExternalDockHostDropPreview();
}
bool EditorWorkspaceWindowContentController::TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const {
return m_shellRuntime.TryResolveDockTabDragHotspot(
nodeId,
panelId,
point,
outHotspot);
}
UIEditorDockHostTabDropTarget EditorWorkspaceWindowContentController::ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const {
return m_shellRuntime.ResolveDockTabDropTarget(point);
}
bool EditorWorkspaceWindowContentController::HasHostedContentCapture() const {
return m_shellRuntime.HasHostedContentCapture();
}
bool EditorWorkspaceWindowContentController::HasShellInteractiveCapture() const {
return m_shellRuntime.HasShellInteractiveCapture();
}
bool EditorWorkspaceWindowContentController::HasInteractiveCapture() const {
return m_shellRuntime.HasInteractiveCapture();
}
EditorWindowContentCursorKind
EditorWorkspaceWindowContentController::GetHostedContentCursorKind() const {
return ToContentCursorKind(m_shellRuntime.GetHostedContentCursorKind());
}
EditorWindowContentCursorKind EditorWorkspaceWindowContentController::GetDockCursorKind() const {
return ToContentCursorKind(m_shellRuntime.GetDockCursorKind());
}
::XCEngine::UI::UISize EditorWorkspaceWindowContentController::ResolveMinimumOuterSize() const {
return ResolveUIEditorDetachedWorkspaceMinimumOuterSize(m_workspaceController);
}
bool EditorWorkspaceWindowContentController::ShouldUseDetachedTitleBarTabStrip() const {
return HasUIEditorSingleVisibleRootTab(m_workspaceController);
}
std::string EditorWorkspaceWindowContentController::ResolveTabStripTitleText(
std::string_view fallbackTitle) const {
return ResolveUIEditorDetachedWorkspaceTitle(m_workspaceController, fallbackTitle);
}
std::string EditorWorkspaceWindowContentController::ResolveDetachedWindowTitleText(
std::string_view fallbackWindowTitle) const {
return ResolveUIEditorDetachedWorkspaceTitle(m_workspaceController, fallbackWindowTitle);
}
std::unique_ptr<EditorWindowContentController> CreateEditorWorkspaceWindowContentController(
UIEditorWorkspaceController workspaceController) {
return std::make_unique<EditorWorkspaceWindowContentController>(
std::move(workspaceController));
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,79 @@
#pragma once
#include "Composition/EditorShellRuntime.h"
#include "Platform/Win32/Content/EditorWindowContentController.h"
#include "Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h"
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <memory>
namespace XCEngine::UI::Editor::App {
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;
void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) override;
void Initialize(const EditorWindowContentInitializationContext& context) override;
void Shutdown() override;
void ResetInteractionState() override;
void SetViewportSurfacePresentationEnabled(bool enabled) override;
EditorWindowFrameTransferRequests UpdateAndAppend(
const EditorWindowContentFrameContext& context,
::XCEngine::UI::UIDrawData& drawData) override;
void RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext) override;
const UIEditorShellInteractionFrame& GetShellFrame() const override;
const UIEditorShellInteractionState& GetShellInteractionState() const override;
void SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) override;
void ClearExternalDockHostDropPreview() override;
bool TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const override;
UIEditorDockHostTabDropTarget ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const override;
bool HasHostedContentCapture() const override;
bool HasShellInteractiveCapture() const override;
bool HasInteractiveCapture() const override;
EditorWindowContentCursorKind GetHostedContentCursorKind() const override;
EditorWindowContentCursorKind GetDockCursorKind() const override;
::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 = {};
EditorShellRuntime m_shellRuntime = {};
EditorWindowFrameOrchestrator m_frameOrchestrator = {};
};
std::unique_ptr<EditorWindowContentController> CreateEditorWorkspaceWindowContentController(
UIEditorWorkspaceController workspaceController);
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,46 @@
#include "Platform/Win32/Runtime/EditorWindowFrameDriver.h"
#include "Platform/Win32/Chrome/EditorWindowChromeController.h"
#include "Platform/Win32/Windowing/EditorWindow.h"
namespace XCEngine::UI::Editor::App {
EditorWindowFrameTransferRequests EditorWindowFrameDriver::DriveFrameInternal(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive,
bool requestSkipNextSteadyStateFrame) {
if (!window.IsRenderReady() ||
window.GetHwnd() == nullptr ||
window.GetLifecycleState() != EditorWindowLifecycleState::Running) {
return {};
}
EditorWindowFrameTransferRequests transferRequests =
window.RenderFrame(editorContext, globalTabDragActive);
if (const HWND hwnd = window.GetHwnd();
hwnd != nullptr && IsWindow(hwnd)) {
ValidateRect(hwnd, nullptr);
}
if (requestSkipNextSteadyStateFrame) {
window.RequestSkipNextSteadyStateFrame();
}
return transferRequests;
}
EditorWindowFrameTransferRequests EditorWindowFrameDriver::DriveFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive) {
return DriveFrameInternal(window, editorContext, globalTabDragActive, false);
}
EditorWindowFrameTransferRequests EditorWindowFrameDriver::DriveImmediateFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive) {
return DriveFrameInternal(window, editorContext, globalTabDragActive, true);
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,29 @@
#pragma once
#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h"
namespace XCEngine::UI::Editor::App {
class EditorContext;
class EditorWindow;
class EditorWindowFrameDriver final {
public:
static EditorWindowFrameTransferRequests DriveFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive);
static EditorWindowFrameTransferRequests DriveImmediateFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive);
private:
static EditorWindowFrameTransferRequests DriveFrameInternal(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive,
bool requestSkipNextSteadyStateFrame);
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,35 +1,28 @@
#include "Windowing/Content/EditorWindowFrameOrchestrator.h"
#include "Platform/Win32/Runtime/EditorWindowFrameOrchestrator.h"
#include "Composition/EditorContext.h"
#include "Composition/EditorShellRuntime.h"
#include "Composition/EditorShellVariant.h"
#include "Support/EnvironmentFlags.h"
#include "Windowing/Content/EditorWindowContentStyle.h"
#include "Windowing/Utility/EditorUtilityWindowRequestSink.h"
#include "Windowing/Workspace/WindowWorkspaceTransferQueue.h"
#include "Platform/Win32/Windowing/EditorWindowSupport.h"
#include "Windowing/Workspace/UIEditorDetachedWindowPolicy.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <XCEngine/UI/DrawData.h>
#include <sstream>
#include <utility>
namespace XCEngine::UI::Editor::App {
using namespace EditorWindowContentStyle;
using namespace EditorWindowSupport;
using ::XCEngine::UI::UIDrawData;
using ::XCEngine::UI::UIDrawList;
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPoint;
namespace WindowingDomain = ::XCEngine::UI::Editor::Windowing::Domain;
namespace {
bool IsVerboseRuntimeTraceEnabled() {
static const bool s_enabled = IsEnvironmentFlagEnabled("XCUIEDITOR_VERBOSE_TRACE");
static const bool s_enabled = ResolveVerboseRuntimeTraceEnabled();
return s_enabled;
}
@@ -50,75 +43,10 @@ std::string DescribeInputEventType(const UIInputEvent& event) {
}
}
WindowingDomain::WindowCursorType ToWindowCursorType(ProjectPanel::CursorKind cursorType) {
switch (cursorType) {
case ProjectPanel::CursorKind::ResizeEW:
return WindowingDomain::WindowCursorType::ResizeEW;
case ProjectPanel::CursorKind::Arrow:
default:
return WindowingDomain::WindowCursorType::Arrow;
}
}
WindowingDomain::WindowCursorType ToWindowCursorType(
Widgets::UIEditorDockHostCursorKind cursorType) {
switch (cursorType) {
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
return WindowingDomain::WindowCursorType::ResizeEW;
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
return WindowingDomain::WindowCursorType::ResizeNS;
case Widgets::UIEditorDockHostCursorKind::Arrow:
default:
return WindowingDomain::WindowCursorType::Arrow;
}
}
WindowingDomain::WindowCaptureDemand BuildCaptureDemand(
const EditorShellRuntime& shellRuntime) {
return WindowingDomain::WindowCaptureDemand{
.shellInteractive = shellRuntime.HasShellInteractiveCapture(),
.hostedContent = shellRuntime.HasHostedContentCapture(),
};
}
WindowingDomain::WindowCursorType ResolveContentCursorType(
const EditorShellRuntime& shellRuntime) {
const WindowingDomain::WindowCursorType hostedCursorType =
ToWindowCursorType(shellRuntime.GetHostedContentCursorType());
if (hostedCursorType != WindowingDomain::WindowCursorType::Arrow) {
return hostedCursorType;
}
return ToWindowCursorType(shellRuntime.GetDockCursorType());
}
void QueueWorkspaceTransferRequest(
WindowWorkspaceTransferQueue& workspaceTransferQueue,
WindowWorkspaceTransferRequest::Type type,
std::string_view sourceWindowId,
std::string sourceNodeId,
std::string panelId,
std::int32_t cursorScreenX,
std::int32_t cursorScreenY) {
WindowWorkspaceTransferRequest request = {};
request.type = type;
request.sourceWindowId = std::string(sourceWindowId);
request.sourceNodeId = std::move(sourceNodeId);
request.panelId = std::move(panelId);
request.screenX = cursorScreenX;
request.screenY = cursorScreenY;
request.hasScreenPoint = true;
workspaceTransferQueue.QueueWorkspaceTransferRequest(request);
}
} // namespace
EditorWindowContentUpdateResult EditorWindowFrameOrchestrator::UpdateAndAppend(
EditorWindowFrameTransferRequests EditorWindowFrameOrchestrator::UpdateAndAppend(
EditorContext& editorContext,
std::string_view sourceWindowId,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
WindowWorkspaceTransferQueue& workspaceTransferQueue,
UIEditorWorkspaceController& workspaceController,
EditorShellRuntime& shellRuntime,
const ::XCEngine::UI::UIRect& workspaceBounds,
@@ -127,9 +55,6 @@ EditorWindowContentUpdateResult EditorWindowFrameOrchestrator::UpdateAndAppend(
bool primary,
bool globalTabDragActive,
bool useDetachedTitleBarTabStrip,
std::int32_t cursorScreenX,
std::int32_t cursorScreenY,
bool hasCursorScreenPoint,
UIDrawData& drawData) const {
LogInputTrace(
editorContext,
@@ -137,15 +62,8 @@ EditorWindowContentUpdateResult EditorWindowFrameOrchestrator::UpdateAndAppend(
shellRuntime.GetShellInteractionState(),
frameEvents);
utilityRequestSink.ConfigureFrameSource(
sourceWindowId,
cursorScreenX,
cursorScreenY,
hasCursorScreenPoint);
shellRuntime.Update(
editorContext,
utilityWindowResultState,
utilityRequestSink,
workspaceController,
workspaceBounds,
frameEvents,
@@ -159,28 +77,27 @@ EditorWindowContentUpdateResult EditorWindowFrameOrchestrator::UpdateAndAppend(
shellRuntime.GetShellInteractionState().workspaceInteractionState.dockHostInteractionState;
LogFrameInteractionTrace(workspaceController, frameEvents, shellFrame);
EditorWindowContentUpdateResult updateResult = {};
updateResult.contentOutput.captureDemand = BuildCaptureDemand(shellRuntime);
updateResult.contentOutput.cursorType = ResolveContentCursorType(shellRuntime);
updateResult.contentOutput.titleBarMode =
HasUIEditorSingleVisibleRootTab(workspaceController)
? WindowingDomain::WindowTitleBarMode::DetachedTabStrip
: WindowingDomain::WindowTitleBarMode::SystemChrome;
AppendWorkspaceTransferRequests(
sourceWindowId,
globalTabDragActive,
dockHostInteractionState,
shellFrame,
cursorScreenX,
cursorScreenY,
hasCursorScreenPoint,
workspaceTransferQueue);
EditorWindowFrameTransferRequests transferRequests =
BuildShellTransferRequests(globalTabDragActive, dockHostInteractionState, shellFrame);
POINT screenPoint = {};
if (const std::optional<EditorUtilityWindowKind> requestedKind =
editorContext.ConsumeOpenUtilityWindowRequest();
requestedKind.has_value()) {
transferRequests.openUtilityWindow = EditorWindowOpenUtilityWindowRequest{
.kind = *requestedKind,
.useCursorPlacement = GetCursorPos(&screenPoint) != FALSE,
};
if (transferRequests.openUtilityWindow->useCursorPlacement) {
transferRequests.openUtilityWindow->screenPoint = screenPoint;
}
}
for (const WorkspaceTraceEntry& entry : shellRuntime.GetTraceEntries()) {
AppendUIEditorRuntimeTrace(entry.channel, entry.message);
LogRuntimeTrace(entry.channel, entry.message);
}
shellRuntime.Append(drawData);
return updateResult;
return transferRequests;
}
void EditorWindowFrameOrchestrator::AppendInvalidFrame(
@@ -229,7 +146,7 @@ void EditorWindowFrameOrchestrator::LogInputTrace(
return;
}
AppendUIEditorRuntimeTrace(
LogRuntimeTrace(
"input",
DescribeInputEvents(frameEvents) + " | " +
editorContext.DescribeWorkspaceState(
@@ -261,51 +178,38 @@ void EditorWindowFrameOrchestrator::LogFrameInteractionTrace(
<< workspaceController.GetWorkspace().activePanelId
<< " message="
<< shellFrame.result.workspaceResult.dockHostResult.layoutResult.message;
AppendUIEditorRuntimeTrace("frame", frameTrace.str());
LogRuntimeTrace("frame", frameTrace.str());
}
void EditorWindowFrameOrchestrator::AppendWorkspaceTransferRequests(
std::string_view sourceWindowId,
EditorWindowFrameTransferRequests EditorWindowFrameOrchestrator::BuildShellTransferRequests(
bool globalTabDragActive,
const UIEditorDockHostInteractionState& dockHostInteractionState,
const UIEditorShellInteractionFrame& shellFrame,
std::int32_t cursorScreenX,
std::int32_t cursorScreenY,
bool hasCursorScreenPoint,
WindowWorkspaceTransferQueue& workspaceTransferQueue) const {
const UIEditorShellInteractionFrame& shellFrame) const {
EditorWindowFrameTransferRequests transferRequests = {};
POINT screenPoint = {};
const bool hasScreenPoint = GetCursorPos(&screenPoint) != FALSE;
if (!globalTabDragActive &&
!dockHostInteractionState.activeTabDragNodeId.empty() &&
!dockHostInteractionState.activeTabDragPanelId.empty() &&
hasCursorScreenPoint) {
QueueWorkspaceTransferRequest(
workspaceTransferQueue,
WindowWorkspaceTransferRequest::Type::StartGlobalTabDrag,
sourceWindowId,
hasScreenPoint) {
transferRequests.beginGlobalTabDrag = EditorWindowPanelTransferRequest{
dockHostInteractionState.activeTabDragNodeId,
dockHostInteractionState.activeTabDragPanelId,
cursorScreenX,
cursorScreenY);
screenPoint,
};
}
if (shellFrame.result.workspaceResult.dockHostResult.detachRequested &&
hasCursorScreenPoint) {
QueueWorkspaceTransferRequest(
workspaceTransferQueue,
WindowWorkspaceTransferRequest::Type::DetachPanel,
sourceWindowId,
if (shellFrame.result.workspaceResult.dockHostResult.detachRequested && hasScreenPoint) {
transferRequests.detachPanel = EditorWindowPanelTransferRequest{
shellFrame.result.workspaceResult.dockHostResult.detachedNodeId,
shellFrame.result.workspaceResult.dockHostResult.detachedPanelId,
cursorScreenX,
cursorScreenY);
screenPoint,
};
}
return transferRequests;
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,10 +1,9 @@
#pragma once
#include "Windowing/Application/EditorWindowContentUpdateResult.h"
#include "Platform/Win32/Windowing/EditorWindowTransferRequests.h"
#include <XCEngine/UI/Types.h>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
@@ -32,10 +31,7 @@ struct UIEditorShellInteractionState;
namespace XCEngine::UI::Editor::App {
class EditorContext;
struct EditorUtilityWindowResultState;
class EditorShellRuntime;
class EditorUtilityWindowRequestSink;
class WindowWorkspaceTransferQueue;
class EditorWindowFrameOrchestrator final {
public:
@@ -47,12 +43,8 @@ public:
EditorWindowFrameOrchestrator(EditorWindowFrameOrchestrator&&) = delete;
EditorWindowFrameOrchestrator& operator=(EditorWindowFrameOrchestrator&&) = delete;
EditorWindowContentUpdateResult UpdateAndAppend(
EditorWindowFrameTransferRequests UpdateAndAppend(
EditorContext& editorContext,
std::string_view sourceWindowId,
EditorUtilityWindowResultState& utilityWindowResultState,
EditorUtilityWindowRequestSink& utilityRequestSink,
WindowWorkspaceTransferQueue& workspaceTransferQueue,
UIEditorWorkspaceController& workspaceController,
EditorShellRuntime& shellRuntime,
const ::XCEngine::UI::UIRect& workspaceBounds,
@@ -61,9 +53,6 @@ public:
bool primary,
bool globalTabDragActive,
bool useDetachedTitleBarTabStrip,
std::int32_t cursorScreenX,
std::int32_t cursorScreenY,
bool hasCursorScreenPoint,
::XCEngine::UI::UIDrawData& drawData) const;
void AppendInvalidFrame(
EditorContext& editorContext,
@@ -81,18 +70,10 @@ private:
const UIEditorWorkspaceController& workspaceController,
const std::vector<::XCEngine::UI::UIInputEvent>& frameEvents,
const UIEditorShellInteractionFrame& shellFrame) const;
void AppendWorkspaceTransferRequests(
std::string_view sourceWindowId,
EditorWindowFrameTransferRequests BuildShellTransferRequests(
bool globalTabDragActive,
const UIEditorDockHostInteractionState& dockHostInteractionState,
const UIEditorShellInteractionFrame& shellFrame,
std::int32_t cursorScreenX,
std::int32_t cursorScreenY,
bool hasCursorScreenPoint,
WindowWorkspaceTransferQueue& workspaceTransferQueue) const;
const UIEditorShellInteractionFrame& shellFrame) const;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -36,30 +36,65 @@ std::uint64_t GetInputEventTimestampNanoseconds() {
} // namespace
bool EditorWindowInputController::AcquirePointerCapture(HWND hwnd) {
if (hwnd == nullptr || !IsWindow(hwnd)) {
return false;
bool EditorWindowInputController::IsTrackingMouseLeave() const {
return m_trackingMouseLeave;
}
void EditorWindowInputController::SetTrackingMouseLeave(bool trackingMouseLeave) {
m_trackingMouseLeave = trackingMouseLeave;
}
EditorWindowPointerCaptureOwner EditorWindowInputController::GetPointerCaptureOwner() const {
return m_pointerCaptureOwner;
}
bool EditorWindowInputController::OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const {
return m_pointerCaptureOwner == owner;
}
bool EditorWindowInputController::HasPointerCaptureOwner() const {
return m_pointerCaptureOwner != EditorWindowPointerCaptureOwner::None;
}
void EditorWindowInputController::AcquirePointerCapture(
HWND hwnd,
EditorWindowPointerCaptureOwner owner) {
if (owner == EditorWindowPointerCaptureOwner::None ||
hwnd == nullptr ||
!IsWindow(hwnd)) {
return;
}
m_pointerCaptureOwner = owner;
if (GetCapture() != hwnd) {
SetCapture(hwnd);
}
return GetCapture() == hwnd;
}
void EditorWindowInputController::ReleasePointerCapture(HWND hwnd) {
void EditorWindowInputController::ReleasePointerCapture(
HWND hwnd,
EditorWindowPointerCaptureOwner owner) {
if (m_pointerCaptureOwner != owner) {
return;
}
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
if (hwnd != nullptr && GetCapture() == hwnd) {
ReleaseCapture();
}
}
void EditorWindowInputController::ForceReleasePointerCapture(HWND hwnd) {
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
if (hwnd != nullptr && GetCapture() == hwnd) {
ReleaseCapture();
}
}
void EditorWindowInputController::ClearPointerCaptureOwner() {
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
}
void EditorWindowInputController::QueuePointerEvent(
UIInputEventType type,
UIPointerButton button,
@@ -198,11 +233,15 @@ void EditorWindowInputController::ClearPendingEvents() {
}
void EditorWindowInputController::ResetInteractionState() {
ForceReleasePointerCapture(nullptr);
ClearPendingEvents();
m_trackingMouseLeave = false;
m_modifierTracker.Reset();
}
void EditorWindowInputController::ResetWindowState() {
m_trackingMouseLeave = false;
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
m_pendingDoubleClickButtons = 0u;
}

Some files were not shown because too many files have changed in this diff Show More