#include #include "panels/XCUIDemoPanel.h" #include "XCUIBackend/XCUIHostedPreviewPresenter.h" #include "XCUIBackend/XCUIPanelCanvasHost.h" #include #include #include #include namespace { using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter; using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost; using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame; using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats; using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest; using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession; using XCEngine::NewEditor::XCUIDemoPanel; class ImGuiContextScope { public: ImGuiContextScope() { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui::StyleColorsDark(); } ~ImGuiContextScope() { ImGui::DestroyContext(); } }; void PrepareImGui(float width = 1280.0f, float height = 900.0f) { ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = ImVec2(width, height); io.DeltaTime = 1.0f / 60.0f; unsigned char* fontPixels = nullptr; int fontWidth = 0; int fontHeight = 0; io.Fonts->GetTexDataAsRGBA32(&fontPixels, &fontWidth, &fontHeight); io.Fonts->SetTexID(static_cast(1)); } class RecordingHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter { public: bool Present(const XCUIHostedPreviewFrame& frame) override { ++presentCallCount; lastCanvasRect = frame.canvasRect; lastLogicalSize = frame.logicalSize; lastDebugName = frame.debugName != nullptr ? frame.debugName : ""; m_lastStats = {}; if (frame.drawData == nullptr) { return false; } lastDrawListCount = frame.drawData->GetDrawListCount(); lastCommandCount = frame.drawData->GetTotalCommandCount(); m_lastStats.presented = true; m_lastStats.submittedDrawListCount = lastDrawListCount; m_lastStats.submittedCommandCount = lastCommandCount; return true; } const XCUIHostedPreviewStats& GetLastStats() const override { return m_lastStats; } std::size_t presentCallCount = 0u; XCEngine::UI::UIRect lastCanvasRect = {}; XCEngine::UI::UISize lastLogicalSize = {}; std::size_t lastDrawListCount = 0u; std::size_t lastCommandCount = 0u; std::string lastDebugName = {}; private: XCUIHostedPreviewStats m_lastStats = {}; }; class StubCanvasHost final : public IXCUIPanelCanvasHost { public: const char* GetDebugName() const override { return "StubCanvasHost"; } XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override { lastRequest = request; ++beginCanvasCallCount; return session; } void DrawFilledRect( const XCEngine::UI::UIRect&, const XCEngine::UI::UIColor&, float) override { } void DrawOutlineRect( const XCEngine::UI::UIRect&, const XCEngine::UI::UIColor&, float, float) override { } void DrawText( const XCEngine::UI::UIPoint&, std::string_view, const XCEngine::UI::UIColor&, float) override { } void EndCanvas() override { ++endCanvasCallCount; } std::size_t beginCanvasCallCount = 0u; std::size_t endCanvasCallCount = 0u; XCUIPanelCanvasRequest lastRequest = {}; XCUIPanelCanvasSession session = { XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f), XCEngine::UI::UIRect(12.0f, 18.0f, 936.0f, 512.0f), XCEngine::UI::UIPoint(120.0f, 140.0f), true, true, true }; }; void RenderPanelFrame(XCUIDemoPanel& panel, ImGuiContextScope&) { PrepareImGui(); ImGui::NewFrame(); panel.Render(); ImGui::Render(); } TEST(NewEditorXCUIDemoPanelTest, DefaultConstructionDoesNotAutoCreateHostedPreviewPresenter) { ImGuiContextScope contextScope; auto canvasHost = std::make_unique(); XCUIDemoPanel panel; panel.SetCanvasHost(std::move(canvasHost)); RenderPanelFrame(panel, contextScope); const XCUIHostedPreviewStats& stats = panel.GetLastPreviewStats(); EXPECT_FALSE(stats.presented); EXPECT_FALSE(stats.queuedToNativePass); EXPECT_EQ(stats.submittedDrawListCount, 0u); EXPECT_EQ(stats.submittedCommandCount, 0u); EXPECT_EQ(stats.flushedDrawListCount, 0u); EXPECT_EQ(stats.flushedCommandCount, 0u); } TEST(NewEditorXCUIDemoPanelTest, ConstructorUsesGenericNullCanvasHostUntilOuterLayerInjectsOne) { ImGuiContextScope contextScope; auto previewPresenter = std::make_unique(); RecordingHostedPreviewPresenter* previewPresenterPtr = previewPresenter.get(); XCUIDemoPanel panel(nullptr, std::move(previewPresenter)); RenderPanelFrame(panel, contextScope); ASSERT_EQ(previewPresenterPtr->presentCallCount, 1u); EXPECT_EQ(previewPresenterPtr->lastDebugName, "XCUI Demo"); EXPECT_FLOAT_EQ(previewPresenterPtr->lastCanvasRect.x, 0.0f); EXPECT_GT(previewPresenterPtr->lastCanvasRect.y, 0.0f); EXPECT_FLOAT_EQ(previewPresenterPtr->lastCanvasRect.width, 0.0f); EXPECT_GT(previewPresenterPtr->lastCanvasRect.height, 0.0f); EXPECT_FLOAT_EQ(previewPresenterPtr->lastLogicalSize.width, 0.0f); EXPECT_FLOAT_EQ( previewPresenterPtr->lastLogicalSize.height, previewPresenterPtr->lastCanvasRect.height); } TEST(NewEditorXCUIDemoPanelTest, ClearingHostedPreviewPresenterDoesNotRestoreImGuiFallback) { ImGuiContextScope contextScope; auto previewPresenter = std::make_unique(); RecordingHostedPreviewPresenter* previewPresenterPtr = previewPresenter.get(); auto canvasHost = std::make_unique(); XCUIDemoPanel panel(nullptr, std::move(previewPresenter)); panel.SetCanvasHost(std::move(canvasHost)); RenderPanelFrame(panel, contextScope); ASSERT_EQ(previewPresenterPtr->presentCallCount, 1u); EXPECT_TRUE(panel.GetLastPreviewStats().presented); panel.SetHostedPreviewPresenter(nullptr); RenderPanelFrame(panel, contextScope); const XCUIHostedPreviewStats& stats = panel.GetLastPreviewStats(); EXPECT_FALSE(stats.presented); EXPECT_FALSE(stats.queuedToNativePass); EXPECT_EQ(stats.submittedDrawListCount, 0u); EXPECT_EQ(stats.submittedCommandCount, 0u); EXPECT_EQ(stats.flushedDrawListCount, 0u); EXPECT_EQ(stats.flushedCommandCount, 0u); } } // namespace