Files
XCEngine/tests/NewEditor/test_xcui_layout_lab_panel.cpp

271 lines
8.3 KiB
C++

#include <gtest/gtest.h>
#include "panels/XCUILayoutLabPanel.h"
#include "XCUIBackend/ImGuiXCUIInputSource.h"
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
#include "XCUIBackend/XCUIPanelCanvasHost.h"
#include <imgui.h>
#include <functional>
#include <memory>
#include <string>
namespace {
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::ImGuiXCUIInputSnapshotSource;
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
using XCEngine::NewEditor::XCUILayoutLabPanel;
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<ImTextureID>(1));
}
class StubHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
public:
bool Present(const XCUIHostedPreviewFrame& frame) override {
m_lastStats = {};
m_lastStats.presented = frame.drawData != nullptr;
return m_lastStats.presented;
}
const XCUIHostedPreviewStats& GetLastStats() const override {
return m_lastStats;
}
private:
XCUIHostedPreviewStats m_lastStats = {};
};
class StubCanvasHost final : public IXCUIPanelCanvasHost {
public:
const char* GetDebugName() const override {
return "StubCanvasHost";
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend GetBackend() const override {
return XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend::Null;
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
return {};
}
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest&) override {
return m_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 {
}
void SetPointerPosition(const XCEngine::UI::UIPoint& position) {
m_session.pointerPosition = position;
}
void SetHovered(bool hovered) {
m_session.hovered = hovered;
}
void SetWindowFocused(bool focused) {
m_session.windowFocused = focused;
}
private:
XCUIPanelCanvasSession m_session = {
XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f),
XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f),
XCEngine::UI::UIPoint(120.0f, 120.0f),
true,
true,
true
};
};
void RenderPanelFrame(
XCUILayoutLabPanel& panel,
ImGuiContextScope&,
const std::function<void(ImGuiIO&)>& configureIo = nullptr) {
PrepareImGui();
if (configureIo) {
configureIo(ImGui::GetIO());
}
ImGui::NewFrame();
panel.Render();
ImGui::Render();
}
void ClickElement(
XCUILayoutLabPanel& panel,
StubCanvasHost& canvasHost,
const std::string& elementId,
ImGuiContextScope& contextScope) {
XCEngine::UI::UIRect elementRect = {};
ASSERT_TRUE(panel.TryGetElementRect(elementId, elementRect));
const XCEngine::UI::UIPoint clickPoint(
elementRect.x + elementRect.width * 0.5f,
elementRect.y + elementRect.height * 0.5f);
canvasHost.SetPointerPosition(clickPoint);
canvasHost.SetHovered(true);
RenderPanelFrame(
panel,
contextScope,
[clickPoint](ImGuiIO& io) {
io.AddMousePosEvent(clickPoint.x, clickPoint.y);
io.AddMouseButtonEvent(ImGuiMouseButton_Left, true);
});
RenderPanelFrame(
panel,
contextScope,
[clickPoint](ImGuiIO& io) {
io.AddMousePosEvent(clickPoint.x, clickPoint.y);
io.AddMouseButtonEvent(ImGuiMouseButton_Left, false);
});
}
void PressKeyOnce(
XCUILayoutLabPanel& panel,
ImGuiContextScope& contextScope,
ImGuiKey key) {
RenderPanelFrame(
panel,
contextScope,
[key](ImGuiIO& io) {
io.AddKeyEvent(key, true);
});
RenderPanelFrame(
panel,
contextScope,
[key](ImGuiIO& io) {
io.AddKeyEvent(key, false);
});
}
TEST(NewEditorXCUILayoutLabPanelTest, MapsPreviousNextHomeAndEndIntoRuntimeNavigation) {
ImGuiContextScope contextScope;
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
auto canvasHost = std::make_unique<StubCanvasHost>();
StubCanvasHost* canvasHostPtr = canvasHost.get();
ImGuiXCUIInputSnapshotSource inputSource(nullptr);
XCUILayoutLabPanel panel(&inputSource, std::move(previewPresenter), std::move(canvasHost));
panel.SetHostedPreviewEnabled(false);
RenderPanelFrame(panel, contextScope);
ClickElement(panel, *canvasHostPtr, "assetLighting", contextScope);
ASSERT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
canvasHostPtr->SetHovered(false);
canvasHostPtr->SetWindowFocused(true);
PressKeyOnce(panel, contextScope, ImGuiKey_DownArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetMaterials");
PressKeyOnce(panel, contextScope, ImGuiKey_UpArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
PressKeyOnce(panel, contextScope, ImGuiKey_End);
const std::string endSelection = panel.GetFrameResult().stats.selectedElementId;
ASSERT_FALSE(endSelection.empty());
EXPECT_NE(endSelection, "assetLighting");
PressKeyOnce(panel, contextScope, ImGuiKey_Home);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
}
TEST(NewEditorXCUILayoutLabPanelTest, MapsCollapseAndExpandIntoRuntimeNavigation) {
ImGuiContextScope contextScope;
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
auto canvasHost = std::make_unique<StubCanvasHost>();
StubCanvasHost* canvasHostPtr = canvasHost.get();
ImGuiXCUIInputSnapshotSource inputSource(nullptr);
XCUILayoutLabPanel panel(&inputSource, std::move(previewPresenter), std::move(canvasHost));
panel.SetHostedPreviewEnabled(false);
RenderPanelFrame(panel, contextScope);
ClickElement(panel, *canvasHostPtr, "treeScenes", contextScope);
ASSERT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
canvasHostPtr->SetHovered(false);
canvasHostPtr->SetWindowFocused(true);
PressKeyOnce(panel, contextScope, ImGuiKey_LeftArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
PressKeyOnce(panel, contextScope, ImGuiKey_LeftArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
EXPECT_EQ(panel.GetFrameResult().stats.expandedTreeItemCount, 0u);
PressKeyOnce(panel, contextScope, ImGuiKey_RightArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
EXPECT_EQ(panel.GetFrameResult().stats.expandedTreeItemCount, 1u);
PressKeyOnce(panel, contextScope, ImGuiKey_RightArrow);
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
}
TEST(NewEditorXCUILayoutLabPanelTest, DefaultFallbackDoesNotCreateImplicitHostedPreviewPresenter) {
ImGuiContextScope contextScope;
XCUILayoutLabPanel panel(nullptr);
RenderPanelFrame(panel, contextScope);
EXPECT_FALSE(panel.IsUsingNativeHostedPreview());
EXPECT_FALSE(panel.GetLastPreviewStats().presented);
EXPECT_EQ(panel.GetLastPreviewStats().submittedDrawListCount, 0u);
EXPECT_EQ(panel.GetLastPreviewStats().submittedCommandCount, 0u);
}
} // namespace