Contain XCUI ImGui adapters behind explicit host seams

This commit is contained in:
2026-04-05 13:24:14 +08:00
parent 56f596548d
commit f943a07862
23 changed files with 1134 additions and 290 deletions

View File

@@ -1,8 +1,6 @@
#include "XCUIDemoPanel.h"
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
#include "XCUIBackend/ImGuiXCUIInputAdapter.h"
#include "XCUIBackend/NullXCUIPanelCanvasHost.h"
#include <XCEngine/UI/Types.h>
@@ -55,15 +53,27 @@ void DrawRectOverlay(
}
}
const char* GetPreviewPathLabel(bool nativeHostedPreview) {
return nativeHostedPreview ? "native queued offscreen surface" : "legacy imgui transition";
const char* GetPreviewPathLabel(
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter) {
if (previewPresenter == nullptr) {
return "not injected";
}
return previewPresenter->IsNativeQueued()
? "native queued offscreen surface"
: "hosted presenter";
}
const char* GetPreviewStateLabel(
bool nativeHostedPreview,
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter,
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& previewStats,
bool hasHostedSurfaceDescriptor,
bool showHostedSurfaceImage) {
if (previewPresenter == nullptr) {
return "disabled";
}
const bool nativeHostedPreview = previewPresenter->IsNativeQueued();
if (nativeHostedPreview) {
if (showHostedSurfaceImage) {
return "live";
@@ -77,20 +87,37 @@ const char* GetPreviewStateLabel(
return previewStats.presented ? "live" : "idle";
}
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot BuildPassiveSnapshot(
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions& options) {
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot snapshot = {};
snapshot.pointerPosition = canvasSession.pointerPosition;
snapshot.pointerInside = options.hasPointerInsideOverride
? options.pointerInsideOverride
: (canvasSession.validCanvas && canvasSession.hovered);
snapshot.windowFocused = options.windowFocused;
snapshot.timestampNanoseconds = options.timestampNanoseconds;
return snapshot;
}
} // namespace
XCUIDemoPanel::XCUIDemoPanel(::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource)
: XCUIDemoPanel(inputSource, ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter()) {}
XCUIDemoPanel::XCUIDemoPanel(::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource)
: XCUIDemoPanel(
inputSource,
nullptr,
::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost()) {}
XCUIDemoPanel::XCUIDemoPanel(
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource,
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter)
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource,
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter,
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost)
: Panel("XCUI Demo")
, m_inputSource(inputSource)
, m_previewPresenter(std::move(previewPresenter))
, m_canvasHost(::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost()) {
if (m_previewPresenter == nullptr) {
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
, m_canvasHost(std::move(canvasHost)) {
if (m_canvasHost == nullptr) {
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
}
m_lastReloadSucceeded = m_runtime.ReloadDocuments();
}
@@ -113,9 +140,6 @@ const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& XCUIDemoPanel::Ge
void XCUIDemoPanel::SetHostedPreviewPresenter(
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
m_previewPresenter = std::move(previewPresenter);
if (m_previewPresenter == nullptr) {
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
}
m_lastPreviewStats = {};
}
@@ -123,7 +147,7 @@ void XCUIDemoPanel::SetCanvasHost(
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost) {
m_canvasHost = std::move(canvasHost);
if (m_canvasHost == nullptr) {
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
}
}
@@ -160,7 +184,7 @@ void XCUIDemoPanel::Render() {
const float canvasHeight = (std::max)(140.0f, hostRegion.y - diagnosticsHeight);
if (m_canvasHost == nullptr) {
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
}
const bool nativeHostedPreview = IsUsingNativeHostedPreview();
@@ -174,7 +198,7 @@ void XCUIDemoPanel::Render() {
nativeHostedPreview &&
m_previewPresenter != nullptr &&
m_previewPresenter->TryGetSurfaceImage(kPreviewDebugName, hostedSurfaceImage);
const char* const previewPathLabel = GetPreviewPathLabel(nativeHostedPreview);
const char* const previewPathLabel = GetPreviewPathLabel(m_previewPresenter.get());
const float topInset = m_showCanvasHud ? (kCanvasHudHeight + kCanvasHudPadding) : 0.0f;
::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest canvasRequest = {};
canvasRequest.childId = "XCUIDemoCanvasHost";
@@ -183,11 +207,11 @@ void XCUIDemoPanel::Render() {
canvasRequest.showSurfaceImage = showHostedSurfaceImage;
canvasRequest.surfaceImage = hostedSurfaceImage;
canvasRequest.placeholderTitle =
nativeHostedPreview ? "Native XCUI preview pending" : "Legacy XCUI canvas host";
nativeHostedPreview ? "Native XCUI preview pending" : "Injected XCUI canvas host";
canvasRequest.placeholderSubtitle =
nativeHostedPreview
? "Waiting for native queued render output to publish back into the sandbox panel."
: "Legacy ImGui transition path stays active until native offscreen preview is enabled.";
: "Inject a concrete canvas host to render the demo sandbox inside this panel.";
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession canvasSession =
m_canvasHost->BeginCanvas(canvasRequest);
const UI::UIRect canvasRect = canvasSession.canvasRect;
@@ -211,10 +235,7 @@ void XCUIDemoPanel::Render() {
bridgeOptions.hasPointerInsideOverride = true;
bridgeOptions.pointerInsideOverride = validCanvas && canvasSession.hovered;
bridgeOptions.windowFocused = canvasSession.windowFocused;
snapshot = ::XCEngine::Editor::XCUIBackend::ImGuiXCUIInputAdapter::CaptureSnapshot(
ImGui::GetIO(),
bridgeOptions);
snapshot.pointerPosition = canvasSession.pointerPosition;
snapshot = BuildPassiveSnapshot(canvasSession, bridgeOptions);
}
if (!m_inputBridge.HasBaseline()) {
@@ -253,7 +274,7 @@ void XCUIDemoPanel::Render() {
const ::XCEngine::Editor::XCUIBackend::XCUIDemoFrameStats& stats = frame.stats;
const char* const previewStateLabel = GetPreviewStateLabel(
nativeHostedPreview,
m_previewPresenter.get(),
m_lastPreviewStats,
hasHostedSurfaceDescriptor,
showHostedSurfaceImage);