Refactor editor rendering contracts

This commit is contained in:
2026-04-28 02:57:49 +08:00
parent 3bc0cfcf08
commit b1ae6c462d
47 changed files with 798 additions and 377 deletions

View File

@@ -48,9 +48,13 @@ incomplete:
code to load built-in PNGs, title-bar branding, or executable-relative
capture output paths.
- Scene viewport shader paths now flow through runtime initialization. The
scene viewport feature builds the paths from the runtime repo root and
viewport runtime service builds the paths from the runtime repo root and
injects them into the render service/pass bundle instead of letting render
passes infer source-tree paths from a compile-time repo-root macro.
- Editor icon and viewport runtime contracts now live under
`editor/app/Core/Assets` and `editor/app/Core/Viewport`. Concrete icon
loading, viewport host services, scene viewport rendering, render targets,
and object-id picking stay under `editor/app/Rendering`.
- Feature panels no longer use `Composition/EditorContext.h` directly. The
app-core and app feature/viewport test targets now exercise `XCEditorCore`
outside the executable host.
@@ -105,9 +109,13 @@ Completed boundary cuts:
- The private `editor/app` compatibility include root is gone from
`XCEditorCore` and `XCEditor`. App implementation files now include through
explicit module roots such as `app/Composition`, `app/Features`,
`app/Windowing`, `app/Rendering`, `app/Scene`, `app/Services`,
`app/Support`, `app/Host/Interfaces`, `app/Host/Win32`, and
`app/Host/D3D12`; only executable-host code consumes `app/Bootstrap`.
`app/Windowing`, `app/Scene`, `app/Services`, `app/Support`,
`app/Host/Interfaces`, `app/Host/Win32`, and `app/Host/D3D12`; only
executable-host code consumes `app/Bootstrap`.
- Concrete `app/Rendering/**` files now build through the
`XCEditorCoreRendering` object library. `XCEditorCore` consumes the object
files but does not expose `app/Rendering` to Composition, Features, or Core
sources.
- `editor_app_core_tests` now links `XCEditorCore` directly and uses explicit
app module include roots. Its initial suite covers host command routing,
project runtime, shell asset validation, project browser model, hierarchy
@@ -143,11 +151,13 @@ The refactor should converge on this shape:
```text
editor/app/
Core/
Assets/
Commands/
Panels/
Scene/
State/
UtilityWindows/
Viewport/
Windowing/
WorkspacePanels/
@@ -175,6 +185,10 @@ editor/app/
Win32/
D3D12/
Rendering/
Assets/
Viewport/
Bootstrap/
Support/
```
@@ -183,6 +197,12 @@ This is a convergence target, not a requirement to move every file at once.
The first cut should only move contracts that are already acting as global app
interfaces.
Same domain names under different layers are acceptable only when the layer
meaning is explicit and build-checked: `Core/Viewport` is the shared contract
surface, while `Rendering/Viewport` is the concrete implementation. If a
Composition or Feature file needs a viewport concept, it should include the
Core contract, not the concrete Rendering path.
## Dependency Rules
The final direction should be:
@@ -197,6 +217,12 @@ Within `XCEditorCore`:
`XCUIEditor`.
- `Composition` must not include concrete feature panel headers.
- `Features` may depend on `Core`, `Services`, and `XCUIEditor`.
- `Composition` and `Features` must not include concrete `app/Rendering/**`
headers. They should use `Core/Assets/EditorIconService.h` and
`Core/Viewport/**` contracts.
- `app/Rendering/**` may depend on `Core`, `Host/Interfaces`, `XCUIEditor`,
and engine renderer/editor support. It implements Core contracts and is wired
from `Application`.
- `Services` must not depend on `Features`.
- `State` must not depend on `Composition`.
- `Windowing` may depend on `Core`, `Composition` interfaces, and
@@ -458,7 +484,7 @@ not a rendering implementation detail. Keep future scene-to-viewport request
values under `Core/Scene` so scene services can build requests without taking
an `app/Rendering/**` include dependency.
- Scene viewport shader paths are runtime configuration now. Build them from
the runtime repo root in `SceneViewportFeature`, inject them into
the runtime repo root in the viewport runtime service, inject them into
`SceneViewportRenderService`, and keep grid/selection render passes from
inferring source-tree paths with compile-time macros or `__FILE__`.
@@ -554,8 +580,25 @@ Completed cuts:
scene viewport request contract without depending on `app/Rendering/**`, and
`editor_app_core_tests` no longer needs the app rendering include root to
validate scene runtime behavior.
- Scene viewport shader/resource paths are now injected from
`SceneViewportFeature` into `SceneViewportRenderService` and
- Editor icon contracts now live under
`editor/app/Core/Assets/EditorIconService.h`. `BuiltInIcons` remains the
concrete `editor/app/Rendering` implementation, and panels/tool overlays
resolve icons through the contract instead of loading resource files or
naming concrete icon storage.
- Viewport runtime contracts now live under `editor/app/Core/Viewport/**`.
`SceneViewportFeature` consumes `EditorSceneViewportRuntime`, while
`ViewportHostService` and `SceneViewportRenderService` stay concrete
rendering implementations behind `CreateEditorViewportRuntimeServices()`.
- `Application` injects `CreateEditorIconService()` and
`CreateEditorViewportRuntimeServices()` into `EditorShellRuntime`, making
the executable startup path the only place that names those concrete
rendering factories.
- `app/Rendering/**` now builds as `XCEditorCoreRendering`, a dedicated object
library consumed by `XCEditorCore`. This keeps rendering behavior in the
product core while preventing Composition/Features/Core from regaining an
`app/Rendering` include root.
- Scene viewport shader/resource paths are now injected from the viewport
runtime service into `SceneViewportRenderService` and
`SceneViewportRenderPassBundle`. The concrete grid and selection-outline
passes no longer depend on `XCUIEDITOR_REPO_ROOT` or `__FILE__` source-tree
fallback logic to find editor shaders.
@@ -615,6 +658,8 @@ The refactor is complete when:
- `XCEditor` executable source is limited to host startup and concrete
platform/render backend wiring.
- `Composition` no longer includes concrete feature panel headers.
- `Composition` and `Features` no longer include concrete `app/Rendering/**`
headers; icon and viewport use flows through Core contracts.
- `Windowing` no longer includes concrete composition runtime/state headers;
it depends on `Core/Windowing` composition interfaces instead.
- `Services` no longer include `Features/**`.

View File

