487 lines
15 KiB
C++
487 lines
15 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 "Product/EditorProductManifest.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 = {};
|
|
};
|
|
|
|
std::unique_ptr<EditorWorkspacePanel> CreateWorkspacePanelRuntime(
|
|
const EditorProductPanelDescriptor& panel) {
|
|
switch (panel.runtimeKind) {
|
|
case EditorProductPanelRuntimeKind::Console:
|
|
return std::make_unique<ConsoleWorkspacePanel>();
|
|
case EditorProductPanelRuntimeKind::Hierarchy:
|
|
return std::make_unique<HierarchyWorkspacePanel>();
|
|
case EditorProductPanelRuntimeKind::Inspector:
|
|
return std::make_unique<InspectorWorkspacePanel>();
|
|
case EditorProductPanelRuntimeKind::Project:
|
|
return std::make_unique<ProjectWorkspacePanel>();
|
|
case EditorProductPanelRuntimeKind::Scene:
|
|
return std::make_unique<SceneWorkspacePanel>();
|
|
case EditorProductPanelRuntimeKind::None:
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
EditorWorkspacePanelRuntimeSet CreateEditorWorkspacePanelRuntimeSet() {
|
|
EditorWorkspacePanelRuntimeSet panels = {};
|
|
for (const EditorProductPanelDescriptor& panel : GetEditorProductPanels()) {
|
|
if (std::unique_ptr<EditorWorkspacePanel> runtime =
|
|
CreateWorkspacePanelRuntime(panel);
|
|
runtime != nullptr) {
|
|
panels.AddPanel(std::move(runtime));
|
|
}
|
|
}
|
|
return panels;
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::App
|