Files
XCEngine/new_editor/app/Composition/EditorContext.cpp

377 lines
12 KiB
C++

#include "EditorContext.h"
#include "Composition/EditorShellAssetBuilder.h"
#include "Scene/EditorSceneRuntime.h"
#include "Composition/EditorPanelIds.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <sstream>
#include <utility>
namespace XCEngine::UI::Editor::App {
namespace {
using ::XCEngine::UI::Editor::BuildEditorShellShortcutManager;
using ::XCEngine::UI::Editor::UIEditorWorkspacePanelPresentationModel;
using ::XCEngine::UI::Editor::AppendUIEditorRuntimeTrace;
std::string ComposeStatusText(
std::string_view status,
std::string_view message) {
if (status.empty()) {
return std::string(message);
}
if (message.empty()) {
return std::string(status);
}
return std::string(status) + ": " + std::string(message);
}
UIEditorWorkspacePanelPresentationModel* FindMutablePresentation(
std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
std::string_view panelId) {
for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) {
if (presentation.panelId == panelId) {
return &presentation;
}
}
return nullptr;
}
} // namespace
bool EditorContext::Initialize(const std::filesystem::path& repoRoot) {
AppendUIEditorRuntimeTrace("startup", "EditorContext::Initialize begin");
m_shellAsset = BuildEditorApplicationShellAsset(repoRoot);
AppendUIEditorRuntimeTrace("startup", "BuildEditorApplicationShellAsset complete");
m_shellValidation = ValidateEditorShellAsset(m_shellAsset);
AppendUIEditorRuntimeTrace(
"startup",
std::string("ValidateEditorShellAsset complete valid=") +
(m_shellValidation.IsValid() ? "1" : "0"));
if (!m_shellValidation.IsValid()) {
return false;
}
m_session = {};
m_session.repoRoot = repoRoot;
m_session.projectRoot = (repoRoot / "project").lexically_normal();
m_commandFocusService = {};
m_selectionService = {};
m_projectRuntime.Reset();
AppendUIEditorRuntimeTrace("startup", "EditorProjectRuntime::Initialize begin");
m_projectRuntime.Initialize(repoRoot);
AppendUIEditorRuntimeTrace("startup", "EditorProjectRuntime::Initialize end");
m_projectRuntime.BindSelectionService(&m_selectionService);
m_sceneRuntime.Reset();
AppendUIEditorRuntimeTrace("startup", "EditorSceneRuntime::Initialize begin");
m_sceneRuntime.Initialize(m_session.projectRoot);
AppendUIEditorRuntimeTrace("startup", "EditorSceneRuntime::Initialize end");
m_sceneRuntime.BindSelectionService(&m_selectionService);
ResetEditorColorPickerToolState(m_colorPickerToolState);
SyncSessionFromSelectionService();
m_hostCommandBridge.BindSession(m_session);
m_hostCommandBridge.BindCommandFocusService(m_commandFocusService);
SyncSessionFromCommandFocusService();
m_shortcutManager = BuildEditorShellShortcutManager(m_shellAsset);
m_shortcutManager.SetHostCommandHandler(&m_hostCommandBridge);
m_shellServices = {};
m_shellServices.commandDispatcher = &m_shortcutManager.GetCommandDispatcher();
m_shellServices.shortcutManager = &m_shortcutManager;
m_lastStatus.clear();
m_lastMessage.clear();
SetReadyStatus();
AppendUIEditorRuntimeTrace("startup", "EditorContext::Initialize end");
return true;
}
void EditorContext::AttachTextMeasurer(
const UIEditorTextMeasurer& textMeasurer) {
m_shellServices.textMeasurer = &textMeasurer;
}
void EditorContext::SetSystemInteractionHost(Ports::SystemInteractionPort* systemInteractionHost) {
m_systemInteractionHost = systemInteractionHost;
}
void EditorContext::BindEditCommandRoutes(
EditorEditCommandRoute* hierarchyRoute,
EditorEditCommandRoute* projectRoute,
EditorEditCommandRoute* sceneRoute,
EditorEditCommandRoute* inspectorRoute) {
m_hostCommandBridge.BindEditCommandRoutes(
hierarchyRoute,
projectRoute,
sceneRoute,
inspectorRoute);
}
void EditorContext::SetExitRequestHandler(std::function<void()> handler) {
m_hostCommandBridge.SetExitRequestHandler(std::move(handler));
}
void EditorContext::SyncSessionFromWorkspace(
const UIEditorWorkspaceController& workspaceController) {
SyncEditorSessionFromWorkspace(m_session, workspaceController);
SyncSessionFromCommandFocusService();
}
bool EditorContext::IsValid() const {
return m_shellValidation.IsValid();
}
const std::string& EditorContext::GetValidationMessage() const {
return m_shellValidation.message;
}
const EditorShellAsset& EditorContext::GetShellAsset() const {
return m_shellAsset;
}
const EditorSession& EditorContext::GetSession() const {
return m_session;
}
EditorCommandFocusService& EditorContext::GetCommandFocusService() {
return m_commandFocusService;
}
const EditorCommandFocusService& EditorContext::GetCommandFocusService() const {
return m_commandFocusService;
}
EditorProjectRuntime& EditorContext::GetProjectRuntime() {
return m_projectRuntime;
}
const EditorProjectRuntime& EditorContext::GetProjectRuntime() const {
return m_projectRuntime;
}
EditorSceneRuntime& EditorContext::GetSceneRuntime() {
return m_sceneRuntime;
}
const EditorSceneRuntime& EditorContext::GetSceneRuntime() const {
return m_sceneRuntime;
}
EditorColorPickerToolState& EditorContext::GetColorPickerToolState() {
return m_colorPickerToolState;
}
const EditorColorPickerToolState& EditorContext::GetColorPickerToolState() const {
return m_colorPickerToolState;
}
void EditorContext::SetSelection(EditorSelectionState selection) {
m_selectionService.SetSelection(std::move(selection));
SyncSessionFromSelectionService();
}
void EditorContext::ClearSelection() {
m_selectionService.ClearSelection();
SyncSessionFromSelectionService();
}
void EditorContext::SyncSessionFromSelectionService() {
m_session.selection = m_selectionService.GetSelection();
}
void EditorContext::SyncSessionFromCommandFocusService() {
m_session.activeRoute = m_commandFocusService.ResolveRoute(
ResolveEditorActionRoute(m_session.activePanelId));
}
Ports::SystemInteractionPort* EditorContext::GetSystemInteractionHost() {
return m_systemInteractionHost;
}
const Ports::SystemInteractionPort* EditorContext::GetSystemInteractionHost() const {
return m_systemInteractionHost;
}
UIEditorWorkspaceController EditorContext::BuildWorkspaceController() const {
return UIEditorWorkspaceController(
m_shellAsset.panelRegistry,
m_shellAsset.workspace,
m_shellAsset.workspaceSession);
}
const UIEditorShellInteractionServices& EditorContext::GetShellServices() const {
return m_shellServices;
}
UIEditorShellInteractionDefinition EditorContext::BuildShellDefinition(
const UIEditorWorkspaceController& workspaceController,
std::string_view captureText,
EditorShellVariant variant) const {
UIEditorShellInteractionDefinition definition =
BuildEditorApplicationShellInteractionDefinition(
m_shellAsset,
workspaceController,
ComposeStatusText(m_lastStatus, m_lastMessage),
captureText,
variant);
if (UIEditorWorkspacePanelPresentationModel* scenePresentation =
FindMutablePresentation(definition.workspacePresentations, kScenePanelId);
scenePresentation != nullptr) {
scenePresentation->viewportShellModel.spec.chrome.showTopBar = true;
scenePresentation->viewportShellModel.spec.chrome.topBarHeight = 24.0f;
scenePresentation->viewportShellModel.spec.chrome.title = {};
scenePresentation->viewportShellModel.spec.chrome.subtitle = {};
scenePresentation->viewportShellModel.spec.toolItems.clear();
scenePresentation->viewportShellModel.spec.visualState.hoveredToolIndex =
Widgets::UIEditorViewportSlotInvalidIndex;
scenePresentation->viewportShellModel.spec.visualState.activeToolIndex =
Widgets::UIEditorViewportSlotInvalidIndex;
}
return definition;
}
std::string EditorContext::DescribeWorkspaceState(
const UIEditorWorkspaceController& workspaceController,
const UIEditorShellInteractionState& interactionState) const {
std::ostringstream stream = {};
stream << "active=" << workspaceController.GetWorkspace().activePanelId;
const auto visiblePanels =
CollectUIEditorWorkspaceVisiblePanels(
workspaceController.GetWorkspace(),
workspaceController.GetSession());
stream << " visible=[";
for (std::size_t index = 0; index < visiblePanels.size(); ++index) {
if (index > 0u) {
stream << ',';
}
stream << visiblePanels[index].panelId;
}
stream << ']';
const auto& dockState =
interactionState.workspaceInteractionState.dockHostInteractionState;
stream << " dragNode=" << dockState.activeTabDragNodeId;
stream << " dragPanel=" << dockState.activeTabDragPanelId;
if (dockState.dockHostState.dropPreview.visible) {
stream << " dropTarget=" << dockState.dockHostState.dropPreview.targetNodeId;
}
return stream.str();
}
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
namespace {
constexpr std::size_t kMaxConsoleEntries = 256u;
std::string ResolveViewportStatusMessage(
const UIEditorShellInteractionResult& result) {
if (result.viewportInputFrame.captureStarted) {
return "Viewport capture started.";
}
if (result.viewportInputFrame.captureEnded) {
return "Viewport capture ended.";
}
if (result.viewportInputFrame.focusGained) {
return "Viewport focused.";
}
if (result.viewportInputFrame.focusLost) {
return "Viewport focus lost.";
}
if (result.viewportInputFrame.pointerPressedInside) {
return "Viewport pointer down.";
}
if (result.viewportInputFrame.pointerReleasedInside) {
return "Viewport pointer up.";
}
if (result.viewportInputFrame.pointerMoved) {
return "Viewport pointer move.";
}
if (result.viewportInputFrame.wheelDelta != 0.0f) {
return "Viewport wheel.";
}
return {};
}
} // namespace
void EditorContext::SetReadyStatus() {
SetStatus("Ready", "Application shell loaded.");
}
void EditorContext::SetStatus(
std::string status,
std::string message) {
if (m_lastStatus != status || m_lastMessage != message) {
AppendConsoleEntry(status, message);
}
m_lastStatus = std::move(status);
m_lastMessage = std::move(message);
}
void EditorContext::UpdateStatusFromShellResult(
const UIEditorWorkspaceController& workspaceController,
const UIEditorShellInteractionResult& result) {
(void)workspaceController;
if (result.commandDispatched) {
SetStatus(
std::string(GetUIEditorCommandDispatchStatusName(result.commandDispatchResult.status)),
result.commandDispatchResult.message.empty()
? result.commandDispatchResult.displayName
: result.commandDispatchResult.message);
return;
}
if (result.workspaceResult.dockHostResult.layoutChanged) {
SetStatus("Layout", result.workspaceResult.dockHostResult.layoutResult.message);
return;
}
if (result.workspaceResult.dockHostResult.commandExecuted) {
SetStatus("Workspace", result.workspaceResult.dockHostResult.commandResult.message);
return;
}
if (!result.viewportPanelId.empty()) {
std::string message = ResolveViewportStatusMessage(result);
if (!message.empty()) {
SetStatus(result.viewportPanelId, std::move(message));
}
return;
}
if (!result.menuMutation.changed) {
return;
}
if (!result.itemId.empty() && !result.menuMutation.openedPopupId.empty()) {
SetStatus("Menu", result.itemId + " opened child popup.");
} else if (!result.menuId.empty() && !result.menuMutation.openedPopupId.empty()) {
SetStatus("Menu", result.menuId + " opened.");
} else {
SetStatus("Menu", "Popup chain dismissed.");
}
}
void EditorContext::AppendConsoleEntry(
std::string channel,
std::string message) {
EditorConsoleEntry entry = {};
entry.channel = std::move(channel);
entry.message = std::move(message);
m_session.consoleEntries.push_back(std::move(entry));
if (m_session.consoleEntries.size() > kMaxConsoleEntries) {
m_session.consoleEntries.erase(m_session.consoleEntries.begin());
}
}
} // namespace XCEngine::UI::Editor::App