@@ -35,8 +35,12 @@ change.
contracts under `app/Core` and `app/Host/Interfaces`.
- `XCEditorCore` also does not consume the whole `editor/app` root privately.
Its implementation include paths enumerate concrete app module roots such as
`app/Composition`, `app/Features`, `app/Windowing`, `app/Rendering`,
`app/Scene`, `app/Services`, and `app/Support`.
`app/Composition`, `app/Features`, `app/Windowing`, `app/Scene`,
`app/Services`, and `app/Support`.
- Concrete `app/Rendering/**` implementation builds as the
`XCEditorCoreRendering` object library. `XCEditorCore` consumes those object
files, but it does not publish or privately widen its include surface back to
`app/Rendering`.
- `XCEditorCore` and `XCEditor` require
`XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT=ON`; the root build defaults that
support on when either the core library or app executable is enabled.
@@ -71,8 +75,9 @@ change.
state contracts, panel IDs, shared window type contracts, host window
geometry/metrics, frame transfer requests, the panel-facing service view,
the windowing-facing frame-services/shell-runtime contracts,
scene-viewport request contracts, workspace-panel runtime interface, and
utility-window runtime/descriptors.
scene-viewport request contracts, icon-service and viewport-runtime
contracts, workspace-panel runtime interface, and utility-window
runtime/descriptors.
- `app/Host/Interfaces/` contains neutral host-facing contracts used across
editor core and executable host code: editor window host interfaces,
render-runtime factories, UI texture hosts, viewport render hosts, host
@@ -86,7 +91,9 @@ change.
- `app/Windowing/` owns window instances, content controllers, lifecycle,
workspace synchronization, and utility-window creation.
- `app/Rendering/` owns built-in icons, viewport render targets, object
picking, scene viewport passes, and viewport render services.
picking, scene viewport passes, and viewport render services. It is the
concrete implementation side of Core-owned editor icon and viewport runtime
contracts.
- `app/Features/` contains user-facing panels and editor tools: Hierarchy,
Scene viewport, Inspector, Project, Console, Color Picker, and component UI.
- `app/Features/EditorWorkspacePanelRegistry.*` is the concrete workspace
@@ -115,6 +122,11 @@ change.
shared value contracts in `app/Core`. Do not add new public app contracts
under concrete `app/Windowing`, `app/Rendering`, `app/Host/Win32`,
`app/Host/D3D12`, or legacy `app/Platform` paths.
- `app/Composition/**` and `app/Features/**` may depend on
`app/Core/Assets/EditorIconService.h` and `app/Core/Viewport/**`, but they
must not include concrete `app/Rendering/**` headers such as
`Assets/BuiltInIcons.h`, `Viewport/ViewportHostService.h`, or
`Viewport/SceneViewportRenderService.h`.
- `app/Windowing/**` may depend on `app/Core/Windowing` contracts such as
`EditorFrameServices` and `EditorWorkspaceShellRuntime`, but it must not
include concrete `app/Composition/EditorContext.h` or
@@ -166,17 +178,20 @@ change.
`UIEditorWorkspaceController` every frame. A live controller writes mutations
through to the authoritative window workspace state; a copied controller is
only a preview.
- `EditorShellRuntime` owns per-window interactive runtime state: viewport host
service, built-in icons, the workspace panel runtime set, shell interaction
state/frame, splitter correction state, trace entries, draw composer,
interaction engine, hosted panel coordinator, and session coordinator.
- `EditorShellRuntime` owns per-window interactive runtime state: injected
editor icon and viewport-runtime services, the workspace panel runtime set,
shell interaction state/frame, splitter correction state, trace entries,
draw composer, interaction engine, hosted panel coordinator, and session
coordinator.
- `EditorWorkspaceShellRuntime` is the windowing-facing shell runtime contract.
`EditorShellRuntime` is the current concrete implementation, and
`Application` injects it through the content factory instead of letting
`app/Windowing/**` construct or name the concrete type directly.
- The workspace shell runtime factory passed into windowing is intentionally
zero-argument. `Application` composes the concrete workspace-panel runtime
set with `EditorShellRuntime`; `app/Windowing/**` must not accept or call
set, `CreateEditorIconService()`, and
`CreateEditorViewportRuntimeServices()` with `EditorShellRuntime`;
`app/Windowing/**` must not accept or call
`EditorWorkspacePanelRuntimeSetFactory`.
- `EditorWindowRuntimeController` owns the content controller, render runtime,
screenshot controller, title-bar logo texture, text measurer access, DPI
@@ -288,18 +303,27 @@ inside pure shell/widget code.
- Scene and Game are `ViewportShell` presentations. The Scene panel is the
active editor viewport implementation; Game is registered as a viewport panel
but is not equivalent to the runtime game view yet.
- `SceneViewportFeature` owns `SceneViewportController` and
`SceneViewportRenderService`.
- `ViewportHostService` is the per-window manager for viewport requests,
render-target allocation, retirement, fallback clearing, and dispatch to the
attached `ViewportRenderHost`.
- `SceneViewportRenderService` renders scene content through the engine
renderer and owns object-id picking state. Keep editor picking/render support
behind `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT`.
- Core viewport contracts now live under `app/Core/Viewport/**`: shared
viewport frame/resource types, object-picking contracts, and the editor
scene/runtime service abstractions.
- `SceneViewportFeature` owns `SceneViewportController` and consumes the
injected `EditorSceneViewportRuntime` contract instead of constructing or
naming concrete rendering services.
- `ViewportHostService` is the concrete per-window implementation of
`EditorViewportRuntimeServices`. It manages viewport requests, render-target
allocation, retirement, fallback clearing, and dispatch to the attached
`ViewportRenderHost`.
- `SceneViewportRenderService` is the concrete `EditorSceneViewportRuntime`
implementation. It renders scene content through the engine renderer and
owns object-id picking state. Keep editor picking/render support behind
`XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT`.
- Core icon contracts now live under `app/Core/Assets/EditorIconService.h`.
`BuiltInIcons` is the concrete implementation, and scene/tool overlays must
resolve editor icons through that contract rather than probing
`editor/resources/Icons` directly.
- Scene viewport shader/resource paths are runtime data. Build them from the
startup/runtime repo root in `SceneViewportFeature`, pass them into
`SceneViewportRenderService`, and keep render passes free of compile-time
source-tree path discovery.
startup/runtime repo root inside the rendering runtime service and keep
render passes free of compile-time source-tree path discovery.
- D3D12 window rendering is behind the abstract
`Rendering::Host::EditorWindowRenderRuntime`; native startup surface data is
passed through the neutral
@@ -317,6 +341,10 @@ inside pure shell/widget code.
`EditorWorkspacePanel` adapter interface; do not include concrete feature
panel headers from `EditorShellRuntime`, `EditorShellHostedPanelCoordinator`,
`EditorShellDrawComposer`, or `EditorShellSessionCoordinator`.
- Add new icon/viewport cross-layer contracts under `app/Core/Assets` or
`app/Core/Viewport`. Keep concrete texture loading, render-target ownership,
viewport host wiring, and scene viewport rendering in `app/Rendering/**`,
then inject those implementations from `Application`.
- Add new workspace panels by updating the panel ID constants, panel registry,
default workspace model, shell presentation, workspace panel runtime adapter,
and command/menu entries together.
@@ -352,6 +380,10 @@ inside pure shell/widget code.
`app/Host/Interfaces`, `include`, and engine headers;
implementation files use explicit module roots instead of the app-wide
compatibility root.
- Concrete rendering stays behind the `XCEditorCoreRendering` object library.
`XCEditorCore` consumes the object files, while Composition/Features/Core
continue to see only `app/Core` contracts and never gain an `app/Rendering`
include root.
- App-facing unit tests follow the same rule. `editor_app_core_tests` uses
explicit module include roots and must not regain the whole `editor/app`
root to make stale tests compile.
@@ -362,6 +394,11 @@ inside pure shell/widget code.
- `XCEditor` is the thin executable host that wires `XCEditorCore` to concrete
Win32 and D3D12 implementations. Do not move concrete platform/render host
code into `XCEditorCore` without first introducing neutral host contracts.
- `Application` is also the composition root for concrete editor icon and
viewport runtime services. It wires `CreateEditorIconService()` and
`CreateEditorViewportRuntimeServices()` into
`CreateEditorWorkspaceShellRuntime(...)` so `app/Composition/**` and
`app/Features/**` do not take concrete `app/Rendering/**` dependencies.
- `app/Core/Windowing/EditorFrameServices.h` and
`app/Core/Windowing/EditorWorkspaceShellRuntime.h` are the current
composition-to-windowing contract boundary. `EditorContext` and
@@ -436,7 +473,11 @@ inside pure shell/widget code.
- `editor/app/Host/Win32/Windowing/EditorWindowMessageDispatcher.cpp`
- `editor/app/Host/Interfaces/EditorWindowRenderRuntime.h`
- `editor/app/Host/Interfaces/EditorWindowHostInterfaces.h`
- `editor/app/Core/Assets/EditorIconService.h`
- `editor/app/Core/Viewport/EditorViewportRuntimeServices.h`
- `editor/app/Core/Windowing/EditorWindowTransferRequests.h`
- `editor/app/Rendering/Assets/EditorIconServiceFactory.h`
- `editor/app/Rendering/Viewport/EditorViewportRuntimeServicesFactory.h`
- `editor/app/Rendering/Viewport/ViewportHostService.h`
- `tests/UI/Editor/unit/CMakeLists.txt`
- `tests/UI/Editor/smoke/CMakeLists.txt`
@@ -529,8 +570,18 @@ ownership rule.
`app/Host/Win32/Resources`, so `XCEditorCore` no longer consumes
`app/Bootstrap` or Win32 resource helpers to initialize built-in icons,
title-bar branding, or screenshot output roots.
- Scene viewport shader paths are now injected at runtime from
`SceneViewportFeature` into `SceneViewportRenderService` and its pass bundle.
- Concrete editor icons and scene viewport runtime services are now hidden
behind `Core/Assets/EditorIconService.h` and `Core/Viewport/**` contracts.
`Application` injects `CreateEditorIconService()` and
`CreateEditorViewportRuntimeServices()` into `EditorShellRuntime`, so
`app/Composition/**` and `app/Features/**` no longer include concrete
`app/Rendering/**` headers.
- `XCEditorCoreRendering` now builds `app/Rendering/**` as a dedicated object
library. That keeps concrete rendering implementation in the core product
build without reopening `app/Rendering` as an include root for
Composition/Features/Core.
- Scene viewport shader paths are now injected at runtime by the viewport
runtime service into `SceneViewportRenderService` and its pass bundle.
Grid/selection passes no longer infer source-tree shader paths through
`XCUIEDITOR_REPO_ROOT` or `__FILE__`.
- `Application` no longer resolves the editor repo root from a compile-time

View File

