Split legacy ImGui shell out of Application
This commit is contained in:
@@ -27,6 +27,9 @@ Old `editor` replacement is explicitly out of scope for this phase.
|
|||||||
- The default native text path is now also de-ImGuiized inside `new_editor`:
|
- The default native text path is now also de-ImGuiized inside `new_editor`:
|
||||||
- `XCUIStandaloneTextAtlasProvider` now builds and owns its atlas through a Windows/GDI raster path instead of using ImGui font-atlas internals
|
- `XCUIStandaloneTextAtlasProvider` now builds and owns its atlas through a Windows/GDI raster path instead of using ImGui font-atlas internals
|
||||||
- the standalone atlas provider now exposes both `RGBA32` and `Alpha8` views, supports non-nominal size resolution, lazily adds non-prebaked BMP glyphs, and falls back to `?` when a glyph cannot be rasterized
|
- the standalone atlas provider now exposes both `RGBA32` and `Alpha8` views, supports non-nominal size resolution, lazily adds non-prebaked BMP glyphs, and falls back to `?` when a glyph cannot be rasterized
|
||||||
|
- The default native shell path now also has a cleaner translation-unit seam:
|
||||||
|
- legacy ImGui shell chrome / HUD rendering now lives in a dedicated legacy-only `Application` translation unit instead of keeping direct `ImGui::*` calls inside the main native host TU
|
||||||
|
- `Application.cpp` no longer directly includes `<imgui.h>`, even though the compatibility host path is still compiled into `new_editor`
|
||||||
- Old `editor` replacement remains deferred; all active execution still stays inside XCUI shared code and `new_editor`.
|
- Old `editor` replacement remains deferred; all active execution still stays inside XCUI shared code and `new_editor`.
|
||||||
|
|
||||||
## Three-Layer Status
|
## Three-Layer Status
|
||||||
@@ -276,6 +279,9 @@ Current gap:
|
|||||||
- atlas ownership now stays inside a standalone provider implementation built on Windows/GDI glyph rasterization
|
- atlas ownership now stays inside a standalone provider implementation built on Windows/GDI glyph rasterization
|
||||||
- default editor atlas prewarms the current supported nominal sizes, exposes both `RGBA32` and `Alpha8` atlas views, lazily inserts non-prebaked BMP glyphs, and falls back to `?` for unrasterizable codepoints
|
- default editor atlas prewarms the current supported nominal sizes, exposes both `RGBA32` and `Alpha8` atlas views, lazily inserts non-prebaked BMP glyphs, and falls back to `?` for unrasterizable codepoints
|
||||||
- standalone atlas coverage now includes reset/rebuild, non-nominal size resolution, lazy glyph insertion/fallback behavior, and smoke use without any ImGui context
|
- 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
|
||||||
|
|
||||||
## Phase Risks Still Open
|
## Phase Risks Still Open
|
||||||
|
|
||||||
|
|||||||
@@ -44,13 +44,16 @@ endif()
|
|||||||
set(NEW_EDITOR_SOURCES
|
set(NEW_EDITOR_SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/Application.cpp
|
src/Application.cpp
|
||||||
|
src/ApplicationLegacyImGui.cpp
|
||||||
src/panels/Panel.cpp
|
src/panels/Panel.cpp
|
||||||
src/panels/XCUIDemoPanel.cpp
|
src/panels/XCUIDemoPanel.cpp
|
||||||
src/panels/XCUILayoutLabPanel.cpp
|
src/panels/XCUILayoutLabPanel.cpp
|
||||||
src/Rendering/MainWindowBackdropPass.cpp
|
src/Rendering/MainWindowBackdropPass.cpp
|
||||||
src/Rendering/MainWindowNativeBackdropRenderer.cpp
|
src/Rendering/MainWindowNativeBackdropRenderer.cpp
|
||||||
src/XCUIBackend/ImGuiXCUIInputAdapter.cpp
|
src/XCUIBackend/ImGuiXCUIInputAdapter.cpp
|
||||||
|
src/XCUIBackend/LegacyImGuiHostInterop.cpp
|
||||||
src/XCUIBackend/ImGuiHostCompositor.cpp
|
src/XCUIBackend/ImGuiHostCompositor.cpp
|
||||||
|
src/XCUIBackend/NativeWindowUICompositor.cpp
|
||||||
src/XCUIBackend/XCUIEditorFontSetup.cpp
|
src/XCUIBackend/XCUIEditorFontSetup.cpp
|
||||||
src/XCUIBackend/XCUIAssetDocumentSource.cpp
|
src/XCUIBackend/XCUIAssetDocumentSource.cpp
|
||||||
src/XCUIBackend/XCUIEditorCommandRouter.cpp
|
src/XCUIBackend/XCUIEditorCommandRouter.cpp
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||||
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
|
||||||
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
|
||||||
#include "XCUIBackend/NativeWindowUICompositor.h"
|
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||||||
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||||
#include <XCEngine/UI/DrawData.h>
|
#include <XCEngine/UI/DrawData.h>
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -41,13 +37,6 @@ void ShutdownAndDelete(ResourceType*& resource) {
|
|||||||
resource = nullptr;
|
resource = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureFonts() {
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImFont* uiFont = nullptr;
|
|
||||||
::XCEngine::Editor::XCUIBackend::BuildDefaultXCUIEditorFontAtlas(*io.Fonts, uiFont);
|
|
||||||
io.FontDefault = uiFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GetHostedPreviewPathLabel(bool nativeRequested, bool nativePresenterBound) {
|
const char* GetHostedPreviewPathLabel(bool nativeRequested, bool nativePresenterBound) {
|
||||||
if (nativeRequested && nativePresenterBound) {
|
if (nativeRequested && nativePresenterBound) {
|
||||||
return "native queued offscreen surface";
|
return "native queued offscreen surface";
|
||||||
@@ -193,13 +182,34 @@ Application::CreateHostedPreviewPresenter(bool nativePreview) {
|
|||||||
m_hostedPreviewSurfaceRegistry);
|
m_hostedPreviewSurfaceRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
return ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiHostedPreviewPresenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::IsNativeWindowHostEnabled() const {
|
bool Application::IsNativeWindowHostEnabled() const {
|
||||||
return m_windowHostMode == WindowHostMode::NativeXCUI;
|
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() {
|
void Application::InitializeNativeShell() {
|
||||||
m_nativeActivePanel = m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo)
|
m_nativeActivePanel = m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo)
|
||||||
? ShellPanelId::XCUIDemo
|
? ShellPanelId::XCUIDemo
|
||||||
@@ -323,9 +333,7 @@ Application::DispatchShellShortcuts(
|
|||||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot) {
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot) {
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot shellSnapshot = snapshot;
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot shellSnapshot = snapshot;
|
||||||
if (!IsNativeWindowHostEnabled()) {
|
if (!IsNativeWindowHostEnabled()) {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
::XCEngine::Editor::XCUIBackend::ApplyLegacyImGuiHostInputCapture(shellSnapshot);
|
||||||
shellSnapshot.wantCaptureKeyboard = io.WantCaptureKeyboard;
|
|
||||||
shellSnapshot.wantTextInput = io.WantTextInput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_shellInputBridge.HasBaseline()) {
|
if (!m_shellInputBridge.HasBaseline()) {
|
||||||
@@ -419,19 +427,7 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InitializeWindowCompositor();
|
InitializeWindowCompositor();
|
||||||
if (IsNativeWindowHostEnabled()) {
|
InitializePanelsForActiveWindowHost();
|
||||||
InitializeNativeShell();
|
|
||||||
} else {
|
|
||||||
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
|
||||||
&m_xcuiInputSource,
|
|
||||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)),
|
|
||||||
::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost());
|
|
||||||
m_layoutLabPanel = std::make_unique<XCUILayoutLabPanel>(
|
|
||||||
&m_xcuiInputSource,
|
|
||||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)),
|
|
||||||
::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost());
|
|
||||||
ConfigureHostedPreviewPresenters();
|
|
||||||
}
|
|
||||||
m_shellInputBridge.Reset();
|
m_shellInputBridge.Reset();
|
||||||
ConfigureShellCommandRouter();
|
ConfigureShellCommandRouter();
|
||||||
m_running = true;
|
m_running = true;
|
||||||
@@ -565,12 +561,12 @@ bool Application::InitializeRenderer() {
|
|||||||
void Application::InitializeWindowCompositor() {
|
void Application::InitializeWindowCompositor() {
|
||||||
m_windowCompositor = IsNativeWindowHostEnabled()
|
m_windowCompositor = IsNativeWindowHostEnabled()
|
||||||
? ::XCEngine::Editor::XCUIBackend::CreateNativeWindowUICompositor()
|
? ::XCEngine::Editor::XCUIBackend::CreateNativeWindowUICompositor()
|
||||||
: ::XCEngine::Editor::XCUIBackend::CreateImGuiWindowUICompositor();
|
: ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiWindowUICompositor();
|
||||||
if (m_windowCompositor != nullptr) {
|
if (m_windowCompositor != nullptr) {
|
||||||
m_windowCompositor->Initialize(
|
m_windowCompositor->Initialize(
|
||||||
m_hwnd,
|
m_hwnd,
|
||||||
m_windowRenderer,
|
m_windowRenderer,
|
||||||
[]() { ConfigureFonts(); });
|
[]() { (void)::XCEngine::Editor::XCUIBackend::ConfigureLegacyImGuiHostFonts(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1001,7 +997,7 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
|||||||
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
||||||
panelState->previewDebugName.data(),
|
panelState->previewDebugName.data(),
|
||||||
hostedSurfaceImage);
|
hostedSurfaceImage);
|
||||||
const NativeHostedPreviewConsumption previewConsumption =
|
const Application::NativeHostedPreviewConsumption previewConsumption =
|
||||||
Application::ResolveNativeHostedPreviewConsumption(
|
Application::ResolveNativeHostedPreviewConsumption(
|
||||||
nativeHostedPreview,
|
nativeHostedPreview,
|
||||||
hasHostedSurfaceDescriptor,
|
hasHostedSurfaceDescriptor,
|
||||||
@@ -1168,7 +1164,7 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
|||||||
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
||||||
panelState->previewDebugName.data(),
|
panelState->previewDebugName.data(),
|
||||||
hostedSurfaceImage);
|
hostedSurfaceImage);
|
||||||
const NativeHostedPreviewConsumption previewConsumption =
|
const Application::NativeHostedPreviewConsumption previewConsumption =
|
||||||
Application::ResolveNativeHostedPreviewConsumption(
|
Application::ResolveNativeHostedPreviewConsumption(
|
||||||
nativeHostedPreview,
|
nativeHostedPreview,
|
||||||
hasHostedSurfaceDescriptor,
|
hasHostedSurfaceDescriptor,
|
||||||
@@ -1309,83 +1305,6 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
|||||||
return composedDrawData;
|
return composedDrawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::FrameLegacyImGuiHost() {
|
|
||||||
Application::BeginHostedPreviewFrameLifecycle(
|
|
||||||
m_hostedPreviewQueue,
|
|
||||||
m_hostedPreviewSurfaceRegistry);
|
|
||||||
SyncHostedPreviewSurfaces();
|
|
||||||
if (m_windowCompositor == nullptr) {
|
|
||||||
m_xcuiInputSource.ClearFrameTransients();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_windowCompositor->RenderFrame(
|
|
||||||
kClearColor,
|
|
||||||
[this]() {
|
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions options = {};
|
|
||||||
options.timestampNanoseconds = MakeFrameTimestampNanoseconds();
|
|
||||||
options.windowFocused = m_xcuiInputSource.IsWindowFocused();
|
|
||||||
const auto shellSnapshot = m_xcuiInputSource.CaptureSnapshot(options);
|
|
||||||
DispatchShellShortcuts(shellSnapshot);
|
|
||||||
RenderShellChrome();
|
|
||||||
if (m_demoPanel) {
|
|
||||||
m_demoPanel->RenderIfVisible();
|
|
||||||
}
|
|
||||||
if (m_layoutLabPanel) {
|
|
||||||
m_layoutLabPanel->RenderIfVisible();
|
|
||||||
}
|
|
||||||
bool showImGuiDemoWindow = IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow);
|
|
||||||
if (showImGuiDemoWindow) {
|
|
||||||
ImGui::ShowDemoWindow(&showImGuiDemoWindow);
|
|
||||||
SetShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow, showImGuiDemoWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncShellChromePanelStateFromPanels();
|
|
||||||
SyncHostedPreviewSurfaces();
|
|
||||||
},
|
|
||||||
[this](
|
|
||||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
|
||||||
const ::XCEngine::Rendering::RenderSurface& surface) {
|
|
||||||
RenderQueuedHostedPreviews(renderContext, surface);
|
|
||||||
|
|
||||||
if (!IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop) &&
|
|
||||||
!IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindowNativeBackdropRenderer::FrameState frameState = {};
|
|
||||||
frameState.elapsedSeconds = static_cast<float>(
|
|
||||||
std::chrono::duration<double>(std::chrono::steady_clock::now() - m_startTime).count());
|
|
||||||
frameState.pulseAccent = IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent);
|
|
||||||
frameState.drawBackdrop = IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop);
|
|
||||||
if (IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
|
||||||
const float width = static_cast<float>(surface.GetWidth());
|
|
||||||
const float height = static_cast<float>(surface.GetHeight());
|
|
||||||
const float horizontalMargin = (std::min)(width * 0.14f, 128.0f);
|
|
||||||
const float topMargin = (std::min)(height * 0.15f, 132.0f);
|
|
||||||
const float bottomMargin = (std::min)(height * 0.12f, 96.0f);
|
|
||||||
|
|
||||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState overlayInput = {};
|
|
||||||
overlayInput.canvasRect = ::XCEngine::UI::UIRect(
|
|
||||||
horizontalMargin,
|
|
||||||
topMargin,
|
|
||||||
(std::max)(0.0f, width - horizontalMargin * 2.0f),
|
|
||||||
(std::max)(0.0f, height - topMargin - bottomMargin));
|
|
||||||
overlayInput.pointerPosition = m_xcuiInputSource.GetPointerPosition();
|
|
||||||
overlayInput.pointerInside =
|
|
||||||
overlayInput.pointerPosition.x >= overlayInput.canvasRect.x &&
|
|
||||||
overlayInput.pointerPosition.y >= overlayInput.canvasRect.y &&
|
|
||||||
overlayInput.pointerPosition.x <= overlayInput.canvasRect.x + overlayInput.canvasRect.width &&
|
|
||||||
overlayInput.pointerPosition.y <= overlayInput.canvasRect.y + overlayInput.canvasRect.height;
|
|
||||||
const auto& overlayFrame = m_nativeOverlayRuntime.Update(overlayInput);
|
|
||||||
frameState.overlayDrawData = &overlayFrame.drawData;
|
|
||||||
}
|
|
||||||
m_nativeBackdropRenderer.Render(renderContext, surface, frameState);
|
|
||||||
});
|
|
||||||
|
|
||||||
m_xcuiInputSource.ClearFrameTransients();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::FrameNativeXCUIHost() {
|
void Application::FrameNativeXCUIHost() {
|
||||||
Application::BeginHostedPreviewFrameLifecycle(
|
Application::BeginHostedPreviewFrameLifecycle(
|
||||||
m_hostedPreviewQueue,
|
m_hostedPreviewQueue,
|
||||||
@@ -1427,303 +1346,6 @@ void Application::FrameNativeXCUIHost() {
|
|||||||
m_xcuiInputSource.ClearFrameTransients();
|
m_xcuiInputSource.ClearFrameTransients();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::RenderShellChrome() {
|
|
||||||
SyncShellChromePanelStateFromPanels();
|
|
||||||
|
|
||||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
||||||
if (viewport == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGuiWindowFlags windowFlags =
|
|
||||||
ImGuiWindowFlags_NoDocking |
|
|
||||||
ImGuiWindowFlags_NoTitleBar |
|
|
||||||
ImGuiWindowFlags_NoCollapse |
|
|
||||||
ImGuiWindowFlags_NoResize |
|
|
||||||
ImGuiWindowFlags_NoMove |
|
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
|
||||||
ImGuiWindowFlags_NoNavFocus |
|
|
||||||
ImGuiWindowFlags_MenuBar;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(viewport->WorkPos);
|
|
||||||
ImGui::SetNextWindowSize(viewport->WorkSize);
|
|
||||||
ImGui::SetNextWindowViewport(viewport->ID);
|
|
||||||
ImGui::SetNextWindowBgAlpha(0.0f);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
|
||||||
const bool opened = ImGui::Begin("XCNewEditorShell", nullptr, windowFlags);
|
|
||||||
ImGui::PopStyleVar(3);
|
|
||||||
|
|
||||||
if (opened) {
|
|
||||||
if (ImGui::BeginMenuBar()) {
|
|
||||||
if (ImGui::BeginMenu("View")) {
|
|
||||||
const auto drawCommandMenuItem =
|
|
||||||
[this](const char* label, const char* shortcut, bool selected, const char* commandId) {
|
|
||||||
const bool enabled = m_shellCommandRouter.IsCommandEnabled(commandId);
|
|
||||||
if (ImGui::MenuItem(label, shortcut, selected, enabled)) {
|
|
||||||
m_shellCommandRouter.InvokeCommand(commandId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"XCUI Demo",
|
|
||||||
"Ctrl+1",
|
|
||||||
TryGetShellPanelState(ShellPanelId::XCUIDemo) != nullptr &&
|
|
||||||
TryGetShellPanelState(ShellPanelId::XCUIDemo)->visible,
|
|
||||||
ShellCommandIds::ToggleXCUIDemoPanel);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"XCUI Layout Lab",
|
|
||||||
"Ctrl+2",
|
|
||||||
TryGetShellPanelState(ShellPanelId::XCUILayoutLab) != nullptr &&
|
|
||||||
TryGetShellPanelState(ShellPanelId::XCUILayoutLab)->visible,
|
|
||||||
ShellCommandIds::ToggleXCUILayoutLabPanel);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"ImGui Demo",
|
|
||||||
"Ctrl+3",
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow),
|
|
||||||
ShellCommandIds::ToggleImGuiDemoWindow);
|
|
||||||
ImGui::Separator();
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Native Backdrop",
|
|
||||||
"Ctrl+Shift+B",
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop),
|
|
||||||
ShellCommandIds::ToggleNativeBackdrop);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Pulse Accent",
|
|
||||||
"Ctrl+Shift+P",
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent),
|
|
||||||
ShellCommandIds::TogglePulseAccent);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Native XCUI Overlay",
|
|
||||||
"Ctrl+Shift+O",
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay),
|
|
||||||
ShellCommandIds::ToggleNativeXCUIOverlay);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Hosted Preview HUD",
|
|
||||||
"Ctrl+Shift+H",
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud),
|
|
||||||
ShellCommandIds::ToggleHostedPreviewHud);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Native Demo Panel Preview",
|
|
||||||
"Ctrl+Alt+1",
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo),
|
|
||||||
ShellCommandIds::ToggleNativeDemoPanelPreview);
|
|
||||||
drawCommandMenuItem(
|
|
||||||
"Native Layout Lab Preview",
|
|
||||||
"Ctrl+Alt+2",
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab),
|
|
||||||
ShellCommandIds::ToggleNativeLayoutLabPreview);
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SeparatorText("XCUI Sandbox");
|
|
||||||
const MainWindowNativeBackdropRenderer::OverlayStats& nativeOverlayStats =
|
|
||||||
m_nativeBackdropRenderer.GetLastOverlayStats();
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameStats& overlayFrameStats =
|
|
||||||
m_nativeOverlayRuntime.GetFrameResult().stats;
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewDrainStats& hostedPreviewStats =
|
|
||||||
m_hostedPreviewQueue.GetLastDrainStats();
|
|
||||||
if (IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"Native XCUI overlay: %s | runtime %zu cmds (%zu fill, %zu outline, %zu text, %zu image, clips %zu/%zu)",
|
|
||||||
overlayFrameStats.nativeOverlayReady ? "preflight OK" : "preflight issues",
|
|
||||||
overlayFrameStats.commandCount,
|
|
||||||
overlayFrameStats.filledRectCommandCount,
|
|
||||||
overlayFrameStats.rectOutlineCommandCount,
|
|
||||||
overlayFrameStats.textCommandCount,
|
|
||||||
overlayFrameStats.imageCommandCount,
|
|
||||||
overlayFrameStats.clipPushCommandCount,
|
|
||||||
overlayFrameStats.clipPopCommandCount);
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"%s | supported %zu | unsupported %zu | prev native pass %zu cmds, %zu rendered, %zu skipped",
|
|
||||||
overlayFrameStats.nativeOverlayStatusMessage.empty()
|
|
||||||
? "Overlay diagnostics unavailable"
|
|
||||||
: overlayFrameStats.nativeOverlayStatusMessage.c_str(),
|
|
||||||
overlayFrameStats.nativeSupportedCommandCount,
|
|
||||||
overlayFrameStats.nativeUnsupportedCommandCount,
|
|
||||||
nativeOverlayStats.commandCount,
|
|
||||||
nativeOverlayStats.renderedCommandCount,
|
|
||||||
nativeOverlayStats.skippedCommandCount);
|
|
||||||
} else {
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop)
|
|
||||||
? "Transition backend + runtime diagnostics + native backbuffer pass"
|
|
||||||
: "Transition backend + runtime diagnostics");
|
|
||||||
}
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"Hosted preview queue: %zu frames | queued %zu cmds | rendered %zu cmds | skipped %zu cmds",
|
|
||||||
hostedPreviewStats.queuedFrameCount,
|
|
||||||
hostedPreviewStats.queuedCommandCount,
|
|
||||||
hostedPreviewStats.renderedCommandCount,
|
|
||||||
hostedPreviewStats.skippedCommandCount);
|
|
||||||
std::size_t allocatedSurfaceCount = 0u;
|
|
||||||
std::size_t readySurfaceCount = 0u;
|
|
||||||
for (const HostedPreviewOffscreenSurface& previewSurface : m_hostedPreviewSurfaces) {
|
|
||||||
if (previewSurface.colorTexture != nullptr || previewSurface.colorView != nullptr) {
|
|
||||||
++allocatedSurfaceCount;
|
|
||||||
}
|
|
||||||
if (previewSurface.IsReady()) {
|
|
||||||
++readySurfaceCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"Hosted surfaces: %zu registry entries | %zu allocated | %zu ready",
|
|
||||||
m_hostedPreviewSurfaceRegistry.GetDescriptors().size(),
|
|
||||||
allocatedSurfaceCount,
|
|
||||||
readySurfaceCount);
|
|
||||||
if (m_demoPanel != nullptr) {
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"XCUI Demo preview: %s",
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)
|
|
||||||
? "native offscreen preview surface"
|
|
||||||
: "hosted presenter");
|
|
||||||
}
|
|
||||||
if (m_layoutLabPanel != nullptr) {
|
|
||||||
ImGui::TextDisabled(
|
|
||||||
"Layout Lab preview: %s",
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)
|
|
||||||
? "native offscreen preview surface"
|
|
||||||
: "hosted presenter");
|
|
||||||
}
|
|
||||||
ImGui::EndMenuBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::DockSpace(
|
|
||||||
ImGui::GetID("XCNewEditorDockSpace"),
|
|
||||||
ImVec2(0.0f, 0.0f),
|
|
||||||
ImGuiDockNodeFlags_PassthruCentralNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
if (IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud)) {
|
|
||||||
RenderHostedPreviewHud();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::RenderHostedPreviewHud() {
|
|
||||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
||||||
if (viewport == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
|
||||||
const ShellPanelChromeState* layoutLabState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab);
|
|
||||||
const HostedPreviewPanelDiagnostics demoDiagnostics = BuildHostedPreviewPanelDiagnostics(
|
|
||||||
demoState != nullptr ? demoState->previewDebugName.data() : "XCUI Demo",
|
|
||||||
demoState != nullptr ? demoState->previewDebugSource.data() : "new_editor.panels.xcui_demo",
|
|
||||||
demoState != nullptr && demoState->visible,
|
|
||||||
demoState != nullptr && demoState->hostedPreviewEnabled,
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo),
|
|
||||||
m_demoPanel != nullptr && m_demoPanel->IsUsingNativeHostedPreview(),
|
|
||||||
m_demoPanel != nullptr
|
|
||||||
? m_demoPanel->GetLastPreviewStats()
|
|
||||||
: ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats{});
|
|
||||||
const HostedPreviewPanelDiagnostics layoutLabDiagnostics = BuildHostedPreviewPanelDiagnostics(
|
|
||||||
layoutLabState != nullptr ? layoutLabState->previewDebugName.data() : "XCUI Layout Lab",
|
|
||||||
layoutLabState != nullptr ? layoutLabState->previewDebugSource.data() : "new_editor.panels.xcui_layout_lab",
|
|
||||||
layoutLabState != nullptr && layoutLabState->visible,
|
|
||||||
layoutLabState != nullptr && layoutLabState->hostedPreviewEnabled,
|
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab),
|
|
||||||
m_layoutLabPanel != nullptr && m_layoutLabPanel->IsUsingNativeHostedPreview(),
|
|
||||||
m_layoutLabPanel != nullptr
|
|
||||||
? m_layoutLabPanel->GetLastPreviewStats()
|
|
||||||
: ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats{});
|
|
||||||
|
|
||||||
std::size_t allocatedSurfaceCount = 0u;
|
|
||||||
std::size_t readySurfaceCount = 0u;
|
|
||||||
for (const HostedPreviewOffscreenSurface& previewSurface : m_hostedPreviewSurfaces) {
|
|
||||||
if (previewSurface.colorTexture != nullptr || previewSurface.colorView != nullptr) {
|
|
||||||
++allocatedSurfaceCount;
|
|
||||||
}
|
|
||||||
if (previewSurface.IsReady()) {
|
|
||||||
++readySurfaceCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewDrainStats& drainStats =
|
|
||||||
m_hostedPreviewQueue.GetLastDrainStats();
|
|
||||||
|
|
||||||
ImGuiWindowFlags windowFlags =
|
|
||||||
ImGuiWindowFlags_NoDocking |
|
|
||||||
ImGuiWindowFlags_NoSavedSettings |
|
|
||||||
ImGuiWindowFlags_AlwaysAutoResize |
|
|
||||||
ImGuiWindowFlags_NoFocusOnAppearing |
|
|
||||||
ImGuiWindowFlags_NoNav;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowViewport(viewport->ID);
|
|
||||||
ImGui::SetNextWindowPos(
|
|
||||||
ImVec2(viewport->WorkPos.x + viewport->WorkSize.x - 18.0f, viewport->WorkPos.y + 42.0f),
|
|
||||||
ImGuiCond_Always,
|
|
||||||
ImVec2(1.0f, 0.0f));
|
|
||||||
ImGui::SetNextWindowBgAlpha(0.9f);
|
|
||||||
if (!ImGui::Begin("XCUI Hosted Preview HUD", nullptr, windowFlags)) {
|
|
||||||
ImGui::End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TextUnformatted("XCUI Hosted Preview");
|
|
||||||
ImGui::Text(
|
|
||||||
"Registry %zu | surfaces %zu/%zu ready | last native drain %zu rendered, %zu skipped",
|
|
||||||
m_hostedPreviewSurfaceRegistry.GetDescriptors().size(),
|
|
||||||
readySurfaceCount,
|
|
||||||
allocatedSurfaceCount,
|
|
||||||
drainStats.renderedFrameCount,
|
|
||||||
drainStats.skippedFrameCount);
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
const auto drawPanelRow = [](const HostedPreviewPanelDiagnostics& diagnostics) {
|
|
||||||
const char* const pathLabel =
|
|
||||||
GetHostedPreviewPathLabel(diagnostics.nativeRequested, diagnostics.nativePresenterBound);
|
|
||||||
const char* const stateLabel = GetHostedPreviewStateLabel(
|
|
||||||
diagnostics.hostedPreviewEnabled,
|
|
||||||
diagnostics.nativePresenterBound,
|
|
||||||
diagnostics.presentedThisFrame,
|
|
||||||
diagnostics.queuedToNativePassThisFrame,
|
|
||||||
diagnostics.surfaceImageAvailable,
|
|
||||||
diagnostics.surfaceAllocated,
|
|
||||||
diagnostics.surfaceReady,
|
|
||||||
diagnostics.descriptorAvailable);
|
|
||||||
|
|
||||||
ImGui::Text(
|
|
||||||
"%s [%s] %s",
|
|
||||||
diagnostics.debugName.c_str(),
|
|
||||||
diagnostics.visible ? "visible" : "hidden",
|
|
||||||
stateLabel);
|
|
||||||
ImGui::TextDisabled("%s", pathLabel);
|
|
||||||
ImGui::Text(
|
|
||||||
"source %s | submit %zu lists / %zu cmds | flush %zu lists / %zu cmds",
|
|
||||||
diagnostics.debugSource.empty() ? "n/a" : diagnostics.debugSource.c_str(),
|
|
||||||
diagnostics.submittedDrawListCount,
|
|
||||||
diagnostics.submittedCommandCount,
|
|
||||||
diagnostics.flushedDrawListCount,
|
|
||||||
diagnostics.flushedCommandCount);
|
|
||||||
if (diagnostics.nativePresenterBound) {
|
|
||||||
ImGui::Text(
|
|
||||||
"surface %ux%u | logical %.0f x %.0f | descriptor %s | image %s | submit->native %s",
|
|
||||||
diagnostics.surfaceWidth,
|
|
||||||
diagnostics.surfaceHeight,
|
|
||||||
diagnostics.logicalWidth,
|
|
||||||
diagnostics.logicalHeight,
|
|
||||||
diagnostics.descriptorAvailable ? "yes" : "no",
|
|
||||||
diagnostics.surfaceImageAvailable ? "yes" : "no",
|
|
||||||
diagnostics.queuedToNativePassThisFrame ? "yes" : "no");
|
|
||||||
} else {
|
|
||||||
ImGui::Text(
|
|
||||||
"legacy present %s | cached native surface %s",
|
|
||||||
diagnostics.presentedThisFrame ? "yes" : "no",
|
|
||||||
(diagnostics.surfaceAllocated || diagnostics.surfaceImageAvailable) ? "retained" : "none");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
drawPanelRow(demoDiagnostics);
|
|
||||||
ImGui::Separator();
|
|
||||||
drawPanelRow(layoutLabDiagnostics);
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::RenderQueuedHostedPreviews(
|
void Application::RenderQueuedHostedPreviews(
|
||||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||||
const ::XCEngine::Rendering::RenderSurface& surface) {
|
const ::XCEngine::Rendering::RenderSurface& surface) {
|
||||||
|
|||||||
@@ -420,6 +420,9 @@ private:
|
|||||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta DispatchShellShortcuts(
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta DispatchShellShortcuts(
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot);
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot);
|
||||||
bool IsNativeWindowHostEnabled() const;
|
bool IsNativeWindowHostEnabled() const;
|
||||||
|
void InitializePanelsForActiveWindowHost();
|
||||||
|
void InitializeLegacyImGuiPanels();
|
||||||
|
void RenderLegacyImGuiUiFrame();
|
||||||
::XCEngine::UI::UIDrawData BuildNativeShellDrawData(
|
::XCEngine::UI::UIDrawData BuildNativeShellDrawData(
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& shellSnapshot,
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& shellSnapshot,
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta& shellFrameDelta);
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta& shellFrameDelta);
|
||||||
|
|||||||
446
new_editor/src/ApplicationLegacyImGui.cpp
Normal file
446
new_editor/src/ApplicationLegacyImGui.cpp
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace NewEditor {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr float kLegacyHostClearColor[4] = { 0.08f, 0.09f, 0.11f, 1.0f };
|
||||||
|
|
||||||
|
std::uint64_t MakeLegacyHostFrameTimestampNanoseconds() {
|
||||||
|
return static_cast<std::uint64_t>(
|
||||||
|
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
|
.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Application::FrameLegacyImGuiHost() {
|
||||||
|
Application::BeginHostedPreviewFrameLifecycle(
|
||||||
|
m_hostedPreviewQueue,
|
||||||
|
m_hostedPreviewSurfaceRegistry);
|
||||||
|
SyncHostedPreviewSurfaces();
|
||||||
|
if (m_windowCompositor == nullptr) {
|
||||||
|
m_xcuiInputSource.ClearFrameTransients();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_windowCompositor->RenderFrame(
|
||||||
|
kLegacyHostClearColor,
|
||||||
|
[this]() { RenderLegacyImGuiUiFrame(); },
|
||||||
|
[this](
|
||||||
|
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||||
|
const ::XCEngine::Rendering::RenderSurface& surface) {
|
||||||
|
RenderQueuedHostedPreviews(renderContext, surface);
|
||||||
|
|
||||||
|
if (!IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop) &&
|
||||||
|
!IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowNativeBackdropRenderer::FrameState frameState = {};
|
||||||
|
frameState.elapsedSeconds = static_cast<float>(
|
||||||
|
std::chrono::duration<double>(std::chrono::steady_clock::now() - m_startTime).count());
|
||||||
|
frameState.pulseAccent = IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent);
|
||||||
|
frameState.drawBackdrop = IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop);
|
||||||
|
if (IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
||||||
|
const float width = static_cast<float>(surface.GetWidth());
|
||||||
|
const float height = static_cast<float>(surface.GetHeight());
|
||||||
|
const float horizontalMargin = (std::min)(width * 0.14f, 128.0f);
|
||||||
|
const float topMargin = (std::min)(height * 0.15f, 132.0f);
|
||||||
|
const float bottomMargin = (std::min)(height * 0.12f, 96.0f);
|
||||||
|
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState overlayInput = {};
|
||||||
|
overlayInput.canvasRect = ::XCEngine::UI::UIRect(
|
||||||
|
horizontalMargin,
|
||||||
|
topMargin,
|
||||||
|
(std::max)(0.0f, width - horizontalMargin * 2.0f),
|
||||||
|
(std::max)(0.0f, height - topMargin - bottomMargin));
|
||||||
|
overlayInput.pointerPosition = m_xcuiInputSource.GetPointerPosition();
|
||||||
|
overlayInput.pointerInside =
|
||||||
|
overlayInput.pointerPosition.x >= overlayInput.canvasRect.x &&
|
||||||
|
overlayInput.pointerPosition.y >= overlayInput.canvasRect.y &&
|
||||||
|
overlayInput.pointerPosition.x <= overlayInput.canvasRect.x + overlayInput.canvasRect.width &&
|
||||||
|
overlayInput.pointerPosition.y <= overlayInput.canvasRect.y + overlayInput.canvasRect.height;
|
||||||
|
const auto& overlayFrame = m_nativeOverlayRuntime.Update(overlayInput);
|
||||||
|
frameState.overlayDrawData = &overlayFrame.drawData;
|
||||||
|
}
|
||||||
|
m_nativeBackdropRenderer.Render(renderContext, surface, frameState);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_xcuiInputSource.ClearFrameTransients();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::RenderLegacyImGuiUiFrame() {
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions options = {};
|
||||||
|
options.timestampNanoseconds = MakeLegacyHostFrameTimestampNanoseconds();
|
||||||
|
options.windowFocused = m_xcuiInputSource.IsWindowFocused();
|
||||||
|
const auto shellSnapshot = m_xcuiInputSource.CaptureSnapshot(options);
|
||||||
|
DispatchShellShortcuts(shellSnapshot);
|
||||||
|
|
||||||
|
RenderShellChrome();
|
||||||
|
if (m_demoPanel != nullptr) {
|
||||||
|
m_demoPanel->RenderIfVisible();
|
||||||
|
}
|
||||||
|
if (m_layoutLabPanel != nullptr) {
|
||||||
|
m_layoutLabPanel->RenderIfVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool showImGuiDemoWindow = IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow);
|
||||||
|
if (::XCEngine::Editor::XCUIBackend::RenderLegacyImGuiDemoWindow(showImGuiDemoWindow)) {
|
||||||
|
SetShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow, showImGuiDemoWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncShellChromePanelStateFromPanels();
|
||||||
|
SyncHostedPreviewSurfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::RenderShellChrome() {
|
||||||
|
SyncShellChromePanelStateFromPanels();
|
||||||
|
|
||||||
|
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
if (viewport == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiWindowFlags windowFlags =
|
||||||
|
ImGuiWindowFlags_NoDocking |
|
||||||
|
ImGuiWindowFlags_NoTitleBar |
|
||||||
|
ImGuiWindowFlags_NoCollapse |
|
||||||
|
ImGuiWindowFlags_NoResize |
|
||||||
|
ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
|
ImGuiWindowFlags_NoNavFocus |
|
||||||
|
ImGuiWindowFlags_MenuBar;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||||
|
ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||||
|
ImGui::SetNextWindowViewport(viewport->ID);
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
|
const bool opened = ImGui::Begin("XCNewEditorShell", nullptr, windowFlags);
|
||||||
|
ImGui::PopStyleVar(3);
|
||||||
|
|
||||||
|
if (opened) {
|
||||||
|
if (ImGui::BeginMenuBar()) {
|
||||||
|
if (ImGui::BeginMenu("View")) {
|
||||||
|
const auto drawCommandMenuItem =
|
||||||
|
[this](const char* label, const char* shortcut, bool selected, const char* commandId) {
|
||||||
|
const bool enabled = m_shellCommandRouter.IsCommandEnabled(commandId);
|
||||||
|
if (ImGui::MenuItem(label, shortcut, selected, enabled)) {
|
||||||
|
m_shellCommandRouter.InvokeCommand(commandId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"XCUI Demo",
|
||||||
|
"Ctrl+1",
|
||||||
|
TryGetShellPanelState(ShellPanelId::XCUIDemo) != nullptr &&
|
||||||
|
TryGetShellPanelState(ShellPanelId::XCUIDemo)->visible,
|
||||||
|
ShellCommandIds::ToggleXCUIDemoPanel);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"XCUI Layout Lab",
|
||||||
|
"Ctrl+2",
|
||||||
|
TryGetShellPanelState(ShellPanelId::XCUILayoutLab) != nullptr &&
|
||||||
|
TryGetShellPanelState(ShellPanelId::XCUILayoutLab)->visible,
|
||||||
|
ShellCommandIds::ToggleXCUILayoutLabPanel);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"ImGui Demo",
|
||||||
|
"Ctrl+3",
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow),
|
||||||
|
ShellCommandIds::ToggleImGuiDemoWindow);
|
||||||
|
ImGui::Separator();
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Native Backdrop",
|
||||||
|
"Ctrl+Shift+B",
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop),
|
||||||
|
ShellCommandIds::ToggleNativeBackdrop);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Pulse Accent",
|
||||||
|
"Ctrl+Shift+P",
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::PulseAccent),
|
||||||
|
ShellCommandIds::TogglePulseAccent);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Native XCUI Overlay",
|
||||||
|
"Ctrl+Shift+O",
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay),
|
||||||
|
ShellCommandIds::ToggleNativeXCUIOverlay);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Hosted Preview HUD",
|
||||||
|
"Ctrl+Shift+H",
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud),
|
||||||
|
ShellCommandIds::ToggleHostedPreviewHud);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Native Demo Panel Preview",
|
||||||
|
"Ctrl+Alt+1",
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo),
|
||||||
|
ShellCommandIds::ToggleNativeDemoPanelPreview);
|
||||||
|
drawCommandMenuItem(
|
||||||
|
"Native Layout Lab Preview",
|
||||||
|
"Ctrl+Alt+2",
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab),
|
||||||
|
ShellCommandIds::ToggleNativeLayoutLabPreview);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SeparatorText("XCUI Sandbox");
|
||||||
|
const MainWindowNativeBackdropRenderer::OverlayStats& nativeOverlayStats =
|
||||||
|
m_nativeBackdropRenderer.GetLastOverlayStats();
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameStats& overlayFrameStats =
|
||||||
|
m_nativeOverlayRuntime.GetFrameResult().stats;
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewDrainStats& hostedPreviewStats =
|
||||||
|
m_hostedPreviewQueue.GetLastDrainStats();
|
||||||
|
if (IsShellViewToggleEnabled(ShellViewToggleId::NativeXCUIOverlay)) {
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"Native XCUI overlay: %s | runtime %zu cmds (%zu fill, %zu outline, %zu text, %zu image, clips %zu/%zu)",
|
||||||
|
overlayFrameStats.nativeOverlayReady ? "preflight OK" : "preflight issues",
|
||||||
|
overlayFrameStats.commandCount,
|
||||||
|
overlayFrameStats.filledRectCommandCount,
|
||||||
|
overlayFrameStats.rectOutlineCommandCount,
|
||||||
|
overlayFrameStats.textCommandCount,
|
||||||
|
overlayFrameStats.imageCommandCount,
|
||||||
|
overlayFrameStats.clipPushCommandCount,
|
||||||
|
overlayFrameStats.clipPopCommandCount);
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"%s | supported %zu | unsupported %zu | prev native pass %zu cmds, %zu rendered, %zu skipped",
|
||||||
|
overlayFrameStats.nativeOverlayStatusMessage.empty()
|
||||||
|
? "Overlay diagnostics unavailable"
|
||||||
|
: overlayFrameStats.nativeOverlayStatusMessage.c_str(),
|
||||||
|
overlayFrameStats.nativeSupportedCommandCount,
|
||||||
|
overlayFrameStats.nativeUnsupportedCommandCount,
|
||||||
|
nativeOverlayStats.commandCount,
|
||||||
|
nativeOverlayStats.renderedCommandCount,
|
||||||
|
nativeOverlayStats.skippedCommandCount);
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
IsShellViewToggleEnabled(ShellViewToggleId::NativeBackdrop)
|
||||||
|
? "Transition backend + runtime diagnostics + native backbuffer pass"
|
||||||
|
: "Transition backend + runtime diagnostics");
|
||||||
|
}
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"Hosted preview queue: %zu frames | queued %zu cmds | rendered %zu cmds | skipped %zu cmds",
|
||||||
|
hostedPreviewStats.queuedFrameCount,
|
||||||
|
hostedPreviewStats.queuedCommandCount,
|
||||||
|
hostedPreviewStats.renderedCommandCount,
|
||||||
|
hostedPreviewStats.skippedCommandCount);
|
||||||
|
std::size_t allocatedSurfaceCount = 0u;
|
||||||
|
std::size_t readySurfaceCount = 0u;
|
||||||
|
for (const HostedPreviewOffscreenSurface& previewSurface : m_hostedPreviewSurfaces) {
|
||||||
|
if (previewSurface.colorTexture != nullptr || previewSurface.colorView != nullptr) {
|
||||||
|
++allocatedSurfaceCount;
|
||||||
|
}
|
||||||
|
if (previewSurface.IsReady()) {
|
||||||
|
++readySurfaceCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"Hosted surfaces: %zu registry entries | %zu allocated | %zu ready",
|
||||||
|
m_hostedPreviewSurfaceRegistry.GetDescriptors().size(),
|
||||||
|
allocatedSurfaceCount,
|
||||||
|
readySurfaceCount);
|
||||||
|
if (m_demoPanel != nullptr) {
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"XCUI Demo preview: %s",
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)
|
||||||
|
? "native offscreen preview surface"
|
||||||
|
: "hosted presenter");
|
||||||
|
}
|
||||||
|
if (m_layoutLabPanel != nullptr) {
|
||||||
|
ImGui::TextDisabled(
|
||||||
|
"Layout Lab preview: %s",
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)
|
||||||
|
? "native offscreen preview surface"
|
||||||
|
: "hosted presenter");
|
||||||
|
}
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::DockSpace(
|
||||||
|
ImGui::GetID("XCNewEditorDockSpace"),
|
||||||
|
ImVec2(0.0f, 0.0f),
|
||||||
|
ImGuiDockNodeFlags_PassthruCentralNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
if (IsShellViewToggleEnabled(ShellViewToggleId::HostedPreviewHud)) {
|
||||||
|
RenderHostedPreviewHud();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::RenderHostedPreviewHud() {
|
||||||
|
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
if (viewport == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
||||||
|
const ShellPanelChromeState* layoutLabState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab);
|
||||||
|
const HostedPreviewPanelDiagnostics demoDiagnostics = BuildHostedPreviewPanelDiagnostics(
|
||||||
|
demoState != nullptr ? demoState->previewDebugName.data() : "XCUI Demo",
|
||||||
|
demoState != nullptr ? demoState->previewDebugSource.data() : "new_editor.panels.xcui_demo",
|
||||||
|
demoState != nullptr && demoState->visible,
|
||||||
|
demoState != nullptr && demoState->hostedPreviewEnabled,
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo),
|
||||||
|
m_demoPanel != nullptr && m_demoPanel->IsUsingNativeHostedPreview(),
|
||||||
|
m_demoPanel != nullptr
|
||||||
|
? m_demoPanel->GetLastPreviewStats()
|
||||||
|
: ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats{});
|
||||||
|
const HostedPreviewPanelDiagnostics layoutLabDiagnostics = BuildHostedPreviewPanelDiagnostics(
|
||||||
|
layoutLabState != nullptr ? layoutLabState->previewDebugName.data() : "XCUI Layout Lab",
|
||||||
|
layoutLabState != nullptr ? layoutLabState->previewDebugSource.data() : "new_editor.panels.xcui_layout_lab",
|
||||||
|
layoutLabState != nullptr && layoutLabState->visible,
|
||||||
|
layoutLabState != nullptr && layoutLabState->hostedPreviewEnabled,
|
||||||
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab),
|
||||||
|
m_layoutLabPanel != nullptr && m_layoutLabPanel->IsUsingNativeHostedPreview(),
|
||||||
|
m_layoutLabPanel != nullptr
|
||||||
|
? m_layoutLabPanel->GetLastPreviewStats()
|
||||||
|
: ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats{});
|
||||||
|
|
||||||
|
std::size_t allocatedSurfaceCount = 0u;
|
||||||
|
std::size_t readySurfaceCount = 0u;
|
||||||
|
for (const HostedPreviewOffscreenSurface& previewSurface : m_hostedPreviewSurfaces) {
|
||||||
|
if (previewSurface.colorTexture != nullptr || previewSurface.colorView != nullptr) {
|
||||||
|
++allocatedSurfaceCount;
|
||||||
|
}
|
||||||
|
if (previewSurface.IsReady()) {
|
||||||
|
++readySurfaceCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewDrainStats& drainStats =
|
||||||
|
m_hostedPreviewQueue.GetLastDrainStats();
|
||||||
|
|
||||||
|
ImGuiWindowFlags windowFlags =
|
||||||
|
ImGuiWindowFlags_NoDocking |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings |
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize |
|
||||||
|
ImGuiWindowFlags_NoFocusOnAppearing |
|
||||||
|
ImGuiWindowFlags_NoNav;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowViewport(viewport->ID);
|
||||||
|
ImGui::SetNextWindowPos(
|
||||||
|
ImVec2(viewport->WorkPos.x + viewport->WorkSize.x - 18.0f, viewport->WorkPos.y + 42.0f),
|
||||||
|
ImGuiCond_Always,
|
||||||
|
ImVec2(1.0f, 0.0f));
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.9f);
|
||||||
|
if (!ImGui::Begin("XCUI Hosted Preview HUD", nullptr, windowFlags)) {
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("XCUI Hosted Preview");
|
||||||
|
ImGui::Text(
|
||||||
|
"Registry %zu | surfaces %zu/%zu ready | last native drain %zu rendered, %zu skipped",
|
||||||
|
m_hostedPreviewSurfaceRegistry.GetDescriptors().size(),
|
||||||
|
readySurfaceCount,
|
||||||
|
allocatedSurfaceCount,
|
||||||
|
drainStats.renderedFrameCount,
|
||||||
|
drainStats.skippedFrameCount);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
const auto drawPanelRow = [](const HostedPreviewPanelDiagnostics& diagnostics) {
|
||||||
|
const char* const pathLabel =
|
||||||
|
GetHostedPreviewPathLabel(diagnostics.nativeRequested, diagnostics.nativePresenterBound);
|
||||||
|
const char* const stateLabel = GetHostedPreviewStateLabel(
|
||||||
|
diagnostics.hostedPreviewEnabled,
|
||||||
|
diagnostics.nativePresenterBound,
|
||||||
|
diagnostics.presentedThisFrame,
|
||||||
|
diagnostics.queuedToNativePassThisFrame,
|
||||||
|
diagnostics.surfaceImageAvailable,
|
||||||
|
diagnostics.surfaceAllocated,
|
||||||
|
diagnostics.surfaceReady,
|
||||||
|
diagnostics.descriptorAvailable);
|
||||||
|
|
||||||
|
ImGui::Text(
|
||||||
|
"%s [%s] %s",
|
||||||
|
diagnostics.debugName.c_str(),
|
||||||
|
diagnostics.visible ? "visible" : "hidden",
|
||||||
|
stateLabel);
|
||||||
|
ImGui::TextDisabled("%s", pathLabel);
|
||||||
|
ImGui::Text(
|
||||||
|
"source %s | submit %zu lists / %zu cmds | flush %zu lists / %zu cmds",
|
||||||
|
diagnostics.debugSource.empty() ? "n/a" : diagnostics.debugSource.c_str(),
|
||||||
|
diagnostics.submittedDrawListCount,
|
||||||
|
diagnostics.submittedCommandCount,
|
||||||
|
diagnostics.flushedDrawListCount,
|
||||||
|
diagnostics.flushedCommandCount);
|
||||||
|
if (diagnostics.nativePresenterBound) {
|
||||||
|
ImGui::Text(
|
||||||
|
"surface %ux%u | logical %.0f x %.0f | descriptor %s | image %s | submit->native %s",
|
||||||
|
diagnostics.surfaceWidth,
|
||||||
|
diagnostics.surfaceHeight,
|
||||||
|
diagnostics.logicalWidth,
|
||||||
|
diagnostics.logicalHeight,
|
||||||
|
diagnostics.descriptorAvailable ? "yes" : "no",
|
||||||
|
diagnostics.surfaceImageAvailable ? "yes" : "no",
|
||||||
|
diagnostics.queuedToNativePassThisFrame ? "yes" : "no");
|
||||||
|
} else {
|
||||||
|
ImGui::Text(
|
||||||
|
"legacy present %s | cached native surface %s",
|
||||||
|
diagnostics.presentedThisFrame ? "yes" : "no",
|
||||||
|
(diagnostics.surfaceAllocated || diagnostics.surfaceImageAvailable) ? "retained" : "none");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
drawPanelRow(demoDiagnostics);
|
||||||
|
ImGui::Separator();
|
||||||
|
drawPanelRow(layoutLabDiagnostics);
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NewEditor
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IWindowUICompositor> CreateImGuiWindowUICompositor();
|
std::unique_ptr<IWindowUICompositor> CreateImGuiWindowUICompositor();
|
||||||
|
std::unique_ptr<IWindowUICompositor> CreateNativeWindowUICompositor();
|
||||||
|
|
||||||
} // namespace XCUIBackend
|
} // namespace XCUIBackend
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|||||||
54
new_editor/src/XCUIBackend/LegacyImGuiHostInterop.cpp
Normal file
54
new_editor/src/XCUIBackend/LegacyImGuiHostInterop.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||||
|
|
||||||
|
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
||||||
|
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
||||||
|
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
||||||
|
#include "XCUIBackend/XCUIEditorFontSetup.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Editor {
|
||||||
|
namespace XCUIBackend {
|
||||||
|
|
||||||
|
bool ConfigureLegacyImGuiHostFonts() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImFont* uiFont = nullptr;
|
||||||
|
if (!BuildDefaultXCUIEditorFontAtlas(*io.Fonts, uiFont)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.FontDefault = uiFont;
|
||||||
|
return io.FontDefault != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IWindowUICompositor> CreateLegacyImGuiWindowUICompositor() {
|
||||||
|
return CreateImGuiWindowUICompositor();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IXCUIHostedPreviewPresenter> CreateLegacyImGuiHostedPreviewPresenter() {
|
||||||
|
return CreateImGuiXCUIHostedPreviewPresenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IXCUIPanelCanvasHost> CreateLegacyImGuiPanelCanvasHost() {
|
||||||
|
return CreateImGuiXCUIPanelCanvasHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyLegacyImGuiHostInputCapture(XCUIInputBridgeFrameSnapshot& snapshot) {
|
||||||
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
snapshot.wantCaptureKeyboard = io.WantCaptureKeyboard;
|
||||||
|
snapshot.wantTextInput = io.WantTextInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderLegacyImGuiDemoWindow(bool& visible) {
|
||||||
|
if (!visible) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::ShowDemoWindow(&visible);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace XCUIBackend
|
||||||
|
} // namespace Editor
|
||||||
|
} // namespace XCEngine
|
||||||
28
new_editor/src/XCUIBackend/LegacyImGuiHostInterop.h
Normal file
28
new_editor/src/XCUIBackend/LegacyImGuiHostInterop.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XCUIBackend/XCUIInputBridge.h"
|
||||||
|
#include "XCUIBackend/IWindowUICompositor.h"
|
||||||
|
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||||
|
#include "XCUIBackend/XCUIPanelCanvasHost.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Editor {
|
||||||
|
namespace XCUIBackend {
|
||||||
|
|
||||||
|
bool ConfigureLegacyImGuiHostFonts();
|
||||||
|
|
||||||
|
std::unique_ptr<IWindowUICompositor> CreateLegacyImGuiWindowUICompositor();
|
||||||
|
|
||||||
|
std::unique_ptr<IXCUIHostedPreviewPresenter> CreateLegacyImGuiHostedPreviewPresenter();
|
||||||
|
|
||||||
|
std::unique_ptr<IXCUIPanelCanvasHost> CreateLegacyImGuiPanelCanvasHost();
|
||||||
|
|
||||||
|
void ApplyLegacyImGuiHostInputCapture(XCUIInputBridgeFrameSnapshot& snapshot);
|
||||||
|
|
||||||
|
bool RenderLegacyImGuiDemoWindow(bool& visible);
|
||||||
|
|
||||||
|
} // namespace XCUIBackend
|
||||||
|
} // namespace Editor
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -319,4 +319,90 @@ TEST(ApplicationShellCommandBindingsTest, HostedPreviewRegistrationGuardsAllowTe
|
|||||||
EXPECT_FALSE(Application::HasHostedPreviewPublishedTexture(registration));
|
EXPECT_FALSE(Application::HasHostedPreviewPublishedTexture(registration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ApplicationShellCommandBindingsTest, NativeHostedPreviewConsumptionLeavesHostedPathInDirectAppendMode) {
|
||||||
|
const auto consumption = Application::ResolveNativeHostedPreviewConsumption(
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
"Pending",
|
||||||
|
"Waiting");
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
consumption.surfaceState,
|
||||||
|
Application::NativeHostedPreviewSurfaceState::Disabled);
|
||||||
|
EXPECT_FALSE(consumption.queueRuntimeFrame);
|
||||||
|
EXPECT_TRUE(consumption.appendRuntimeDrawDataToShell);
|
||||||
|
EXPECT_FALSE(consumption.showSurfaceImage);
|
||||||
|
EXPECT_TRUE(consumption.drawRuntimeDebugRects);
|
||||||
|
EXPECT_TRUE(consumption.placeholderTitle.empty());
|
||||||
|
EXPECT_TRUE(consumption.placeholderSubtitle.empty());
|
||||||
|
EXPECT_EQ(
|
||||||
|
Application::ComposeNativeHostedPreviewStatusLine(consumption, "Runtime status"),
|
||||||
|
"Runtime status");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ApplicationShellCommandBindingsTest, NativeHostedPreviewConsumptionQueuesFrameWhileAwaitingFirstSurfacePublish) {
|
||||||
|
const auto consumption = Application::ResolveNativeHostedPreviewConsumption(
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
"Native XCUI preview pending",
|
||||||
|
"Waiting for queued native preview output to publish into the shell card.");
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
consumption.surfaceState,
|
||||||
|
Application::NativeHostedPreviewSurfaceState::AwaitingSubmit);
|
||||||
|
EXPECT_TRUE(consumption.queueRuntimeFrame);
|
||||||
|
EXPECT_FALSE(consumption.appendRuntimeDrawDataToShell);
|
||||||
|
EXPECT_FALSE(consumption.showSurfaceImage);
|
||||||
|
EXPECT_FALSE(consumption.drawRuntimeDebugRects);
|
||||||
|
EXPECT_EQ(consumption.placeholderTitle, "Native XCUI preview pending");
|
||||||
|
EXPECT_EQ(
|
||||||
|
consumption.placeholderSubtitle,
|
||||||
|
"Waiting for queued native preview output to publish into the shell card.");
|
||||||
|
EXPECT_EQ(
|
||||||
|
Application::ComposeNativeHostedPreviewStatusLine(consumption, "Runtime status"),
|
||||||
|
"Native surface awaiting submit | Runtime status");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ApplicationShellCommandBindingsTest, NativeHostedPreviewConsumptionDistinguishesWarmingFromLiveSurfaceStates) {
|
||||||
|
const auto warming = Application::ResolveNativeHostedPreviewConsumption(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
"Native layout preview pending",
|
||||||
|
"Waiting for queued native preview output to publish into the layout card.");
|
||||||
|
const auto live = Application::ResolveNativeHostedPreviewConsumption(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
"Native layout preview pending",
|
||||||
|
"Waiting for queued native preview output to publish into the layout card.");
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
warming.surfaceState,
|
||||||
|
Application::NativeHostedPreviewSurfaceState::Warming);
|
||||||
|
EXPECT_TRUE(warming.queueRuntimeFrame);
|
||||||
|
EXPECT_FALSE(warming.appendRuntimeDrawDataToShell);
|
||||||
|
EXPECT_FALSE(warming.showSurfaceImage);
|
||||||
|
EXPECT_FALSE(warming.drawRuntimeDebugRects);
|
||||||
|
EXPECT_EQ(warming.placeholderTitle, "Native layout preview pending");
|
||||||
|
EXPECT_EQ(
|
||||||
|
Application::ComposeNativeHostedPreviewStatusLine(warming, "Layout status"),
|
||||||
|
"Native surface warming | Layout status");
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
live.surfaceState,
|
||||||
|
Application::NativeHostedPreviewSurfaceState::Live);
|
||||||
|
EXPECT_TRUE(live.queueRuntimeFrame);
|
||||||
|
EXPECT_FALSE(live.appendRuntimeDrawDataToShell);
|
||||||
|
EXPECT_TRUE(live.showSurfaceImage);
|
||||||
|
EXPECT_TRUE(live.drawRuntimeDebugRects);
|
||||||
|
EXPECT_TRUE(live.placeholderTitle.empty());
|
||||||
|
EXPECT_TRUE(live.placeholderSubtitle.empty());
|
||||||
|
EXPECT_EQ(
|
||||||
|
Application::ComposeNativeHostedPreviewStatusLine(live, "Layout status"),
|
||||||
|
"Native surface live | Layout status");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user