diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index 704473b2..4683a9fc 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -221,6 +221,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) set(XCUI_EDITOR_APP_STATE_SOURCES app/State/EditorContext.cpp + app/State/EditorContextStatus.cpp app/State/EditorSession.cpp ) @@ -270,6 +271,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) app/Platform/Win32/EditorWindowBorderlessResize.cpp app/Platform/Win32/EditorWindowFrame.cpp app/Platform/Win32/EditorWindowTitleBar.cpp + app/Platform/Win32/EditorWindowTitleBarDragRestore.cpp app/Platform/Win32/EditorWindowTitleBarInteraction.cpp app/Platform/Win32/EditorWindowTitleBarRendering.cpp app/Platform/Win32/EditorWindowInitialization.cpp @@ -277,7 +279,9 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP) app/Platform/Win32/EditorWindowMetrics.cpp app/Platform/Win32/EditorWindowInput.cpp app/Platform/Win32/EditorWindowResizeLifecycle.cpp + app/Platform/Win32/EditorWindowManagerCreation.cpp app/Platform/Win32/EditorWindowManagerLifecycle.cpp + app/Platform/Win32/EditorWindowManagerLookup.cpp app/Platform/Win32/EditorWindowManagerWindowSet.cpp app/Platform/Win32/EditorWindowManagerTabDrag.cpp app/Platform/Win32/EditorWindowManagerDetach.cpp diff --git a/new_editor/app/Platform/Win32/EditorWindowManagerCreation.cpp b/new_editor/app/Platform/Win32/EditorWindowManagerCreation.cpp new file mode 100644 index 00000000..e7c4f0c5 --- /dev/null +++ b/new_editor/app/Platform/Win32/EditorWindowManagerCreation.cpp @@ -0,0 +1,107 @@ +#include "EditorWindowManager.h" + +#include "State/EditorContext.h" +#include "Bootstrap/EditorResources.h" +#include "EditorWindow.h" + +#include + +namespace XCEngine::UI::Editor::App { + +EditorWindow* EditorWindowManager::CreateEditorWindow( + UIEditorWorkspaceController workspaceController, + const CreateParams& params) { + auto windowPtr = std::make_unique( + params.windowId, + params.title.empty() ? std::wstring(L"XCEngine Editor") : params.title, + params.primary, + std::move(workspaceController)); + EditorWindow* const rawWindow = windowPtr.get(); + m_windows.push_back(std::move(windowPtr)); + + const auto eraseRawWindow = [this, rawWindow]() { + const auto it = std::find_if( + m_windows.begin(), + m_windows.end(), + [rawWindow](const std::unique_ptr& candidate) { + return candidate.get() == rawWindow; + }); + if (it != m_windows.end()) { + m_windows.erase(it); + } + }; + + m_pendingCreateWindow = rawWindow; + const HWND hwnd = CreateWindowExW( + WS_EX_APPWINDOW, + m_hostConfig.windowClassName, + rawWindow->GetTitle().c_str(), + m_hostConfig.windowStyle, + params.initialX, + params.initialY, + params.initialWidth, + params.initialHeight, + nullptr, + nullptr, + m_hostConfig.hInstance, + m_hostConfig.windowUserData); + m_pendingCreateWindow = nullptr; + if (hwnd == nullptr) { + eraseRawWindow(); + return nullptr; + } + + if (!rawWindow->HasHwnd()) { + rawWindow->AttachHwnd(hwnd); + } + + auto failWindowInitialization = [&](std::string_view message) { + LogRuntimeTrace("window", std::string(message)); + DestroyEditorWindow(*rawWindow); + eraseRawWindow(); + return static_cast(nullptr); + }; + + const HICON bigIcon = static_cast( + LoadImageW( + m_hostConfig.hInstance, + MAKEINTRESOURCEW(IDI_APP_ICON), + IMAGE_ICON, + 0, + 0, + LR_DEFAULTSIZE)); + const HICON smallIcon = static_cast( + LoadImageW( + m_hostConfig.hInstance, + MAKEINTRESOURCEW(IDI_APP_ICON_SMALL), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR)); + if (bigIcon != nullptr) { + SendMessageW(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(bigIcon)); + } + if (smallIcon != nullptr) { + SendMessageW(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(smallIcon)); + } + + if (!rawWindow->Initialize( + m_repoRoot, + m_editorContext, + m_editorContext.GetShellAsset().captureRootPath, + params.autoCaptureOnStartup)) { + return failWindowInitialization("managed window initialization failed"); + } + + ShowWindow(hwnd, params.showCommand); + UpdateWindow(hwnd); + return rawWindow; +} + +void EditorWindowManager::HandlePendingNativeWindowCreated(HWND hwnd) { + if (m_pendingCreateWindow != nullptr && !m_pendingCreateWindow->HasHwnd()) { + m_pendingCreateWindow->AttachHwnd(hwnd); + } +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/EditorWindowManagerLifecycle.cpp b/new_editor/app/Platform/Win32/EditorWindowManagerLifecycle.cpp index a8ffdb28..10f820ba 100644 --- a/new_editor/app/Platform/Win32/EditorWindowManagerLifecycle.cpp +++ b/new_editor/app/Platform/Win32/EditorWindowManagerLifecycle.cpp @@ -1,13 +1,10 @@ #include "EditorWindowManager.h" #include "State/EditorContext.h" -#include "Bootstrap/EditorResources.h" #include "EditorWindow.h" #include -#include - namespace XCEngine::UI::Editor::App { EditorWindowManager::EditorWindowManager( @@ -20,102 +17,6 @@ EditorWindowManager::EditorWindowManager( EditorWindowManager::~EditorWindowManager() = default; -EditorWindow* EditorWindowManager::CreateEditorWindow( - UIEditorWorkspaceController workspaceController, - const CreateParams& params) { - auto windowPtr = std::make_unique( - params.windowId, - params.title.empty() ? std::wstring(L"XCEngine Editor") : params.title, - params.primary, - std::move(workspaceController)); - EditorWindow* const rawWindow = windowPtr.get(); - m_windows.push_back(std::move(windowPtr)); - - const auto eraseRawWindow = [this, rawWindow]() { - const auto it = std::find_if( - m_windows.begin(), - m_windows.end(), - [rawWindow](const std::unique_ptr& candidate) { - return candidate.get() == rawWindow; - }); - if (it != m_windows.end()) { - m_windows.erase(it); - } - }; - - m_pendingCreateWindow = rawWindow; - const HWND hwnd = CreateWindowExW( - WS_EX_APPWINDOW, - m_hostConfig.windowClassName, - rawWindow->GetTitle().c_str(), - m_hostConfig.windowStyle, - params.initialX, - params.initialY, - params.initialWidth, - params.initialHeight, - nullptr, - nullptr, - m_hostConfig.hInstance, - m_hostConfig.windowUserData); - m_pendingCreateWindow = nullptr; - if (hwnd == nullptr) { - eraseRawWindow(); - return nullptr; - } - - if (!rawWindow->HasHwnd()) { - rawWindow->AttachHwnd(hwnd); - } - - auto failWindowInitialization = [&](std::string_view message) { - LogRuntimeTrace("window", std::string(message)); - DestroyEditorWindow(*rawWindow); - eraseRawWindow(); - return static_cast(nullptr); - }; - - const HICON bigIcon = static_cast( - LoadImageW( - m_hostConfig.hInstance, - MAKEINTRESOURCEW(IDI_APP_ICON), - IMAGE_ICON, - 0, - 0, - LR_DEFAULTSIZE)); - const HICON smallIcon = static_cast( - LoadImageW( - m_hostConfig.hInstance, - MAKEINTRESOURCEW(IDI_APP_ICON_SMALL), - IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - LR_DEFAULTCOLOR)); - if (bigIcon != nullptr) { - SendMessageW(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(bigIcon)); - } - if (smallIcon != nullptr) { - SendMessageW(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(smallIcon)); - } - - if (!rawWindow->Initialize( - m_repoRoot, - m_editorContext, - m_editorContext.GetShellAsset().captureRootPath, - params.autoCaptureOnStartup)) { - return failWindowInitialization("managed window initialization failed"); - } - - ShowWindow(hwnd, params.showCommand); - UpdateWindow(hwnd); - return rawWindow; -} - -void EditorWindowManager::HandlePendingNativeWindowCreated(HWND hwnd) { - if (m_pendingCreateWindow != nullptr && !m_pendingCreateWindow->HasHwnd()) { - m_pendingCreateWindow->AttachHwnd(hwnd); - } -} - void EditorWindowManager::Shutdown() { for (const std::unique_ptr& window : m_windows) { if (window != nullptr) { @@ -127,56 +28,6 @@ void EditorWindowManager::Shutdown() { m_globalTabDragSession = {}; } -EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) { - if (hwnd == nullptr) { - return nullptr; - } - - for (const std::unique_ptr& window : m_windows) { - if (window != nullptr && window->GetHwnd() == hwnd) { - return window.get(); - } - } - - return nullptr; -} - -const EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) const { - return const_cast(this)->FindWindow(hwnd); -} - -EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) { - if (windowId.empty()) { - return nullptr; - } - - for (const std::unique_ptr& window : m_windows) { - if (window != nullptr && window->GetWindowId() == windowId) { - return window.get(); - } - } - - return nullptr; -} - -const EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) const { - return const_cast(this)->FindWindow(windowId); -} - -EditorWindow* EditorWindowManager::FindPrimaryWindow() { - for (const std::unique_ptr& window : m_windows) { - if (window != nullptr && window->IsPrimary()) { - return window.get(); - } - } - - return nullptr; -} - -const EditorWindow* EditorWindowManager::FindPrimaryWindow() const { - return const_cast(this)->FindPrimaryWindow(); -} - bool EditorWindowManager::HasWindows() const { return !m_windows.empty(); } diff --git a/new_editor/app/Platform/Win32/EditorWindowManagerLookup.cpp b/new_editor/app/Platform/Win32/EditorWindowManagerLookup.cpp new file mode 100644 index 00000000..e7748429 --- /dev/null +++ b/new_editor/app/Platform/Win32/EditorWindowManagerLookup.cpp @@ -0,0 +1,57 @@ +#include "EditorWindowManager.h" + +#include "EditorWindow.h" + +namespace XCEngine::UI::Editor::App { + +EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) { + if (hwnd == nullptr) { + return nullptr; + } + + for (const std::unique_ptr& window : m_windows) { + if (window != nullptr && window->GetHwnd() == hwnd) { + return window.get(); + } + } + + return nullptr; +} + +const EditorWindow* EditorWindowManager::FindWindow(HWND hwnd) const { + return const_cast(this)->FindWindow(hwnd); +} + +EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) { + if (windowId.empty()) { + return nullptr; + } + + for (const std::unique_ptr& window : m_windows) { + if (window != nullptr && window->GetWindowId() == windowId) { + return window.get(); + } + } + + return nullptr; +} + +const EditorWindow* EditorWindowManager::FindWindow(std::string_view windowId) const { + return const_cast(this)->FindWindow(windowId); +} + +EditorWindow* EditorWindowManager::FindPrimaryWindow() { + for (const std::unique_ptr& window : m_windows) { + if (window != nullptr && window->IsPrimary()) { + return window.get(); + } + } + + return nullptr; +} + +const EditorWindow* EditorWindowManager::FindPrimaryWindow() const { + return const_cast(this)->FindPrimaryWindow(); +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/EditorWindowTitleBarDragRestore.cpp b/new_editor/app/Platform/Win32/EditorWindowTitleBarDragRestore.cpp new file mode 100644 index 00000000..af7097dc --- /dev/null +++ b/new_editor/app/Platform/Win32/EditorWindowTitleBarDragRestore.cpp @@ -0,0 +1,97 @@ +#include "Platform/Win32/EditorWindow.h" +#include "Platform/Win32/EditorWindowConstants.h" + +#include + +namespace XCEngine::UI::Editor::App { + +using namespace EditorWindowSupport; + +bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove( + EditorContext& editorContext, + bool globalTabDragActive) { + if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed() || m_window.hwnd == nullptr) { + return false; + } + + POINT currentScreenPoint = {}; + if (!GetCursorPos(¤tScreenPoint)) { + return true; + } + + const POINT initialScreenPoint = + m_chrome.runtime.GetBorderlessWindowDragRestoreInitialScreenPoint(); + const int dragThresholdX = (std::max)(GetSystemMetrics(SM_CXDRAG), 1); + const int dragThresholdY = (std::max)(GetSystemMetrics(SM_CYDRAG), 1); + const LONG deltaX = currentScreenPoint.x - initialScreenPoint.x; + const LONG deltaY = currentScreenPoint.y - initialScreenPoint.y; + if (std::abs(deltaX) < dragThresholdX && + std::abs(deltaY) < dragThresholdY) { + return true; + } + + RECT restoreRect = {}; + RECT currentRect = {}; + RECT workAreaRect = {}; + if (!m_chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect) || + !QueryCurrentWindowRect(currentRect) || + !QueryBorderlessWindowWorkAreaRect(workAreaRect)) { + ClearBorderlessWindowChromeDragRestoreState(); + return true; + } + + const int restoreWidth = restoreRect.right - restoreRect.left; + const int restoreHeight = restoreRect.bottom - restoreRect.top; + const int currentWidth = currentRect.right - currentRect.left; + if (restoreWidth <= 0 || restoreHeight <= 0 || currentWidth <= 0) { + ClearBorderlessWindowChromeDragRestoreState(); + return true; + } + + const float pointerRatio = + static_cast(currentScreenPoint.x - currentRect.left) / + static_cast(currentWidth); + const float clampedPointerRatio = (std::clamp)(pointerRatio, 0.0f, 1.0f); + const int newLeft = + (std::clamp)( + currentScreenPoint.x - + static_cast(clampedPointerRatio * static_cast(restoreWidth)), + workAreaRect.left, + workAreaRect.right - restoreWidth); + const int titleBarHeightPixels = + static_cast(kBorderlessTitleBarHeightDips * GetDpiScale()); + const int newTop = + (std::clamp)( + currentScreenPoint.y - (std::max)(titleBarHeightPixels / 2, 1), + workAreaRect.top, + workAreaRect.bottom - restoreHeight); + const RECT targetRect = { + newLeft, + newTop, + newLeft + restoreWidth, + newTop + restoreHeight + }; + + m_chrome.runtime.SetBorderlessWindowMaximized(false); + ApplyPredictedWindowRectTransition( + editorContext, + globalTabDragActive, + targetRect); + ClearBorderlessWindowChromeDragRestoreState(); + ReleaseCapture(); + SendMessageW(m_window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0); + return true; +} + +void EditorWindow::ClearBorderlessWindowChromeDragRestoreState() { + if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed()) { + return; + } + + m_chrome.runtime.EndBorderlessWindowDragRestore(); + if (GetCapture() == m_window.hwnd) { + ReleaseCapture(); + } +} + +} // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Platform/Win32/EditorWindowTitleBarInteraction.cpp b/new_editor/app/Platform/Win32/EditorWindowTitleBarInteraction.cpp index fcfe6b8f..585a288f 100644 --- a/new_editor/app/Platform/Win32/EditorWindowTitleBarInteraction.cpp +++ b/new_editor/app/Platform/Win32/EditorWindowTitleBarInteraction.cpp @@ -1,8 +1,6 @@ #include "Platform/Win32/EditorWindow.h" #include "Platform/Win32/EditorWindowConstants.h" -#include - #include namespace XCEngine::UI::Editor::App { @@ -132,93 +130,6 @@ bool EditorWindow::HandleBorderlessWindowChromeDoubleClick( return true; } -bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove( - EditorContext& editorContext, - bool globalTabDragActive) { - if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed() || m_window.hwnd == nullptr) { - return false; - } - - POINT currentScreenPoint = {}; - if (!GetCursorPos(¤tScreenPoint)) { - return true; - } - - const POINT initialScreenPoint = - m_chrome.runtime.GetBorderlessWindowDragRestoreInitialScreenPoint(); - const int dragThresholdX = (std::max)(GetSystemMetrics(SM_CXDRAG), 1); - const int dragThresholdY = (std::max)(GetSystemMetrics(SM_CYDRAG), 1); - const LONG deltaX = currentScreenPoint.x - initialScreenPoint.x; - const LONG deltaY = currentScreenPoint.y - initialScreenPoint.y; - if (std::abs(deltaX) < dragThresholdX && - std::abs(deltaY) < dragThresholdY) { - return true; - } - - RECT restoreRect = {}; - RECT currentRect = {}; - RECT workAreaRect = {}; - if (!m_chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect) || - !QueryCurrentWindowRect(currentRect) || - !QueryBorderlessWindowWorkAreaRect(workAreaRect)) { - ClearBorderlessWindowChromeDragRestoreState(); - return true; - } - - const int restoreWidth = restoreRect.right - restoreRect.left; - const int restoreHeight = restoreRect.bottom - restoreRect.top; - const int currentWidth = currentRect.right - currentRect.left; - if (restoreWidth <= 0 || restoreHeight <= 0 || currentWidth <= 0) { - ClearBorderlessWindowChromeDragRestoreState(); - return true; - } - - const float pointerRatio = - static_cast(currentScreenPoint.x - currentRect.left) / - static_cast(currentWidth); - const float clampedPointerRatio = (std::clamp)(pointerRatio, 0.0f, 1.0f); - const int newLeft = - (std::clamp)( - currentScreenPoint.x - - static_cast(clampedPointerRatio * static_cast(restoreWidth)), - workAreaRect.left, - workAreaRect.right - restoreWidth); - const int titleBarHeightPixels = - static_cast(kBorderlessTitleBarHeightDips * GetDpiScale()); - const int newTop = - (std::clamp)( - currentScreenPoint.y - (std::max)(titleBarHeightPixels / 2, 1), - workAreaRect.top, - workAreaRect.bottom - restoreHeight); - const RECT targetRect = { - newLeft, - newTop, - newLeft + restoreWidth, - newTop + restoreHeight - }; - - m_chrome.runtime.SetBorderlessWindowMaximized(false); - ApplyPredictedWindowRectTransition( - editorContext, - globalTabDragActive, - targetRect); - ClearBorderlessWindowChromeDragRestoreState(); - ReleaseCapture(); - SendMessageW(m_window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0); - return true; -} - -void EditorWindow::ClearBorderlessWindowChromeDragRestoreState() { - if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed()) { - return; - } - - m_chrome.runtime.EndBorderlessWindowDragRestore(); - if (GetCapture() == m_window.hwnd) { - ReleaseCapture(); - } -} - void EditorWindow::ClearBorderlessWindowChromeState() { if (m_chrome.chromeState.hoveredTarget == Host::BorderlessWindowChromeHitTarget::None && diff --git a/new_editor/app/State/EditorContext.cpp b/new_editor/app/State/EditorContext.cpp index 1c190f42..9891c3bf 100644 --- a/new_editor/app/State/EditorContext.cpp +++ b/new_editor/app/State/EditorContext.cpp @@ -2,7 +2,6 @@ #include "Composition/EditorShellAssetBuilder.h" -#include #include #include @@ -11,7 +10,6 @@ namespace XCEngine::UI::Editor::App { namespace { using ::XCEngine::UI::Editor::BuildEditorShellShortcutManager; -constexpr std::size_t kMaxConsoleEntries = 256u; std::string ComposeStatusText( std::string_view status, @@ -110,91 +108,6 @@ UIEditorShellInteractionDefinition EditorContext::BuildShellDefinition( variant); } -void EditorContext::SetReadyStatus() { - SetStatus("Ready", "Old editor shell baseline loaded."); -} - -void EditorContext::SetStatus( - std::string status, - std::string message) { - if (m_lastStatus != status || m_lastMessage != message) { - AppendConsoleEntry(status, message); - } - m_lastStatus = std::move(status); - m_lastMessage = std::move(message); -} - -void EditorContext::UpdateStatusFromShellResult( - const UIEditorWorkspaceController& workspaceController, - const UIEditorShellInteractionResult& result) { - if (result.commandDispatched) { - SetStatus( - std::string(GetUIEditorCommandDispatchStatusName(result.commandDispatchResult.status)), - result.commandDispatchResult.message.empty() - ? result.commandDispatchResult.displayName - : result.commandDispatchResult.message); - return; - } - - if (result.workspaceResult.dockHostResult.layoutChanged) { - SetStatus("Layout", result.workspaceResult.dockHostResult.layoutResult.message); - return; - } - - if (result.workspaceResult.dockHostResult.commandExecuted) { - SetStatus("Workspace", result.workspaceResult.dockHostResult.commandResult.message); - return; - } - - if (!result.viewportPanelId.empty()) { - std::string message = {}; - if (result.viewportInputFrame.captureStarted) { - message = "Viewport capture started."; - } else if (result.viewportInputFrame.captureEnded) { - message = "Viewport capture ended."; - } else if (result.viewportInputFrame.focusGained) { - message = "Viewport focused."; - } else if (result.viewportInputFrame.focusLost) { - message = "Viewport focus lost."; - } else if (result.viewportInputFrame.pointerPressedInside) { - message = "Viewport pointer down."; - } else if (result.viewportInputFrame.pointerReleasedInside) { - message = "Viewport pointer up."; - } else if (result.viewportInputFrame.pointerMoved) { - message = "Viewport pointer move."; - } else if (result.viewportInputFrame.wheelDelta != 0.0f) { - message = "Viewport wheel."; - } - - if (!message.empty()) { - SetStatus(result.viewportPanelId, std::move(message)); - } - return; - } - - if (result.menuMutation.changed) { - if (!result.itemId.empty() && !result.menuMutation.openedPopupId.empty()) { - SetStatus("Menu", result.itemId + " opened child popup."); - } else if (!result.menuId.empty() && !result.menuMutation.openedPopupId.empty()) { - SetStatus("Menu", result.menuId + " opened."); - } else { - SetStatus("Menu", "Popup chain dismissed."); - } - } -} - -void EditorContext::AppendConsoleEntry( - std::string channel, - std::string message) { - EditorConsoleEntry entry = {}; - entry.channel = std::move(channel); - entry.message = std::move(message); - m_session.consoleEntries.push_back(std::move(entry)); - if (m_session.consoleEntries.size() > kMaxConsoleEntries) { - m_session.consoleEntries.erase(m_session.consoleEntries.begin()); - } -} - std::string EditorContext::DescribeWorkspaceState( const UIEditorWorkspaceController& workspaceController, const UIEditorShellInteractionState& interactionState) const { diff --git a/new_editor/app/State/EditorContextStatus.cpp b/new_editor/app/State/EditorContextStatus.cpp new file mode 100644 index 00000000..5e7abf33 --- /dev/null +++ b/new_editor/app/State/EditorContextStatus.cpp @@ -0,0 +1,115 @@ +#include "EditorContext.h" + +#include +#include + +namespace XCEngine::UI::Editor::App { + +namespace { + +constexpr std::size_t kMaxConsoleEntries = 256u; + +std::string ResolveViewportStatusMessage( + const UIEditorShellInteractionResult& result) { + if (result.viewportInputFrame.captureStarted) { + return "Viewport capture started."; + } + if (result.viewportInputFrame.captureEnded) { + return "Viewport capture ended."; + } + if (result.viewportInputFrame.focusGained) { + return "Viewport focused."; + } + if (result.viewportInputFrame.focusLost) { + return "Viewport focus lost."; + } + if (result.viewportInputFrame.pointerPressedInside) { + return "Viewport pointer down."; + } + if (result.viewportInputFrame.pointerReleasedInside) { + return "Viewport pointer up."; + } + if (result.viewportInputFrame.pointerMoved) { + return "Viewport pointer move."; + } + if (result.viewportInputFrame.wheelDelta != 0.0f) { + return "Viewport wheel."; + } + + return {}; +} + +} // namespace + +void EditorContext::SetReadyStatus() { + SetStatus("Ready", "Old editor shell baseline loaded."); +} + +void EditorContext::SetStatus( + std::string status, + std::string message) { + if (m_lastStatus != status || m_lastMessage != message) { + AppendConsoleEntry(status, message); + } + m_lastStatus = std::move(status); + m_lastMessage = std::move(message); +} + +void EditorContext::UpdateStatusFromShellResult( + const UIEditorWorkspaceController& workspaceController, + const UIEditorShellInteractionResult& result) { + (void)workspaceController; + + if (result.commandDispatched) { + SetStatus( + std::string(GetUIEditorCommandDispatchStatusName(result.commandDispatchResult.status)), + result.commandDispatchResult.message.empty() + ? result.commandDispatchResult.displayName + : result.commandDispatchResult.message); + return; + } + + if (result.workspaceResult.dockHostResult.layoutChanged) { + SetStatus("Layout", result.workspaceResult.dockHostResult.layoutResult.message); + return; + } + + if (result.workspaceResult.dockHostResult.commandExecuted) { + SetStatus("Workspace", result.workspaceResult.dockHostResult.commandResult.message); + return; + } + + if (!result.viewportPanelId.empty()) { + std::string message = ResolveViewportStatusMessage(result); + if (!message.empty()) { + SetStatus(result.viewportPanelId, std::move(message)); + } + return; + } + + if (!result.menuMutation.changed) { + return; + } + + if (!result.itemId.empty() && !result.menuMutation.openedPopupId.empty()) { + SetStatus("Menu", result.itemId + " opened child popup."); + } else if (!result.menuId.empty() && !result.menuMutation.openedPopupId.empty()) { + SetStatus("Menu", result.menuId + " opened."); + } else { + SetStatus("Menu", "Popup chain dismissed."); + } +} + +void EditorContext::AppendConsoleEntry( + std::string channel, + std::string message) { + EditorConsoleEntry entry = {}; + entry.channel = std::move(channel); + entry.message = std::move(message); + m_session.consoleEntries.push_back(std::move(entry)); + if (m_session.consoleEntries.size() > kMaxConsoleEntries) { + m_session.consoleEntries.erase(m_session.consoleEntries.begin()); + } +} + +} // namespace XCEngine::UI::Editor::App