@@ -265,7 +265,9 @@ if(XCENGINE_BUILD_XCUI_EDITOR_CORE)
)
set(XCUI_EDITOR_APP_RENDERING_SOURCES
app/Rendering/Assets/EditorIconServiceFactory.cpp
app/Rendering/Assets/BuiltInIcons.cpp
app/Rendering/Viewport/EditorViewportRuntimeServicesFactory.cpp
app/Rendering/Viewport/Passes/SceneViewportGridPass.cpp
app/Rendering/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp
app/Rendering/Viewport/Passes/SceneViewportSelectedHelpersPass.cpp
@@ -289,13 +291,35 @@ if(XCENGINE_BUILD_XCUI_EDITOR_CORE)
${XCUI_EDITOR_APP_COMMAND_SOURCES}
${XCUI_EDITOR_APP_COMPOSITION_SOURCES}
${XCUI_EDITOR_APP_FEATURE_SOURCES}
${XCUI_EDITOR_APP_RENDERING_SOURCES}
${XCUI_EDITOR_APP_SUPPORT_SOURCES}
)
add_library(XCEditorCoreRendering OBJECT
${XCUI_EDITOR_APP_RENDERING_SOURCES}
)
target_include_directories(XCEditorCoreRendering
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/app/Core
${CMAKE_CURRENT_SOURCE_DIR}/app/Host/Interfaces
${CMAKE_CURRENT_SOURCE_DIR}/app/Rendering
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/engine/include
${CMAKE_SOURCE_DIR}/engine/third_party/stb
)
xcui_editor_apply_common_target_settings(XCEditorCoreRendering PRIVATE)
target_link_libraries(XCEditorCoreRendering PRIVATE
XCEngine
XCUIEditor
XCEngineRenderingEditorSupport
)
set(XCUI_EDITOR_CORE_SOURCES
${XCUI_EDITOR_APP_WINDOWING_SOURCES}
${XCUI_EDITOR_APP_CORE_SOURCES}
$<TARGET_OBJECTS:XCEditorCoreRendering>
)
add_library(XCEditorCore STATIC
@@ -312,7 +336,6 @@ if(XCENGINE_BUILD_XCUI_EDITOR_CORE)
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/app/Composition
${CMAKE_CURRENT_SOURCE_DIR}/app/Features
${CMAKE_CURRENT_SOURCE_DIR}/app/Rendering
${CMAKE_CURRENT_SOURCE_DIR}/app/Scene
${CMAKE_CURRENT_SOURCE_DIR}/app/Services
${CMAKE_CURRENT_SOURCE_DIR}/app/Support

View File

@@ -6,7 +6,9 @@
#include "EditorUtilityWindowRegistry.h"
#include "EditorWorkspacePanelRegistry.h"
#include "EditorWindowManager.h"
#include "Assets/EditorIconServiceFactory.h"
#include "Diagnostics/Win32CrashTrace.h"
#include "Viewport/EditorViewportRuntimeServicesFactory.h"
#include "System/Win32SystemInteractionHost.h"
#include "Resources/Win32EditorResourceService.h"
#include "Windowing/EditorWindow.h"
@@ -153,7 +155,9 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
std::make_unique<Host::D3D12EditorWindowRenderRuntimeFactory>();
App::EditorWorkspaceShellRuntimeFactory workspaceShellRuntimeFactory = []() {
return App::CreateEditorWorkspaceShellRuntime(
App::CreateEditorWorkspacePanelRuntimeSet());
App::CreateEditorWorkspacePanelRuntimeSet(),
App::CreateEditorIconService(),
App::CreateEditorViewportRuntimeServices());
};
m_windowManager = std::make_unique<App::EditorWindowManager>(
*m_editorContext,

View File

@@ -14,3 +14,13 @@ IDR_PNG_LOGO_ICON PNG "../resources/Icons/logo_icon.png"
IDR_PNG_PLAY_BUTTON_ICON PNG "../resources/Icons/play_button.png"
IDR_PNG_PAUSE_BUTTON_ICON PNG "../resources/Icons/pause_button.png"
IDR_PNG_STEP_BUTTON_ICON PNG "../resources/Icons/step_button.png"
IDR_PNG_VIEW_MOVE_TOOL_ICON PNG "../resources/Icons/view_move_tool.png"
IDR_PNG_VIEW_MOVE_TOOL_ACTIVE_ICON PNG "../resources/Icons/view_move_tool_on.png"
IDR_PNG_MOVE_TOOL_ICON PNG "../resources/Icons/move_tool.png"
IDR_PNG_MOVE_TOOL_ACTIVE_ICON PNG "../resources/Icons/move_tool_on.png"
IDR_PNG_ROTATE_TOOL_ICON PNG "../resources/Icons/rotate_tool.png"
IDR_PNG_ROTATE_TOOL_ACTIVE_ICON PNG "../resources/Icons/rotate_tool_on.png"
IDR_PNG_SCALE_TOOL_ICON PNG "../resources/Icons/scale_tool.png"
IDR_PNG_SCALE_TOOL_ACTIVE_ICON PNG "../resources/Icons/scale_tool_on.png"
IDR_PNG_TRANSFORM_TOOL_ICON PNG "../resources/Icons/transform_tool.png"
IDR_PNG_TRANSFORM_TOOL_ACTIVE_ICON PNG "../resources/Icons/transform_tool_on.png"

View File

@@ -14,3 +14,13 @@
#define IDR_PNG_PLAY_BUTTON_ICON 210
#define IDR_PNG_PAUSE_BUTTON_ICON 211
#define IDR_PNG_STEP_BUTTON_ICON 212
#define IDR_PNG_VIEW_MOVE_TOOL_ICON 213
#define IDR_PNG_VIEW_MOVE_TOOL_ACTIVE_ICON 214
#define IDR_PNG_MOVE_TOOL_ICON 215
#define IDR_PNG_MOVE_TOOL_ACTIVE_ICON 216
#define IDR_PNG_ROTATE_TOOL_ICON 217
#define IDR_PNG_ROTATE_TOOL_ACTIVE_ICON 218
#define IDR_PNG_SCALE_TOOL_ICON 219
#define IDR_PNG_SCALE_TOOL_ACTIVE_ICON 220
#define IDR_PNG_TRANSFORM_TOOL_ICON 221
#define IDR_PNG_TRANSFORM_TOOL_ACTIVE_ICON 222

View File

@@ -6,7 +6,7 @@
#include <utility>
#include "Panels/EditorPanelIds.h"
#include <XCEngine/Input/InputTypes.h>
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
namespace XCEngine::UI::Editor::App {

View File

@@ -1,7 +1,7 @@
#include "EditorShellDrawComposer.h"
#include "WorkspacePanels/EditorWorkspacePanelRuntime.h"
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
#include <XCEditor/Foundation/UIEditorTheme.h>
#include <XCEditor/Shell/UIEditorShellInteraction.h>
@@ -18,16 +18,16 @@ using ::XCEngine::UI::UIDrawList;
class BuiltInIconResolver final : public UIEditorShellIconResolver {
public:
explicit BuiltInIconResolver(const BuiltInIcons& icons)
: m_icons(icons) {}
explicit BuiltInIconResolver(const EditorIconService& iconService)
: m_iconService(iconService) {}
const ::XCEngine::UI::UITextureHandle* TryResolveIcon(
std::uint8_t iconKind) const override {
return &m_icons.Resolve(static_cast<BuiltInIconKind>(iconKind));
return &m_iconService.Resolve(static_cast<BuiltInIconKind>(iconKind));
}
private:
const BuiltInIcons& m_icons;
const EditorIconService& m_iconService;
};
UIEditorShellComposeModel BuildShellComposeModelFromFrame(
@@ -90,7 +90,7 @@ void EditorShellDrawComposer::Append(
const auto& palette = ResolveUIEditorShellInteractionPalette();
const UIEditorShellComposeModel shellComposeModel =
BuildShellComposeModelFromFrame(context.shellFrame);
const BuiltInIconResolver iconResolver(context.builtInIcons);
const BuiltInIconResolver iconResolver(context.iconService);
AppendDrawPacket(
drawData,

View File

@@ -11,13 +11,13 @@ struct UIEditorShellInteractionState;
namespace XCEngine::UI::Editor::App {
class BuiltInIcons;
class EditorIconService;
class EditorWorkspacePanelRuntimeSet;
struct EditorShellDrawComposerContext {
const UIEditorShellInteractionFrame& shellFrame;
const UIEditorShellInteractionState& shellInteractionState;
const BuiltInIcons& builtInIcons;
const EditorIconService& iconService;
const EditorWorkspacePanelRuntimeSet& workspacePanels;
};

View File

@@ -18,7 +18,7 @@ bool IsViewportPanel(std::string_view panelId) {
}
void ApplyViewportFrameToPresentation(
const ViewportFrame& viewportFrame,
const EditorViewportFrame& viewportFrame,
UIEditorWorkspacePanelPresentationModel& presentation) {
presentation.viewportShellModel.frame.texture = viewportFrame.texture;
presentation.viewportShellModel.frame.requestedSize = viewportFrame.requestedSize;
@@ -28,7 +28,7 @@ void ApplyViewportFrameToPresentation(
}
void ApplyViewportFrameToShellModel(
const ViewportFrame& viewportFrame,
const EditorViewportFrame& viewportFrame,
UIEditorViewportShellModel& shellModel) {
shellModel.frame.texture = viewportFrame.texture;
shellModel.frame.requestedSize = viewportFrame.requestedSize;
@@ -51,7 +51,7 @@ UIEditorWorkspacePanelPresentationModel* FindMutableWorkspacePresentation(
void ApplyViewportFramesToShellFrame(
UIEditorShellInteractionFrame& shellFrame,
ViewportHostService& viewportHostService) {
EditorViewportRuntimeServices& viewportRuntimeServices) {
auto applyToViewportFrames =
[&](std::vector<UIEditorWorkspaceViewportComposeFrame>& viewportFrames) {
for (UIEditorWorkspaceViewportComposeFrame& viewportComposeFrame : viewportFrames) {
@@ -59,8 +59,8 @@ void ApplyViewportFramesToShellFrame(
continue;
}
const ViewportFrame viewportFrame =
viewportHostService.RequestViewport(
const EditorViewportFrame viewportFrame =
viewportRuntimeServices.RequestViewport(
viewportComposeFrame.panelId,
viewportComposeFrame.viewportShellFrame.requestedViewportSize);
ApplyViewportFrameToShellModel(
@@ -128,7 +128,7 @@ void EditorShellInteractionEngine::Update(
const Widgets::UIEditorDockHostLayout preUpdateDockLayout =
context.shellFrame.workspaceInteractionFrame.dockHostFrame.layout;
context.viewportHostService.BeginFrame();
context.viewportRuntimeServices.BeginFrame();
const std::vector<UIInputEvent> shellEvents =
context.hostedContentCaptureActive
? FilterShellInputEventsForHostedContentCapture(context.inputEvents)
@@ -160,7 +160,7 @@ void EditorShellInteractionEngine::Update(
metrics);
}
ApplyViewportFramesToShellFrame(context.shellFrame, context.viewportHostService);
ApplyViewportFramesToShellFrame(context.shellFrame, context.viewportRuntimeServices);
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,6 @@
#pragma once
#include "Viewport/ViewportHostService.h"
#include "Viewport/EditorViewportRuntimeServices.h"
#include <XCEditor/Shell/UIEditorShellInteraction.h>
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
@@ -33,7 +33,7 @@ struct EditorShellInteractionEngineContext {
bool useDetachedTitleBarTabStrip = false;
float detachedTitleBarTabHeight = 0.0f;
float detachedWindowChromeHeight = 0.0f;
ViewportHostService& viewportHostService;
EditorViewportRuntimeServices& viewportRuntimeServices;
};
class EditorShellInteractionEngine final {

View File

@@ -4,40 +4,57 @@
#include <XCEditor/Shell/UIEditorShellCapturePolicy.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <cassert>
#include <utility>
namespace XCEngine::UI::Editor::App {
EditorShellRuntime::EditorShellRuntime(EditorWorkspacePanelRuntimeSet workspacePanels)
: m_workspacePanels(std::move(workspacePanels)) {}
EditorShellRuntime::EditorShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices)
: m_iconService(std::move(iconService))
, m_viewportRuntimeServices(std::move(viewportRuntimeServices))
, m_workspacePanels(std::move(workspacePanels)) {}
void EditorShellRuntime::Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& textureHost,
Host::EditorHostResourceService& resourceService,
UIEditorTextMeasurer& textMeasurer) {
m_textureHost = &textureHost;
m_builtInIcons.Initialize(textureHost, resourceService);
assert(m_iconService != nullptr);
assert(m_viewportRuntimeServices != nullptr);
if (m_iconService == nullptr || m_viewportRuntimeServices == nullptr) {
return;
}
m_iconService->Initialize(textureHost, resourceService);
m_viewportRuntimeServices->Initialize(repoRoot);
m_workspacePanels.Initialize(
EditorWorkspacePanelInitializationContext{
.repoRoot = repoRoot,
.textureHost = textureHost,
.textMeasurer = textMeasurer,
.builtInIcons = m_builtInIcons,
.viewportHostService = m_viewportHostService,
.iconService = *m_iconService,
.sceneViewportRuntime = &m_viewportRuntimeServices->GetSceneViewportRuntime(),
});
}
void EditorShellRuntime::AttachViewportWindowRenderer(Rendering::Host::ViewportRenderHost& renderer) {
m_viewportHostService.AttachWindowRenderer(renderer);
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->AttachWindowRenderer(renderer);
}
}
void EditorShellRuntime::DetachViewportWindowRenderer() {
m_viewportHostService.DetachWindowRenderer();
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->DetachWindowRenderer();
}
}
void EditorShellRuntime::SetViewportSurfacePresentationEnabled(bool enabled) {
m_viewportHostService.SetSurfacePresentationEnabled(enabled);
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->SetSurfacePresentationEnabled(enabled);
}
}
void EditorShellRuntime::Shutdown() {
@@ -45,20 +62,14 @@ void EditorShellRuntime::Shutdown() {
m_shellInteractionState = {};
m_splitterDragCorrectionState = {};
m_traceEntries.clear();
if (m_textureHost != nullptr) {
m_workspacePanels.Shutdown(
EditorWorkspacePanelShutdownContext{
.textureHost = *m_textureHost,
.viewportHostService = m_viewportHostService,
});
m_workspacePanels = {};
m_builtInIcons.Shutdown();
m_textureHost = nullptr;
} else {
m_workspacePanels = {};
m_builtInIcons.Shutdown();
m_workspacePanels.Shutdown(EditorWorkspacePanelShutdownContext{});
m_workspacePanels = {};
if (m_iconService != nullptr) {
m_iconService->Shutdown();
}
if (m_viewportRuntimeServices != nullptr) {
m_viewportRuntimeServices->Shutdown();
}
m_viewportHostService.Shutdown();
}
void EditorShellRuntime::ResetInteractionState() {
@@ -82,7 +93,8 @@ const std::vector<WorkspaceTraceEntry>& EditorShellRuntime::GetTraceEntries() co
}
const std::string& EditorShellRuntime::GetBuiltInIconError() const {
return m_builtInIcons.GetLastError();
static const std::string kEmptyError = {};
return m_iconService != nullptr ? m_iconService->GetLastError() : kEmptyError;
}
void EditorShellRuntime::SetExternalDockHostDropPreview(
@@ -144,8 +156,13 @@ bool EditorShellRuntime::HasInteractiveCapture() const {
}
std::unique_ptr<EditorWorkspaceShellRuntime> CreateEditorWorkspaceShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels) {
return std::make_unique<EditorShellRuntime>(std::move(workspacePanels));
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices) {
return std::make_unique<EditorShellRuntime>(
std::move(workspacePanels),
std::move(iconService),
std::move(viewportRuntimeServices));
}
} // namespace XCEngine::UI::Editor::App
@@ -154,15 +171,21 @@ namespace XCEngine::UI::Editor::App {
void EditorShellRuntime::RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext) {
m_viewportHostService.RenderRequestedViewports(renderContext);
if (m_viewportRuntimeServices != nullptr) {
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,
.builtInIcons = m_builtInIcons,
.iconService = *m_iconService,
.workspacePanels = m_workspacePanels,
},
drawData);
@@ -182,6 +205,10 @@ void EditorShellRuntime::Update(
bool useDetachedTitleBarTabStrip,
float detachedTitleBarTabHeight,
float detachedWindowChromeHeight) {
if (m_viewportRuntimeServices == nullptr) {
return;
}
const auto buildDefinition = [&]() {
return m_sessionCoordinator.PrepareShellDefinition(
EditorShellSessionCoordinatorContext{
@@ -206,7 +233,7 @@ void EditorShellRuntime::Update(
.useDetachedTitleBarTabStrip = useDetachedTitleBarTabStrip,
.detachedTitleBarTabHeight = detachedTitleBarTabHeight,
.detachedWindowChromeHeight = detachedWindowChromeHeight,
.viewportHostService = m_viewportHostService,
.viewportRuntimeServices = *m_viewportRuntimeServices,
});
m_sessionCoordinator.FinalizeFrame(frameServices, workspaceController, m_shellFrame.result);

View File

@@ -4,10 +4,10 @@
#include "EditorShellHostedPanelCoordinator.h"
#include "EditorShellInteractionEngine.h"
#include "EditorShellSessionCoordinator.h"
#include "Assets/EditorIconService.h"
#include "Viewport/EditorViewportRuntimeServices.h"
#include "Windowing/EditorWorkspaceShellRuntime.h"
#include "WorkspacePanels/EditorWorkspacePanelRuntime.h"
#include "Assets/BuiltInIcons.h"
#include "Viewport/ViewportHostService.h"
#include <XCEditor/Shell/UIEditorShellInteraction.h>
#include <XCEditor/Docking/UIEditorDockHostTransfer.h>
@@ -45,8 +45,10 @@ namespace XCEngine::UI::Editor::App {
class EditorShellRuntime final : public EditorWorkspaceShellRuntime {
public:
EditorShellRuntime() = default;
explicit EditorShellRuntime(EditorWorkspacePanelRuntimeSet workspacePanels);
EditorShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices);
void Initialize(
const std::filesystem::path& repoRoot,
@@ -95,9 +97,8 @@ public:
bool HasInteractiveCapture() const override;
private:
ViewportHostService m_viewportHostService = {};
BuiltInIcons m_builtInIcons = {};
Rendering::Host::UiTextureHost* m_textureHost = nullptr;
std::unique_ptr<EditorIconService> m_iconService = {};
std::unique_ptr<EditorViewportRuntimeServices> m_viewportRuntimeServices = {};
EditorWorkspacePanelRuntimeSet m_workspacePanels = {};
UIEditorShellInteractionState m_shellInteractionState = {};
UIEditorShellInteractionFrame m_shellFrame = {};
@@ -110,7 +111,9 @@ private:
};
std::unique_ptr<EditorWorkspaceShellRuntime> CreateEditorWorkspaceShellRuntime(
EditorWorkspacePanelRuntimeSet workspacePanels);
EditorWorkspacePanelRuntimeSet workspacePanels,
std::unique_ptr<EditorIconService> iconService,
std::unique_ptr<EditorViewportRuntimeServices> viewportRuntimeServices);
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,60 @@
#pragma once
#include "HostFwd.h"
#include <XCEngine/UI/Types.h>
#include <cstdint>
#include <filesystem>
#include <string>
namespace XCEngine::UI::Editor::Rendering::Host {
class UiTextureHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
enum class BuiltInIconKind : std::uint8_t {
Folder = 0,
GameObject,
Scene,
CameraGizmo,
DirectionalLightGizmo,
PointLightGizmo,
SpotLightGizmo,
PlayButton,
PauseButton,
StepButton,
ViewMoveTool,
ViewMoveToolActive,
MoveTool,
MoveToolActive,
RotateTool,
RotateToolActive,
ScaleTool,
ScaleToolActive,
TransformTool,
TransformToolActive
};
class EditorIconService {
public:
virtual ~EditorIconService() = default;
virtual void Initialize(
Rendering::Host::UiTextureHost& renderer,
Host::EditorHostResourceService& resourceService) = 0;
virtual void Shutdown() = 0;
virtual void BeginFrame() = 0;
[[nodiscard]] virtual const ::XCEngine::UI::UITextureHandle& Resolve(
BuiltInIconKind kind) const = 0;
[[nodiscard]] virtual const ::XCEngine::UI::UITextureHandle* ResolveAssetPreview(
const std::filesystem::path& assetPath,
const std::filesystem::path& projectRoot) = 0;
[[nodiscard]] virtual const std::string& GetLastError() const = 0;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,41 @@
#pragma once
#include <XCEngine/Rendering/Picking/ObjectIdCodec.h>
#include <XCEngine/UI/Types.h>
#include <cstdint>
namespace XCEngine::UI::Editor::App {
enum class ViewportObjectIdPickStatus : std::uint8_t {
Unavailable = 0,
Success,
ReadbackFailed
};
struct ViewportObjectIdPickResult {
ViewportObjectIdPickStatus status = ViewportObjectIdPickStatus::Unavailable;
std::uint64_t frameSerial = 0u;
::XCEngine::Rendering::RenderObjectId renderObjectId =
::XCEngine::Rendering::kInvalidRenderObjectId;
std::uint64_t resolvedEntityId = 0u;
bool HasResolvedSample() const {
return status == ViewportObjectIdPickStatus::Success;
}
bool HasResolvedEntity() const {
return HasResolvedSample() && resolvedEntityId != 0u;
}
};
class IViewportObjectPickerService {
public:
virtual ~IViewportObjectPickerService() = default;
virtual ViewportObjectIdPickResult PickObject(
const ::XCEngine::UI::UISize& viewportSize,
const ::XCEngine::UI::UIPoint& viewportMousePosition) const = 0;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,50 @@
#pragma once
#include "Scene/SceneViewportRenderRequest.h"
#include "Viewport/EditorViewportPicking.h"
#include "Viewport/EditorViewportTypes.h"
#include <filesystem>
#include <string_view>
namespace XCEngine::Rendering {
class RenderContext;
} // namespace XCEngine::Rendering
namespace XCEngine::UI::Editor::Rendering::Host {
class ViewportRenderHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
class EditorSceneViewportRuntime {
public:
virtual ~EditorSceneViewportRuntime() = default;
virtual void SetRenderRequest(SceneViewportRenderRequest request) = 0;
[[nodiscard]] virtual const IViewportObjectPickerService& GetObjectPicker() const = 0;
};
class EditorViewportRuntimeServices {
public:
virtual ~EditorViewportRuntimeServices() = default;
virtual void Initialize(const std::filesystem::path& repoRoot) = 0;
virtual void Shutdown() = 0;
virtual void AttachWindowRenderer(Rendering::Host::ViewportRenderHost& windowRenderer) = 0;
virtual void DetachWindowRenderer() = 0;
virtual void SetSurfacePresentationEnabled(bool enabled) = 0;
virtual void BeginFrame() = 0;
[[nodiscard]] virtual EditorViewportFrame RequestViewport(
std::string_view viewportId,
const ::XCEngine::UI::UISize& requestedSize) = 0;
virtual void RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext) = 0;
[[nodiscard]] virtual EditorSceneViewportRuntime& GetSceneViewportRuntime() = 0;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,24 @@
#pragma once
#include <XCEngine/UI/Types.h>
#include <string>
namespace XCEngine::UI::Editor::App {
struct EditorViewportResourceRequirements {
bool requiresDepthSampling = false;
bool requiresObjectIdSurface = false;
bool requiresSelectionMaskSurface = false;
};
struct EditorViewportFrame {
::XCEngine::UI::UITextureHandle texture = {};
::XCEngine::UI::UISize requestedSize = {};
::XCEngine::UI::UISize renderSize = {};
bool hasTexture = false;
bool wasRequested = false;
std::string statusText = {};
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,8 +1,10 @@
#pragma once
#include "Assets/EditorIconService.h"
#include "Commands/EditorEditCommandRoute.h"
#include "State/EditorSession.h"
#include "Panels/EditorPanelServices.h"
#include "Viewport/EditorViewportRuntimeServices.h"
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEditor/Panels/UIEditorHostedPanelDispatch.h>
@@ -25,17 +27,8 @@ struct UIInputEvent;
} // namespace XCEngine::UI
namespace XCEngine::UI::Editor::Rendering::Host {
class UiTextureHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
class BuiltInIcons;
class ViewportHostService;
enum class EditorWorkspacePanelCursorKind : std::uint8_t {
Arrow = 0,
ResizeEW
@@ -54,16 +47,12 @@ struct EditorWorkspacePanelFrameEvent {
struct EditorWorkspacePanelInitializationContext {
const std::filesystem::path& repoRoot;
Rendering::Host::UiTextureHost& textureHost;
UIEditorTextMeasurer& textMeasurer;
BuiltInIcons& builtInIcons;
ViewportHostService& viewportHostService;
EditorIconService& iconService;
EditorSceneViewportRuntime* sceneViewportRuntime = nullptr;
};
struct EditorWorkspacePanelShutdownContext {
Rendering::Host::UiTextureHost& textureHost;
ViewportHostService& viewportHostService;
};
struct EditorWorkspacePanelShutdownContext {};
struct EditorWorkspacePanelUpdateContext {
EditorPanelServices& services;

View File

@@ -7,8 +7,6 @@
#include "Project/ProjectPanel.h"
#include "Scene/SceneEditCommandRoute.h"
#include "Scene/SceneViewportFeature.h"
#include "Assets/BuiltInIcons.h"
#include "Viewport/ViewportHostService.h"
#include <XCEditor/Panels/UIEditorHostedPanelDispatch.h>
@@ -219,7 +217,7 @@ public:
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
m_panel.SetBuiltInIcons(&context.builtInIcons);
m_panel.SetIconService(&context.iconService);
m_panel.SetTextMeasurer(&context.textMeasurer);
m_panel.Initialize();
}
@@ -330,7 +328,7 @@ public:
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
m_panel.SetBuiltInIcons(&context.builtInIcons);
m_panel.SetIconService(&context.iconService);
m_panel.SetTextMeasurer(&context.textMeasurer);
}
@@ -406,15 +404,16 @@ public:
}
void Initialize(const EditorWorkspacePanelInitializationContext& context) override {
m_feature.Initialize(
context.repoRoot,
context.textureHost,
&context.builtInIcons,
context.viewportHostService);
if (context.sceneViewportRuntime != nullptr) {
m_feature.Initialize(
&context.iconService,
*context.sceneViewportRuntime);
}
}
void Shutdown(const EditorWorkspacePanelShutdownContext& context) override {
m_feature.Shutdown(context.textureHost, context.viewportHostService);
(void)context;
m_feature.Shutdown();
m_commandRoute.BindSceneRuntime(nullptr);
}

View File

@@ -1,5 +1,5 @@
#include "HierarchyPanel.h"
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
#include <XCEditor/Foundation/UIEditorPanelInputFilter.h>
#include <XCEditor/Foundation/UIEditorTheme.h>
#include "EditorSceneRuntime.h"
@@ -15,13 +15,13 @@ using ::XCEngine::UI::UIColor;
inline constexpr float kDragThreshold = 4.0f;
inline constexpr UIColor kDragPreviewColor(0.92f, 0.92f, 0.92f, 0.42f);
::XCEngine::UI::UITextureHandle ResolveGameObjectIcon(const BuiltInIcons* icons);
::XCEngine::UI::UITextureHandle ResolveGameObjectIcon(const EditorIconService* icons);
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::App {
::XCEngine::UI::UITextureHandle ResolveGameObjectIcon(const BuiltInIcons* icons) {
::XCEngine::UI::UITextureHandle ResolveGameObjectIcon(const EditorIconService* icons) {
return icons != nullptr
? icons->Resolve(BuiltInIconKind::GameObject)
: ::XCEngine::UI::UITextureHandle {};
@@ -80,7 +80,7 @@ void HierarchyPanel::SetCommandFocusService(
m_commandFocusService = commandFocusService;
}
void HierarchyPanel::SetBuiltInIcons(const BuiltInIcons* icons) {
void HierarchyPanel::SetIconService(const EditorIconService* icons) {
m_icons = icons;
RebuildItems();
}

View File

@@ -20,8 +20,8 @@
namespace XCEngine::UI::Editor::App {
class BuiltInIcons;
class EditorCommandFocusService;
class EditorIconService;
class EditorSceneRuntime;
class HierarchyPanel final : public EditorEditCommandRoute {
@@ -44,7 +44,7 @@ public:
void Initialize();
void SetSceneRuntime(EditorSceneRuntime* sceneRuntime);
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);
void SetBuiltInIcons(const BuiltInIcons* icons);
void SetIconService(const EditorIconService* icons);
void SetTextMeasurer(const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer);
void ResetInteractionState();
void Update(
@@ -90,7 +90,7 @@ private:
const std::vector<Widgets::UIEditorTreeViewItem>& GetPresentedTreeItems() const;
const ::XCEngine::UI::Widgets::UIExpansionModel& GetPresentedExpansionModel() const;
const BuiltInIcons* m_icons = nullptr;
const EditorIconService* m_icons = nullptr;
EditorCommandFocusService* m_commandFocusService = nullptr;
EditorSceneRuntime* m_sceneRuntime = nullptr;
HierarchyModel m_model = {};

View File

@@ -1,5 +1,5 @@
#include "ProjectPanel.h"
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
#include <XCEditor/Collections/UIEditorScrollView.h>
#include <XCEditor/Collections/UIEditorTreeView.h>
#include <XCEditor/Foundation/UIEditorTheme.h>
@@ -71,7 +71,7 @@ float MeasureTextWidth(
const UIEditorTextMeasurer* textMeasurer,
std::string_view text,
float fontSize);
::XCEngine::UI::UITextureHandle ResolveFolderIcon(const BuiltInIcons* icons);
::XCEngine::UI::UITextureHandle ResolveFolderIcon(const EditorIconService* icons);
float ClampNavigationWidth(float value, float totalWidth);
UIRect ComputeFittedTextureRect(
const UIRect& bounds,
@@ -129,7 +129,7 @@ float MeasureTextWidth(
return static_cast<float>(text.size()) * fontSize * 0.56f;
}
::XCEngine::UI::UITextureHandle ResolveFolderIcon(const BuiltInIcons* icons) {
::XCEngine::UI::UITextureHandle ResolveFolderIcon(const EditorIconService* icons) {
return icons != nullptr
? icons->Resolve(BuiltInIconKind::Folder)
: ::XCEngine::UI::UITextureHandle {};
@@ -425,7 +425,7 @@ void ProjectPanel::SetSystemInteractionHost(
m_systemInteractionHost = systemInteractionHost;
}
void ProjectPanel::SetBuiltInIcons(BuiltInIcons* icons) {
void ProjectPanel::SetIconService(EditorIconService* icons) {
m_icons = icons;
RebuildWindowTreeItems();
}

View File

@@ -29,8 +29,8 @@
namespace XCEngine::UI::Editor::App {
class BuiltInIcons;
class EditorCommandFocusService;
class EditorIconService;
} // namespace XCEngine::UI::Editor::App
@@ -86,7 +86,7 @@ public:
void SetProjectRuntime(EditorProjectRuntime* projectRuntime);
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);
void SetSystemInteractionHost(System::SystemInteractionService* systemInteractionHost);
void SetBuiltInIcons(BuiltInIcons* icons);
void SetIconService(EditorIconService* icons);
void SetTextMeasurer(const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer);
void ResetInteractionState();
void Update(
@@ -254,7 +254,7 @@ private:
EditorProjectRuntime* m_projectRuntime = nullptr;
EditorCommandFocusService* m_commandFocusService = nullptr;
System::SystemInteractionService* m_systemInteractionHost = nullptr;
BuiltInIcons* m_icons = nullptr;
EditorIconService* m_icons = nullptr;
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* m_textMeasurer = nullptr;
std::vector<Widgets::UIEditorTreeViewItem> m_windowTreeItems = {};
::XCEngine::UI::Widgets::UISelectionModel m_folderSelection = {};

View File

@@ -1,6 +1,6 @@
#include "Scene/SceneViewportController.h"
#include "Viewport/ViewportObjectPickerService.h"
#include "Viewport/EditorViewportPicking.h"
#include "EditorSceneRuntime.h"
#include "State/EditorCommandFocusService.h"
@@ -136,17 +136,15 @@ void ApplySceneViewportToggleButton(
} // namespace
void SceneViewportController::Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& renderer,
const BuiltInIcons* builtInIcons) {
m_toolOverlay.Initialize(repoRoot, renderer);
m_sceneOverlay.SetBuiltInIcons(builtInIcons);
void SceneViewportController::Initialize(const EditorIconService* iconService) {
m_toolOverlay.SetIconService(iconService);
m_sceneOverlay.SetIconService(iconService);
ResetInteractionState();
}
void SceneViewportController::Shutdown(Rendering::Host::UiTextureHost& renderer) {
m_toolOverlay.Shutdown(renderer);
void SceneViewportController::Shutdown() {
m_toolOverlay.SetIconService(nullptr);
m_sceneOverlay.SetIconService(nullptr);
ResetInteractionState();
}

View File

@@ -10,32 +10,18 @@
#include <XCEngine/UI/Types.h>
#include <chrono>
#include <filesystem>
namespace XCEngine::UI::Editor::App {
class EditorCommandFocusService;
class BuiltInIcons;
class EditorIconService;
class EditorSceneRuntime;
class IViewportObjectPickerService;
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::Rendering::Host {
class UiTextureHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
class SceneViewportController {
public:
void Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& renderer,
const BuiltInIcons* builtInIcons);
void Shutdown(Rendering::Host::UiTextureHost& renderer);
void Initialize(const EditorIconService* iconService);
void Shutdown();
void ResetInteractionState();
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);

View File

@@ -1,33 +1,20 @@
#include "Scene/SceneViewportFeature.h"
#include "Panels/EditorPanelIds.h"
#include "UiTextureHost.h"
#include "Viewport/SceneViewportResourcePaths.h"
#include "Viewport/ViewportHostService.h"
#include "EditorSceneRuntime.h"
#include "State/EditorCommandFocusService.h"
namespace XCEngine::UI::Editor::App {
void SceneViewportFeature::Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& textureHost,
const BuiltInIcons* builtInIcons,
ViewportHostService& viewportHostService) {
m_renderService.Initialize(BuildSceneViewportShaderPaths(repoRoot));
viewportHostService.SetContentRenderer(
kScenePanelId,
&m_renderService,
SceneViewportRenderService::GetViewportResourceRequirements());
m_controller.Initialize(repoRoot, textureHost, builtInIcons);
const EditorIconService* iconService,
EditorSceneViewportRuntime& sceneViewportRuntime) {
m_sceneViewportRuntime = &sceneViewportRuntime;
m_controller.Initialize(iconService);
}
void SceneViewportFeature::Shutdown(
Rendering::Host::UiTextureHost& textureHost,
ViewportHostService& viewportHostService) {
viewportHostService.SetContentRenderer(kScenePanelId, nullptr, {});
m_controller.Shutdown(textureHost);
m_renderService.Shutdown();
void SceneViewportFeature::Shutdown() {
m_controller.Shutdown();
m_sceneViewportRuntime = nullptr;
}
void SceneViewportFeature::ResetInteractionState() {
@@ -40,17 +27,23 @@ void SceneViewportFeature::SetCommandFocusService(
}
void SceneViewportFeature::SyncRenderRequest(EditorSceneRuntime& sceneRuntime) {
m_renderService.SetRenderRequest(
sceneRuntime.BuildSceneViewportRenderRequest());
if (m_sceneViewportRuntime != nullptr) {
m_sceneViewportRuntime->SetRenderRequest(
sceneRuntime.BuildSceneViewportRenderRequest());
}
}
void SceneViewportFeature::Update(
EditorSceneRuntime& sceneRuntime,
const UIEditorWorkspaceComposeState& composeState,
const UIEditorWorkspaceComposeFrame& composeFrame) {
if (m_sceneViewportRuntime == nullptr) {
return;
}
m_controller.Update(
sceneRuntime,
m_renderService,
m_sceneViewportRuntime->GetObjectPicker(),
composeState,
composeFrame);
SyncRenderRequest(sceneRuntime);

View File

@@ -1,42 +1,24 @@
#pragma once
#include "Assets/EditorIconService.h"
#include "Scene/SceneViewportController.h"
#include "Viewport/SceneViewportRenderService.h"
#include "Viewport/EditorViewportRuntimeServices.h"
#include <XCEditor/Workspace/UIEditorWorkspaceCompose.h>
#include <XCEngine/UI/DrawData.h>
#include <filesystem>
namespace XCEngine::UI::Editor::App {
class EditorCommandFocusService;
class BuiltInIcons;
class EditorSceneRuntime;
} // namespace XCEngine::UI::Editor::App
namespace XCEngine::UI::Editor::Rendering::Host {
class UiTextureHost;
} // namespace XCEngine::UI::Editor::Rendering::Host
namespace XCEngine::UI::Editor::App {
class ViewportHostService;
class SceneViewportFeature {
public:
void Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& textureHost,
const BuiltInIcons* builtInIcons,
ViewportHostService& viewportHostService);
void Shutdown(
Rendering::Host::UiTextureHost& textureHost,
ViewportHostService& viewportHostService);
const EditorIconService* iconService,
EditorSceneViewportRuntime& sceneViewportRuntime);
void Shutdown();
void ResetInteractionState();
void SetCommandFocusService(EditorCommandFocusService* commandFocusService);
void SyncRenderRequest(EditorSceneRuntime& sceneRuntime);
@@ -47,7 +29,7 @@ public:
void Append(::XCEngine::UI::UIDrawList& drawList) const;
private:
SceneViewportRenderService m_renderService = {};
EditorSceneViewportRuntime* m_sceneViewportRuntime = nullptr;
SceneViewportController m_controller = {};
};

View File

@@ -1,7 +1,7 @@
#include "Scene/SceneViewportSceneOverlay.h"
#include "Scene/SceneViewportTransformGizmoSupport.h"
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
#include "EditorSceneRuntime.h"
#include <XCEngine/Components/CameraComponent.h>
@@ -68,14 +68,14 @@ SceneViewportGizmoSupport::SceneViewportOverlayData BuildOverlayData(
return overlay;
}
::XCEngine::UI::UITextureHandle ResolveCameraIcon(const BuiltInIcons* icons) {
::XCEngine::UI::UITextureHandle ResolveCameraIcon(const EditorIconService* icons) {
return icons != nullptr
? icons->Resolve(BuiltInIconKind::CameraGizmo)
: ::XCEngine::UI::UITextureHandle();
}
::XCEngine::UI::UITextureHandle ResolveLightIcon(
const BuiltInIcons* icons,
const EditorIconService* icons,
const LightComponent& light) {
if (icons == nullptr) {
return {};
@@ -95,7 +95,7 @@ SceneViewportGizmoSupport::SceneViewportOverlayData BuildOverlayData(
} // namespace
void SceneViewportSceneOverlay::SetBuiltInIcons(const BuiltInIcons* icons) {
void SceneViewportSceneOverlay::SetIconService(const EditorIconService* icons) {
m_icons = icons;
if (m_icons == nullptr) {
ResetFrame();

View File

@@ -7,8 +7,8 @@
namespace XCEngine::UI::Editor::App {
class BuiltInIcons;
class EditorSceneRuntime;
class EditorIconService;
class SceneViewportSceneOverlay {
public:
@@ -21,7 +21,7 @@ public:
}
};
void SetBuiltInIcons(const BuiltInIcons* icons);
void SetIconService(const EditorIconService* icons);
void ResetFrame();
void Refresh(
EditorSceneRuntime& sceneRuntime,
@@ -42,7 +42,7 @@ public:
};
private:
const BuiltInIcons* m_icons = nullptr;
const EditorIconService* m_icons = nullptr;
Frame m_frame = {};
};

View File

@@ -1,7 +1,5 @@
#include "Scene/SceneViewportToolOverlay.h"
#include "UiTextureHost.h"
#include <XCEditor/Widgets/UIEditorTextLayout.h>
#include <algorithm>
@@ -39,16 +37,16 @@ constexpr float kToggleMinWidth = 60.0f;
struct ToolButtonSpec {
SceneToolMode mode = SceneToolMode::View;
const char* label = "";
const char* inactiveFile = "";
const char* activeFile = "";
BuiltInIconKind inactiveIcon = BuiltInIconKind::ViewMoveTool;
BuiltInIconKind activeIcon = BuiltInIconKind::ViewMoveToolActive;
};
constexpr std::array<ToolButtonSpec, 5> kToolButtonSpecs = {{
{ SceneToolMode::View, "View", "view_move_tool.png", "view_move_tool_on.png" },
{ SceneToolMode::Translate, "Move", "move_tool.png", "move_tool_on.png" },
{ SceneToolMode::Rotate, "Rotate", "rotate_tool.png", "rotate_tool_on.png" },
{ SceneToolMode::Scale, "Scale", "scale_tool.png", "scale_tool_on.png" },
{ SceneToolMode::Transform, "Transform", "transform_tool.png", "transform_tool_on.png" }
{ SceneToolMode::View, "View", BuiltInIconKind::ViewMoveTool, BuiltInIconKind::ViewMoveToolActive },
{ SceneToolMode::Translate, "Move", BuiltInIconKind::MoveTool, BuiltInIconKind::MoveToolActive },
{ SceneToolMode::Rotate, "Rotate", BuiltInIconKind::RotateTool, BuiltInIconKind::RotateToolActive },
{ SceneToolMode::Scale, "Scale", BuiltInIconKind::ScaleTool, BuiltInIconKind::ScaleToolActive },
{ SceneToolMode::Transform, "Transform", BuiltInIconKind::TransformTool, BuiltInIconKind::TransformToolActive }
}};
bool ContainsPoint(const UIRect& rect, const UIPoint& point) {
@@ -198,47 +196,10 @@ UIRect BuildToggleButtonRect(
return kToggleIdle;
}
} // namespace
bool SceneViewportToolOverlay::Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& renderer) {
Shutdown(renderer);
const std::filesystem::path iconRoot =
(repoRoot / "editor" / "resources" / "Icons").lexically_normal();
bool loadedAnyTexture = false;
for (std::size_t index = 0; index < kToolButtonSpecs.size(); ++index) {
const ToolButtonSpec& path = kToolButtonSpecs[index];
ToolTextureSet& textureSet = m_toolTextures[index];
textureSet = {};
textureSet.mode = path.mode;
textureSet.label = path.label;
std::string error = {};
loadedAnyTexture =
renderer.LoadTextureFromFile(
iconRoot / path.inactiveFile,
textureSet.inactiveTexture,
error) || loadedAnyTexture;
error.clear();
loadedAnyTexture =
renderer.LoadTextureFromFile(
iconRoot / path.activeFile,
textureSet.activeTexture,
error) || loadedAnyTexture;
}
return loadedAnyTexture;
}
void SceneViewportToolOverlay::Shutdown(Rendering::Host::UiTextureHost& renderer) {
for (ToolTextureSet& textureSet : m_toolTextures) {
renderer.ReleaseTexture(textureSet.inactiveTexture);
renderer.ReleaseTexture(textureSet.activeTexture);
textureSet = {};
}
void SceneViewportToolOverlay::SetIconService(const EditorIconService* iconService) {
m_iconService = iconService;
ResetFrame();
}
@@ -305,7 +266,6 @@ void SceneViewportToolOverlay::BuildFrame(
for (std::size_t index = 0; index < m_frame.buttons.size(); ++index) {
const ToolButtonSpec& spec = kToolButtonSpecs[index];
const ToolTextureSet& textureSet = m_toolTextures[index];
SceneViewportToolOverlayButtonFrame& button = m_frame.buttons[index];
button = {};
button.mode = spec.mode;
@@ -314,9 +274,10 @@ void SceneViewportToolOverlay::BuildFrame(
button.active = spec.mode == activeMode;
button.hovered = index == hoveredIndex;
button.pressed = index == pressedIndex;
button.texture = spec.mode == activeMode
? textureSet.activeTexture
: textureSet.inactiveTexture;
if (m_iconService != nullptr) {
button.texture = m_iconService->Resolve(
spec.mode == activeMode ? spec.activeIcon : spec.inactiveIcon);
}
}
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include "SceneToolState.h"
#include "HostFwd.h"
#include "Assets/EditorIconService.h"
#include <XCEngine/UI/DrawData.h>
#include <XCEngine/UI/Types.h>
@@ -9,7 +9,6 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <string>
namespace XCEngine::UI::Editor::App {
@@ -57,10 +56,7 @@ struct SceneViewportToolOverlayFrame {
class SceneViewportToolOverlay {
public:
bool Initialize(
const std::filesystem::path& repoRoot,
Rendering::Host::UiTextureHost& renderer);
void Shutdown(Rendering::Host::UiTextureHost& renderer);
void SetIconService(const EditorIconService* iconService);
void ResetFrame();
void BuildFrame(
@@ -82,15 +78,8 @@ public:
const SceneViewportToolOverlayFrame& GetFrame() const;
private:
struct ToolTextureSet {
SceneToolMode mode = SceneToolMode::View;
const char* label = "";
::XCEngine::UI::UITextureHandle inactiveTexture = {};
::XCEngine::UI::UITextureHandle activeTexture = {};
};
std::array<ToolTextureSet, 5> m_toolTextures = {};
SceneViewportToolOverlayFrame m_frame = {};
const EditorIconService* m_iconService = nullptr;
};
void AppendSceneViewportToolOverlay(

View File

@@ -20,6 +20,16 @@ enum class EditorHostPngResourceKind : std::uint8_t {
PlayButtonIcon,
PauseButtonIcon,
StepButtonIcon,
ViewMoveToolIcon,
ViewMoveToolActiveIcon,
MoveToolIcon,
MoveToolActiveIcon,
RotateToolIcon,
RotateToolActiveIcon,
ScaleToolIcon,
ScaleToolActiveIcon,
TransformToolIcon,
TransformToolActiveIcon,
};
struct EditorHostResourceBytes {

View File

@@ -34,6 +34,26 @@ int ResolvePngResourceId(EditorHostPngResourceKind kind) {
return IDR_PNG_PAUSE_BUTTON_ICON;
case EditorHostPngResourceKind::StepButtonIcon:
return IDR_PNG_STEP_BUTTON_ICON;
case EditorHostPngResourceKind::ViewMoveToolIcon:
return IDR_PNG_VIEW_MOVE_TOOL_ICON;
case EditorHostPngResourceKind::ViewMoveToolActiveIcon:
return IDR_PNG_VIEW_MOVE_TOOL_ACTIVE_ICON;
case EditorHostPngResourceKind::MoveToolIcon:
return IDR_PNG_MOVE_TOOL_ICON;
case EditorHostPngResourceKind::MoveToolActiveIcon:
return IDR_PNG_MOVE_TOOL_ACTIVE_ICON;
case EditorHostPngResourceKind::RotateToolIcon:
return IDR_PNG_ROTATE_TOOL_ICON;
case EditorHostPngResourceKind::RotateToolActiveIcon:
return IDR_PNG_ROTATE_TOOL_ACTIVE_ICON;
case EditorHostPngResourceKind::ScaleToolIcon:
return IDR_PNG_SCALE_TOOL_ICON;
case EditorHostPngResourceKind::ScaleToolActiveIcon:
return IDR_PNG_SCALE_TOOL_ACTIVE_ICON;
case EditorHostPngResourceKind::TransformToolIcon:
return IDR_PNG_TRANSFORM_TOOL_ICON;
case EditorHostPngResourceKind::TransformToolActiveIcon:
return IDR_PNG_TRANSFORM_TOOL_ACTIVE_ICON;
default:
return 0;
}

View File

@@ -584,6 +584,76 @@ void BuiltInIcons::Initialize(
"step_button.png",
m_stepButtonIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::ViewMoveToolIcon,
"view_move_tool.png",
m_viewMoveToolIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::ViewMoveToolActiveIcon,
"view_move_tool_on.png",
m_viewMoveToolActiveIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::MoveToolIcon,
"move_tool.png",
m_moveToolIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::MoveToolActiveIcon,
"move_tool_on.png",
m_moveToolActiveIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::RotateToolIcon,
"rotate_tool.png",
m_rotateToolIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::RotateToolActiveIcon,
"rotate_tool_on.png",
m_rotateToolActiveIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::ScaleToolIcon,
"scale_tool.png",
m_scaleToolIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::ScaleToolActiveIcon,
"scale_tool_on.png",
m_scaleToolActiveIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::TransformToolIcon,
"transform_tool.png",
m_transformToolIcon,
errorStream);
LoadEmbeddedIconTexture(
renderer,
resourceService,
Host::EditorHostPngResourceKind::TransformToolActiveIcon,
"transform_tool_on.png",
m_transformToolActiveIcon,
errorStream);
m_frameIndex = 0;
m_previewLoadsThisFrame = 0;
@@ -605,6 +675,16 @@ void BuiltInIcons::Shutdown() {
m_renderer->ReleaseTexture(m_playButtonIcon);
m_renderer->ReleaseTexture(m_pauseButtonIcon);
m_renderer->ReleaseTexture(m_stepButtonIcon);
m_renderer->ReleaseTexture(m_viewMoveToolIcon);
m_renderer->ReleaseTexture(m_viewMoveToolActiveIcon);
m_renderer->ReleaseTexture(m_moveToolIcon);
m_renderer->ReleaseTexture(m_moveToolActiveIcon);
m_renderer->ReleaseTexture(m_rotateToolIcon);
m_renderer->ReleaseTexture(m_rotateToolActiveIcon);
m_renderer->ReleaseTexture(m_scaleToolIcon);
m_renderer->ReleaseTexture(m_scaleToolActiveIcon);
m_renderer->ReleaseTexture(m_transformToolIcon);
m_renderer->ReleaseTexture(m_transformToolActiveIcon);
}
m_renderer = nullptr;
@@ -944,6 +1024,26 @@ const ::XCEngine::UI::UITextureHandle& BuiltInIcons::Resolve(
return m_pauseButtonIcon;
case BuiltInIconKind::StepButton:
return m_stepButtonIcon;
case BuiltInIconKind::ViewMoveTool:
return m_viewMoveToolIcon;
case BuiltInIconKind::ViewMoveToolActive:
return m_viewMoveToolActiveIcon;
case BuiltInIconKind::MoveTool:
return m_moveToolIcon;
case BuiltInIconKind::MoveToolActive:
return m_moveToolActiveIcon;
case BuiltInIconKind::RotateTool:
return m_rotateToolIcon;
case BuiltInIconKind::RotateToolActive:
return m_rotateToolActiveIcon;
case BuiltInIconKind::ScaleTool:
return m_scaleToolIcon;
case BuiltInIconKind::ScaleToolActive:
return m_scaleToolActiveIcon;
case BuiltInIconKind::TransformTool:
return m_transformToolIcon;
case BuiltInIconKind::TransformToolActive:
return m_transformToolActiveIcon;
default:
return m_folderIcon;
}

View File

@@ -1,8 +1,6 @@
#pragma once
#include "HostFwd.h"
#include <XCEngine/UI/Types.h>
#include "Assets/EditorIconService.h"
#include <condition_variable>
#include <cstdint>
@@ -17,32 +15,19 @@
namespace XCEngine::UI::Editor::App {
enum class BuiltInIconKind : std::uint8_t {
Folder = 0,
GameObject,
Scene,
CameraGizmo,
DirectionalLightGizmo,
PointLightGizmo,
SpotLightGizmo,
PlayButton,
PauseButton,
StepButton
};
class BuiltInIcons {
class BuiltInIcons final : public EditorIconService {
public:
void Initialize(
Rendering::Host::UiTextureHost& renderer,
Host::EditorHostResourceService& resourceService);
void Shutdown();
void BeginFrame();
Host::EditorHostResourceService& resourceService) override;
void Shutdown() override;
void BeginFrame() override;
const ::XCEngine::UI::UITextureHandle& Resolve(BuiltInIconKind kind) const;
const ::XCEngine::UI::UITextureHandle& Resolve(BuiltInIconKind kind) const override;
const ::XCEngine::UI::UITextureHandle* ResolveAssetPreview(
const std::filesystem::path& assetPath,
const std::filesystem::path& projectRoot);
const std::string& GetLastError() const;
const std::filesystem::path& projectRoot) override;
const std::string& GetLastError() const override;
struct LoadedTexturePixels {
std::vector<std::uint8_t> rgbaPixels = {};
@@ -121,6 +106,16 @@ private:
::XCEngine::UI::UITextureHandle m_playButtonIcon = {};
::XCEngine::UI::UITextureHandle m_pauseButtonIcon = {};
::XCEngine::UI::UITextureHandle m_stepButtonIcon = {};
::XCEngine::UI::UITextureHandle m_viewMoveToolIcon = {};
::XCEngine::UI::UITextureHandle m_viewMoveToolActiveIcon = {};
::XCEngine::UI::UITextureHandle m_moveToolIcon = {};
::XCEngine::UI::UITextureHandle m_moveToolActiveIcon = {};
::XCEngine::UI::UITextureHandle m_rotateToolIcon = {};
::XCEngine::UI::UITextureHandle m_rotateToolActiveIcon = {};
::XCEngine::UI::UITextureHandle m_scaleToolIcon = {};
::XCEngine::UI::UITextureHandle m_scaleToolActiveIcon = {};
::XCEngine::UI::UITextureHandle m_transformToolIcon = {};
::XCEngine::UI::UITextureHandle m_transformToolActiveIcon = {};
std::unordered_map<std::string, CachedAssetPreview> m_assetPreviews = {};
std::vector<std::thread> m_previewWorkers = {};
std::deque<PreviewDecodeJob> m_previewDecodeQueue = {};

View File

@@ -0,0 +1,11 @@
#include "Assets/EditorIconServiceFactory.h"
#include "Assets/BuiltInIcons.h"
namespace XCEngine::UI::Editor::App {
std::unique_ptr<EditorIconService> CreateEditorIconService() {
return std::make_unique<BuiltInIcons>();
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,11 @@
#pragma once
#include "Assets/EditorIconService.h"
#include <memory>
namespace XCEngine::UI::Editor::App {
std::unique_ptr<EditorIconService> CreateEditorIconService();
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,11 @@
#include "Viewport/EditorViewportRuntimeServicesFactory.h"
#include "Viewport/ViewportHostService.h"
namespace XCEngine::UI::Editor::App {
std::unique_ptr<EditorViewportRuntimeServices> CreateEditorViewportRuntimeServices() {
return std::make_unique<ViewportHostService>();
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,11 @@
#pragma once
#include "Viewport/EditorViewportRuntimeServices.h"
#include <memory>
namespace XCEngine::UI::Editor::App {
std::unique_ptr<EditorViewportRuntimeServices> CreateEditorViewportRuntimeServices();
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,5 +1,7 @@
#include "Viewport/SceneViewportRenderService.h"
#include "Viewport/ViewportObjectIdPicker.h"
#include <XCEngine/Rendering/Picking/RenderObjectIdRegistry.h>
#include <XCEngine/Rendering/Execution/SceneRenderer.h>
#include <XCEngine/Scene/Scene.h>
@@ -41,9 +43,9 @@ SceneViewportRenderService::SceneViewportRenderService() = default;
SceneViewportRenderService::~SceneViewportRenderService() = default;
ViewportResourceRequirements
EditorViewportResourceRequirements
SceneViewportRenderService::GetViewportResourceRequirements() {
ViewportResourceRequirements requirements = {};
EditorViewportResourceRequirements requirements = {};
requirements.requiresDepthSampling = true;
requirements.requiresObjectIdSurface = true;
requirements.requiresSelectionMaskSurface = true;
@@ -79,6 +81,10 @@ void SceneViewportRenderService::SetRenderRequest(
m_renderRequest = std::move(request);
}
const IViewportObjectPickerService& SceneViewportRenderService::GetObjectPicker() const {
return *this;
}
ViewportRenderResult SceneViewportRenderService::Render(
ViewportRenderTargets& targets,
::XCEngine::RHI::RHIDevice& device,

View File

@@ -1,9 +1,8 @@
#pragma once
#include "Viewport/EditorViewportRuntimeServices.h"
#include "Viewport/ViewportContentRenderer.h"
#include "Viewport/ViewportObjectPickerService.h"
#include "Viewport/SceneViewportRenderPassBundle.h"
#include "Scene/SceneViewportRenderRequest.h"
#include <memory>
#include <string>
@@ -28,16 +27,18 @@ namespace XCEngine::UI::Editor::App {
class SceneViewportRenderService
: public IViewportContentRenderer
, public EditorSceneViewportRuntime
, public IViewportObjectPickerService {
public:
SceneViewportRenderService();
~SceneViewportRenderService();
static ViewportResourceRequirements GetViewportResourceRequirements();
static EditorViewportResourceRequirements GetViewportResourceRequirements();
void Initialize(const SceneViewportShaderPaths& shaderPaths);
void Shutdown();
void SetRenderRequest(SceneViewportRenderRequest request);
void SetRenderRequest(SceneViewportRenderRequest request) override;
const IViewportObjectPickerService& GetObjectPicker() const override;
ViewportRenderResult Render(
ViewportRenderTargets& targets,

View File

@@ -1,5 +1,7 @@
#include "ViewportHostService.h"
#include "Panels/EditorPanelIds.h"
#include "Viewport/SceneViewportResourcePaths.h"
#include "ViewportRenderHost.h"
#include <XCEngine/RHI/RHICommandList.h>
@@ -18,6 +20,14 @@ ViewportHostService::ViewportHostService() = default;
ViewportHostService::~ViewportHostService() = default;
void ViewportHostService::Initialize(const std::filesystem::path& repoRoot) {
m_sceneViewportRuntime.Initialize(BuildSceneViewportShaderPaths(repoRoot));
SetContentRenderer(
kScenePanelId,
&m_sceneViewportRuntime,
SceneViewportRenderService::GetViewportResourceRequirements());
}
void ViewportHostService::AttachWindowRenderer(
Rendering::Host::ViewportRenderHost& windowRenderer) {
if (m_windowRenderer == &windowRenderer) {
@@ -43,13 +53,15 @@ void ViewportHostService::SetSurfacePresentationEnabled(bool enabled) {
void ViewportHostService::SetContentRenderer(
std::string_view viewportId,
IViewportContentRenderer* renderer,
const ViewportResourceRequirements& requirements) {
const EditorViewportResourceRequirements& requirements) {
ViewportEntry& entry = GetOrCreateEntry(viewportId);
entry.renderer = renderer;
entry.requirements = requirements;
}
void ViewportHostService::Shutdown() {
SetContentRenderer(kScenePanelId, nullptr, {});
m_sceneViewportRuntime.Shutdown();
for (auto& [viewportId, entry] : m_entries) {
DestroyViewportEntry(entry);
}
@@ -155,7 +167,7 @@ void ViewportHostService::RetireViewportTargets(ViewportRenderTargets& targets)
std::swap(m_retiredTargetsBySlot[activeSlot].back(), targets);
}
ViewportFrame ViewportHostService::RequestViewport(
EditorViewportFrame ViewportHostService::RequestViewport(
std::string_view viewportId,
const ::XCEngine::UI::UISize& requestedSize) {
ViewportEntry& entry = GetOrCreateEntry(viewportId);
@@ -302,10 +314,10 @@ void ViewportHostService::ClearViewport(
entry.renderTargets.objectIdFrameSerial = 0u;
}
ViewportFrame ViewportHostService::BuildFrame(
EditorViewportFrame ViewportHostService::BuildFrame(
const ViewportEntry& entry,
const ::XCEngine::UI::UISize& requestedSize) const {
ViewportFrame frame = {};
EditorViewportFrame frame = {};
frame.requestedSize = requestedSize;
frame.renderSize = ::XCEngine::UI::UISize(
static_cast<float>(entry.renderTargets.width),
@@ -322,4 +334,8 @@ ViewportFrame ViewportHostService::BuildFrame(
return frame;
}
EditorSceneViewportRuntime& ViewportHostService::GetSceneViewportRuntime() {
return m_sceneViewportRuntime;
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,6 +1,8 @@
#pragma once
#include "Viewport/EditorViewportRuntimeServices.h"
#include "HostFwd.h"
#include "Viewport/SceneViewportRenderService.h"
#include "Viewport/ViewportContentRenderer.h"
#include "ViewportRenderTargets.h"
@@ -15,33 +17,35 @@
namespace XCEngine::UI::Editor::App {
class ViewportHostService {
class ViewportHostService final : public EditorViewportRuntimeServices {
public:
ViewportHostService();
~ViewportHostService();
void AttachWindowRenderer(Rendering::Host::ViewportRenderHost& windowRenderer);
void DetachWindowRenderer();
void SetSurfacePresentationEnabled(bool enabled);
void Initialize(const std::filesystem::path& repoRoot) override;
void Shutdown() override;
void AttachWindowRenderer(Rendering::Host::ViewportRenderHost& windowRenderer) override;
void DetachWindowRenderer() override;
void SetSurfacePresentationEnabled(bool enabled) override;
void SetContentRenderer(
std::string_view viewportId,
IViewportContentRenderer* renderer,
const ViewportResourceRequirements& requirements = {});
const EditorViewportResourceRequirements& requirements = {});
void Shutdown();
void BeginFrame();
void BeginFrame() override;
ViewportFrame RequestViewport(
EditorViewportFrame RequestViewport(
std::string_view viewportId,
const ::XCEngine::UI::UISize& requestedSize);
const ::XCEngine::UI::UISize& requestedSize) override;
void RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext);
const ::XCEngine::Rendering::RenderContext& renderContext) override;
EditorSceneViewportRuntime& GetSceneViewportRuntime() override;
private:
struct ViewportEntry {
IViewportContentRenderer* renderer = nullptr;
ViewportResourceRequirements requirements = {};
EditorViewportResourceRequirements requirements = {};
std::uint32_t requestedWidth = 0;
std::uint32_t requestedHeight = 0;
bool requestedThisFrame = false;
@@ -68,7 +72,7 @@ private:
float g,
float b,
float a);
ViewportFrame BuildFrame(
EditorViewportFrame BuildFrame(
const ViewportEntry& entry,
const ::XCEngine::UI::UISize& requestedSize) const;
@@ -78,6 +82,7 @@ private:
bool m_surfacePresentationEnabled = false;
std::unordered_map<std::string, ViewportEntry> m_entries = {};
std::vector<std::vector<ViewportRenderTargets>> m_retiredTargetsBySlot = {};
SceneViewportRenderService m_sceneViewportRuntime = {};
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,10 +1,11 @@
#pragma once
#include "Viewport/EditorViewportPicking.h"
#include <XCEngine/RHI/RHICommandQueue.h>
#include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/Rendering/Picking/ObjectIdCodec.h>
#include <XCEngine/UI/Types.h>
#include <algorithm>
#include <array>
@@ -36,28 +37,6 @@ struct ViewportObjectIdReadbackRequest {
std::uint32_t pixelY = 0;
};
enum class ViewportObjectIdPickStatus : std::uint8_t {
Unavailable = 0,
Success,
ReadbackFailed
};
struct ViewportObjectIdPickResult {
ViewportObjectIdPickStatus status = ViewportObjectIdPickStatus::Unavailable;
std::uint64_t frameSerial = 0u;
::XCEngine::Rendering::RenderObjectId renderObjectId =
::XCEngine::Rendering::kInvalidRenderObjectId;
std::uint64_t resolvedEntityId = 0u;
bool HasResolvedSample() const {
return status == ViewportObjectIdPickStatus::Success;
}
bool HasResolvedEntity() const {
return HasResolvedSample() && resolvedEntityId != 0u;
}
};
inline bool CanPickViewportObjectId(const ViewportObjectIdPickContext& context) {
return context.commandQueue != nullptr &&
context.texture != nullptr &&

View File

@@ -1,16 +1,3 @@
#pragma once
#include "Viewport/ViewportObjectIdPicker.h"
namespace XCEngine::UI::Editor::App {
class IViewportObjectPickerService {
public:
virtual ~IViewportObjectPickerService() = default;
virtual ViewportObjectIdPickResult PickObject(
const ::XCEngine::UI::UISize& viewportSize,
const ::XCEngine::UI::UIPoint& viewportMousePosition) const = 0;
};
} // namespace XCEngine::UI::Editor::App
#include "Viewport/EditorViewportPicking.h"

View File

@@ -1,25 +1,11 @@
#pragma once
#include <XCEngine/UI/Types.h>
#include <string>
#include "Viewport/EditorViewportTypes.h"
namespace XCEngine::UI::Editor::App {
struct ViewportResourceRequirements {
bool requiresDepthSampling = false;
bool requiresObjectIdSurface = false;
bool requiresSelectionMaskSurface = false;
};
struct ViewportFrame {
::XCEngine::UI::UITextureHandle texture = {};
::XCEngine::UI::UISize requestedSize = {};
::XCEngine::UI::UISize renderSize = {};
bool hasTexture = false;
bool wasRequested = false;
std::string statusText = {};
};
using ViewportResourceRequirements = EditorViewportResourceRequirements;
using ViewportFrame = EditorViewportFrame;
} // namespace XCEngine::UI::Editor::App

View File

@@ -1,5 +1,5 @@
#include "Project/ProjectPanel.h"
#include "Assets/BuiltInIcons.h"
#include "Assets/EditorIconService.h"
#include "SystemInteractionService.h"
#include "Panels/EditorPanelIds.h"
@@ -40,6 +40,33 @@ public:
std::filesystem::path lastRevealPath = {};
};
class FakeIconService final : public EditorIconService {
public:
void Initialize(
Rendering::Host::UiTextureHost&,
Host::EditorHostResourceService&) override {}
void Shutdown() override {}
void BeginFrame() override {}
const ::XCEngine::UI::UITextureHandle& Resolve(BuiltInIconKind) const override {
return texture;
}
const ::XCEngine::UI::UITextureHandle* ResolveAssetPreview(
const std::filesystem::path&,
const std::filesystem::path&) override {
return nullptr;
}
const std::string& GetLastError() const override {
return error;
}
private:
::XCEngine::UI::UITextureHandle texture = {};
std::string error = {};
};
class TemporaryRepo final {
public:
TemporaryRepo() {
@@ -249,13 +276,13 @@ TEST(ProjectPanelTests, InjectedRuntimeCurrentFolderDrivesRenameFallbackWithoutT
EXPECT_EQ(evaluation.message, "Rename project item 'FolderA'.");
}
TEST(ProjectPanelTests, BuiltInIconsCanBeConfiguredBeforeRuntimeInitialization) {
TEST(ProjectPanelTests, IconServiceCanBeConfiguredBeforeRuntimeInitialization) {
TemporaryRepo repo = {};
ProjectPanel panel = {};
BuiltInIcons icons = {};
FakeIconService icons = {};
panel.SetBuiltInIcons(&icons);
panel.SetIconService(&icons);
panel.Initialize(repo.Root());
const UIEditorHostCommandEvaluationResult evaluation =