381 lines
14 KiB
C++
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
|