Files
XCEngine/editor/app/Composition/EditorShellRuntime.cpp

292 lines
11 KiB
C++

#include "EditorShellRuntime.h"
#include "UiTextureHost.h"
#include "ViewportRenderHost.h"
#include <XCEditor/Shell/UIEditorShellCapturePolicy.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <cassert>
#include <utility>
namespace XCEngine::UI::Editor::App {
EditorShellRuntime::EditorShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices,
UIEditorShortcutManager shortcutManager,
EditorHostCommandBridge::RuntimeCommandOwner& runtimeCommandOwner,
std::function<void()> requestExit)
: m_iconService(std::move(iconService))
, m_viewportRuntimeServices(std::move(viewportRuntimeServices))
, m_workspacePanels(std::move(workspacePanels))
, m_shortcutManager(std::move(shortcutManager)) {
m_hostCommandBridge.BindRuntimeCommandOwner(&runtimeCommandOwner);
m_hostCommandBridge.SetExitRequestHandler(std::move(requestExit));
m_shortcutManager.SetHostCommandHandler(&m_hostCommandBridge);
m_shellServices.commandDispatcher = &m_shortcutManager.GetCommandDispatcher();
m_shellServices.shortcutManager = &m_shortcutManager;
}
void EditorShellRuntime::Initialize(
const EditorRuntimePaths& runtimePaths,
Rendering::Host::UiTextureHost& textureHost,
Host::EditorHostResourceService& resourceService,
UIEditorTextMeasurer& textMeasurer,
SceneViewportEngineBridge& sceneViewportEngineBridge,
GameViewportEngineBridge& gameViewportEngineBridge,
EditorShaderProvider& shaderProvider) {
assert(m_iconService != nullptr);
assert(m_viewportRuntimeServices != nullptr);
if (m_iconService == nullptr || m_viewportRuntimeServices == nullptr) {
return;
}
m_iconService->Initialize(textureHost, resourceService);
m_viewportRuntimeServices->Initialize(
runtimePaths,
sceneViewportEngineBridge,
gameViewportEngineBridge,
shaderProvider);
m_shellServices.textMeasurer = &textMeasurer;
m_workspacePanels.Initialize(
EditorWorkspacePanelInitializationContext{
.runtimePaths = runtimePaths,
.textMeasurer = textMeasurer,
.iconService = *m_iconService,
.sceneViewportRuntime = &m_viewportRuntimeServices->GetSceneViewportRuntime(),
});
}
void EditorShellRuntime::AttachViewportWindowRenderer(Rendering::Host::ViewportRenderHost& renderer) {
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->AttachWindowRenderer(renderer);
}
}
void EditorShellRuntime::DetachViewportWindowRenderer() {
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->DetachWindowRenderer();
}
}
void EditorShellRuntime::SetViewportSurfacePresentationEnabled(bool enabled) {
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->SetSurfacePresentationEnabled(enabled);
}
}
void EditorShellRuntime::Shutdown() {
m_shellFrame = {};
m_shellInteractionState = {};
m_splitterDragCorrectionState = {};
m_traceEntries.clear();
m_workspacePanels.Shutdown(EditorWorkspacePanelShutdownContext{});
m_workspacePanels = {};
m_shellServices.textMeasurer = nullptr;
if (m_iconService != nullptr) {
m_iconService->Shutdown();
}
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->Shutdown();
}
}
void EditorShellRuntime::ResetInteractionState() {
m_shellFrame = {};
m_shellInteractionState = {};
m_splitterDragCorrectionState = {};
m_traceEntries.clear();
m_workspacePanels.ResetInteractionState();
}
const UIEditorShellInteractionFrame& EditorShellRuntime::GetShellFrame() const {
return m_shellFrame;
}
const UIEditorShellInteractionState& EditorShellRuntime::GetShellInteractionState() const {
return m_shellInteractionState;
}
const std::vector<WorkspaceTraceEntry>& EditorShellRuntime::GetTraceEntries() const {
return m_traceEntries;
}
const std::string& EditorShellRuntime::GetBuiltInIconError() const {
static const std::string kEmptyError = {};
return m_iconService != nullptr ? m_iconService->GetLastError() : kEmptyError;
}
void EditorShellRuntime::SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) {
m_shellInteractionState.workspaceInteractionState.dockHostInteractionState
.dockHostState.dropPreview = preview;
}
void EditorShellRuntime::ClearExternalDockHostDropPreview() {
m_shellInteractionState.workspaceInteractionState.dockHostInteractionState
.dockHostState.dropPreview = {};
}
EditorWorkspaceShellCursorKind EditorShellRuntime::GetHostedContentCursorKind() const {
switch (m_workspacePanels.GetHostedContentCursorKind()) {
case EditorWorkspacePanelCursorKind::ResizeEW:
return EditorWorkspaceShellCursorKind::ResizeEW;
case EditorWorkspacePanelCursorKind::Arrow:
default:
return EditorWorkspaceShellCursorKind::Arrow;
}
}
Widgets::UIEditorDockHostCursorKind EditorShellRuntime::GetDockCursorKind() const {
return Widgets::ResolveUIEditorDockHostCursorKind(
m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout);
}
bool EditorShellRuntime::TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const {
return TryResolveUIEditorDockHostTabDragHotspot(
m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout,
nodeId,
panelId,
point,
outHotspot);
}
UIEditorDockHostTabDropTarget EditorShellRuntime::ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const {
return ResolveUIEditorDockHostTabDropTarget(
m_shellFrame.workspaceInteractionFrame.dockHostFrame.layout,
point);
}
bool EditorShellRuntime::HasHostedContentCapture() const {
return m_workspacePanels.HasActivePointerCapture();
}
bool EditorShellRuntime::HasShellInteractiveCapture() const {
return HasActiveUIEditorShellInteractiveCapture(m_shellInteractionState);
}
bool EditorShellRuntime::HasInteractiveCapture() const {
return HasHostedContentCapture() || HasShellInteractiveCapture();
}
std::unique_ptr<EditorWorkspaceShellRuntime> CreateEditorWorkspaceShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices,
UIEditorShortcutManager shortcutManager,
EditorHostCommandBridge::RuntimeCommandOwner& runtimeCommandOwner,
std::function<void()> requestExit) {
return std::make_unique<EditorShellRuntime>(
std::move(workspacePanels),
std::move(iconService),
std::move(viewportRuntimeServices),
std::move(shortcutManager),
runtimeCommandOwner,
std::move(requestExit));
}
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
void EditorShellRuntime::RenderRequestedViewports(
EditorFrameServices& frameServices,
const ::XCEngine::Rendering::RenderContext& renderContext) {
if (m_viewportRuntimeServices != nullptr) {
frameServices.SyncSceneViewportRenderRequest(
m_viewportRuntimeServices->GetSceneViewportRuntime());
m_viewportRuntimeServices->RenderRequestedViewports(renderContext);
}
}
void EditorShellRuntime::Append(::XCEngine::UI::UIDrawData& drawData) const {
if (m_iconService == nullptr) {
return;
}
m_drawComposer.Append(
EditorShellDrawComposerContext{
.shellFrame = m_shellFrame,
.shellInteractionState = m_shellInteractionState,
.iconService = *m_iconService,
.workspacePanels = m_workspacePanels,
},
drawData);
}
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
void EditorShellRuntime::Update(
EditorFrameServices& frameServices,
UIEditorWorkspaceController& workspaceController,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
std::string_view captureText,
EditorShellVariant shellVariant,
bool useDetachedTitleBarTabStrip,
float detachedTitleBarTabHeight,
float detachedWindowChromeHeight) {
if (m_viewportRuntimeServices == nullptr) {
return;
}
m_hostCommandBridge.BindCommandFocusService(
m_workspacePanels.GetCommandFocusService());
m_hostCommandBridge.BindEditCommandRoutes(
m_workspacePanels.FindCommandRoute(EditorActionRoute::Hierarchy),
m_workspacePanels.FindCommandRoute(EditorActionRoute::Project),
m_workspacePanels.FindCommandRoute(EditorActionRoute::Scene),
m_workspacePanels.FindCommandRoute(EditorActionRoute::Inspector));
const auto buildDefinition = [&]() {
return m_sessionCoordinator.PrepareShellDefinition(
EditorShellSessionCoordinatorContext{
.frameServices = frameServices,
.workspaceController = workspaceController,
.captureText = captureText,
.shellVariant = shellVariant,
.workspacePanels = m_workspacePanels,
});
};
m_interactionEngine.Update(
EditorShellInteractionEngineContext{
.shellInteractionState = m_shellInteractionState,
.shellFrame = m_shellFrame,
.splitterDragCorrectionState = m_splitterDragCorrectionState,
.workspaceController = workspaceController,
.bounds = bounds,
.inputEvents = inputEvents,
.shellServices = m_shellServices,
.buildDefinition = buildDefinition,
.hostedContentCaptureActive = HasHostedContentCapture(),
.useDetachedTitleBarTabStrip = useDetachedTitleBarTabStrip,
.detachedTitleBarTabHeight = detachedTitleBarTabHeight,
.detachedWindowChromeHeight = detachedWindowChromeHeight,
.viewportRuntimeServices = *m_viewportRuntimeServices,
});
m_sessionCoordinator.FinalizeFrame(frameServices, workspaceController, m_shellFrame.result);
m_hostedPanelCoordinator.Update(
EditorShellHostedPanelCoordinatorContext{
.frameServices = frameServices,
.shellFrame = m_shellFrame,
.shellInteractionState = m_shellInteractionState,
.inputEvents = inputEvents,
.shellInteractiveCaptureActive = HasShellInteractiveCapture(),
.workspacePanels = m_workspacePanels,
});
m_traceEntries = frameServices.SyncWorkspacePanelFrameEvents(
m_workspacePanels.CollectFrameEvents());
}
} // namespace XCEngine::UI::Editor::App