Add XCUI window compositor seam
This commit is contained in:
@@ -15,6 +15,7 @@ Old `editor` replacement is explicitly out of scope for this phase.
|
||||
- engine runtime coverage was tightened again around `UISystem` and concrete document-host rendering
|
||||
- `LayoutLab` continues as the editor widget proving ground for tree/list/property-section style controls
|
||||
- the demo sandbox and editor bridge APIs were tightened again without touching the old editor replacement scope
|
||||
- `new_editor` now has an explicit window-level compositor seam through `IEditorHostCompositor` / `ImGuiHostCompositor`
|
||||
- Old `editor` replacement remains deferred; all active execution still stays inside XCUI shared code and `new_editor`.
|
||||
|
||||
## Three-Layer Status
|
||||
@@ -59,6 +60,7 @@ Current gap:
|
||||
- `LayoutLab` now also covers editor-facing widget prototypes: `TreeView`, `TreeItem`, `ListView`, `ListItem`, `PropertySection`, and `FieldRow`.
|
||||
- Panel diagnostics were expanded to clearly separate preview/runtime/input state and native vs legacy paths.
|
||||
- The editor bridge layer now has smoke coverage for swapchain after-UI rendering hooks and SRV-backed ImGui texture descriptor registration.
|
||||
- `Application` no longer owns the ImGui backend directly; window presentation now routes through `IEditorHostCompositor` with an `ImGuiHostCompositor` implementation.
|
||||
- `XCNewEditor` builds successfully to `build/new_editor/bin/Debug/XCNewEditor.exe`.
|
||||
|
||||
Current gap:
|
||||
@@ -116,6 +118,10 @@ Current gap:
|
||||
- an `afterUiRender` swapchain callback hook in `D3D12WindowRenderer`
|
||||
- SRV-view based texture descriptor registration in `ImGuiBackendBridge`
|
||||
- smoke tests for window renderer, ImGui backend bridge, and console sink registration
|
||||
- `new_editor` host presentation now has a first-class compositor seam:
|
||||
- `IEditorHostCompositor`
|
||||
- `ImGuiHostCompositor`
|
||||
- `Application` frame/present flow routed through the compositor instead of direct `m_imguiBackend` ownership
|
||||
- `new_editor` panel/shell diagnostics improvements for hosted preview state.
|
||||
- XCUI asset document loading changed to prefer direct source compilation before `ResourceManager` fallback for the sandbox path, fixing the LayoutLab crash.
|
||||
- `UIDocumentCompiler.cpp` repaired enough to restore full local builds after the duplicated schema-helper regression.
|
||||
@@ -133,6 +139,6 @@ Current gap:
|
||||
|
||||
1. Expand runtime/game-layer ownership from the current document host + layered `UISystem` into reusable menu/HUD stack patterns and engine runtime integration.
|
||||
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 and more native shell-owned chrome.
|
||||
3. Start the window-level compositor split in `new_editor` so the editor shell can run through `ImGuiHostCompositor` first and then grow a native XCUI compositor path on the same seam.
|
||||
4. Reduce remaining ImGui leakage in hosted preview surfaces and panel contracts after the compositor seam is in place.
|
||||
3. Add a native XCUI host compositor on the existing window-level compositor seam so `new_editor` can present without going through ImGui-owned draw data.
|
||||
4. Reduce remaining ImGui leakage in hosted preview surfaces and panel contracts now that the compositor seam is in place.
|
||||
5. Continue phased validation, commit, push, and plan refresh after each stable batch.
|
||||
|
||||
@@ -50,6 +50,7 @@ set(NEW_EDITOR_SOURCES
|
||||
src/Rendering/MainWindowBackdropPass.cpp
|
||||
src/Rendering/MainWindowNativeBackdropRenderer.cpp
|
||||
src/XCUIBackend/ImGuiXCUIInputAdapter.cpp
|
||||
src/XCUIBackend/ImGuiHostCompositor.cpp
|
||||
src/XCUIBackend/XCUIEditorFontSetup.cpp
|
||||
src/XCUIBackend/XCUIAssetDocumentSource.cpp
|
||||
src/XCUIBackend/XCUIInputBridge.cpp
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
||||
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
|
||||
#include <imgui.h>
|
||||
@@ -179,7 +181,7 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
InitializeImGui();
|
||||
InitializeWindowCompositor();
|
||||
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
||||
&m_xcuiInputSource,
|
||||
CreateHostedPreviewPresenter(m_showNativeDemoPanelPreview));
|
||||
@@ -210,7 +212,7 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
||||
|
||||
m_demoPanel.reset();
|
||||
m_layoutLabPanel.reset();
|
||||
ShutdownImGui();
|
||||
ShutdownWindowCompositor();
|
||||
ShutdownRenderer();
|
||||
resourceManager.Shutdown();
|
||||
return static_cast<int>(message.wParam);
|
||||
@@ -232,7 +234,8 @@ LRESULT CALLBACK Application::StaticWndProc(HWND hwnd, UINT message, WPARAM wPar
|
||||
LRESULT Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
m_xcuiInputSource.HandleWindowMessage(hwnd, message, wParam, lParam);
|
||||
|
||||
if (::XCEngine::Editor::UI::ImGuiBackendBridge::HandleWindowMessage(hwnd, message, wParam, lParam)) {
|
||||
if (m_windowCompositor != nullptr &&
|
||||
m_windowCompositor->HandleWindowMessage(hwnd, message, wParam, lParam)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,28 +316,22 @@ bool Application::InitializeRenderer() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void Application::InitializeImGui() {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
ConfigureFonts();
|
||||
ImGui::StyleColorsDark();
|
||||
m_imguiBackend.Initialize(
|
||||
void Application::InitializeWindowCompositor() {
|
||||
m_windowCompositor = ::XCEngine::Editor::XCUIBackend::CreateImGuiWindowUICompositor();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->Initialize(
|
||||
m_hwnd,
|
||||
m_windowRenderer.GetDevice(),
|
||||
m_windowRenderer.GetCommandQueue(),
|
||||
m_windowRenderer.GetSrvHeap(),
|
||||
m_windowRenderer.GetSrvDescriptorSize(),
|
||||
m_windowRenderer.GetSrvDescriptorCount());
|
||||
m_windowRenderer,
|
||||
[]() { ConfigureFonts(); });
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ShutdownImGui() {
|
||||
void Application::ShutdownWindowCompositor() {
|
||||
DestroyHostedPreviewSurfaces();
|
||||
m_imguiBackend.Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->Shutdown();
|
||||
m_windowCompositor.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ShutdownRenderer() {
|
||||
@@ -347,7 +344,11 @@ void Application::ShutdownRenderer() {
|
||||
void Application::DestroyHostedPreviewSurfaces() {
|
||||
for (HostedPreviewOffscreenSurface& previewSurface : m_hostedPreviewSurfaces) {
|
||||
if (previewSurface.imguiCpuHandle.ptr != 0) {
|
||||
m_imguiBackend.FreeTextureDescriptor(previewSurface.imguiCpuHandle, previewSurface.imguiGpuHandle);
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->FreeTextureDescriptor(
|
||||
previewSurface.imguiCpuHandle,
|
||||
previewSurface.imguiGpuHandle);
|
||||
}
|
||||
}
|
||||
ShutdownAndDelete(previewSurface.colorView);
|
||||
ShutdownAndDelete(previewSurface.colorTexture);
|
||||
@@ -435,7 +436,11 @@ bool Application::EnsureHostedPreviewSurface(
|
||||
}
|
||||
|
||||
if (previewSurface.imguiCpuHandle.ptr != 0) {
|
||||
m_imguiBackend.FreeTextureDescriptor(previewSurface.imguiCpuHandle, previewSurface.imguiGpuHandle);
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->FreeTextureDescriptor(
|
||||
previewSurface.imguiCpuHandle,
|
||||
previewSurface.imguiGpuHandle);
|
||||
}
|
||||
}
|
||||
ShutdownAndDelete(previewSurface.colorView);
|
||||
ShutdownAndDelete(previewSurface.colorTexture);
|
||||
@@ -474,7 +479,8 @@ bool Application::EnsureHostedPreviewSurface(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_imguiBackend.CreateTextureDescriptor(
|
||||
if (m_windowCompositor == nullptr ||
|
||||
!m_windowCompositor->CreateTextureDescriptor(
|
||||
m_windowRenderer.GetRHIDevice(),
|
||||
previewSurface.colorTexture,
|
||||
&previewSurface.imguiCpuHandle,
|
||||
@@ -867,7 +873,14 @@ void Application::Frame() {
|
||||
m_hostedPreviewQueue.BeginFrame();
|
||||
m_hostedPreviewSurfaceRegistry.BeginFrame();
|
||||
SyncHostedPreviewSurfaces();
|
||||
m_imguiBackend.BeginFrame();
|
||||
if (m_windowCompositor == nullptr) {
|
||||
m_xcuiInputSource.ClearFrameTransients();
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowCompositor->RenderFrame(
|
||||
kClearColor,
|
||||
[this]() {
|
||||
RenderShellChrome();
|
||||
if (m_demoPanel) {
|
||||
m_demoPanel->RenderIfVisible();
|
||||
@@ -880,11 +893,7 @@ void Application::Frame() {
|
||||
}
|
||||
|
||||
SyncHostedPreviewSurfaces();
|
||||
|
||||
ImGui::Render();
|
||||
m_windowRenderer.Render(
|
||||
m_imguiBackend,
|
||||
kClearColor,
|
||||
},
|
||||
[this](
|
||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||
const ::XCEngine::Rendering::RenderSurface& surface) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
#include "Rendering/MainWindowNativeBackdropRenderer.h"
|
||||
#include "UI/ImGuiBackendBridge.h"
|
||||
#include "XCUIBackend/IWindowUICompositor.h"
|
||||
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||
#include "XCUIBackend/XCUIInputBridge.h"
|
||||
#include "XCUIBackend/XCUILayoutLabRuntime.h"
|
||||
@@ -77,8 +77,8 @@ private:
|
||||
|
||||
bool CreateMainWindow(HINSTANCE instance, int nCmdShow);
|
||||
bool InitializeRenderer();
|
||||
void InitializeImGui();
|
||||
void ShutdownImGui();
|
||||
void InitializeWindowCompositor();
|
||||
void ShutdownWindowCompositor();
|
||||
void ShutdownRenderer();
|
||||
void DestroyHostedPreviewSurfaces();
|
||||
void SyncHostedPreviewSurfaces();
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
|
||||
HWND m_hwnd = nullptr;
|
||||
::XCEngine::Editor::Platform::D3D12WindowRenderer m_windowRenderer;
|
||||
::XCEngine::Editor::UI::ImGuiBackendBridge m_imguiBackend;
|
||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IWindowUICompositor> m_windowCompositor;
|
||||
std::unique_ptr<XCUIDemoPanel> m_demoPanel;
|
||||
std::unique_ptr<XCUILayoutLabPanel> m_layoutLabPanel;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource m_xcuiInputSource;
|
||||
|
||||
52
new_editor/src/XCUIBackend/IEditorHostCompositor.h
Normal file
52
new_editor/src/XCUIBackend/IEditorHostCompositor.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "Platform/D3D12WindowRenderer.h"
|
||||
|
||||
#include <XCEngine/RHI/RHIDevice.h>
|
||||
#include <XCEngine/RHI/RHITexture.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <windows.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace XCUIBackend {
|
||||
|
||||
class IEditorHostCompositor {
|
||||
public:
|
||||
using ConfigureFontsCallback = std::function<void()>;
|
||||
using RenderCallback = ::XCEngine::Editor::Platform::D3D12WindowRenderer::RenderCallback;
|
||||
|
||||
virtual ~IEditorHostCompositor() = default;
|
||||
|
||||
virtual bool Initialize(
|
||||
HWND hwnd,
|
||||
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||||
const ConfigureFontsCallback& configureFonts) = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual bool HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) = 0;
|
||||
virtual void BeginFrame() = 0;
|
||||
virtual void EndFrameAndPresent(
|
||||
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||||
const float clearColor[4],
|
||||
const RenderCallback& beforeUiRender = {},
|
||||
const RenderCallback& afterUiRender = {}) = 0;
|
||||
virtual bool CreateTextureDescriptor(
|
||||
::XCEngine::RHI::RHIDevice* device,
|
||||
::XCEngine::RHI::RHITexture* texture,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle,
|
||||
ImTextureID* outTextureId) = 0;
|
||||
virtual void FreeTextureDescriptor(
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IEditorHostCompositor> CreateImGuiHostCompositor();
|
||||
|
||||
} // namespace XCUIBackend
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
99
new_editor/src/XCUIBackend/ImGuiHostCompositor.cpp
Normal file
99
new_editor/src/XCUIBackend/ImGuiHostCompositor.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "XCUIBackend/IEditorHostCompositor.h"
|
||||
|
||||
#include "UI/ImGuiBackendBridge.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace XCUIBackend {
|
||||
|
||||
namespace {
|
||||
|
||||
class ImGuiHostCompositor final : public IEditorHostCompositor {
|
||||
public:
|
||||
bool Initialize(
|
||||
HWND hwnd,
|
||||
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||||
const ConfigureFontsCallback& configureFonts) override {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
if (configureFonts) {
|
||||
configureFonts();
|
||||
}
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
m_backend.Initialize(
|
||||
hwnd,
|
||||
windowRenderer.GetDevice(),
|
||||
windowRenderer.GetCommandQueue(),
|
||||
windowRenderer.GetSrvHeap(),
|
||||
windowRenderer.GetSrvDescriptorSize(),
|
||||
windowRenderer.GetSrvDescriptorCount());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown() override {
|
||||
m_backend.Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
bool HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) override {
|
||||
return ::XCEngine::Editor::UI::ImGuiBackendBridge::HandleWindowMessage(
|
||||
hwnd,
|
||||
message,
|
||||
wParam,
|
||||
lParam);
|
||||
}
|
||||
|
||||
void BeginFrame() override {
|
||||
m_backend.BeginFrame();
|
||||
}
|
||||
|
||||
void EndFrameAndPresent(
|
||||
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||||
const float clearColor[4],
|
||||
const RenderCallback& beforeUiRender,
|
||||
const RenderCallback& afterUiRender) override {
|
||||
ImGui::Render();
|
||||
windowRenderer.Render(m_backend, clearColor, beforeUiRender, afterUiRender);
|
||||
}
|
||||
|
||||
bool CreateTextureDescriptor(
|
||||
::XCEngine::RHI::RHIDevice* device,
|
||||
::XCEngine::RHI::RHITexture* texture,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle,
|
||||
ImTextureID* outTextureId) override {
|
||||
return m_backend.CreateTextureDescriptor(
|
||||
device,
|
||||
texture,
|
||||
outCpuHandle,
|
||||
outGpuHandle,
|
||||
outTextureId);
|
||||
}
|
||||
|
||||
void FreeTextureDescriptor(
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle) override {
|
||||
m_backend.FreeTextureDescriptor(cpuHandle, gpuHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
::XCEngine::Editor::UI::ImGuiBackendBridge m_backend;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<IEditorHostCompositor> CreateImGuiHostCompositor() {
|
||||
return std::make_unique<ImGuiHostCompositor>();
|
||||
}
|
||||
|
||||
} // namespace XCUIBackend
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user