#include #include #include namespace XCEngine::UI::Editor { namespace { using Widgets::AppendUIEditorDockHostBackground; using Widgets::AppendUIEditorDockHostForeground; using Widgets::AppendUIEditorViewportSlotBackground; using Widgets::AppendUIEditorViewportSlotForeground; using Widgets::BuildUIEditorDockHostLayout; using Widgets::UIEditorDockHostForegroundOptions; const UIEditorWorkspacePanelPresentationState* FindPanelStateImpl( const UIEditorWorkspaceComposeState& state, std::string_view panelId) { for (const UIEditorWorkspacePanelPresentationState& panelState : state.panelStates) { if (panelState.panelId == panelId) { return &panelState; } } return nullptr; } UIEditorWorkspacePanelPresentationState* FindMutablePanelStateImpl( UIEditorWorkspaceComposeState& state, std::string_view panelId) { for (UIEditorWorkspacePanelPresentationState& panelState : state.panelStates) { if (panelState.panelId == panelId) { return &panelState; } } return nullptr; } bool SupportsExternalViewportPresentation( const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspacePanelPresentationModel& presentation) { if (presentation.kind != UIEditorPanelPresentationKind::ViewportShell) { return false; } const UIEditorPanelDescriptor* descriptor = FindUIEditorPanelDescriptor(panelRegistry, presentation.panelId); return descriptor != nullptr && descriptor->presentationKind == UIEditorPanelPresentationKind::ViewportShell; } UIEditorWorkspacePanelPresentationState& EnsurePanelState( UIEditorWorkspaceComposeState& state, std::string_view panelId) { for (UIEditorWorkspacePanelPresentationState& panelState : state.panelStates) { if (panelState.panelId == panelId) { return panelState; } } UIEditorWorkspacePanelPresentationState panelState = {}; panelState.panelId = std::string(panelId); state.panelStates.push_back(std::move(panelState)); return state.panelStates.back(); } void ResetHiddenViewportPresentationState( UIEditorWorkspaceComposeState& state, std::string_view panelId) { UIEditorWorkspacePanelPresentationState* panelState = FindMutablePanelStateImpl(state, panelId); if (panelState == nullptr) { return; } panelState->viewportShellState = {}; } void TrimObsoleteViewportPresentationStates( UIEditorWorkspaceComposeState& state, const UIEditorPanelRegistry& panelRegistry, const std::vector& presentations) { state.panelStates.erase( std::remove_if( state.panelStates.begin(), state.panelStates.end(), [&](const UIEditorWorkspacePanelPresentationState& panelState) { for (const UIEditorWorkspacePanelPresentationModel& presentation : presentations) { if (presentation.panelId == panelState.panelId && SupportsExternalViewportPresentation(panelRegistry, presentation)) { return false; } } return true; }), state.panelStates.end()); } } // namespace const UIEditorWorkspacePanelPresentationModel* FindUIEditorWorkspacePanelPresentationModel( const std::vector& presentations, std::string_view panelId) { for (const UIEditorWorkspacePanelPresentationModel& presentation : presentations) { if (presentation.panelId == panelId) { return &presentation; } } return nullptr; } const UIEditorWorkspacePanelPresentationState* FindUIEditorWorkspacePanelPresentationState( const UIEditorWorkspaceComposeState& state, std::string_view panelId) { return FindPanelStateImpl(state, panelId); } const UIEditorWorkspaceViewportComposeRequest* FindUIEditorWorkspaceViewportPresentationRequest( const UIEditorWorkspaceComposeRequest& request, std::string_view panelId) { for (const UIEditorWorkspaceViewportComposeRequest& viewportRequest : request.viewportRequests) { if (viewportRequest.panelId == panelId) { return &viewportRequest; } } return nullptr; } const UIEditorWorkspaceViewportComposeFrame* FindUIEditorWorkspaceViewportPresentationFrame( const UIEditorWorkspaceComposeFrame& frame, std::string_view panelId) { for (const UIEditorWorkspaceViewportComposeFrame& viewportFrame : frame.viewportFrames) { if (viewportFrame.panelId == panelId) { return &viewportFrame; } } return nullptr; } UIEditorWorkspaceComposeRequest ResolveUIEditorWorkspaceComposeRequest( const Widgets::UIEditorDockHostLayout& dockHostLayout, const UIEditorPanelRegistry& panelRegistry, const std::vector& presentations, const Widgets::UIEditorViewportSlotMetrics& viewportMetrics, const UIEditorTextMeasurer* textMeasurer) { UIEditorWorkspaceComposeRequest request = {}; request.dockHostLayout = dockHostLayout; request.contentHostRequest = ResolveUIEditorPanelContentHostRequest( request.dockHostLayout, panelRegistry); request.viewportRequests.reserve(request.contentHostRequest.mountRequests.size()); for (const UIEditorPanelContentHostMountRequest& mountRequest : request.contentHostRequest.mountRequests) { if (mountRequest.kind != UIEditorPanelPresentationKind::ViewportShell) { continue; } const UIEditorWorkspacePanelPresentationModel* presentation = FindUIEditorWorkspacePanelPresentationModel(presentations, mountRequest.panelId); if (presentation == nullptr || !SupportsExternalViewportPresentation(panelRegistry, *presentation)) { continue; } UIEditorWorkspaceViewportComposeRequest viewportRequest = {}; viewportRequest.panelId = mountRequest.panelId; viewportRequest.bounds = mountRequest.bounds; viewportRequest.viewportShellModel = ResolveUIEditorViewportShellMeasuredModel( presentation->viewportShellModel, viewportMetrics, textMeasurer); viewportRequest.viewportShellRequest = ResolveUIEditorViewportShellRequest( mountRequest.bounds, viewportRequest.viewportShellModel.spec, viewportMetrics); request.viewportRequests.push_back(std::move(viewportRequest)); } return request; } UIEditorWorkspaceComposeRequest ResolveUIEditorWorkspaceComposeRequest( const ::XCEngine::UI::UIRect& bounds, const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspaceModel& workspace, const UIEditorWorkspaceSession& session, const std::vector& presentations, const Widgets::UIEditorDockHostState& dockHostState, const Widgets::UIEditorDockHostMetrics& dockHostMetrics, const Widgets::UIEditorViewportSlotMetrics& viewportMetrics, const UIEditorTextMeasurer* textMeasurer) { const Widgets::UIEditorDockHostLayout dockHostLayout = BuildUIEditorDockHostLayout( bounds, panelRegistry, workspace, session, dockHostState, dockHostMetrics, textMeasurer); return ResolveUIEditorWorkspaceComposeRequest( dockHostLayout, panelRegistry, presentations, viewportMetrics, textMeasurer); } UIEditorWorkspaceComposeFrame UpdateUIEditorWorkspaceCompose( UIEditorWorkspaceComposeState& state, const UIEditorWorkspaceComposeRequest& request, const UIEditorPanelRegistry& panelRegistry, const std::vector& presentations, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents, const UIEditorWorkspaceInputOwner* inputOwner) { UIEditorWorkspaceComposeFrame frame = {}; frame.dockHostLayout = request.dockHostLayout; frame.contentHostFrame = UpdateUIEditorPanelContentHost( state.contentHostState, request.contentHostRequest, panelRegistry); TrimObsoleteViewportPresentationStates(state, panelRegistry, presentations); frame.viewportFrames.reserve(request.viewportRequests.size()); for (const UIEditorWorkspacePanelPresentationModel& presentation : presentations) { if (!SupportsExternalViewportPresentation(panelRegistry, presentation)) { continue; } const UIEditorWorkspaceViewportComposeRequest* viewportRequest = FindUIEditorWorkspaceViewportPresentationRequest(request, presentation.panelId); if (viewportRequest == nullptr) { ResetHiddenViewportPresentationState(state, presentation.panelId); continue; } UIEditorWorkspacePanelPresentationState& panelState = EnsurePanelState(state, presentation.panelId); UIEditorWorkspaceViewportComposeFrame viewportFrame = {}; viewportFrame.panelId = presentation.panelId; viewportFrame.bounds = viewportRequest->bounds; viewportFrame.viewportShellModel = viewportRequest->viewportShellModel; UIEditorViewportInputBridgeRequest inputRequest = {}; if (inputOwner != nullptr) { inputRequest.focusMode = UIEditorViewportInputBridgeFocusMode::External; inputRequest.focused = IsUIEditorWorkspaceViewportInputOwner(*inputOwner, presentation.panelId); } viewportFrame.viewportShellFrame = UpdateUIEditorViewportShell( panelState.viewportShellState, viewportRequest->viewportShellRequest, viewportFrame.viewportShellModel, inputEvents, inputRequest); frame.viewportFrames.push_back(std::move(viewportFrame)); } return frame; } UIEditorWorkspaceComposeFrame UpdateUIEditorWorkspaceCompose( UIEditorWorkspaceComposeState& state, const ::XCEngine::UI::UIRect& bounds, const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspaceModel& workspace, const UIEditorWorkspaceSession& session, const std::vector& presentations, const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents, const Widgets::UIEditorDockHostState& dockHostState, const Widgets::UIEditorDockHostMetrics& dockHostMetrics, const Widgets::UIEditorViewportSlotMetrics& viewportMetrics, const UIEditorWorkspaceInputOwner* inputOwner, const UIEditorTextMeasurer* textMeasurer) { const UIEditorWorkspaceComposeRequest request = ResolveUIEditorWorkspaceComposeRequest( bounds, panelRegistry, workspace, session, presentations, dockHostState, dockHostMetrics, viewportMetrics, textMeasurer); return UpdateUIEditorWorkspaceCompose( state, request, panelRegistry, presentations, inputEvents, inputOwner); } std::vector CollectUIEditorWorkspaceComposeExternalBodyPanelIds( const UIEditorWorkspaceComposeFrame& frame) { return CollectMountedUIEditorPanelContentHostPanelIds(frame.contentHostFrame); } void AppendUIEditorWorkspaceCompose( ::XCEngine::UI::UIDrawList& drawList, const UIEditorWorkspaceComposeFrame& frame, const Widgets::UIEditorDockHostPalette& dockHostPalette, const Widgets::UIEditorDockHostMetrics& dockHostMetrics, const Widgets::UIEditorViewportSlotPalette& viewportPalette, const Widgets::UIEditorViewportSlotMetrics& viewportMetrics, const UIEditorWorkspaceComposeAppendOptions& options) { AppendUIEditorDockHostBackground( drawList, frame.dockHostLayout, dockHostPalette, dockHostMetrics); for (const UIEditorWorkspaceViewportComposeFrame& viewportFrame : frame.viewportFrames) { AppendUIEditorViewportSlotBackground( drawList, viewportFrame.viewportShellFrame.slotLayout, viewportFrame.viewportShellModel.spec.toolItems, viewportFrame.viewportShellModel.spec.statusSegments, viewportFrame.viewportShellFrame.slotState, viewportPalette, viewportMetrics); AppendUIEditorViewportSlotForeground( drawList, viewportFrame.viewportShellFrame.slotLayout, viewportFrame.viewportShellModel.spec.chrome, viewportFrame.viewportShellModel.frame, viewportFrame.viewportShellModel.spec.toolItems, viewportFrame.viewportShellModel.spec.statusSegments, viewportFrame.viewportShellFrame.slotState, viewportPalette, viewportMetrics, Widgets::UIEditorViewportSlotForegroundAppendOptions{ options.includeViewportTextures }); } UIEditorDockHostForegroundOptions foregroundOptions = {}; foregroundOptions.externalBodyPanelIds = CollectUIEditorWorkspaceComposeExternalBodyPanelIds(frame); foregroundOptions.deferDropPreviewOverlay = options.deferDockPreviewOverlay; AppendUIEditorDockHostForeground( drawList, frame.dockHostLayout, foregroundOptions, dockHostPalette, dockHostMetrics); } void AppendUIEditorWorkspaceComposeOverlay( ::XCEngine::UI::UIDrawList& drawList, const UIEditorWorkspaceComposeFrame& frame, const Widgets::UIEditorDockHostPalette& dockHostPalette, const Widgets::UIEditorDockHostMetrics& dockHostMetrics) { AppendUIEditorDockHostOverlay( drawList, frame.dockHostLayout, dockHostPalette, dockHostMetrics); } void AppendUIEditorWorkspaceComposeViewportTextures( ::XCEngine::UI::UIDrawList& drawList, const UIEditorWorkspaceComposeFrame& frame, const Widgets::UIEditorViewportSlotPalette& viewportPalette) { for (const UIEditorWorkspaceViewportComposeFrame& viewportFrame : frame.viewportFrames) { Widgets::AppendUIEditorViewportSlotSurfaceTexture( drawList, viewportFrame.viewportShellFrame.slotLayout, viewportFrame.viewportShellModel.frame, viewportPalette); } } } // namespace XCEngine::UI::Editor