Split legacy ImGui shell out of Application
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
#include "Application.h"
|
||||
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
||||
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
||||
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
||||
#include "XCUIBackend/LegacyImGuiHostInterop.h"
|
||||
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||||
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
@@ -41,13 +37,6 @@ void ShutdownAndDelete(ResourceType*& resource) {
|
||||
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) {
|
||||
if (nativeRequested && nativePresenterBound) {
|
||||
return "native queued offscreen surface";
|
||||
@@ -193,13 +182,34 @@ Application::CreateHostedPreviewPresenter(bool nativePreview) {
|
||||
m_hostedPreviewSurfaceRegistry);
|
||||
}
|
||||
|
||||
return ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
||||
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
|
||||
@@ -323,9 +333,7 @@ Application::DispatchShellShortcuts(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot) {
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot shellSnapshot = snapshot;
|
||||
if (!IsNativeWindowHostEnabled()) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
shellSnapshot.wantCaptureKeyboard = io.WantCaptureKeyboard;
|
||||
shellSnapshot.wantTextInput = io.WantTextInput;
|
||||
::XCEngine::Editor::XCUIBackend::ApplyLegacyImGuiHostInputCapture(shellSnapshot);
|
||||
}
|
||||
|
||||
if (!m_shellInputBridge.HasBaseline()) {
|
||||
@@ -419,19 +427,7 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
||||
}
|
||||
|
||||
InitializeWindowCompositor();
|
||||
if (IsNativeWindowHostEnabled()) {
|
||||
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();
|
||||
}
|
||||
InitializePanelsForActiveWindowHost();
|
||||
m_shellInputBridge.Reset();
|
||||
ConfigureShellCommandRouter();
|
||||
m_running = true;
|
||||
@@ -565,12 +561,12 @@ bool Application::InitializeRenderer() {
|
||||
void Application::InitializeWindowCompositor() {
|
||||
m_windowCompositor = IsNativeWindowHostEnabled()
|
||||
? ::XCEngine::Editor::XCUIBackend::CreateNativeWindowUICompositor()
|
||||
: ::XCEngine::Editor::XCUIBackend::CreateImGuiWindowUICompositor();
|
||||
: ::XCEngine::Editor::XCUIBackend::CreateLegacyImGuiWindowUICompositor();
|
||||
if (m_windowCompositor != nullptr) {
|
||||
m_windowCompositor->Initialize(
|
||||
m_hwnd,
|
||||
m_windowRenderer,
|
||||
[]() { ConfigureFonts(); });
|
||||
[]() { (void)::XCEngine::Editor::XCUIBackend::ConfigureLegacyImGuiHostFonts(); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1001,7 +997,7 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
||||
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
||||
panelState->previewDebugName.data(),
|
||||
hostedSurfaceImage);
|
||||
const NativeHostedPreviewConsumption previewConsumption =
|
||||
const Application::NativeHostedPreviewConsumption previewConsumption =
|
||||
Application::ResolveNativeHostedPreviewConsumption(
|
||||
nativeHostedPreview,
|
||||
hasHostedSurfaceDescriptor,
|
||||
@@ -1168,7 +1164,7 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
||||
m_hostedPreviewSurfaceRegistry.TryGetSurfaceImage(
|
||||
panelState->previewDebugName.data(),
|
||||
hostedSurfaceImage);
|
||||
const NativeHostedPreviewConsumption previewConsumption =
|
||||
const Application::NativeHostedPreviewConsumption previewConsumption =
|
||||
Application::ResolveNativeHostedPreviewConsumption(
|
||||
nativeHostedPreview,
|
||||
hasHostedSurfaceDescriptor,
|
||||
@@ -1309,83 +1305,6 @@ bool Application::RenderHostedPreviewOffscreenSurface(
|
||||
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() {
|
||||
Application::BeginHostedPreviewFrameLifecycle(
|
||||
m_hostedPreviewQueue,
|
||||
@@ -1427,303 +1346,6 @@ void Application::FrameNativeXCUIHost() {
|
||||
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(
|
||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||
const ::XCEngine::Rendering::RenderSurface& surface) {
|
||||
|
||||
@@ -420,6 +420,9 @@ private:
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta DispatchShellShortcuts(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& snapshot);
|
||||
bool IsNativeWindowHostEnabled() const;
|
||||
void InitializePanelsForActiveWindowHost();
|
||||
void InitializeLegacyImGuiPanels();
|
||||
void RenderLegacyImGuiUiFrame();
|
||||
::XCEngine::UI::UIDrawData BuildNativeShellDrawData(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot& shellSnapshot,
|
||||
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> CreateNativeWindowUICompositor();
|
||||
|
||||
} // namespace XCUIBackend
|
||||
} // 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
|
||||
Reference in New Issue
Block a user