Files
XCEngine/new_editor/src/Workspace/UIEditorWorkspaceCompose.cpp

381 lines
14 KiB
C++

#include <XCEditor/Workspace/UIEditorWorkspaceCompose.h>
#include <algorithm>
#include <utility>
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<UIEditorWorkspacePanelPresentationModel>& 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<UIEditorWorkspacePanelPresentationModel>& 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<UIEditorWorkspacePanelPresentationModel>& 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<UIEditorWorkspacePanelPresentationModel>& 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<UIEditorWorkspacePanelPresentationModel>& 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<UIEditorWorkspacePanelPresentationModel>& 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<std::string> 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