Isolate XCNewEditor default build from ImGui headers
This commit is contained in:
@@ -32,7 +32,11 @@ Old `editor` replacement is explicitly out of scope for this phase.
|
||||
- `Application.cpp` no longer directly includes `<imgui.h>`, even though the compatibility host path is still compiled into `new_editor`
|
||||
- The `new_editor` build now also has an explicit compatibility-source slice:
|
||||
- legacy ImGui shell sources and vendored ImGui backend sources are now grouped into a dedicated compatibility static library instead of being compiled directly as part of the main `XCNewEditor` source list
|
||||
- the main `XCNewEditor` target still sees ImGui headers through older editor bridge headers, but its default implementation source list is now narrower than the compatibility source list
|
||||
- the main `XCNewEditor` target no longer compiles those legacy sources directly, but it still carries `${IMGUI_SOURCE_DIR}` / `${IMGUI_SOURCE_DIR}/backends` on its private include surface and still reaches `<imgui.h>` through older editor bridge headers such as `editor/src/UI/ImGuiBackendBridge.h`
|
||||
- The next checkpoint to append after this file should be the main-target header-isolation milestone:
|
||||
- `XCNewEditor` drops direct `${IMGUI_SOURCE_DIR}` / `${IMGUI_SOURCE_DIR}/backends` include-directory requirements
|
||||
- the default native compile path no longer reaches `<imgui.h>` through `editor/src/UI/ImGuiBackendBridge.h` or equivalent bridge headers
|
||||
- `XCNewEditorImGuiCompat` remains the explicit compatibility-only consumer of legacy ImGui headers and backend sources
|
||||
- Old `editor` replacement remains deferred; all active execution still stays inside XCUI shared code and `new_editor`.
|
||||
|
||||
## Three-Layer Status
|
||||
@@ -127,7 +131,7 @@ Current gap:
|
||||
Current gap:
|
||||
|
||||
- The default shell host is now native, but the legacy ImGui shell and panel path still exists as a compatibility host and is still compiled into `new_editor`.
|
||||
- The default native shell path is still compiled through an `Application` translation unit that directly includes legacy ImGui host/presenter/compositor code, and `new_editor/CMakeLists.txt` still treats those legacy ImGui sources and include paths as target-global defaults.
|
||||
- The default native shell path is now split away from direct `ImGui::*` calls at the translation-unit/source-list level, but the main `XCNewEditor` target still keeps ImGui on its header/include surface through `target_include_directories(...)` and older editor bridge headers.
|
||||
- The native shell currently proves direct runtime composition, but its shell chrome is still a bespoke `Application`-side layout rather than a fully shared XCUI-authored editor shell document.
|
||||
- Editor-specialized widgets are still incomplete at the shared-module level: the authored prototypes exist, but virtualization, multi-selection/focus traversal, toolbar/menu chrome, menu interaction widgets, and icon-atlas widgets are not yet extracted into reusable XCUI modules.
|
||||
- The default native text path now uses a standalone Windows/GDI atlas through `XCUIStandaloneTextAtlasProvider`, but that provider still lives inside `new_editor` and is not yet promoted into a shared/cross-platform text subsystem.
|
||||
@@ -284,17 +288,18 @@ Current gap:
|
||||
- standalone atlas coverage now includes reset/rebuild, non-nominal size resolution, lazy glyph insertion/fallback behavior, and smoke use without any ImGui context
|
||||
- Legacy shell chrome / HUD rendering is now split out of the main `Application.cpp` translation unit:
|
||||
- the direct `ImGui::*` shell rendering path now lives in a dedicated legacy-only `Application` implementation file
|
||||
- the main `Application.cpp` native host path no longer directly includes `<imgui.h>`, reducing default-path compile-time coupling before the larger compat-target split
|
||||
- the main `Application.cpp` native host path no longer directly includes `<imgui.h>`, reducing default-path compile-time coupling while the remaining main-target header/include cleanup stays open
|
||||
- `new_editor` build composition is now split into main/native and compatibility slices:
|
||||
- the main `XCNewEditor` target no longer compiles legacy ImGui shell/panel/backend source files directly
|
||||
- legacy ImGui shell/panel/backend sources plus vendored ImGui sources now build behind a dedicated compatibility static library that the main executable links
|
||||
- the remaining build-side cleanup is narrower now: `XCNewEditor` still carries ImGui include directories and older editor bridge headers on its direct compile surface, so the next checkpoint is header/include isolation rather than another source-list split
|
||||
|
||||
## Phase Risks Still Open
|
||||
|
||||
- Schema instance validation is still open beyond `.xcschema` self-definition and artifact round-trip coverage.
|
||||
- `ScrollView` is still authored/static; no wheel-driven scrolling or virtualization yet.
|
||||
- The default native shell path still compiles through an `Application.cpp` unit that directly pulls in ImGui compatibility host code, so the native default path is not yet isolated at the translation-unit boundary.
|
||||
- `new_editor/CMakeLists.txt` still builds the legacy ImGui host/compositor/backend sources and include directories as target-global defaults instead of a compatibility-only slice.
|
||||
- `Application.cpp` is now split away from direct `ImGui::*` calls, but `XCNewEditor` still depends on ImGui at the header/include level because `new_editor/CMakeLists.txt` still adds `${IMGUI_SOURCE_DIR}` / `${IMGUI_SOURCE_DIR}/backends` to the main target and the editor bridge chain still reaches `editor/src/UI/ImGuiBackendBridge.h` -> `<imgui.h>`.
|
||||
- `XCNewEditorImGuiCompat` is now the compatibility-source slice, but the main executable still links it unconditionally and has not yet reduced its direct include surface to a compat-free default-path baseline.
|
||||
- The default native text path now owns its atlas without ImGui, but the provider is still Windows-only and remains trapped inside `new_editor` instead of a shared/cross-platform text layer.
|
||||
- Hosted-preview compatibility presentation still depends on an ImGui-only inline presenter path when not using the queued native surface path.
|
||||
- Editor widget coverage is still prototype-driven inside `LayoutLab`; it has not yet been promoted into a full reusable shared widget/runtime layer with command routing, virtualization, and property-edit transactions.
|
||||
@@ -302,12 +307,12 @@ Current gap:
|
||||
## Execution-Plan Alignment
|
||||
|
||||
- Against `XCUI完整架构设计与执行计划.md`, current `new_editor` progress should be treated as an early `Phase 8` foothold rather than full `Milestone E` completion:
|
||||
- landed: `NativeWindowUICompositor`, native shell packet composition, native hosted-preview publication, XCUI-owned texture registrations, native panel surface-image presentation, standalone native text-atlas ownership inside `new_editor`
|
||||
- not yet landed: default-path translation-unit isolation from legacy ImGui host code, promotion of the native text-atlas path into a shared/cross-platform text subsystem, shared XCUI-authored editor shell chrome
|
||||
- landed: `NativeWindowUICompositor`, native shell packet composition, native hosted-preview publication, XCUI-owned texture registrations, native panel surface-image presentation, standalone native text-atlas ownership inside `new_editor`, legacy `Application` TU split, and `XCNewEditorImGuiCompat`
|
||||
- not yet landed: main-target header/include isolation from ImGui, promotion of the native text-atlas path into a shared/cross-platform text subsystem, shared XCUI-authored editor shell chrome
|
||||
- That means the next de-ImGui push should not keep centering on hosted-preview publication; that milestone is now effectively closed for the default native shell path.
|
||||
- The real remaining default-path blockers are:
|
||||
- isolate legacy ImGui shell/compositor/presenter wiring from the default `Application` build path
|
||||
- stop treating ImGui include paths and backend sources as the default `new_editor` compilation surface
|
||||
- remove the main `XCNewEditor` target's direct ImGui header dependency by cutting the `D3D12WindowRenderer` / `ImGuiBackendBridge` include chain off the default compile path
|
||||
- stop treating ImGui include paths as part of the default `new_editor` compilation surface, leaving them only on the compatibility slice
|
||||
- harden and promote `XCUIStandaloneTextAtlasProvider` / editor font bootstrap into a shared native text subsystem
|
||||
- move native shell chrome out of bespoke `Application` layout code and into a shared XCUI shell model or authored shell document
|
||||
|
||||
@@ -315,7 +320,7 @@ Current gap:
|
||||
|
||||
1. Expand runtime/game-layer ownership from the current `SceneRuntime` UI context into scene-declared HUD/menu bootstrapping, draw submission, and higher-level runtime UI policies.
|
||||
2. Promote the current editor-facing widget prototypes out of authored `LayoutLab` content and into reusable XCUI widget/runtime modules, then continue with toolbar/menu chrome, shell-state adoption, virtualization, and broader focus/multi-selection behavior.
|
||||
3. Isolate legacy ImGui shell/compositor/presenter wiring from the default native path first, starting with `Application` translation-unit separation and a `new_editor` build split that stops treating ImGui include paths and sources as the default compilation surface.
|
||||
3. Finish the remaining main-target de-ImGui cleanup first: remove direct ImGui header/include requirements from `XCNewEditor`, keep ImGui confined to `XCNewEditorImGuiCompat`, and append the next checkpoint once the default native compile path no longer reaches `<imgui.h>`.
|
||||
4. Promote the current standalone native text/font path out of `new_editor`, harden its atlas invalidation/caching contract, and remove the remaining default-path ImGui text/bootstrap ownership around compatibility-only code.
|
||||
5. Promote the native shell chrome and card layout out of bespoke `Application` code into a shared XCUI/editor-layer shell model or authored shell document.
|
||||
6. Continue phased validation, commit, push, and plan refresh after each stable batch.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Application.h"
|
||||
#include "Platform/D3D12WindowRendererImGuiInterop.h"
|
||||
#include "Core/EditorLoggingSetup.h"
|
||||
#include "Core/ProjectRootResolver.h"
|
||||
#include "Core/EditorWindowTitle.h"
|
||||
@@ -264,7 +265,8 @@ void Application::RenderEditorFrame() {
|
||||
m_layerStack.onUIRender();
|
||||
UpdateWindowTitle();
|
||||
ImGui::Render();
|
||||
m_windowRenderer.Render(
|
||||
Platform::RenderImGuiFrame(
|
||||
m_windowRenderer,
|
||||
m_imguiBackend,
|
||||
kClearColor,
|
||||
[this](const Rendering::RenderContext& renderContext, const Rendering::RenderSurface&) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "UI/ImGuiBackendBridge.h"
|
||||
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/RHI/RHICommandList.h>
|
||||
@@ -16,6 +14,10 @@
|
||||
#include <XCEngine/RHI/D3D12/D3D12Device.h>
|
||||
#include <XCEngine/RHI/D3D12/D3D12SwapChain.h>
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
@@ -179,66 +181,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Render(
|
||||
UI::ImGuiBackendBridge& imguiBackend,
|
||||
const float clearColor[4],
|
||||
const RenderCallback& beforeUiRender = {},
|
||||
const RenderCallback& afterUiRender = {}) {
|
||||
auto* d3d12Queue = GetD3D12CommandQueue();
|
||||
auto* d3d12CommandList = GetD3D12CommandList();
|
||||
if (m_swapChain == nullptr ||
|
||||
d3d12Queue == nullptr ||
|
||||
d3d12CommandList == nullptr ||
|
||||
m_srvHeap == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t backBufferIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
if (backBufferIndex >= m_backBufferViews.size() ||
|
||||
backBufferIndex >= m_backBufferSurfaces.size() ||
|
||||
m_backBufferViews[backBufferIndex] == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* renderTargetView = m_backBufferViews[backBufferIndex];
|
||||
Rendering::RenderSurface& renderSurface = m_backBufferSurfaces[backBufferIndex];
|
||||
d3d12CommandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::Present,
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
d3d12CommandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
d3d12CommandList->ClearRenderTarget(renderTargetView, clearColor);
|
||||
|
||||
// Host-owned swapchain surfaces are handed to the callback already bound and ready for rendering.
|
||||
// The callback must leave the color attachment in RenderTarget state so ImGui can render after it.
|
||||
if (beforeUiRender) {
|
||||
beforeUiRender(GetRenderContext(), renderSurface);
|
||||
|
||||
// Viewport rendering can bind offscreen render targets on the shared command list.
|
||||
// Rebind the swapchain backbuffer so the subsequent ImGui draw data lands on the main window.
|
||||
d3d12CommandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
}
|
||||
|
||||
ID3D12DescriptorHeap* descriptorHeaps[] = { m_srvHeap->GetDescriptorHeap() };
|
||||
d3d12CommandList->SetDescriptorHeaps(1, descriptorHeaps);
|
||||
imguiBackend.RenderDrawData(d3d12CommandList->GetCommandList());
|
||||
|
||||
if (afterUiRender) {
|
||||
d3d12CommandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
afterUiRender(GetRenderContext(), renderSurface);
|
||||
}
|
||||
|
||||
d3d12CommandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
RHI::ResourceStates::Present);
|
||||
m_commandList->Close();
|
||||
|
||||
void* commandLists[] = { m_commandList };
|
||||
m_commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
m_swapChain->Present(1, 0);
|
||||
}
|
||||
|
||||
ID3D12Device* GetDevice() const {
|
||||
const auto* device = GetD3D12Device();
|
||||
return device ? device->GetDevice() : nullptr;
|
||||
|
||||
82
editor/src/Platform/D3D12WindowRendererImGuiInterop.h
Normal file
82
editor/src/Platform/D3D12WindowRendererImGuiInterop.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "D3D12WindowRenderer.h"
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include "../UI/ImGuiBackendBridge.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace Platform {
|
||||
|
||||
inline void RenderImGuiFrame(
|
||||
D3D12WindowRenderer& windowRenderer,
|
||||
UI::ImGuiBackendBridge& imguiBackend,
|
||||
const float clearColor[4],
|
||||
const D3D12WindowRenderer::RenderCallback& beforeUiRender = {},
|
||||
const D3D12WindowRenderer::RenderCallback& afterUiRender = {}) {
|
||||
const Rendering::RenderSurface* renderSurface = windowRenderer.GetCurrentRenderSurface();
|
||||
Rendering::RenderContext renderContext = windowRenderer.GetRenderContext();
|
||||
if (!renderContext.IsValid() ||
|
||||
renderContext.commandList == nullptr ||
|
||||
renderContext.commandQueue == nullptr ||
|
||||
windowRenderer.GetSwapChain() == nullptr ||
|
||||
renderSurface == nullptr ||
|
||||
windowRenderer.GetSrvHeap() == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto* d3d12CommandList = static_cast<RHI::D3D12CommandList*>(renderContext.commandList);
|
||||
|
||||
const auto& colorAttachments = renderSurface->GetColorAttachments();
|
||||
if (colorAttachments.empty() || colorAttachments[0] == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* renderTargetView = colorAttachments[0];
|
||||
renderContext.commandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::Present,
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
renderContext.commandList->ClearRenderTarget(renderTargetView, clearColor);
|
||||
|
||||
// Host-owned swapchain surfaces are handed to the callback already bound and ready for rendering.
|
||||
// The callback must leave the color attachment in RenderTarget state so ImGui can render after it.
|
||||
if (beforeUiRender) {
|
||||
beforeUiRender(renderContext, *renderSurface);
|
||||
|
||||
// Viewport rendering can bind offscreen render targets on the shared command list.
|
||||
// Rebind the swapchain backbuffer so the subsequent ImGui draw data lands on the main window.
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
}
|
||||
|
||||
ID3D12DescriptorHeap* descriptorHeaps[] = { windowRenderer.GetSrvHeap() };
|
||||
d3d12CommandList->SetDescriptorHeaps(1, descriptorHeaps);
|
||||
imguiBackend.RenderDrawData(d3d12CommandList->GetCommandList());
|
||||
|
||||
if (afterUiRender) {
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
afterUiRender(renderContext, *renderSurface);
|
||||
}
|
||||
|
||||
renderContext.commandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
RHI::ResourceStates::Present);
|
||||
renderContext.commandList->Close();
|
||||
|
||||
void* commandLists[] = { renderContext.commandList };
|
||||
renderContext.commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
windowRenderer.GetSwapChain()->Present(1, 0);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -79,27 +79,27 @@ set(NEW_EDITOR_IMGUI_COMPAT_SOURCES
|
||||
add_library(XCNewEditorImGuiCompat STATIC ${NEW_EDITOR_IMGUI_COMPAT_SOURCES})
|
||||
add_executable(${PROJECT_NAME} WIN32 ${NEW_EDITOR_SOURCES})
|
||||
|
||||
target_include_directories(XCNewEditorImGuiCompat PRIVATE
|
||||
set(NEW_EDITOR_COMMON_INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${XCENGINE_ROOT_DIR}/engine/include
|
||||
${XCENGINE_ROOT_DIR}/editor/src
|
||||
)
|
||||
|
||||
set(NEW_EDITOR_IMGUI_COMPAT_INCLUDE_DIRS
|
||||
${NEW_EDITOR_COMMON_INCLUDE_DIRS}
|
||||
${IMGUI_SOURCE_DIR}
|
||||
${IMGUI_SOURCE_DIR}/backends
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${XCENGINE_ROOT_DIR}/engine/include
|
||||
${XCENGINE_ROOT_DIR}/editor/src
|
||||
${IMGUI_SOURCE_DIR}
|
||||
${IMGUI_SOURCE_DIR}/backends
|
||||
)
|
||||
target_include_directories(XCNewEditorImGuiCompat PRIVATE ${NEW_EDITOR_IMGUI_COMPAT_INCLUDE_DIRS})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${NEW_EDITOR_COMMON_INCLUDE_DIRS})
|
||||
|
||||
file(TO_CMAKE_PATH "${XCENGINE_ROOT_DIR}" XCENGINE_ROOT_DIR_CMAKE)
|
||||
|
||||
target_compile_definitions(XCNewEditorImGuiCompat PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
NOMINMAX
|
||||
XCENGINE_NEW_EDITOR_REPO_ROOT="${XCENGINE_ROOT_DIR_CMAKE}"
|
||||
)
|
||||
target_compile_options(XCNewEditorImGuiCompat PRIVATE /utf-8)
|
||||
@@ -107,6 +107,7 @@ target_compile_options(XCNewEditorImGuiCompat PRIVATE /utf-8)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
NOMINMAX
|
||||
XCENGINE_NEW_EDITOR_REPO_ROOT="${XCENGINE_ROOT_DIR_CMAKE}"
|
||||
)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /utf-8)
|
||||
@@ -123,7 +124,12 @@ if(MSVC)
|
||||
COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/new_editor/compile-pdb-compat/Debug"
|
||||
COMPILE_PDB_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/new_editor/compile-pdb-compat/Release"
|
||||
COMPILE_PDB_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/new_editor/compile-pdb-compat/MinSizeRel"
|
||||
COMPILE_PDB_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/new_editor/compile-pdb-compat/RelWithDebInfo")
|
||||
COMPILE_PDB_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/new_editor/compile-pdb-compat/RelWithDebInfo"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/new_editor/pdb-compat"
|
||||
PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/new_editor/pdb-compat/Debug"
|
||||
PDB_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/new_editor/pdb-compat/Release"
|
||||
PDB_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/new_editor/pdb-compat/MinSizeRel"
|
||||
PDB_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/new_editor/pdb-compat/RelWithDebInfo")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:/INCREMENTAL:NO>)
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "Application.h"
|
||||
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||||
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
@@ -9,6 +8,10 @@
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef DrawText
|
||||
#undef DrawText
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace NewEditor {
|
||||
|
||||
@@ -37,48 +40,6 @@ void ShutdownAndDelete(ResourceType*& resource) {
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
const char* GetHostedPreviewPathLabel(bool nativeRequested, bool nativePresenterBound) {
|
||||
if (nativeRequested && nativePresenterBound) {
|
||||
return "native queued offscreen surface";
|
||||
}
|
||||
if (nativeRequested) {
|
||||
return "native requested, hosted presenter bound";
|
||||
}
|
||||
if (nativePresenterBound) {
|
||||
return "hosted presenter requested, native presenter still bound";
|
||||
}
|
||||
return "hosted presenter";
|
||||
}
|
||||
|
||||
const char* GetHostedPreviewStateLabel(
|
||||
bool hostedPreviewEnabled,
|
||||
bool nativePresenterBound,
|
||||
bool presentedThisFrame,
|
||||
bool queuedToNativePassThisFrame,
|
||||
bool surfaceImageAvailable,
|
||||
bool surfaceAllocated,
|
||||
bool surfaceReady,
|
||||
bool descriptorAvailable) {
|
||||
if (!hostedPreviewEnabled) {
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
if (nativePresenterBound) {
|
||||
if (surfaceImageAvailable && surfaceReady) {
|
||||
return "live";
|
||||
}
|
||||
if (queuedToNativePassThisFrame || surfaceAllocated || descriptorAvailable) {
|
||||
return "warming";
|
||||
}
|
||||
return "awaiting submit";
|
||||
}
|
||||
|
||||
if (presentedThisFrame) {
|
||||
return "live";
|
||||
}
|
||||
return "idle";
|
||||
}
|
||||
|
||||
bool ContainsPoint(const UI::UIRect& rect, const UI::UIPoint& point) {
|
||||
return point.x >= rect.x &&
|
||||
point.y >= rect.y &&
|
||||
@@ -174,42 +135,10 @@ NativeShellPanelLayout MakePanelLayout(
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter>
|
||||
Application::CreateHostedPreviewPresenter(bool nativePreview) {
|
||||
if (nativePreview) {
|
||||
return ::XCEngine::Editor::XCUIBackend::CreateQueuedNativeXCUIHostedPreviewPresenter(
|
||||
m_hostedPreviewQueue,
|
||||
m_hostedPreviewSurfaceRegistry);
|
||||
}
|
||||
|
||||
return ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiHostedPreviewPresenter();
|
||||
}
|
||||
|
||||
bool Application::IsNativeWindowHostEnabled() const {
|
||||
return m_windowHostMode == WindowHostMode::NativeXCUI;
|
||||
}
|
||||
|
||||
void Application::InitializePanelsForActiveWindowHost() {
|
||||
if (IsNativeWindowHostEnabled()) {
|
||||
InitializeNativeShell();
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeLegacyImGuiPanels();
|
||||
ConfigureHostedPreviewPresenters();
|
||||
}
|
||||
|
||||
void Application::InitializeLegacyImGuiPanels() {
|
||||
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
||||
&m_xcuiInputSource,
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)),
|
||||
::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiPanelCanvasHost());
|
||||
m_layoutLabPanel = std::make_unique<XCUILayoutLabPanel>(
|
||||
&m_xcuiInputSource,
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)),
|
||||
::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiPanelCanvasHost());
|
||||
}
|
||||
|
||||
void Application::InitializeNativeShell() {
|
||||
m_nativeActivePanel = m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo)
|
||||
? ShellPanelId::XCUIDemo
|
||||
@@ -238,115 +167,6 @@ bool Application::IsNativeHostedPreviewEnabled(ShellPanelId panelId) const {
|
||||
return m_shellChromeState.IsNativeHostedPreviewActive(panelId);
|
||||
}
|
||||
|
||||
void Application::ConfigureHostedPreviewPresenters() {
|
||||
const ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
||||
if (m_demoPanel != nullptr) {
|
||||
m_demoPanel->SetVisible(demoState != nullptr && demoState->visible);
|
||||
m_demoPanel->SetHostedPreviewEnabled(demoState == nullptr || demoState->hostedPreviewEnabled);
|
||||
m_demoPanel->SetHostedPreviewPresenter(CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)));
|
||||
}
|
||||
|
||||
const ShellPanelChromeState* layoutLabState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab);
|
||||
if (m_layoutLabPanel != nullptr) {
|
||||
m_layoutLabPanel->SetVisible(layoutLabState != nullptr && layoutLabState->visible);
|
||||
m_layoutLabPanel->SetHostedPreviewEnabled(layoutLabState == nullptr || layoutLabState->hostedPreviewEnabled);
|
||||
m_layoutLabPanel->SetHostedPreviewPresenter(
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ConfigureShellCommandRouter() {
|
||||
m_shellCommandRouter.Clear();
|
||||
|
||||
ShellCommandBindings bindings = {};
|
||||
bindings.getXCUIDemoPanelVisible = [this]() {
|
||||
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo);
|
||||
};
|
||||
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
||||
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUIDemo, visible);
|
||||
if (m_demoPanel != nullptr) {
|
||||
m_demoPanel->SetVisible(visible);
|
||||
}
|
||||
};
|
||||
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
||||
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUILayoutLab);
|
||||
};
|
||||
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
||||
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUILayoutLab, visible);
|
||||
if (m_layoutLabPanel != nullptr) {
|
||||
m_layoutLabPanel->SetVisible(visible);
|
||||
}
|
||||
};
|
||||
bindings.getImGuiDemoWindowVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow);
|
||||
};
|
||||
bindings.setImGuiDemoWindowVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow, visible);
|
||||
};
|
||||
bindings.getNativeBackdropVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop);
|
||||
};
|
||||
bindings.setNativeBackdropVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop, visible);
|
||||
};
|
||||
bindings.getPulseAccentEnabled = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent);
|
||||
};
|
||||
bindings.setPulseAccentEnabled = [this](bool enabled) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::PulseAccent, enabled);
|
||||
};
|
||||
bindings.getNativeXCUIOverlayVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay);
|
||||
};
|
||||
bindings.setNativeXCUIOverlayVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay, visible);
|
||||
};
|
||||
bindings.getHostedPreviewHudVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud);
|
||||
};
|
||||
bindings.setHostedPreviewHudVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud, visible);
|
||||
};
|
||||
bindings.getNativeDemoPanelPreviewEnabled = [this]() {
|
||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo);
|
||||
};
|
||||
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
||||
m_shellChromeState.SetHostedPreviewMode(
|
||||
ShellPanelId::XCUIDemo,
|
||||
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||
};
|
||||
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab);
|
||||
};
|
||||
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
||||
m_shellChromeState.SetHostedPreviewMode(
|
||||
ShellPanelId::XCUILayoutLab,
|
||||
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||
};
|
||||
bindings.onHostedPreviewModeChanged = [this]() { ConfigureHostedPreviewPresenters(); };
|
||||
|
||||
Application::RegisterShellViewCommands(m_shellCommandRouter, bindings);
|
||||
}
|
||||
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta
|
||||
Application::DispatchShellShortcuts(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot) {
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot shellSnapshot = snapshot;
|
||||
if (!IsNativeWindowHostEnabled()) {
|
||||
::XCEngine::Editor::XCUIBackend::ApplyLegacyImGuiHostInputCapture(shellSnapshot);
|
||||
}
|
||||
|
||||
if (!m_shellInputBridge.HasBaseline()) {
|
||||
m_shellInputBridge.Prime(shellSnapshot);
|
||||
}
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta frameDelta =
|
||||
m_shellInputBridge.Translate(shellSnapshot);
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIEditorCommandInputSnapshot commandSnapshot =
|
||||
Application::BuildShellShortcutSnapshot(frameDelta);
|
||||
m_shellCommandRouter.InvokeMatchingShortcut({ &commandSnapshot });
|
||||
return frameDelta;
|
||||
}
|
||||
|
||||
Application::HostedPreviewPanelDiagnostics Application::BuildHostedPreviewPanelDiagnostics(
|
||||
const char* debugName,
|
||||
const char* fallbackDebugSource,
|
||||
@@ -452,8 +272,7 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
||||
Frame();
|
||||
}
|
||||
|
||||
m_demoPanel.reset();
|
||||
m_layoutLabPanel.reset();
|
||||
ResetLegacyPanels();
|
||||
ShutdownWindowCompositor();
|
||||
ShutdownRenderer();
|
||||
resourceManager.Shutdown();
|
||||
@@ -558,18 +377,6 @@ bool Application::InitializeRenderer() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void Application::InitializeWindowCompositor() {
|
||||
m_windowCompositor = IsNativeWindowHostEnabled()
|
||||
? ::XCEngine::Editor::XCUIBackend::CreateNativeWindowUICompositor()
|
||||
: ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiWindowUICompositor();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->Initialize(
|
||||
m_hwnd,
|
||||
m_windowRenderer,
|
||||
[]() { (void)::XCEngine::Editor::XCUIBackend::ConfigureLegacyImGuiHostFonts(); });
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ShutdownWindowCompositor() {
|
||||
DestroyHostedPreviewSurfaces();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
@@ -599,15 +406,6 @@ void Application::DestroyHostedPreviewSurfaces() {
|
||||
m_hostedPreviewSurfaces.clear();
|
||||
}
|
||||
|
||||
void Application::SyncShellChromePanelStateFromPanels() {
|
||||
m_shellChromeState.SetPanelVisible(
|
||||
ShellPanelId::XCUIDemo,
|
||||
m_demoPanel != nullptr && m_demoPanel->IsVisible());
|
||||
m_shellChromeState.SetPanelVisible(
|
||||
ShellPanelId::XCUILayoutLab,
|
||||
m_layoutLabPanel != nullptr && m_layoutLabPanel->IsVisible());
|
||||
}
|
||||
|
||||
void Application::SyncHostedPreviewSurfaces() {
|
||||
const auto isNativePreviewEnabled = [this](const std::string& debugName) {
|
||||
const ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
#include "XCUIBackend/XCUIEditorCommandRouter.h"
|
||||
#include "panels/XCUIDemoPanel.h"
|
||||
#include "panels/XCUILayoutLabPanel.h"
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#include "Rendering/MainWindowNativeBackdropRenderer.h"
|
||||
#include "XCUIBackend/IWindowUICompositor.h"
|
||||
#include "XCUIBackend/NativeXCUIPanelCanvasHost.h"
|
||||
#include "XCUIBackend/XCUIDemoRuntime.h"
|
||||
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||
@@ -17,6 +11,9 @@
|
||||
#include "XCUIBackend/XCUIRHIRenderBackend.h"
|
||||
#include "XCUIBackend/XCUIShellChromeState.h"
|
||||
#include "XCUIBackend/XCUIStandaloneTextAtlasProvider.h"
|
||||
#include "XCUIBackend/UITextureRegistration.h"
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#include "Rendering/MainWindowNativeBackdropRenderer.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
@@ -29,10 +26,24 @@
|
||||
#include <windows.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace XCUIBackend {
|
||||
|
||||
class IWindowUICompositor;
|
||||
|
||||
} // namespace XCUIBackend
|
||||
} // namespace Editor
|
||||
|
||||
namespace NewEditor {
|
||||
|
||||
class XCUIDemoPanel;
|
||||
class XCUILayoutLabPanel;
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
using ShellChromeState = ::XCEngine::Editor::XCUIBackend::XCUIShellChromeState;
|
||||
using ShellPanelId = ::XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
||||
using ShellViewToggleId = ::XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
||||
@@ -416,6 +427,7 @@ private:
|
||||
HostedPreviewOffscreenSurface& previewSurface,
|
||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||
const ::XCEngine::UI::UIDrawData& drawData);
|
||||
void ResetLegacyPanels();
|
||||
void ConfigureShellCommandRouter();
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta DispatchShellShortcuts(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||
#include "panels/XCUIDemoPanel.h"
|
||||
#include "panels/XCUILayoutLabPanel.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -65,6 +67,176 @@ const char* GetHostedPreviewStateLabel(
|
||||
|
||||
} // namespace
|
||||
|
||||
Application::Application() = default;
|
||||
Application::~Application() = default;
|
||||
|
||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter>
|
||||
Application::CreateHostedPreviewPresenter(bool nativePreview) {
|
||||
if (nativePreview) {
|
||||
return ::XCEngine::Editor::XCUIBackend::CreateQueuedNativeXCUIHostedPreviewPresenter(
|
||||
m_hostedPreviewQueue,
|
||||
m_hostedPreviewSurfaceRegistry);
|
||||
}
|
||||
|
||||
return ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiHostedPreviewPresenter();
|
||||
}
|
||||
|
||||
void Application::InitializePanelsForActiveWindowHost() {
|
||||
if (IsNativeWindowHostEnabled()) {
|
||||
InitializeNativeShell();
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeLegacyImGuiPanels();
|
||||
ConfigureHostedPreviewPresenters();
|
||||
}
|
||||
|
||||
void Application::InitializeLegacyImGuiPanels() {
|
||||
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
||||
&m_xcuiInputSource,
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)),
|
||||
::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiPanelCanvasHost());
|
||||
m_layoutLabPanel = std::make_unique<XCUILayoutLabPanel>(
|
||||
&m_xcuiInputSource,
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)),
|
||||
::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiPanelCanvasHost());
|
||||
}
|
||||
|
||||
void Application::ConfigureHostedPreviewPresenters() {
|
||||
const ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
||||
if (m_demoPanel != nullptr) {
|
||||
m_demoPanel->SetVisible(demoState != nullptr && demoState->visible);
|
||||
m_demoPanel->SetHostedPreviewEnabled(demoState == nullptr || demoState->hostedPreviewEnabled);
|
||||
m_demoPanel->SetHostedPreviewPresenter(CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)));
|
||||
}
|
||||
|
||||
const ShellPanelChromeState* layoutLabState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab);
|
||||
if (m_layoutLabPanel != nullptr) {
|
||||
m_layoutLabPanel->SetVisible(layoutLabState != nullptr && layoutLabState->visible);
|
||||
m_layoutLabPanel->SetHostedPreviewEnabled(layoutLabState == nullptr || layoutLabState->hostedPreviewEnabled);
|
||||
m_layoutLabPanel->SetHostedPreviewPresenter(
|
||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ResetLegacyPanels() {
|
||||
m_demoPanel.reset();
|
||||
m_layoutLabPanel.reset();
|
||||
}
|
||||
|
||||
void Application::SyncShellChromePanelStateFromPanels() {
|
||||
m_shellChromeState.SetPanelVisible(
|
||||
ShellPanelId::XCUIDemo,
|
||||
m_demoPanel != nullptr && m_demoPanel->IsVisible());
|
||||
m_shellChromeState.SetPanelVisible(
|
||||
ShellPanelId::XCUILayoutLab,
|
||||
m_layoutLabPanel != nullptr && m_layoutLabPanel->IsVisible());
|
||||
}
|
||||
|
||||
void Application::ConfigureShellCommandRouter() {
|
||||
m_shellCommandRouter.Clear();
|
||||
|
||||
ShellCommandBindings bindings = {};
|
||||
bindings.getXCUIDemoPanelVisible = [this]() {
|
||||
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo);
|
||||
};
|
||||
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
||||
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUIDemo, visible);
|
||||
if (m_demoPanel != nullptr) {
|
||||
m_demoPanel->SetVisible(visible);
|
||||
}
|
||||
};
|
||||
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
||||
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUILayoutLab);
|
||||
};
|
||||
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
||||
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUILayoutLab, visible);
|
||||
if (m_layoutLabPanel != nullptr) {
|
||||
m_layoutLabPanel->SetVisible(visible);
|
||||
}
|
||||
};
|
||||
bindings.getImGuiDemoWindowVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow);
|
||||
};
|
||||
bindings.setImGuiDemoWindowVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow, visible);
|
||||
};
|
||||
bindings.getNativeBackdropVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop);
|
||||
};
|
||||
bindings.setNativeBackdropVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop, visible);
|
||||
};
|
||||
bindings.getPulseAccentEnabled = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent);
|
||||
};
|
||||
bindings.setPulseAccentEnabled = [this](bool enabled) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::PulseAccent, enabled);
|
||||
};
|
||||
bindings.getNativeXCUIOverlayVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay);
|
||||
};
|
||||
bindings.setNativeXCUIOverlayVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay, visible);
|
||||
};
|
||||
bindings.getHostedPreviewHudVisible = [this]() {
|
||||
return IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud);
|
||||
};
|
||||
bindings.setHostedPreviewHudVisible = [this](bool visible) {
|
||||
SetShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud, visible);
|
||||
};
|
||||
bindings.getNativeDemoPanelPreviewEnabled = [this]() {
|
||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo);
|
||||
};
|
||||
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
||||
m_shellChromeState.SetHostedPreviewMode(
|
||||
ShellPanelId::XCUIDemo,
|
||||
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||
};
|
||||
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab);
|
||||
};
|
||||
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
||||
m_shellChromeState.SetHostedPreviewMode(
|
||||
ShellPanelId::XCUILayoutLab,
|
||||
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||
};
|
||||
bindings.onHostedPreviewModeChanged = [this]() { ConfigureHostedPreviewPresenters(); };
|
||||
|
||||
Application::RegisterShellViewCommands(m_shellCommandRouter, bindings);
|
||||
}
|
||||
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta
|
||||
Application::DispatchShellShortcuts(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot) {
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot shellSnapshot = snapshot;
|
||||
if (!IsNativeWindowHostEnabled()) {
|
||||
::XCEngine::Editor::XCUIBackend::ApplyLegacyImGuiHostInputCapture(shellSnapshot);
|
||||
}
|
||||
|
||||
if (!m_shellInputBridge.HasBaseline()) {
|
||||
m_shellInputBridge.Prime(shellSnapshot);
|
||||
}
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta frameDelta =
|
||||
m_shellInputBridge.Translate(shellSnapshot);
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIEditorCommandInputSnapshot commandSnapshot =
|
||||
Application::BuildShellShortcutSnapshot(frameDelta);
|
||||
m_shellCommandRouter.InvokeMatchingShortcut({ &commandSnapshot });
|
||||
return frameDelta;
|
||||
}
|
||||
|
||||
void Application::InitializeWindowCompositor() {
|
||||
m_windowCompositor = IsNativeWindowHostEnabled()
|
||||
? ::XCEngine::Editor::XCUIBackend::CreateNativeWindowUICompositor()
|
||||
: ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiWindowUICompositor();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->Initialize(
|
||||
m_hwnd,
|
||||
m_windowRenderer,
|
||||
[]() { (void)::XCEngine::Editor::XCUIBackend::ConfigureLegacyImGuiHostFonts(); });
|
||||
}
|
||||
}
|
||||
|
||||
void Application::FrameLegacyImGuiHost() {
|
||||
Application::BeginHostedPreviewFrameLifecycle(
|
||||
m_hostedPreviewQueue,
|
||||
|
||||
7
new_editor/src/Platform/D3D12WindowRenderer.h
Normal file
7
new_editor/src/Platform/D3D12WindowRenderer.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "../../../editor/src/Platform/D3D12WindowRenderer.h"
|
||||
83
new_editor/src/Platform/D3D12WindowRendererImGuiInterop.h
Normal file
83
new_editor/src/Platform/D3D12WindowRendererImGuiInterop.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "D3D12WindowRenderer.h"
|
||||
|
||||
#include "../UI/ImGuiBackendBridge.h"
|
||||
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandList.h>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace Platform {
|
||||
|
||||
inline void RenderImGuiFrame(
|
||||
D3D12WindowRenderer& windowRenderer,
|
||||
UI::ImGuiBackendBridge& imguiBackend,
|
||||
const float clearColor[4],
|
||||
const D3D12WindowRenderer::RenderCallback& beforeUiRender = {},
|
||||
const D3D12WindowRenderer::RenderCallback& afterUiRender = {}) {
|
||||
const Rendering::RenderSurface* renderSurface = windowRenderer.GetCurrentRenderSurface();
|
||||
Rendering::RenderContext renderContext = windowRenderer.GetRenderContext();
|
||||
auto* d3d12CommandList = dynamic_cast<RHI::D3D12CommandList*>(renderContext.commandList);
|
||||
if (!renderContext.IsValid() ||
|
||||
d3d12CommandList == nullptr ||
|
||||
renderContext.commandQueue == nullptr ||
|
||||
windowRenderer.GetSwapChain() == nullptr ||
|
||||
renderSurface == nullptr ||
|
||||
windowRenderer.GetSrvHeap() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& colorAttachments = renderSurface->GetColorAttachments();
|
||||
if (colorAttachments.empty() || colorAttachments[0] == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* renderTargetView = colorAttachments[0];
|
||||
renderContext.commandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::Present,
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
renderContext.commandList->ClearRenderTarget(renderTargetView, clearColor);
|
||||
|
||||
if (beforeUiRender) {
|
||||
beforeUiRender(renderContext, *renderSurface);
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
}
|
||||
|
||||
ID3D12DescriptorHeap* descriptorHeaps[] = { windowRenderer.GetSrvHeap() };
|
||||
d3d12CommandList->SetDescriptorHeaps(1, descriptorHeaps);
|
||||
imguiBackend.RenderDrawData(d3d12CommandList->GetCommandList());
|
||||
|
||||
if (afterUiRender) {
|
||||
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||||
afterUiRender(renderContext, *renderSurface);
|
||||
}
|
||||
|
||||
renderContext.commandList->TransitionBarrier(
|
||||
renderTargetView,
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
RHI::ResourceStates::Present);
|
||||
renderContext.commandList->Close();
|
||||
|
||||
void* commandLists[] = { renderContext.commandList };
|
||||
renderContext.commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
windowRenderer.GetSwapChain()->Present(1, 0);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -1,23 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "XCUIBackend/UITextureRegistration.h"
|
||||
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/RHI/RHIDevice.h>
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace Platform {
|
||||
|
||||
class D3D12WindowRenderer;
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
namespace XCUIBackend {
|
||||
|
||||
class IEditorHostCompositor {
|
||||
public:
|
||||
using ConfigureFontsCallback = std::function<void()>;
|
||||
using RenderCallback = ::XCEngine::Editor::Platform::D3D12WindowRenderer::RenderCallback;
|
||||
using RenderCallback =
|
||||
std::function<void(const ::XCEngine::Rendering::RenderContext&, const ::XCEngine::Rendering::RenderSurface&)>;
|
||||
|
||||
virtual ~IEditorHostCompositor() = default;
|
||||
|
||||
|
||||
@@ -1,24 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "XCUIBackend/UITextureRegistration.h"
|
||||
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/RHI/RHIDevice.h>
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace Platform {
|
||||
|
||||
class D3D12WindowRenderer;
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
namespace XCUIBackend {
|
||||
|
||||
class IWindowUICompositor {
|
||||
public:
|
||||
using ConfigureFontsCallback = std::function<void()>;
|
||||
using UiRenderCallback = std::function<void()>;
|
||||
using RenderCallback = ::XCEngine::Editor::Platform::D3D12WindowRenderer::RenderCallback;
|
||||
using RenderCallback =
|
||||
std::function<void(const ::XCEngine::Rendering::RenderContext&, const ::XCEngine::Rendering::RenderSurface&)>;
|
||||
|
||||
virtual ~IWindowUICompositor() = default;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "XCUIBackend/IEditorHostCompositor.h"
|
||||
|
||||
#include "Platform/D3D12WindowRendererImGuiInterop.h"
|
||||
#include "UI/ImGuiBackendBridge.h"
|
||||
|
||||
#include <imgui.h>
|
||||
@@ -61,7 +62,12 @@ public:
|
||||
const RenderCallback& beforeUiRender,
|
||||
const RenderCallback& afterUiRender) override {
|
||||
ImGui::Render();
|
||||
windowRenderer.Render(m_backend, clearColor, beforeUiRender, afterUiRender);
|
||||
::XCEngine::Editor::Platform::RenderImGuiFrame(
|
||||
windowRenderer,
|
||||
m_backend,
|
||||
clearColor,
|
||||
beforeUiRender,
|
||||
afterUiRender);
|
||||
}
|
||||
|
||||
bool CreateTextureDescriptor(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/RHI/RHICommandList.h>
|
||||
|
||||
@@ -85,6 +85,9 @@ set(NEW_EDITOR_SHELL_CHROME_STATE_HEADER
|
||||
set(NEW_EDITOR_SHELL_CHROME_STATE_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIShellChromeState.cpp
|
||||
)
|
||||
set(NEW_EDITOR_NATIVE_SHELL_LAYOUT_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUINativeShellLayout.h
|
||||
)
|
||||
set(NEW_EDITOR_APPLICATION_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/Application.h
|
||||
)
|
||||
@@ -115,6 +118,9 @@ set(NEW_EDITOR_IMGUI_TEXT_ATLAS_PROVIDER_HEADER
|
||||
set(NEW_EDITOR_IMGUI_TEXT_ATLAS_PROVIDER_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/ImGuiTextAtlasProvider.cpp
|
||||
)
|
||||
set(NEW_EDITOR_IMGUI_HOST_COMPOSITOR_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/ImGuiHostCompositor.cpp
|
||||
)
|
||||
set(NEW_EDITOR_FONT_SETUP_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIEditorFontSetup.h
|
||||
)
|
||||
@@ -130,6 +136,12 @@ set(NEW_EDITOR_STANDALONE_TEXT_ATLAS_PROVIDER_SOURCE
|
||||
set(NEW_EDITOR_HOSTED_PREVIEW_PRESENTER_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIHostedPreviewPresenter.h
|
||||
)
|
||||
set(NEW_EDITOR_LEGACY_IMGUI_HOST_INTEROP_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/LegacyImGuiHostInterop.h
|
||||
)
|
||||
set(NEW_EDITOR_LEGACY_IMGUI_HOST_INTEROP_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/LegacyImGuiHostInterop.cpp
|
||||
)
|
||||
set(NEW_EDITOR_WINDOW_UI_COMPOSITOR_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/IWindowUICompositor.h
|
||||
)
|
||||
@@ -411,6 +423,51 @@ else()
|
||||
message(STATUS "Skipping new_editor_xcui_hosted_preview_presenter_tests because presenter header or ImGui sources are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_LEGACY_IMGUI_HOST_INTEROP_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_LEGACY_IMGUI_HOST_INTEROP_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_legacy_imgui_host_interop.cpp" AND
|
||||
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||
add_executable(new_editor_legacy_imgui_host_interop_tests
|
||||
test_legacy_imgui_host_interop.cpp
|
||||
${NEW_EDITOR_LEGACY_IMGUI_HOST_INTEROP_SOURCE}
|
||||
${NEW_EDITOR_IMGUI_HOST_COMPOSITOR_SOURCE}
|
||||
${NEW_EDITOR_FONT_SETUP_SOURCE}
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_demo.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_widgets.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends/imgui_impl_win32.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends/imgui_impl_dx12.cpp
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_legacy_imgui_host_interop_tests)
|
||||
|
||||
target_link_libraries(new_editor_legacy_imgui_host_interop_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
d3d12
|
||||
dxgi
|
||||
user32
|
||||
gdi32
|
||||
comdlg32
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_legacy_imgui_host_interop_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
${CMAKE_SOURCE_DIR}/editor/src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_legacy_imgui_host_interop_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_legacy_imgui_host_interop_tests because helper, test source, or ImGui sources are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_WINDOW_UI_COMPOSITOR_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_IMGUI_WINDOW_UI_COMPOSITOR_HEADER}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_imgui_window_ui_compositor.cpp")
|
||||
@@ -469,9 +526,6 @@ if(EXISTS "${NEW_EDITOR_WINDOW_UI_COMPOSITOR_HEADER}" AND
|
||||
target_include_directories(new_editor_native_window_ui_compositor_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
${CMAKE_SOURCE_DIR}/editor/src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_native_window_ui_compositor_tests)
|
||||
@@ -586,6 +640,31 @@ else()
|
||||
message(STATUS "Skipping new_editor_xcui_shell_chrome_state_tests because shell chrome state files or the test source are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_NATIVE_SHELL_LAYOUT_HEADER}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_native_shell_layout.cpp")
|
||||
add_executable(new_editor_xcui_native_shell_layout_tests
|
||||
test_xcui_native_shell_layout.cpp
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_xcui_native_shell_layout_tests)
|
||||
|
||||
target_link_libraries(new_editor_xcui_native_shell_layout_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_xcui_native_shell_layout_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_xcui_native_shell_layout_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_xcui_native_shell_layout_tests because the layout helper header or the test source is missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_APPLICATION_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_COMMAND_ROUTER_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_application_shell_command_bindings.cpp")
|
||||
@@ -606,9 +685,6 @@ if(EXISTS "${NEW_EDITOR_APPLICATION_HEADER}" AND
|
||||
target_include_directories(new_editor_application_shell_command_bindings_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
${CMAKE_SOURCE_DIR}/editor/src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_application_shell_command_bindings_tests)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#include "XCUIBackend/IWindowUICompositor.h"
|
||||
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||||
#include "XCUIBackend/UITextureRegistration.h"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#include "Platform/D3D12WindowRendererImGuiInterop.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@@ -16,7 +17,8 @@ TEST(D3D12WindowRendererApiTest, ExposesSurfaceAwareRenderCallbackAndAccessor) {
|
||||
decltype(std::declval<D3D12WindowRenderer&>().GetCurrentRenderSurface()),
|
||||
const RenderSurface*>);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<D3D12WindowRenderer&>().Render(
|
||||
decltype(::XCEngine::Editor::Platform::RenderImGuiFrame(
|
||||
std::declval<D3D12WindowRenderer&>(),
|
||||
std::declval<::XCEngine::Editor::UI::ImGuiBackendBridge&>(),
|
||||
std::declval<const float*>(),
|
||||
std::declval<const Callback&>())),
|
||||
|
||||
Reference in New Issue
Block a user