Files
XCEngine/editor/app/Features/EditorWorkspacePanelRegistry.cpp

465 lines
14 KiB
C++

#include "EditorWorkspacePanelRegistry.h"
#include "Panels/EditorPanelIds.h"
#include "Console/ConsolePanel.h"
#include "Hierarchy/HierarchyPanel.h"
#include "Inspector/InspectorPanel.h"
#include "Project/ProjectPanel.h"
#include "Scene/SceneEditCommandRoute.h"
#include "Scene/SceneViewportFeature.h"
#include <XCEditor/Panels/UIEditorHostedPanelDispatch.h>
#include <memory>
#include <sstream>
namespace XCEngine::UI::Editor::App {
namespace {
constexpr int kSceneUpdatePriority = 0;
constexpr int kHierarchyUpdatePriority = 10;
constexpr int kProjectUpdatePriority = 20;
constexpr int kInspectorUpdatePriority = 30;
constexpr int kConsoleUpdatePriority = 40;
const UIEditorHostedPanelDispatchEntry& ResolveHostedPanelDispatchEntry(
const UIEditorHostedPanelDispatchFrame& dispatchFrame,
std::string_view panelId) {
static const UIEditorHostedPanelDispatchEntry kEmptyEntry = {};
if (const UIEditorHostedPanelDispatchEntry* entry =
FindUIEditorHostedPanelDispatchEntry(dispatchFrame, panelId);
entry != nullptr) {
return *entry;
}
return kEmptyEntry;
}
std::string_view DescribeProjectItemKind(ProjectBrowserModel::ItemKind kind) {
switch (kind) {
case ProjectBrowserModel::ItemKind::Folder:
return "Folder";
case ProjectBrowserModel::ItemKind::Scene:
return "Scene";
case ProjectBrowserModel::ItemKind::Model:
return "Model";
case ProjectBrowserModel::ItemKind::Material:
return "Material";
case ProjectBrowserModel::ItemKind::Texture:
return "Texture";
case ProjectBrowserModel::ItemKind::Script:
return "Script";
case ProjectBrowserModel::ItemKind::File:
default:
return "File";
}
}
std::string DescribeProjectPanelEvent(const ProjectPanel::Event& event) {
std::ostringstream stream = {};
switch (event.kind) {
case ProjectPanel::EventKind::AssetSelected:
stream << "AssetSelected";
break;
case ProjectPanel::EventKind::AssetSelectionCleared:
stream << "AssetSelectionCleared";
break;
case ProjectPanel::EventKind::FolderNavigated:
stream << "FolderNavigated";
break;
case ProjectPanel::EventKind::AssetOpened:
stream << "AssetOpened";
break;
case ProjectPanel::EventKind::RenameRequested:
stream << "RenameRequested";
break;
case ProjectPanel::EventKind::ContextMenuRequested:
stream << "ContextMenuRequested";
break;
case ProjectPanel::EventKind::None:
default:
stream << "None";
break;
}
stream << " source=";
switch (event.source) {
case ProjectPanel::EventSource::Tree:
stream << "Tree";
break;
case ProjectPanel::EventSource::Breadcrumb:
stream << "Breadcrumb";
break;
case ProjectPanel::EventSource::GridPrimary:
stream << "GridPrimary";
break;
case ProjectPanel::EventSource::GridDoubleClick:
stream << "GridDoubleClick";
break;
case ProjectPanel::EventSource::GridSecondary:
stream << "GridSecondary";
break;
case ProjectPanel::EventSource::GridDrag:
stream << "GridDrag";
break;
case ProjectPanel::EventSource::Command:
stream << "Command";
break;
case ProjectPanel::EventSource::Background:
stream << "Background";
break;
case ProjectPanel::EventSource::None:
default:
stream << "None";
break;
}
if (!event.itemId.empty()) {
stream << " item=" << event.itemId;
}
if (!event.displayName.empty()) {
stream << " label=" << event.displayName;
}
if (!event.itemId.empty()) {
stream << " kind=" << DescribeProjectItemKind(event.itemKind);
}
return stream.str();
}
std::string DescribeHierarchyPanelEvent(const HierarchyPanel::Event& event) {
std::ostringstream stream = {};
switch (event.kind) {
case HierarchyPanel::EventKind::SelectionChanged:
stream << "SelectionChanged";
break;
case HierarchyPanel::EventKind::Reparented:
stream << "Reparented";
break;
case HierarchyPanel::EventKind::MovedToRoot:
stream << "MovedToRoot";
break;
case HierarchyPanel::EventKind::RenameRequested:
stream << "RenameRequested";
break;
case HierarchyPanel::EventKind::None:
default:
stream << "None";
break;
}
if (!event.itemId.empty()) {
stream << " item=" << event.itemId;
}
if (!event.targetItemId.empty()) {
stream << " target=" << event.targetItemId;
}
if (!event.label.empty()) {
stream << " label=" << event.label;
}
return stream.str();
}
class ConsoleWorkspacePanel final : public EditorWorkspacePanel {
public:
std::string_view GetPanelId() const override {
return kConsolePanelId;
}
std::string_view GetDrawListId() const override {
return "XCEditorPanel.Console";
}
EditorActionRoute GetActionRoute() const override {
return EditorActionRoute::Console;
}
EditorWorkspacePanelUpdatePhase GetUpdatePhase() const override {
return EditorWorkspacePanelUpdatePhase::AfterCommandFocusSync;
}
int GetUpdatePriority() const override {
return kConsoleUpdatePriority;
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.Update(
context.services.session,
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()));
}
void Append(::XCEngine::UI::UIDrawList& drawList) const override {
m_panel.Append(drawList);
}
private:
ConsolePanel m_panel = {};
};
class HierarchyWorkspacePanel final : public EditorWorkspacePanel {
public:
std::string_view GetPanelId() const override {
return kHierarchyPanelId;
}
std::string_view GetDrawListId() const override {
return "XCEditorPanel.Hierarchy";
}
EditorActionRoute GetActionRoute() const override {
return EditorActionRoute::Hierarchy;
}
int GetUpdatePriority() const override {
return kHierarchyUpdatePriority;
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
m_panel.SetIconService(&context.iconService);
m_panel.SetTextMeasurer(&context.textMeasurer);
m_panel.Initialize();
}
void ResetInteractionState() override {
m_panel.ResetInteractionState();
}
void PrepareForShellDefinition(
EditorPanelServices& services,
UIEditorWorkspaceController&) override {
m_panel.SetSceneRuntime(&services.sceneRuntime);
m_panel.SetCommandFocusService(&services.commandFocusService);
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.Update(
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()),
context.hostedContentEvents);
}
void Append(::XCEngine::UI::UIDrawList& drawList) const override {
m_panel.Append(drawList);
}
bool HasActivePointerCapture() const override {
return m_panel.HasActivePointerCapture();
}
EditorEditCommandRoute* GetEditCommandRoute() override {
return &m_panel;
}
std::vector<EditorWorkspacePanelFrameEvent> CollectFrameEvents() const override {
std::vector<EditorWorkspacePanelFrameEvent> events = {};
for (const HierarchyPanel::Event& event : m_panel.GetFrameEvents()) {
events.push_back(EditorWorkspacePanelFrameEvent{
.status = std::string(kHierarchyPanelTitle),
.traceChannel = std::string(kHierarchyPanelId),
.message = DescribeHierarchyPanelEvent(event),
});
}
return events;
}
private:
HierarchyPanel m_panel = {};
};
class InspectorWorkspacePanel final : public EditorWorkspacePanel {
public:
std::string_view GetPanelId() const override {
return kInspectorPanelId;
}
std::string_view GetDrawListId() const override {
return "XCEditorPanel.Inspector";
}
EditorActionRoute GetActionRoute() const override {
return EditorActionRoute::Inspector;
}
int GetUpdatePriority() const override {
return kInspectorUpdatePriority;
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.SetCommandFocusService(&context.services.commandFocusService);
m_panel.Update(
context.services,
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()),
context.hostedContentEvents);
}
void Append(::XCEngine::UI::UIDrawList& drawList) const override {
m_panel.Append(drawList);
}
EditorEditCommandRoute* GetEditCommandRoute() override {
return &m_panel;
}
private:
InspectorPanel m_panel = {};
};
class ProjectWorkspacePanel final : public EditorWorkspacePanel {
public:
std::string_view GetPanelId() const override {
return kProjectPanelId;
}
std::string_view GetDrawListId() const override {
return "XCEditorPanel.Project";
}
EditorActionRoute GetActionRoute() const override {
return EditorActionRoute::Project;
}
int GetUpdatePriority() const override {
return kProjectUpdatePriority;
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
m_panel.SetIconService(&context.iconService);
m_panel.SetTextMeasurer(&context.textMeasurer);
}
void ResetInteractionState() override {
m_panel.ResetInteractionState();
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_panel.SetProjectRuntime(&context.services.projectRuntime);
m_panel.SetCommandFocusService(&context.services.commandFocusService);
m_panel.SetSystemInteractionHost(context.services.systemInteractionHost);
m_panel.Update(
ResolveHostedPanelDispatchEntry(
context.shellFrame.hostedPanelDispatchFrame,
GetPanelId()),
context.hostedContentEvents);
}
void Append(::XCEngine::UI::UIDrawList& drawList) const override {
m_panel.Append(drawList);
}
bool HasActivePointerCapture() const override {
return m_panel.HasActivePointerCapture();
}
EditorWorkspacePanelCursorKind GetCursorKind() const override {
switch (m_panel.GetCursorKind()) {
case ProjectPanel::CursorKind::ResizeEW:
return EditorWorkspacePanelCursorKind::ResizeEW;
case ProjectPanel::CursorKind::Arrow:
default:
return EditorWorkspacePanelCursorKind::Arrow;
}
}
EditorEditCommandRoute* GetEditCommandRoute() override {
return &m_panel;
}
std::vector<EditorWorkspacePanelFrameEvent> CollectFrameEvents() const override {
std::vector<EditorWorkspacePanelFrameEvent> events = {};
for (const ProjectPanel::Event& event : m_panel.GetFrameEvents()) {
events.push_back(EditorWorkspacePanelFrameEvent{
.status = std::string(kProjectPanelTitle),
.traceChannel = std::string(kProjectPanelId),
.message = DescribeProjectPanelEvent(event),
});
}
return events;
}
private:
ProjectPanel m_panel = {};
};
class SceneWorkspacePanel final : public EditorWorkspacePanel {
public:
std::string_view GetPanelId() const override {
return kScenePanelId;
}
std::string_view GetDrawListId() const override {
return "XCEditorPanel.SceneOverlay";
}
EditorActionRoute GetActionRoute() const override {
return EditorActionRoute::Scene;
}
int GetUpdatePriority() const override {
return kSceneUpdatePriority;
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
if (context.sceneViewportRuntime != nullptr) {
m_feature.Initialize(
&context.iconService,
*context.sceneViewportRuntime);
}
}
void Shutdown(const EditorWorkspacePanelShutdownContext& context) override {
(void)context;
m_feature.Shutdown();
m_commandRoute.BindSceneRuntime(nullptr);
}
void ResetInteractionState() override {
m_feature.ResetInteractionState();
}
void PrepareForShellDefinition(
EditorPanelServices& services,
UIEditorWorkspaceController&) override {
m_commandRoute.BindSceneRuntime(&services.sceneRuntime);
m_feature.SetCommandFocusService(&services.commandFocusService);
m_feature.SyncRenderRequest(services.sceneRuntime);
}
void Update(const EditorWorkspacePanelUpdateContext& context) override {
m_feature.Update(
context.services.sceneRuntime,
context.shellInteractionState.workspaceInteractionState.composeState,
context.shellFrame.workspaceInteractionFrame.composeFrame);
}
void Append(::XCEngine::UI::UIDrawList& drawList) const override {
m_feature.Append(drawList);
}
EditorEditCommandRoute* GetEditCommandRoute() override {
return &m_commandRoute;
}
private:
SceneViewportFeature m_feature = {};
SceneEditCommandRoute m_commandRoute = {};
};
} // namespace
EditorWorkspacePanelRuntimeSet CreateEditorWorkspacePanelRuntimeSet() {
EditorWorkspacePanelRuntimeSet panels = {};
panels.AddPanel(std::make_unique<ConsoleWorkspacePanel>());
panels.AddPanel(std::make_unique<HierarchyWorkspacePanel>());
panels.AddPanel(std::make_unique<InspectorWorkspacePanel>());
panels.AddPanel(std::make_unique<ProjectWorkspacePanel>());
panels.AddPanel(std::make_unique<SceneWorkspacePanel>());
return panels;
}
} // namespace XCEngine::UI::Editor::App