refactor(new_editor/app): reorganize host structure and add smoke test
This commit is contained in:
235
new_editor/app/Platform/Win32/EditorWindowFrame.cpp
Normal file
235
new_editor/app/Platform/Win32/EditorWindowFrame.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowConstants.h"
|
||||
#include "Platform/Win32/EditorWindowInputSupport.h"
|
||||
#include "Platform/Win32/EditorWindowRuntimeSupport.h"
|
||||
#include "Platform/Win32/EditorWindowStyle.h"
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
using namespace EditorWindowSupport;
|
||||
using ::XCEngine::UI::UIDrawData;
|
||||
using ::XCEngine::UI::UIDrawList;
|
||||
using ::XCEngine::UI::UIInputEvent;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
|
||||
void EditorWindow::RenderFrame(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_render.ready || m_window.hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
UINT pixelWidth = 0u;
|
||||
UINT pixelHeight = 0u;
|
||||
if (!ResolveRenderClientPixelSize(pixelWidth, pixelHeight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float width = PixelsToDips(static_cast<float>(pixelWidth));
|
||||
const float height = PixelsToDips(static_cast<float>(pixelHeight));
|
||||
const UIRect workspaceBounds = ResolveWorkspaceBounds(width, height);
|
||||
|
||||
UIDrawData drawData = {};
|
||||
UIDrawList& drawList = drawData.EmplaceDrawList("XCEditorShell");
|
||||
drawList.AddFilledRect(
|
||||
UIRect(0.0f, 0.0f, width, height),
|
||||
kShellSurfaceColor);
|
||||
|
||||
if (editorContext.IsValid()) {
|
||||
std::vector<UIInputEvent> frameEvents = std::move(m_input.pendingEvents);
|
||||
m_input.pendingEvents.clear();
|
||||
if (!frameEvents.empty() && IsVerboseRuntimeTraceEnabled()) {
|
||||
LogRuntimeTrace(
|
||||
"input",
|
||||
DescribeInputEvents(frameEvents) + " | " +
|
||||
editorContext.DescribeWorkspaceState(
|
||||
m_composition.workspaceController,
|
||||
m_composition.shellRuntime.GetShellInteractionState()));
|
||||
}
|
||||
|
||||
const Host::D3D12WindowRenderLoopFrameContext frameContext =
|
||||
m_render.windowRenderLoop.BeginFrame();
|
||||
if (!frameContext.warning.empty()) {
|
||||
LogRuntimeTrace("viewport", frameContext.warning);
|
||||
}
|
||||
|
||||
editorContext.AttachTextMeasurer(m_render.renderer);
|
||||
m_composition.shellRuntime.Update(
|
||||
editorContext,
|
||||
m_composition.workspaceController,
|
||||
workspaceBounds,
|
||||
frameEvents,
|
||||
BuildCaptureStatusText(),
|
||||
m_window.primary
|
||||
? EditorShellVariant::Primary
|
||||
: EditorShellVariant::DetachedWindow);
|
||||
const UIEditorShellInteractionFrame& shellFrame =
|
||||
m_composition.shellRuntime.GetShellFrame();
|
||||
const UIEditorDockHostInteractionState& dockHostInteractionState =
|
||||
m_composition.shellRuntime
|
||||
.GetShellInteractionState()
|
||||
.workspaceInteractionState
|
||||
.dockHostInteractionState;
|
||||
if (IsVerboseRuntimeTraceEnabled() &&
|
||||
(!frameEvents.empty() ||
|
||||
shellFrame.result.workspaceResult.dockHostResult.layoutChanged ||
|
||||
shellFrame.result.workspaceResult.dockHostResult.commandExecuted)) {
|
||||
std::ostringstream frameTrace = {};
|
||||
frameTrace << "result consumed="
|
||||
<< (shellFrame.result.consumed ? "true" : "false")
|
||||
<< " layoutChanged="
|
||||
<< (shellFrame.result.workspaceResult.dockHostResult.layoutChanged ? "true" : "false")
|
||||
<< " commandExecuted="
|
||||
<< (shellFrame.result.workspaceResult.dockHostResult.commandExecuted ? "true" : "false")
|
||||
<< " active="
|
||||
<< m_composition.workspaceController.GetWorkspace().activePanelId
|
||||
<< " message="
|
||||
<< shellFrame.result.workspaceResult.dockHostResult.layoutResult.message;
|
||||
LogRuntimeTrace("frame", frameTrace.str());
|
||||
}
|
||||
|
||||
if (!globalTabDragActive &&
|
||||
!dockHostInteractionState.activeTabDragNodeId.empty() &&
|
||||
!dockHostInteractionState.activeTabDragPanelId.empty()) {
|
||||
QueuePendingTabDragStart(
|
||||
dockHostInteractionState.activeTabDragNodeId,
|
||||
dockHostInteractionState.activeTabDragPanelId);
|
||||
}
|
||||
|
||||
if (shellFrame.result.workspaceResult.dockHostResult.detachRequested) {
|
||||
QueuePendingDetachRequest(
|
||||
shellFrame.result.workspaceResult.dockHostResult.detachedNodeId,
|
||||
shellFrame.result.workspaceResult.dockHostResult.detachedPanelId);
|
||||
}
|
||||
|
||||
ApplyHostCaptureRequests(shellFrame.result);
|
||||
for (const WorkspaceTraceEntry& entry : m_composition.shellRuntime.GetTraceEntries()) {
|
||||
LogRuntimeTrace(entry.channel, entry.message);
|
||||
}
|
||||
ApplyHostedContentCaptureRequests();
|
||||
ApplyCurrentCursor();
|
||||
m_composition.shellRuntime.Append(drawList);
|
||||
if (frameContext.canRenderViewports) {
|
||||
m_composition.shellRuntime.RenderRequestedViewports(frameContext.renderContext);
|
||||
}
|
||||
} else {
|
||||
drawList.AddText(
|
||||
UIPoint(28.0f, 28.0f),
|
||||
"Editor shell asset invalid.",
|
||||
kShellTextColor,
|
||||
16.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(28.0f, 54.0f),
|
||||
editorContext.GetValidationMessage().empty()
|
||||
? std::string("Unknown validation error.")
|
||||
: editorContext.GetValidationMessage(),
|
||||
kShellMutedTextColor,
|
||||
12.0f);
|
||||
}
|
||||
|
||||
AppendBorderlessWindowChrome(drawList, width);
|
||||
|
||||
const Host::D3D12WindowRenderLoopPresentResult presentResult =
|
||||
m_render.windowRenderLoop.Present(drawData);
|
||||
if (!presentResult.warning.empty()) {
|
||||
LogRuntimeTrace("present", presentResult.warning);
|
||||
}
|
||||
|
||||
m_render.autoScreenshot.CaptureIfRequested(
|
||||
m_render.renderer,
|
||||
drawData,
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
presentResult.framePresented);
|
||||
}
|
||||
|
||||
void EditorWindow::OnPaintMessage(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_render.ready || m_window.hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
PAINTSTRUCT paintStruct = {};
|
||||
BeginPaint(m_window.hwnd, &paintStruct);
|
||||
RenderFrame(editorContext, globalTabDragActive);
|
||||
EndPaint(m_window.hwnd, &paintStruct);
|
||||
}
|
||||
|
||||
UIRect EditorWindow::ResolveWorkspaceBounds(float clientWidthDips, float clientHeightDips) const {
|
||||
if (!IsBorderlessWindowEnabled()) {
|
||||
return UIRect(0.0f, 0.0f, clientWidthDips, clientHeightDips);
|
||||
}
|
||||
|
||||
const float titleBarHeight = (std::min)(kBorderlessTitleBarHeightDips, clientHeightDips);
|
||||
return UIRect(
|
||||
0.0f,
|
||||
titleBarHeight,
|
||||
clientWidthDips,
|
||||
(std::max)(0.0f, clientHeightDips - titleBarHeight));
|
||||
}
|
||||
|
||||
std::string EditorWindow::BuildCaptureStatusText() const {
|
||||
if (m_render.autoScreenshot.HasPendingCapture()) {
|
||||
return "Shot pending...";
|
||||
}
|
||||
|
||||
if (!m_render.autoScreenshot.GetLastCaptureError().empty()) {
|
||||
return TruncateText(m_render.autoScreenshot.GetLastCaptureError(), 38u);
|
||||
}
|
||||
|
||||
if (!m_render.autoScreenshot.GetLastCaptureSummary().empty()) {
|
||||
return TruncateText(m_render.autoScreenshot.GetLastCaptureSummary(), 38u);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void EditorWindow::ApplyHostCaptureRequests(const UIEditorShellInteractionResult& result) {
|
||||
if (result.requestPointerCapture && GetCapture() != m_window.hwnd) {
|
||||
SetCapture(m_window.hwnd);
|
||||
}
|
||||
if (result.releasePointerCapture && GetCapture() == m_window.hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWindow::ApplyHostedContentCaptureRequests() {
|
||||
if (m_composition.shellRuntime.WantsHostPointerCapture() &&
|
||||
GetCapture() != m_window.hwnd) {
|
||||
SetCapture(m_window.hwnd);
|
||||
}
|
||||
|
||||
if (m_composition.shellRuntime.WantsHostPointerRelease() &&
|
||||
GetCapture() == m_window.hwnd &&
|
||||
!m_composition.shellRuntime.HasShellInteractiveCapture()) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
std::string EditorWindow::DescribeInputEvents(
|
||||
const std::vector<UIInputEvent>& events) const {
|
||||
std::ostringstream stream = {};
|
||||
stream << "events=[";
|
||||
for (std::size_t index = 0; index < events.size(); ++index) {
|
||||
if (index > 0u) {
|
||||
stream << " | ";
|
||||
}
|
||||
const UIInputEvent& event = events[index];
|
||||
stream << DescribeInputEventType(event)
|
||||
<< '@'
|
||||
<< static_cast<int>(event.position.x)
|
||||
<< ','
|
||||
<< static_cast<int>(event.position.y);
|
||||
}
|
||||
stream << ']';
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
Reference in New Issue
Block a user