refactor(new_editor): finish shell runtime stage split

This commit is contained in:
2026-04-22 15:15:40 +08:00
parent 77fe0a97a4
commit 17326f455e
7 changed files with 335 additions and 294 deletions

View File

@@ -4,36 +4,9 @@
#include "Composition/EditorContext.h"
#include "Composition/EditorPanelIds.h"
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEditor/Foundation/UIEditorTheme.h>
#include <algorithm>
#include "Features/PanelInputContext.h"
namespace XCEngine::UI::Editor::App {
void ApplyViewportFramesToShellFrame(
UIEditorShellInteractionFrame& shellFrame,
ViewportHostService& viewportHostService);
std::vector<::XCEngine::UI::UIInputEvent> FilterShellInputEventsForHostedContentCapture(
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents);
bool ShouldHostedContentYieldPointerStream(
const UIEditorShellInteractionFrame& shellFrame,
bool shellInteractiveCaptureActive);
std::vector<::XCEngine::UI::UIInputEvent> FilterHostedContentInputEventsForShellOwnership(
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
bool shellOwnsPointerStream);
UIEditorShellComposeModel BuildShellComposeModelFromFrame(
const UIEditorShellInteractionFrame& frame);
void AppendShellPopups(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorShellInteractionFrame& frame,
const UIEditorShellInteractionPalette& palette,
const UIEditorShellInteractionMetrics& metrics);
void EditorShellRuntime::Initialize(
const std::filesystem::path& repoRoot,
Ports::TexturePort& textureHost,
@@ -155,35 +128,10 @@ UIEditorDockHostTabDropTarget EditorShellRuntime::ResolveDockTabDropTarget(
}
EditorShellPointerOwner EditorShellRuntime::GetPointerOwner() const {
const auto& dockHostInteractionState =
m_shellInteractionState.workspaceInteractionState.dockHostInteractionState;
if (dockHostInteractionState.splitterDragState.active ||
!dockHostInteractionState.activeTabDragNodeId.empty()) {
return EditorShellPointerOwner::DockHost;
}
for (const auto& panelState :
m_shellInteractionState.workspaceInteractionState.composeState.panelStates) {
if (!panelState.viewportShellState.inputBridgeState.captured) {
continue;
}
if (panelState.panelId == kGamePanelId) {
return EditorShellPointerOwner::GameViewport;
}
return EditorShellPointerOwner::SceneViewport;
}
if (m_hierarchyPanel.HasActivePointerCapture()) {
return EditorShellPointerOwner::HierarchyPanel;
}
if (m_projectPanel.HasActivePointerCapture()) {
return EditorShellPointerOwner::ProjectPanel;
}
return EditorShellPointerOwner::None;
return m_hostedPanelCoordinator.ResolvePointerOwner(
m_shellInteractionState,
m_hierarchyPanel,
m_projectPanel);
}
bool EditorShellRuntime::WantsHostPointerCapture() const {
@@ -235,93 +183,6 @@ void EditorShellRuntime::Append(::XCEngine::UI::UIDrawData& drawData) const {
namespace XCEngine::UI::Editor::App {
namespace {
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using Widgets::UIEditorDockHostHitTargetKind;
bool IsPointerInputEventType(UIInputEventType type) {
switch (type) {
case UIInputEventType::PointerMove:
case UIInputEventType::PointerEnter:
case UIInputEventType::PointerLeave:
case UIInputEventType::PointerButtonDown:
case UIInputEventType::PointerButtonUp:
case UIInputEventType::PointerWheel:
return true;
default:
return false;
}
}
const UIEditorPanelDescriptor* ResolveSingleVisibleToolWindowPanelDescriptor(
const UIEditorWorkspaceController& workspaceController) {
const UIEditorWorkspaceNode& root = workspaceController.GetWorkspace().root;
if (root.kind != UIEditorWorkspaceNodeKind::TabStack) {
return nullptr;
}
const UIEditorWorkspaceSession& session = workspaceController.GetSession();
const UIEditorPanelRegistry& panelRegistry = workspaceController.GetPanelRegistry();
const UIEditorPanelDescriptor* visibleDescriptor = nullptr;
std::size_t visibleCount = 0u;
for (const UIEditorWorkspaceNode& child : root.children) {
if (child.kind != UIEditorWorkspaceNodeKind::Panel) {
continue;
}
const UIEditorPanelSessionState* panelState =
FindUIEditorPanelSessionState(session, child.panel.panelId);
if (panelState == nullptr || !panelState->open || !panelState->visible) {
continue;
}
const UIEditorPanelDescriptor* descriptor =
FindUIEditorPanelDescriptor(panelRegistry, child.panel.panelId);
if (descriptor == nullptr) {
return nullptr;
}
++visibleCount;
visibleDescriptor = descriptor;
if (visibleCount > 1u) {
return nullptr;
}
}
return visibleDescriptor != nullptr && visibleDescriptor->toolWindow
? visibleDescriptor
: nullptr;
}
} // namespace
std::vector<UIInputEvent> FilterShellInputEventsForHostedContentCapture(
const std::vector<UIInputEvent>& inputEvents) {
std::vector<UIInputEvent> filteredEvents = {};
filteredEvents.reserve(inputEvents.size());
for (const UIInputEvent& event : inputEvents) {
switch (event.type) {
case UIInputEventType::PointerMove:
case UIInputEventType::PointerEnter:
case UIInputEventType::PointerLeave:
case UIInputEventType::PointerButtonDown:
case UIInputEventType::PointerButtonUp:
case UIInputEventType::PointerWheel:
break;
default:
filteredEvents.push_back(event);
break;
}
}
return filteredEvents;
}
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
void EditorShellRuntime::Update(
EditorContext& context,
UIEditorWorkspaceController& workspaceController,
@@ -332,37 +193,8 @@ void EditorShellRuntime::Update(
bool useDetachedTitleBarTabStrip,
float detachedTitleBarTabHeight,
float detachedWindowChromeHeight) {
UIEditorShellInteractionMetrics metrics = ResolveUIEditorShellInteractionMetrics();
if (const UIEditorPanelDescriptor* toolWindowDescriptor =
ResolveSingleVisibleToolWindowPanelDescriptor(workspaceController);
toolWindowDescriptor != nullptr) {
metrics.shellMetrics.dockHostMetrics.tabStripMetrics.layoutMetrics.headerHeight = 0.0f;
const float minimumContentWidth =
toolWindowDescriptor->minimumDetachedWindowSize.width > 0.0f
? toolWindowDescriptor->minimumDetachedWindowSize.width
: metrics.shellMetrics.dockHostMetrics.minimumStandalonePanelBodySize.width;
const float minimumContentHeight =
toolWindowDescriptor->minimumDetachedWindowSize.height > detachedWindowChromeHeight
? toolWindowDescriptor->minimumDetachedWindowSize.height -
detachedWindowChromeHeight
: metrics.shellMetrics.dockHostMetrics.minimumStandalonePanelBodySize.height;
metrics.shellMetrics.dockHostMetrics.minimumStandalonePanelBodySize =
::XCEngine::UI::UISize(minimumContentWidth, minimumContentHeight);
metrics.shellMetrics.dockHostMetrics.minimumTabContentBodySize =
metrics.shellMetrics.dockHostMetrics.minimumStandalonePanelBodySize;
}
if (useDetachedTitleBarTabStrip && detachedTitleBarTabHeight > 0.0f) {
metrics.shellMetrics.dockHostMetrics.tabStripMetrics.layoutMetrics.headerHeight =
detachedTitleBarTabHeight;
}
const UIEditorWorkspaceLayoutSnapshot preUpdateSnapshot =
workspaceController.CaptureLayoutSnapshot();
const Widgets::UIEditorDockHostLayout preUpdateDockLayout =
m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout;
UIEditorShellInteractionDefinition definition =
m_sessionCoordinator.PrepareShellDefinition(
const auto buildDefinition = [&]() {
return m_sessionCoordinator.PrepareShellDefinition(
EditorShellSessionCoordinatorContext{
.context = context,
.workspaceController = workspaceController,
@@ -374,52 +206,23 @@ void EditorShellRuntime::Update(
.sceneEditCommandRoute = m_sceneEditCommandRoute,
.sceneViewportFeature = m_sceneViewportFeature,
});
m_viewportHostService.BeginFrame();
const std::vector<::XCEngine::UI::UIInputEvent> shellEvents =
HasHostedContentCapture()
? FilterShellInputEventsForHostedContentCapture(inputEvents)
: inputEvents;
m_shellFrame = UpdateUIEditorShellInteraction(
m_shellInteractionState,
workspaceController,
bounds,
definition,
shellEvents,
context.GetShellServices(),
metrics);
if (TryApplyUIEditorWorkspaceSplitterDragCorrection(
m_splitterDragCorrectionState,
m_shellInteractionState.workspaceInteractionState.dockHostInteractionState,
preUpdateSnapshot,
preUpdateDockLayout,
workspaceController,
metrics.shellMetrics.dockHostMetrics)) {
definition =
m_sessionCoordinator.PrepareShellDefinition(
EditorShellSessionCoordinatorContext{
.context = context,
.workspaceController = workspaceController,
.captureText = captureText,
.shellVariant = shellVariant,
.hierarchyPanel = m_hierarchyPanel,
.inspectorPanel = m_inspectorPanel,
.projectPanel = m_projectPanel,
.sceneEditCommandRoute = m_sceneEditCommandRoute,
.sceneViewportFeature = m_sceneViewportFeature,
});
m_shellFrame = UpdateUIEditorShellInteraction(
m_shellInteractionState,
workspaceController,
bounds,
definition,
{},
context.GetShellServices(),
metrics);
}
ApplyViewportFramesToShellFrame(m_shellFrame, m_viewportHostService);
};
m_interactionEngine.Update(
EditorShellInteractionEngineContext{
.shellInteractionState = m_shellInteractionState,
.shellFrame = m_shellFrame,
.splitterDragCorrectionState = m_splitterDragCorrectionState,
.workspaceController = workspaceController,
.bounds = bounds,
.inputEvents = inputEvents,
.shellServices = context.GetShellServices(),
.buildDefinition = buildDefinition,
.hostedContentCaptureActive = HasHostedContentCapture(),
.useDetachedTitleBarTabStrip = useDetachedTitleBarTabStrip,
.detachedTitleBarTabHeight = detachedTitleBarTabHeight,
.detachedWindowChromeHeight = detachedWindowChromeHeight,
.viewportHostService = m_viewportHostService,
});
m_sessionCoordinator.FinalizeFrame(context, workspaceController, m_shellFrame.result);
m_hostedPanelCoordinator.Update(
@@ -441,78 +244,4 @@ void EditorShellRuntime::Update(
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
namespace {
bool IsViewportPanel(std::string_view panelId) {
return IsEditorViewportPanelId(panelId);
}
void ApplyViewportFrameToPresentation(
const ViewportFrame& viewportFrame,
UIEditorWorkspacePanelPresentationModel& presentation) {
presentation.viewportShellModel.frame.texture = viewportFrame.texture;
presentation.viewportShellModel.frame.requestedSize = viewportFrame.requestedSize;
presentation.viewportShellModel.frame.presentedSize = viewportFrame.renderSize;
presentation.viewportShellModel.frame.hasTexture = viewportFrame.hasTexture;
presentation.viewportShellModel.frame.statusText = viewportFrame.statusText;
}
void ApplyViewportFrameToShellModel(
const ViewportFrame& viewportFrame,
UIEditorViewportShellModel& shellModel) {
shellModel.frame.texture = viewportFrame.texture;
shellModel.frame.requestedSize = viewportFrame.requestedSize;
shellModel.frame.presentedSize = viewportFrame.renderSize;
shellModel.frame.hasTexture = viewportFrame.hasTexture;
shellModel.frame.statusText = viewportFrame.statusText;
}
UIEditorWorkspacePanelPresentationModel* FindMutableWorkspacePresentation(
std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
std::string_view panelId) {
for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) {
if (presentation.panelId == panelId) {
return &presentation;
}
}
return nullptr;
}
} // namespace
void ApplyViewportFramesToShellFrame(
UIEditorShellInteractionFrame& shellFrame,
ViewportHostService& viewportHostService) {
auto applyToViewportFrames =
[&](std::vector<UIEditorWorkspaceViewportComposeFrame>& viewportFrames) {
for (UIEditorWorkspaceViewportComposeFrame& viewportComposeFrame : viewportFrames) {
if (!IsViewportPanel(viewportComposeFrame.panelId)) {
continue;
}
const ViewportFrame viewportFrame =
viewportHostService.RequestViewport(
viewportComposeFrame.panelId,
viewportComposeFrame.viewportShellFrame.requestedViewportSize);
ApplyViewportFrameToShellModel(
viewportFrame,
viewportComposeFrame.viewportShellModel);
if (UIEditorWorkspacePanelPresentationModel* presentation =
FindMutableWorkspacePresentation(
shellFrame.model.workspacePresentations,
viewportComposeFrame.panelId);
presentation != nullptr) {
ApplyViewportFrameToPresentation(viewportFrame, *presentation);
}
}
};
applyToViewportFrames(shellFrame.workspaceInteractionFrame.composeFrame.viewportFrames);
}
} // namespace XCEngine::UI::Editor::App