build: Update ImGui Test Engine

This commit is contained in:
WerWolv
2025-09-19 18:21:57 +02:00
parent 07a6a9b7d4
commit 4dc3f9e033
7 changed files with 103 additions and 15 deletions

View File

@@ -157,6 +157,7 @@ struct IMGUI_API ImGuiTestGenericItemStatus
{
int RetValue; // return value
int Hovered; // result of IsItemHovered()
int HoveredAllowDisabled; // result of IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)
int Active; // result of IsItemActive()
int Focused; // result of IsItemFocused()
int Clicked; // result of IsItemClicked()
@@ -169,7 +170,7 @@ struct IMGUI_API ImGuiTestGenericItemStatus
ImGuiTestGenericItemStatus() { Clear(); }
void Clear() { memset(this, 0, sizeof(*this)); }
void QuerySet(bool ret_val = false) { Clear(); QueryInc(ret_val); }
void QueryInc(bool ret_val = false) { RetValue += ret_val; Hovered += ImGui::IsItemHovered(); Active += ImGui::IsItemActive(); Focused += ImGui::IsItemFocused(); Clicked += ImGui::IsItemClicked(); Visible += ImGui::IsItemVisible(); Edited += ImGui::IsItemEdited(); Activated += ImGui::IsItemActivated(); Deactivated += ImGui::IsItemDeactivated(); DeactivatedAfterEdit += ImGui::IsItemDeactivatedAfterEdit(); }
void QueryInc(bool ret_val = false) { RetValue += ret_val; Hovered += ImGui::IsItemHovered(); HoveredAllowDisabled += ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled); Active += ImGui::IsItemActive(); Focused += ImGui::IsItemFocused(); Clicked += ImGui::IsItemClicked(); Visible += ImGui::IsItemVisible(); Edited += ImGui::IsItemEdited(); Activated += ImGui::IsItemActivated(); Deactivated += ImGui::IsItemDeactivated(); DeactivatedAfterEdit += ImGui::IsItemDeactivatedAfterEdit(); }
void Draw() { ImGui::Text("Ret: %d, Hovered: %d, Active: %d, Focused: %d\nClicked: %d, Visible: %d, Edited: %d\nActivated: %d, Deactivated: %d, DeactivatedAfterEdit: %d", RetValue, Hovered, Active, Focused, Clicked, Visible, Edited, Activated, Deactivated, DeactivatedAfterEdit); }
};
@@ -187,6 +188,7 @@ struct IMGUI_API ImGuiTestGenericVars
ImGuiWindowFlags WindowFlags;
ImGuiTableFlags TableFlags;
ImGuiPopupFlags PopupFlags;
ImGuiInputTextFlags InputTextFlags;
ImGuiTestGenericItemStatus Status;
bool ShowWindow1, ShowWindow2;
bool UseClipper;
@@ -400,6 +402,9 @@ struct IMGUI_API ImGuiTestContext
void ScrollToY(ImGuiTestRef ref, float scroll_y) { ScrollTo(ref, ImGuiAxis_Y, scroll_y); }
void ScrollToTop(ImGuiTestRef ref);
void ScrollToBottom(ImGuiTestRef ref);
void ScrollToPos(ImGuiTestRef window_ref, float pos_v, ImGuiAxis axis, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void ScrollToPosX(ImGuiTestRef window_ref, float pos_x);
void ScrollToPosY(ImGuiTestRef window_ref, float pos_y);
void ScrollToItem(ImGuiTestRef ref, ImGuiAxis axis, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void ScrollToItemX(ImGuiTestRef ref);
void ScrollToItemY(ImGuiTestRef ref);

View File

@@ -156,6 +156,7 @@ struct ImGuiTestEngine
ImGuiContext* UiContextActive = nullptr; // imgui context for testing == UiContextTarget or nullptr
bool Started = false;
bool UiContextHasHooks = false;
ImU64 BatchStartTime = 0;
ImU64 BatchEndTime = 0;
int FrameCount = 0;

View File

@@ -936,6 +936,9 @@ static void ItemInfoErrorLog(ImGuiTestContext* ctx, ImGuiTestRef ref, ImGuiID fu
if (flags & ImGuiTestOpFlags_NoError)
return;
if (ctx->Engine->UiContextHasHooks == false)
IM_ERRORF_NOHDR("%s", "IMGUI DOES NOT SEEM COMPILED WITH '#define IMGUI_ENABLE_TEST_ENGINE'!\nMAKE SURE THAT BOTH 'imgui' AND 'imgui_test_engine' ARE USING THE SAME 'imconfig' FILE.");
// Prefixing the string with / ignore the reference/current ID
Str256 msg;
if (ref.Path && ref.Path[0] == '/' && ctx->RefStr[0] != 0)
@@ -1412,6 +1415,39 @@ void ImGuiTestContext::ScrollTo(ImGuiTestRef ref, ImGuiAxis axis, float scrol
Yield();
}
// Supported values for ImGuiTestOpFlags:
// - ImGuiTestOpFlags_NoFocusWindow
void ImGuiTestContext::ScrollToPos(ImGuiTestRef window_ref, float pos_v, ImGuiAxis axis, ImGuiTestOpFlags flags)
{
if (IsError())
return;
IMGUI_TEST_CONTEXT_REGISTER_DEPTH(this);
LogDebug("ScrollToPos %c %.2f", 'X' + axis, pos_v);
// Ensure window size and ScrollMax are up-to-date
Yield();
ImGuiWindow* window = GetWindowByRef(window_ref);
IM_CHECK_SILENT(window != NULL);
float item_curr = pos_v;
float item_target = ImFloor(window->InnerClipRect.GetCenter()[axis]);
float scroll_delta = item_target - item_curr;
float scroll_target = ImClamp(window->Scroll[axis] - scroll_delta, 0.0f, window->ScrollMax[axis]);
ScrollTo(window->ID, axis, scroll_target, (flags & ImGuiTestOpFlags_NoFocusWindow));
}
void ImGuiTestContext::ScrollToPosX(ImGuiTestRef window_ref, float pos_x)
{
ScrollToPos(window_ref, pos_x, ImGuiAxis_X);
}
void ImGuiTestContext::ScrollToPosY(ImGuiTestRef window_ref, float pos_y)
{
ScrollToPos(window_ref, pos_y, ImGuiAxis_Y);
}
// Supported values for ImGuiTestOpFlags:
// - ImGuiTestOpFlags_NoFocusWindow
void ImGuiTestContext::ScrollToItem(ImGuiTestRef ref, ImGuiAxis axis, ImGuiTestOpFlags flags)
@@ -3599,6 +3635,10 @@ void ImGuiTestContext::ComboClick(ImGuiTestRef ref)
Str128f combo_item_buf = Str128f("//%s/**/%s", popup->Name, p + 1);
ItemClick(combo_item_buf.c_str());
// For if Combo Selectables uses ImGuiSelectableFlags_NoAutoClosePopups
if (GetWindowByRef("//$FOCUSED") == popup)
KeyPress(ImGuiKey_Enter);
}
void ImGuiTestContext::ComboClickAll(ImGuiTestRef ref_parent)
@@ -3617,6 +3657,10 @@ void ImGuiTestContext::ComboClickAll(ImGuiTestRef ref_parent)
ItemClick(ref_parent);
ItemClick(item.ID);
}
// For if Combo Selectables uses ImGuiSelectableFlags_NoAutoClosePopups
if (GetWindowByRef("//$FOCUSED") == popup)
KeyPress(ImGuiKey_Enter);
}
static ImGuiTableColumn* HelperTableFindColumnByName(ImGuiTable* table, const char* name)
@@ -3641,7 +3685,18 @@ void ImGuiTestContext::TableOpenContextMenu(ImGuiTestRef ref, int column_n)
if (column_n == -1)
column_n = table->RightMostEnabledColumn;
ItemClick(TableGetHeaderID(table, column_n), ImGuiMouseButton_Right);
IM_CHECK(column_n >= 0 && column_n <= table->ColumnsCount);
ImGuiTableColumn* column = &table->Columns[column_n];
IM_CHECK_SILENT(column->IsEnabled);
ImGuiID header_id = TableGetHeaderID(table, column_n);
// Make visible
if (!ItemExists(header_id))
ScrollToPosX(table->InnerWindow->ID, (column->MinX + column->MaxX) * 0.5f);
ItemClick(header_id, ImGuiMouseButton_Right);
Yield();
}
@@ -3658,7 +3713,13 @@ ImGuiSortDirection ImGuiTestContext::TableClickHeader(ImGuiTestRef ref, const ch
if (key_mods != ImGuiMod_None)
KeyDown(key_mods);
ItemClick(TableGetHeaderID(table, label), ImGuiMouseButton_Left);
ImGuiID header_id = TableGetHeaderID(table, label);
// Make visible
if (!ItemExists(header_id))
ScrollToPosX(table->InnerWindow->ID, (column->MinX + column->MaxX) * 0.5f);
ItemClick(header_id, ImGuiMouseButton_Left);
if (key_mods != ImGuiMod_None)
KeyUp(key_mods);
@@ -3674,7 +3735,11 @@ void ImGuiTestContext::TableSetColumnEnabled(ImGuiTestRef ref, const char* label
ImGuiTestRefDesc desc(ref);
LogDebug("TableSetColumnEnabled %s label '%s' enabled = %d", desc.c_str(), label, enabled);
TableOpenContextMenu(ref);
ImGuiTable* table = ImGui::TableFindByID(GetID(ref));
IM_CHECK_SILENT(table != NULL);
ImGuiTableColumn* column = HelperTableFindColumnByName(table, label);
int column_n = column->IsEnabled ? table->Columns.index_from_ptr(column) : -1;
TableOpenContextMenu(ref, column_n);
ImGuiTestRef backup_ref = GetRef();
SetRef("//$FOCUSED");

View File

@@ -197,6 +197,7 @@ void ImGuiTestEngine_BindImGuiContext(ImGuiTestEngine* engine, ImGuiContext* ui_
GImGuiTestEngine = engine;
IM_ASSERT(ui_ctx->TestEngine == nullptr);
ui_ctx->TestEngine = engine;
engine->UiContextHasHooks = false;
}
void ImGuiTestEngine_UnbindImGuiContext(ImGuiTestEngine* engine, ImGuiContext* ui_ctx)
@@ -230,6 +231,7 @@ void ImGuiTestEngine_UnbindImGuiContext(ImGuiTestEngine* engine, ImGuiContext
// Create test context (not bound to any dear imgui context yet)
ImGuiTestEngine* ImGuiTestEngine_CreateContext()
{
IMGUI_CHECKVERSION(); // <--- If you get a crash here: mismatching config, check that both imgui and imgui_test_engine are using same defines (e.g. using the same imconfig file)
ImGuiTestEngine* engine = IM_NEW(ImGuiTestEngine)();
return engine;
}
@@ -1901,7 +1903,7 @@ void ImGuiTestEngine_RunTest(ImGuiTestEngine* engine, ImGuiTestContext* parent_c
// Additional yields to avoid consecutive tests who may share identifiers from missing their window/item activation.
ctx->RunFlags |= ImGuiTestRunFlags_GuiFuncDisable;
ctx->Yield(2);
ctx->Yield(3);
// Restore active func
ctx->ActiveFunc = backup_active_func;
@@ -2177,6 +2179,7 @@ static void ImGuiTestEngineHook_ItemAdd_GatherTask(ImGuiContext* ui_ctx, ImGuiTe
void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ui_ctx, ImGuiID id, const ImRect& bb, const ImGuiLastItemData* item_data)
{
ImGuiTestEngine* engine = (ImGuiTestEngine*)ui_ctx->TestEngine;
engine->UiContextHasHooks = true;
IM_ASSERT(id != 0);
ImGuiContext& g = *ui_ctx;

View File

@@ -271,7 +271,7 @@ static void TestStatusButton(const char* id, const ImVec4& color, bool running,
}
}
static void ShowTestGroup(ImGuiTestEngine* e, ImGuiTestGroup group, Str* filter)
static void ShowTestGroup(ImGuiTestEngine* e, ImGuiTestGroup group, Str* filter, bool run)
{
ImGuiStyle& style = ImGui::GetStyle();
ImGuiIO& io = ImGui::GetIO();
@@ -285,14 +285,14 @@ static void ShowTestGroup(ImGuiTestEngine* e, ImGuiTestGroup group, Str* filter)
//ImGui::Text("TESTS (%d)", engine->TestsAll.Size);
#if IMGUI_VERSION_NUM >= 19066
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip | ImGuiInputFlags_RouteFromRootWindow);
bool run = ImGui::Button("Run");
run |= ImGui::Button("Run");
#elif IMGUI_VERSION_NUM >= 18837
bool run = ImGui::Button("Run") || ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_R);
run |= ImGui::Button("Run") || ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_R);
#if IMGUI_VERSION_NUM > 18963
ImGui::SetItemTooltip("Ctrl+R");
#endif
#else
bool run = ImGui::Button("Run");
run |= ImGui::Button("Run");
#endif
if (run)
{
@@ -652,7 +652,13 @@ static void ImGuiTestEngine_ShowLogAndTools(ImGuiTestEngine* engine)
{
ImGuiIO& io = ImGui::GetIO();
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::Text("TestEngine: HookItems: %d, HookPushId: %d, InfoTasks: %d", g.TestEngineHookItems, g.DebugHookIdInfo != 0, engine->InfoTasks.Size);
ImGui::Text("TestEngine: HookItems: %d, HookPushId: %d, InfoTasks: %d", g.TestEngineHookItems,
#if IMGUI_VERSION_NUM < 19229
g.DebugHookIdInfo != 0,
#else
g.DebugHookIdInfoId != 0,
#endif
engine->InfoTasks.Size);
ImGui::Separator();
if (ImGui::Button("Reboot UI context"))
@@ -739,8 +745,18 @@ static void ImGuiTestEngine_ShowTestTool(ImGuiTestEngine* engine, bool* p_open)
return;
}
bool run = false;
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Tests"))
{
// FIXME: This idiom showcases an issue with menus vs shortcuts. Would be nice if e.g. we could activate a shortcut?
run = ImGui::MenuItem("Run Visible", "Ctrl+R");
ImGui::MenuItem("Filter", "Ctrl+F");
if (p_open != NULL && ImGui::MenuItem("Close"))
*p_open = false;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Tools"))
{
ImGuiContext& g = *GImGui;
@@ -824,12 +840,12 @@ static void ImGuiTestEngine_ShowTestTool(ImGuiTestEngine* engine, bool* p_open)
{
if (ImGui::BeginTabItem("TESTS", nullptr, ImGuiTabItemFlags_NoPushId))
{
ShowTestGroup(engine, ImGuiTestGroup_Tests, engine->UiFilterTests);
ShowTestGroup(engine, ImGuiTestGroup_Tests, engine->UiFilterTests, run);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("PERFS", nullptr, ImGuiTabItemFlags_NoPushId))
{
ShowTestGroup(engine, ImGuiTestGroup_Perfs, engine->UiFilterPerfs);
ShowTestGroup(engine, ImGuiTestGroup_Perfs, engine->UiFilterPerfs, run);
ImGui::EndTabItem();
}
ImGui::EndTabBar();

View File

@@ -16,9 +16,7 @@
#if defined(_WIN32)
#if !defined(_WINDOWS_)
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#include <shellapi.h> // ShellExecuteA()