#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; } std::vector BuildContentHostBindings( const UIEditorPanelRegistry& panelRegistry, const std::vector& presentations) { std::vector bindings = {}; bindings.reserve(presentations.size()); for (const UIEditorWorkspacePanelPresentationModel& presentation : presentations) { const UIEditorPanelDescriptor* descriptor = FindUIEditorPanelDescriptor(panelRegistry, presentation.panelId); if (descriptor == nullptr || descriptor->presentationKind != presentation.kind || !IsUIEditorPanelPresentationExternallyHosted(presentation.kind)) { continue; } UIEditorPanelContentHostBinding binding = {}; binding.panelId = presentation.panelId; binding.kind = presentation.kind; bindings.push_back(std::move(binding)); } return bindings; } 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 ::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) { UIEditorWorkspaceComposeRequest request = {}; request.dockHostLayout = BuildUIEditorDockHostLayout( bounds, panelRegistry, workspace, session, dockHostState, dockHostMetrics); const std::vector contentHostBindings = BuildContentHostBindings(panelRegistry, presentations); request.contentHostRequest = ResolveUIEditorPanelContentHostRequest( request.dockHostLayout, panelRegistry, contentHostBindings); 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.viewportShellRequest = ResolveUIEditorViewportShellRequest( mountRequest.bounds, presentation->viewportShellModel.spec, viewportMetrics); request.viewportRequests.push_back(std::move(viewportRequest)); } return request; } 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) { UIEditorWorkspaceComposeFrame frame = {}; frame.dockHostLayout = BuildUIEditorDockHostLayout( bounds, panelRegistry, workspace, session, dockHostState, dockHostMetrics); const std::vector contentHostBindings = BuildContentHostBindings(panelRegistry, presentations); const UIEditorPanelContentHostRequest contentHostRequest = ResolveUIEditorPanelContentHostRequest( frame.dockHostLayout, panelRegistry, contentHostBindings); frame.contentHostFrame = UpdateUIEditorPanelContentHost( state.contentHostState, contentHostRequest, panelRegistry, contentHostBindings); TrimObsoleteViewportPresentationStates(state, panelRegistry, presentations); for (const UIEditorWorkspacePanelPresentationModel& presentation : presentations) { if (!SupportsExternalViewportPresentation(panelRegistry, presentation)) { continue; } const UIEditorPanelContentHostPanelState* contentHostPanelState = FindUIEditorPanelContentHostPanelState(frame.contentHostFrame, presentation.panelId); if (contentHostPanelState == nullptr || !contentHostPanelState->mounted) { ResetHiddenViewportPresentationState(state, presentation.panelId); continue; } UIEditorWorkspacePanelPresentationState& panelState = EnsurePanelState(state, presentation.panelId); UIEditorWorkspaceViewportComposeFrame viewportFrame = {}; viewportFrame.panelId = presentation.panelId; viewportFrame.bounds = contentHostPanelState->bounds; viewportFrame.viewportShellModel = presentation.viewportShellModel; viewportFrame.viewportShellFrame = UpdateUIEditorViewportShell( panelState.viewportShellState, contentHostPanelState->bounds, presentation.viewportShellModel, inputEvents, viewportMetrics); frame.viewportFrames.push_back(std::move(viewportFrame)); } return frame; } 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); } 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); } } // namespace XCEngine::UI::Editor