/
imgui_te_context.h
626 lines (547 loc) · 41.8 KB
/
imgui_te_context.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
// dear imgui test engine
// (context when a running test + end user automation API)
// This is the main (if not only) interface that your Tests will be using.
#pragma once
#include "imgui.h"
#include "imgui_internal.h" // ImGuiAxis, ImGuiItemStatusFlags, ImGuiInputSource, ImGuiWindow
#include "imgui_te_engine.h" // ImGuiTestStatus, ImGuiTestRunFlags, ImGuiTestActiveFunc, ImGuiTestItemInfo, ImGuiTestLogFlags
/*
Index of this file:
// [SECTION] Header mess, warnings
// [SECTION] Forward declarations
// [SECTION] ImGuiTestRef
// [SECTION] Helper keys
// [SECTION] ImGuiTestContext related Flags/Enumerations
// [SECTION] ImGuiTestGenericVars, ImGuiTestGenericItemStatus
// [SECTION] ImGuiTestContext
// [SECTION] Debugging macros: IM_SUSPEND_TESTFUNC()
// [SECTION] Testing/Checking macros: IM_CHECK(), IM_ERRORF() etc.
*/
//-------------------------------------------------------------------------
// [SECTION] Header mess, warnings
//-------------------------------------------------------------------------
// Undo some of the damage done by <windows.h>
#ifdef Yield
#undef Yield
#endif
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#endif
//-------------------------------------------------------------------------
// [SECTION] Forward declarations
//-------------------------------------------------------------------------
// This file
typedef int ImGuiTestOpFlags; // Flags: See ImGuiTestOpFlags_
// External: imgui
struct ImGuiDockNode;
struct ImGuiTabBar;
struct ImGuiWindow;
// External: test engine
struct ImGuiTest; // A test registered with IM_REGISTER_TEST()
struct ImGuiTestEngine; // Test Engine Instance (opaque)
struct ImGuiTestEngineIO; // Test Engine IO structure (configuration flags, state)
struct ImGuiTestItemInfo; // Information gathered about an item: label, status, bounding box etc.
struct ImGuiTestItemList; // Result of an GatherItems() query
struct ImGuiTestInputs; // Test Engine Simulated Inputs structure (opaque)
struct ImGuiTestGatherTask; // Test Engine task for scanning/finding items
struct ImGuiCaptureArgs; // Parameters for ctx->CaptureXXX functions
enum ImGuiTestVerboseLevel : int;
//-------------------------------------------------------------------------
// [SECTION] ImGuiTestRef
//-------------------------------------------------------------------------
// Weak reference to an Item/Window given an hashed ID _or_ a string path ID.
// This is most often passed as argument to function and generally has a very short lifetime.
// Documentation: https://github.com/ocornut/imgui_test_engine/wiki/Named-References
// (SUGGESTION: add those constructors to "VA Step Filter" (Visual Assist) or a .natstepfilter file (Visual Studio) so they are skipped by F11 (StepInto)
struct IMGUI_API ImGuiTestRef
{
ImGuiID ID; // Pre-hashed ID
const char* Path; // Relative or absolute path (string pointed to, not owned, as our lifetime is very short)
ImGuiTestRef() { ID = 0; Path = NULL; }
ImGuiTestRef(ImGuiID id) { ID = id; Path = NULL; }
ImGuiTestRef(const char* path) { ID = 0; Path = path; }
bool IsEmpty() const { return ID == 0 && (Path == NULL || Path[0] == 0); }
};
// Debug helper to output a string showing the Path, ID or Debug Label based on what is available (some items only have ID as we couldn't find/store a Path)
// (The size is arbitrary, this is only used for logging info the user/debugger)
struct IMGUI_API ImGuiTestRefDesc
{
char Buf[80];
const char* c_str() { return Buf; }
ImGuiTestRefDesc(const ImGuiTestRef& ref);
ImGuiTestRefDesc(const ImGuiTestRef& ref, const ImGuiTestItemInfo& item);
};
//-------------------------------------------------------------------------
// [SECTION] ImGuiTestContext related Flags/Enumerations
//-------------------------------------------------------------------------
// Named actions. Generally you will call the named helpers e.g. ItemClick(). This is used by shared/low-level functions such as ItemAction().
enum ImGuiTestAction
{
ImGuiTestAction_Unknown = 0,
ImGuiTestAction_Hover, // Move mouse
ImGuiTestAction_Click, // Move mouse and click
ImGuiTestAction_DoubleClick, // Move mouse and double-click
ImGuiTestAction_Check, // Check item if unchecked (Checkbox, MenuItem or any widget reporting ImGuiItemStatusFlags_Checkable)
ImGuiTestAction_Uncheck, // Uncheck item if checked
ImGuiTestAction_Open, // Open item if closed (TreeNode, BeginMenu or any widget reporting ImGuiItemStatusFlags_Openable)
ImGuiTestAction_Close, // Close item if opened
ImGuiTestAction_Input, // Start text inputing into a field (e.g. CTRL+Click on Drags/Slider, click on InputText etc.)
ImGuiTestAction_NavActivate, // Activate item with navigation
ImGuiTestAction_COUNT
};
// Generic flags for many ImGuiTestContext functions
// Some flags are only supported by a handful of functions. Check function headers for list of supported flags.
enum ImGuiTestOpFlags_
{
ImGuiTestOpFlags_None = 0,
ImGuiTestOpFlags_NoCheckHoveredId = 1 << 1, // Don't check for HoveredId after aiming for a widget. A few situations may want this: while e.g. dragging or another items prevents hovering, or for items that don't use ItemHoverable()
ImGuiTestOpFlags_NoError = 1 << 2, // Don't abort/error e.g. if the item cannot be found or the operation doesn't succeed.
ImGuiTestOpFlags_NoFocusWindow = 1 << 3, // Don't focus window when aiming at an item
ImGuiTestOpFlags_NoAutoUncollapse = 1 << 4, // Disable automatically uncollapsing windows (useful when specifically testing Collapsing behaviors)
ImGuiTestOpFlags_NoAutoOpenFullPath = 1 << 5, // Disable automatically opening intermediaries (e.g. ItemClick("Hello/OK") will automatically first open "Hello" if "OK" isn't found. Only works if ref is a string path.
ImGuiTestOpFlags_NoYield = 1 << 6, // Don't yield (only supported by a few functions), in case you need to manage rigorous per-frame timing.
ImGuiTestOpFlags_IsSecondAttempt = 1 << 7, // Used by recursing functions to indicate a second attempt
ImGuiTestOpFlags_MoveToEdgeL = 1 << 8, // Simple Dumb aiming helpers to test widget that care about clicking position. May need to replace will better functionalities.
ImGuiTestOpFlags_MoveToEdgeR = 1 << 9,
ImGuiTestOpFlags_MoveToEdgeU = 1 << 10,
ImGuiTestOpFlags_MoveToEdgeD = 1 << 11,
};
// Advanced filtering for ItemActionAll()
struct IMGUI_API ImGuiTestActionFilter
{
int MaxDepth;
int MaxPasses;
const int* MaxItemCountPerDepth;
ImGuiItemStatusFlags RequireAllStatusFlags;
ImGuiItemStatusFlags RequireAnyStatusFlags;
ImGuiTestActionFilter() { MaxDepth = -1; MaxPasses = -1; MaxItemCountPerDepth = NULL; RequireAllStatusFlags = RequireAnyStatusFlags = 0; }
};
//-------------------------------------------------------------------------
// [SECTION] ImGuiTestGenericVars, ImGuiTestGenericItemStatus
//-------------------------------------------------------------------------
// Helper struct to store various query-able state of an item.
// This facilitate interactions between GuiFunc and TestFunc, since those state are frequently used.
struct IMGUI_API ImGuiTestGenericItemStatus
{
int RetValue; // return value
int Hovered; // result of IsItemHovered()
int Active; // result of IsItemActive()
int Focused; // result of IsItemFocused()
int Clicked; // result of IsItemClicked()
int Visible; // result of IsItemVisible()
int Edited; // result of IsItemEdited()
int Activated; // result of IsItemActivated()
int Deactivated; // result of IsItemDeactivated()
int DeactivatedAfterEdit; // result of IsItemDeactivatedAfterEdit()
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(); }
};
// Generic structure with various storage fields.
// This is useful for tests to quickly share data between GuiFunc and TestFunc without creating custom data structure.
// If those fields are not enough: using test->SetVarsDataType<>() + ctx->GetVars<>() it is possible to store custom data.
struct IMGUI_API ImGuiTestGenericVars
{
// Generic storage with a bit of semantic to make user/test code look neater
int Step;
int Count;
ImGuiID DockId;
ImGuiID OwnerId;
ImGuiWindowFlags WindowFlags;
ImGuiTableFlags TableFlags;
ImGuiPopupFlags PopupFlags;
ImGuiTestGenericItemStatus Status;
bool ShowWindow1, ShowWindow2;
bool UseClipper;
bool UseViewports;
float Width;
ImVec2 Pos;
ImVec2 Size;
ImVec2 Pivot;
ImVec4 Color1, Color2;
// Generic unnamed storage
int Int1, Int2, IntArray[10];
float Float1, Float2, FloatArray[10];
bool Bool1, Bool2, BoolArray[10];
ImGuiID Id, IdArray[10];
char Str1[256], Str2[256];
ImGuiTestGenericVars() { Clear(); }
void Clear() { memset(this, 0, sizeof(*this)); }
};
//-------------------------------------------------------------------------
// [SECTION] ImGuiTestContext
// Context for a running ImGuiTest
// This is the interface that most tests will interact with.
//-------------------------------------------------------------------------
struct IMGUI_API ImGuiTestContext
{
// User variables
ImGuiTestGenericVars GenericVars; // Generic variables holder for convenience.
void* UserVars = NULL; // Access using ctx->GetVars<Type>(). Setup with test->SetVarsDataType<>().
// Public fields
ImGuiContext* UiContext = NULL; // UI context
ImGuiTestEngineIO* EngineIO = NULL; // Test Engine IO/settings
ImGuiTest* Test = NULL; // Test currently running
ImGuiTestOutput* TestOutput = NULL; // Test output (generally == &Test->Output)
ImGuiTestOpFlags OpFlags = ImGuiTestOpFlags_None; // Flags affecting all operation (supported: ImGuiTestOpFlags_NoAutoUncollapse)
int PerfStressAmount = 0; // Convenience copy of engine->IO.PerfStressAmount
int FrameCount = 0; // Test frame count (restarts from zero every time)
int FirstTestFrameCount = 0; // First frame where TestFunc is running (after warm-up frame). This is generally -1 or 0 depending on whether we have warm up enabled
bool FirstGuiFrame = false;
bool HasDock = false; // #ifdef IMGUI_HAS_DOCK expressed in an easier to test value
ImGuiCaptureArgs* CaptureArgs = NULL; // Capture settings used by ctx->Capture*() functions
//-------------------------------------------------------------------------
// [Internal Fields]
//-------------------------------------------------------------------------
ImGuiTestEngine* Engine = NULL;
ImGuiTestInputs* Inputs = NULL;
ImGuiTestRunFlags RunFlags = ImGuiTestRunFlags_None;
ImGuiTestActiveFunc ActiveFunc = ImGuiTestActiveFunc_None; // None/GuiFunc/TestFunc
double RunningTime = 0.0; // Amount of wall clock time the Test has been running. Used by safety watchdog.
int ActionDepth = 0; // Nested depth of ctx-> function calls (used to decorate log)
int CaptureCounter = 0; // Number of captures
int ErrorCounter = 0; // Number of errors (generally this maxxes at 1 as most functions will early out)
bool Abort = false;
double PerfRefDt = -1.0;
int PerfIterations = 400; // Number of frames for PerfCapture() measurements
char RefStr[256] = { 0 }; // Reference window/path over which all named references are based
ImGuiID RefID = 0; // Reference ID over which all named references are based
ImGuiID RefWindowID = 0; // ID of a window that contains RefID item
ImGuiInputSource InputMode = ImGuiInputSource_Mouse; // Prefer interacting with mouse/keyboard/gamepad
ImVector<char> Clipboard; // Private clipboard for the test instance
ImVector<ImGuiWindow*> ForeignWindowsToHide;
ImGuiTestItemInfo DummyItemInfoNull; // Storage for ItemInfoNull()
bool CachedLinesPrintedToTTY = false;
//-------------------------------------------------------------------------
// Public API
//-------------------------------------------------------------------------
// Main control
void RecoverFromUiContextErrors();
void Finish(ImGuiTestStatus status = ImGuiTestStatus_Success); // Set test status and stop running. Usually called when running test logic from GuiFunc() only.
ImGuiTestStatus RunChildTest(const char* test_name, ImGuiTestRunFlags flags = 0); // [Experimental] Run another test from the current test.
template <typename T> T& GetVars() { IM_ASSERT(UserVars != NULL); return *(T*)(UserVars); }// Campanion to using t->SetVarsDataType<>(). FIXME: Assert to compare sizes
// Main status queries
bool IsError() const { return TestOutput->Status == ImGuiTestStatus_Error || Abort; }
bool IsWarmUpGuiFrame() const { return FrameCount < FirstTestFrameCount; } // Unless test->Flags has ImGuiTestFlags_NoGuiWarmUp, we run GuiFunc() twice before running TestFunc(). Those frames are called "WarmUp" frames.
bool IsFirstGuiFrame() const { return FirstGuiFrame; }
bool IsFirstTestFrame() const { return FrameCount == FirstTestFrameCount; } // First frame where TestFunc is running (after warm-up frame).
bool IsGuiFuncOnly() const { return (RunFlags & ImGuiTestRunFlags_GuiFuncOnly) != 0; }
// Debugging
bool SuspendTestFunc(const char* file = NULL, int line = 0); // [DEBUG] Generally called via IM_SUSPEND_TESTFUNC
// Logging
void LogEx(ImGuiTestVerboseLevel level, ImGuiTestLogFlags flags, const char* fmt, ...) IM_FMTARGS(4);
void LogExV(ImGuiTestVerboseLevel level, ImGuiTestLogFlags flags, const char* fmt, va_list args) IM_FMTLIST(4);
void LogToTTY(ImGuiTestVerboseLevel level, const char* message, const char* message_end = NULL);
void LogToDebugger(ImGuiTestVerboseLevel level, const char* message);
void LogDebug(const char* fmt, ...) IM_FMTARGS(2); // ImGuiTestVerboseLevel_Debug or ImGuiTestVerboseLevel_Trace depending on context depth
void LogInfo(const char* fmt, ...) IM_FMTARGS(2); // ImGuiTestVerboseLevel_Info
void LogWarning(const char* fmt, ...) IM_FMTARGS(2); // ImGuiTestVerboseLevel_Warning
void LogError(const char* fmt, ...) IM_FMTARGS(2); // ImGuiTestVerboseLevel_Error
void LogBasicUiState();
void LogItemList(ImGuiTestItemList* list);
// Yield, Timing
void Yield(int count = 1);
void YieldUntil(int frame_count);
void Sleep(float time_in_second); // Sleep for a given simulation time, unless in Fast mode
void SleepShort(); // Standard short delay of io.ActionDelayShort (~0.15f), unless in Fast mode.
void SleepStandard(); // Standard regular delay of io.ActionDelayStandard (~0.40f), unless in Fast mode.
void SleepNoSkip(float time_in_second, float framestep_in_second);
// Base Reference
// - ItemClick("Window/Button") --> click "Window/Button"
// - SetRef("Window"), ItemClick("Button") --> click "Window/Button"
// - SetRef("Window"), ItemClick("/Button") --> click "Window/Button"
// - SetRef("Window"), ItemClick("//Button") --> click "/Button"
// - SetRef("//$FOCUSED"), ItemClick("Button") --> click "Button" in focused window.
// See https://github.com/ocornut/imgui_test_engine/wiki/Named-References about using ImGuiTestRef in all ImGuiTestContext functions.
// Note: SetRef() may take multiple frames to complete if specified ref is an item id.
void SetRef(ImGuiTestRef ref);
void SetRef(ImGuiWindow* window); // Shortcut to SetRef(window->Name) which works for ChildWindow (see code)
ImGuiTestRef GetRef();
// Windows
ImGuiTestItemInfo WindowInfo(ImGuiTestRef window_ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void WindowClose(ImGuiTestRef window_ref);
void WindowCollapse(ImGuiTestRef window_ref, bool collapsed);
void WindowFocus(ImGuiTestRef window_ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void WindowBringToFront(ImGuiTestRef window_ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void WindowMove(ImGuiTestRef window_ref, ImVec2 pos, ImVec2 pivot = ImVec2(0.0f, 0.0f), ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void WindowResize(ImGuiTestRef window_ref, ImVec2 sz);
bool WindowTeleportToMakePosVisible(ImGuiTestRef window_ref, ImVec2 pos_in_window);
ImGuiWindow*GetWindowByRef(ImGuiTestRef window_ref);
// Popups
void PopupCloseOne();
void PopupCloseAll();
ImGuiID PopupGetWindowID(ImGuiTestRef ref);
// Get hash for a decorated ID Path.
// Note: for windows you may use WindowInfo()
ImGuiID GetID(ImGuiTestRef ref);
ImGuiID GetID(ImGuiTestRef ref, ImGuiTestRef seed_ref);
// Miscellaneous helpers
ImVec2 GetPosOnVoid(ImGuiViewport* viewport); // Find a point that has no windows // FIXME: This needs error return and flag to enable/disable forcefully finding void.
ImVec2 GetWindowTitlebarPoint(ImGuiTestRef window_ref); // Return a clickable point on window title-bar (window tab for docked windows).
ImVec2 GetMainMonitorWorkPos(); // Work pos and size of main viewport when viewports are disabled, or work pos and size of monitor containing main viewport when viewports are enabled.
ImVec2 GetMainMonitorWorkSize();
// Screenshot/Video Captures
void CaptureReset(); // Reset state (use when doing multiple captures)
void CaptureSetExtension(const char* ext); // Set capture file format (otherwise for video this default to EngineIO->VideoCaptureExtension)
bool CaptureAddWindow(ImGuiTestRef ref); // Add window to be captured (default to capture everything)
void CaptureScreenshotWindow(ImGuiTestRef ref, int capture_flags = 0); // Trigger a screen capture of a single window (== CaptureAddWindow() + CaptureScreenshot())
bool CaptureScreenshot(int capture_flags = 0); // Trigger a screen capture
bool CaptureBeginVideo(); // Start a video capture
bool CaptureEndVideo();
// Mouse inputs
void MouseMove(ImGuiTestRef ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void MouseMoveToPos(ImVec2 pos);
void MouseTeleportToPos(ImVec2 pos, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void MouseClick(ImGuiMouseButton button = 0);
void MouseClickMulti(ImGuiMouseButton button, int count);
void MouseDoubleClick(ImGuiMouseButton button = 0);
void MouseDown(ImGuiMouseButton button = 0);
void MouseUp(ImGuiMouseButton button = 0);
void MouseLiftDragThreshold(ImGuiMouseButton button = 0);
void MouseDragWithDelta(ImVec2 delta, ImGuiMouseButton button = 0);
void MouseWheel(ImVec2 delta);
void MouseWheelX(float dx) { MouseWheel(ImVec2(dx, 0.0f)); }
void MouseWheelY(float dy) { MouseWheel(ImVec2(0.0f, dy)); }
void MouseMoveToVoid(ImGuiViewport* viewport = NULL);
void MouseClickOnVoid(ImGuiMouseButton button = 0, ImGuiViewport* viewport = NULL);
ImGuiWindow*FindHoveredWindowAtPos(const ImVec2& pos);
bool FindExistingVoidPosOnViewport(ImGuiViewport* viewport, ImVec2* out);
// Mouse inputs: Viewports
// - This is automatically called by SetRef() and any mouse action taking an item reference (e.g. ItemClick("button"), MouseClick("button"))
// - But when using raw position directy e.g. MouseMoveToPos() / MouseTeleportToPos() without referring to the parent window before, this needs to be set.
void MouseSetViewport(ImGuiWindow* window);
void MouseSetViewportID(ImGuiID viewport_id);
// Keyboard inputs
void KeyDown(ImGuiKeyChord key_chord);
void KeyUp(ImGuiKeyChord key_chord);
void KeyPress(ImGuiKeyChord key_chord, int count = 1);
void KeyHold(ImGuiKeyChord key_chord, float time);
void KeySetEx(ImGuiKeyChord key_chord, bool is_down, float time);
void KeyChars(const char* chars); // Input characters
void KeyCharsAppend(const char* chars); // Input characters at end of field
void KeyCharsAppendEnter(const char* chars); // Input characters at end of field, press Enter
void KeyCharsReplace(const char* chars); // Delete existing field then input characters
void KeyCharsReplaceEnter(const char* chars); // Delete existing field then input characters, press Enter
// Navigation inputs
// FIXME: Need some redesign/refactoring:
// - This was initially intended to: replace mouse action with keyboard/gamepad
// - Abstract keyboard vs gamepad actions
// However this is widely inconsistent and unfinished at this point.
void SetInputMode(ImGuiInputSource input_mode); // Mouse or Keyboard or Gamepad. In Keyboard or Gamepad mode, actions such as ItemClick or ItemInput are using nav facilities instead of Mouse.
void NavMoveTo(ImGuiTestRef ref);
void NavActivate(); // Activate current selected item: activate button, tweak sliders/drags. Equivalent of pressing Space on keyboard, ImGuiKey_GamepadFaceUp on a gamepad.
void NavInput(); // Input into select item: input sliders/drags. Equivalent of pressing Enter on keyboard, ImGuiKey_GamepadFaceDown on a gamepad.
// Scrolling
void ScrollTo(ImGuiTestRef ref, ImGuiAxis axis, float scroll_v, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void ScrollToX(ImGuiTestRef ref, float scroll_x) { ScrollTo(ref, ImGuiAxis_X, scroll_x); }
void ScrollToY(ImGuiTestRef ref, float scroll_y) { ScrollTo(ref, ImGuiAxis_Y, scroll_y); }
void ScrollToTop(ImGuiTestRef ref);
void ScrollToBottom(ImGuiTestRef ref);
void ScrollToItem(ImGuiTestRef ref, ImGuiAxis axis, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void ScrollToItemX(ImGuiTestRef ref);
void ScrollToItemY(ImGuiTestRef ref);
void ScrollToTabItem(ImGuiTabBar* tab_bar, ImGuiID tab_id);
bool ScrollErrorCheck(ImGuiAxis axis, float expected, float actual, int* remaining_attempts);
void ScrollVerifyScrollMax(ImGuiTestRef ref);
// Low-level queries
// - ItemInfo queries never returns a NULL pointer, instead they return an empty instance (info->IsEmpty(), info->ID == 0) and set contexted as errored.
// - You can use ImGuiTestOpFlags_NoError to do a query without marking context as errored. This is what ItemExists() does.
ImGuiTestItemInfo ItemInfo(ImGuiTestRef ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
ImGuiTestItemInfo ItemInfoOpenFullPath(ImGuiTestRef ref, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
ImGuiID ItemInfoHandleWildcardSearch(const char* wildcard_prefix_start, const char* wildcard_prefix_end, const char* wildcard_suffix_start);
ImGuiTestItemInfo ItemInfoNull() { return ImGuiTestItemInfo(); }
void GatherItems(ImGuiTestItemList* out_list, ImGuiTestRef parent, int depth = -1);
// Item/Widgets manipulation
void ItemAction(ImGuiTestAction action, ImGuiTestRef ref, ImGuiTestOpFlags flags = 0, void* action_arg = NULL);
void ItemClick(ImGuiTestRef ref, ImGuiMouseButton button = 0, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Click, ref, flags, (void*)(size_t)button); }
void ItemDoubleClick(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_DoubleClick, ref, flags); }
void ItemCheck(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Check, ref, flags); }
void ItemUncheck(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Uncheck, ref, flags); }
void ItemOpen(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Open, ref, flags); }
void ItemClose(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Close, ref, flags); }
void ItemInput(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_Input, ref, flags); }
void ItemNavActivate(ImGuiTestRef ref, ImGuiTestOpFlags flags = 0) { ItemAction(ImGuiTestAction_NavActivate, ref, flags); }
bool ItemOpenFullPath(ImGuiTestRef);
// Item/Widgets: Batch actions over an entire scope
void ItemActionAll(ImGuiTestAction action, ImGuiTestRef ref_parent, const ImGuiTestActionFilter* filter = NULL);
void ItemOpenAll(ImGuiTestRef ref_parent, int depth = -1, int passes = -1);
void ItemCloseAll(ImGuiTestRef ref_parent, int depth = -1, int passes = -1);
// Item/Widgets: Helpers to easily set a value
void ItemInputValue(ImGuiTestRef ref, int v);
void ItemInputValue(ImGuiTestRef ref, float f);
void ItemInputValue(ImGuiTestRef ref, const char* str);
// Item/Widgets: Helpers to easily read a value by selecting Slider/Drag/Input text, copying into clipboard and parsing it.
// - This requires the item to be selectable (we will later provide helpers that works in more general manner)
// - Original clipboard value is restored afterward.
bool ItemSelectAndReadValue(ImGuiTestRef ref, ImGuiDataType data_type, void* out_data, ImGuiTestOpFlags flags = ImGuiTestOpFlags_None);
void ItemSelectAndReadValue(ImGuiTestRef ref, int* out_v);
void ItemSelectAndReadValue(ImGuiTestRef ref, float* out_v);
// Item/Widgets: Status query
bool ItemExists(ImGuiTestRef ref);
bool ItemIsChecked(ImGuiTestRef ref);
bool ItemIsOpened(ImGuiTestRef ref);
void ItemVerifyCheckedIfAlive(ImGuiTestRef ref, bool checked);
// Item/Widgets: Drag and Mouse operations
void ItemHold(ImGuiTestRef ref, float time);
void ItemHoldForFrames(ImGuiTestRef ref, int frames);
void ItemDragOverAndHold(ImGuiTestRef ref_src, ImGuiTestRef ref_dst);
void ItemDragAndDrop(ImGuiTestRef ref_src, ImGuiTestRef ref_dst, ImGuiMouseButton button = 0);
void ItemDragWithDelta(ImGuiTestRef ref_src, ImVec2 pos_delta);
// Helpers for Tab Bars widgets
void TabClose(ImGuiTestRef ref);
bool TabBarCompareOrder(ImGuiTabBar* tab_bar, const char** tab_order);
// Helpers for MenuBar and Menus widgets
// - e.g. MenuCheck("File/Options/Enable grid");
void MenuAction(ImGuiTestAction action, ImGuiTestRef ref);
void MenuActionAll(ImGuiTestAction action, ImGuiTestRef ref_parent);
void MenuClick(ImGuiTestRef ref) { MenuAction(ImGuiTestAction_Click, ref); }
void MenuCheck(ImGuiTestRef ref) { MenuAction(ImGuiTestAction_Check, ref); }
void MenuUncheck(ImGuiTestRef ref) { MenuAction(ImGuiTestAction_Uncheck, ref); }
void MenuCheckAll(ImGuiTestRef ref_parent) { MenuActionAll(ImGuiTestAction_Check, ref_parent); }
void MenuUncheckAll(ImGuiTestRef ref_parent) { MenuActionAll(ImGuiTestAction_Uncheck, ref_parent); }
// Helpers for Combo Boxes
void ComboClick(ImGuiTestRef ref);
void ComboClickAll(ImGuiTestRef ref);
// Helpers for Tables
void TableOpenContextMenu(ImGuiTestRef ref, int column_n = -1);
ImGuiSortDirection TableClickHeader(ImGuiTestRef ref, const char* label, ImGuiKeyChord key_mods = 0);
void TableSetColumnEnabled(ImGuiTestRef ref, const char* label, bool enabled);
void TableResizeColumn(ImGuiTestRef ref, int column_n, float width);
const ImGuiTableSortSpecs* TableGetSortSpecs(ImGuiTestRef ref);
// Viewports
// IMPORTANT: Those function may alter Platform state (unless using the "Mock Viewport" backend). Use carefully.
// Those are mostly useful to simulate OS actions and testing of viewport-specific features, may not be useful to most users.
#ifdef IMGUI_HAS_VIEWPORT
//void ViewportPlatform_SetWindowPos(ImGuiViewport* viewport, const ImVec2& pos);
//void ViewportPlatform_SetWindowSize(ImGuiViewport* viewport, const ImVec2& size);
void ViewportPlatform_SetWindowFocus(ImGuiViewport* viewport);
void ViewportPlatform_CloseWindow(ImGuiViewport* viewport);
#endif
// Docking
#ifdef IMGUI_HAS_DOCK
void DockClear(const char* window_name, ...);
void DockInto(ImGuiTestRef src_id, ImGuiTestRef dst_id, ImGuiDir split_dir = ImGuiDir_None, bool is_outer_docking = false, ImGuiTestOpFlags flags = 0);
void UndockNode(ImGuiID dock_id);
void UndockWindow(const char* window_name);
bool WindowIsUndockedOrStandalone(ImGuiWindow* window);
bool DockIdIsUndockedOrStandalone(ImGuiID dock_id);
void DockNodeHideTabBar(ImGuiDockNode* node, bool hidden);
#endif
// Performances Measurement (use along with Dear ImGui Perf Tool)
void PerfCalcRef();
void PerfCapture(const char* category = NULL, const char* test_name = NULL, const char* csv_file = NULL);
// Obsolete functions
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// Obsoleted 2022/10/11
ImGuiID GetIDByInt(int n); // Prefer using "$$123"
ImGuiID GetIDByInt(int n, ImGuiTestRef seed_ref);
ImGuiID GetIDByPtr(void* p); // Prefer using "$$(ptr)0xFFFFFFFF"
ImGuiID GetIDByPtr(void* p, ImGuiTestRef seed_ref);
// Obsoleted 2022/09/26
void KeyModDown(ImGuiModFlags mods) { KeyDown(mods); }
void KeyModUp(ImGuiModFlags mods) { KeyUp(mods); }
void KeyModPress(ImGuiModFlags mods) { KeyPress(mods); }
#endif
// [Internal]
// FIXME: Aim to remove this system...
void ForeignWindowsHideOverPos(ImVec2 pos, ImGuiWindow** ignore_list);
void ForeignWindowsUnhideAll();
};
//-------------------------------------------------------------------------
// [SECTION] Debugging macros (IM_SUSPEND_TESTFUNC)
//-------------------------------------------------------------------------
// Debug: Temporarily suspend TestFunc to let user interactively inspect the GUI state (user will need to press the "Continue" button to resume TestFunc execution)
#define IM_SUSPEND_TESTFUNC() do { if (ctx->SuspendTestFunc(__FILE__, __LINE__)) return; } while (0)
//-------------------------------------------------------------------------
// [SECTION] Testing/Checking macros: IM_CHECK(), IM_ERRORF() etc.
//-------------------------------------------------------------------------
// Helpers used by IM_CHECK_OP() macros.
// ImGuiTestEngine_GetTempStringBuilder() returns a shared instance of ImGuiTextBuffer to recycle memory allocations
template<typename T> void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, T v) { buf->append("???"); IM_UNUSED(v); } // FIXME-TESTS: Could improve with some template magic
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, const char* v) { buf->appendf("\"%s\"", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, bool v) { buf->append(v ? "true" : "false"); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImS8 v) { buf->appendf("%d", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImU8 v) { buf->appendf("%u", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImS16 v) { buf->appendf("%hd", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImU16 v) { buf->appendf("%hu", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImS32 v) { buf->appendf("%d", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImU32 v) { buf->appendf("0x%08X", v); } // Assuming ImGuiID
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImS64 v) { buf->appendf("%lld", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImU64 v) { buf->appendf("%llu", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, float v) { buf->appendf("%.3f", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, double v) { buf->appendf("%f", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImVec2 v) { buf->appendf("(%.3f, %.3f)", v.x, v.y); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, const void* v) { buf->appendf("%p", v); }
template<> inline void ImGuiTestEngineUtil_appendf_auto(ImGuiTextBuffer* buf, ImGuiWindow* v){ if (v) buf->appendf("\"%s\"", v->Name); else buf->append("NULL"); }
// We embed every macro in a do {} while(0) statement as a trick to allow using them as regular single statement, e.g. if (XXX) IM_CHECK(A); else IM_CHECK(B)
// We leave the IM_DEBUG_BREAK() outside of the check function to step out faster when using a debugger. It also has the benefit of being lighter than an IM_ASSERT().
#define IM_CHECK(_EXPR) do { bool res = (bool)(_EXPR); if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_None, res, #_EXPR)) { IM_DEBUG_BREAK(); } if (!res) return; } while (0)
#define IM_CHECK_NO_RET(_EXPR) do { bool res = (bool)(_EXPR); if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_None, res, #_EXPR)) { IM_DEBUG_BREAK(); } } while (0)
#define IM_CHECK_SILENT(_EXPR) do { bool res = (bool)(_EXPR); if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_SilentSuccess, res, #_EXPR)) { IM_DEBUG_BREAK(); } if (!res) return; } while (0)
#define IM_CHECK_RETV(_EXPR,_RETV) do { bool res = (bool)(_EXPR); if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_None, res, #_EXPR)) { IM_DEBUG_BREAK(); } if (!res) return _RETV; } while (0)
#define IM_CHECK_SILENT_RETV(_EXPR,_RETV) do { bool res = (bool)(_EXPR); if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_SilentSuccess, res, #_EXPR)) { IM_DEBUG_BREAK(); } if (!res) return _RETV; } while (0)
#define IM_ERRORF(_FMT,...) do { if (ImGuiTestEngine_Error(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_None, _FMT, __VA_ARGS__)) { IM_DEBUG_BREAK(); } } while (0)
#define IM_ERRORF_NOHDR(_FMT,...) do { if (ImGuiTestEngine_Error(NULL, NULL, 0, ImGuiTestCheckFlags_None, _FMT, __VA_ARGS__)) { IM_DEBUG_BREAK(); } } while (0)
// Those macros allow us to print out the values of both LHS and RHS expressions involved in a check.
#define IM_CHECK_OP(_LHS, _RHS, _OP, _RETURN) \
do \
{ \
auto __lhs = _LHS; /* Cache to avoid side effects */ \
auto __rhs = _RHS; \
bool __res = __lhs _OP __rhs; \
ImGuiTextBuffer* expr_buf = ImGuiTestEngine_GetTempStringBuilder(); \
expr_buf->append(#_LHS " ["); \
ImGuiTestEngineUtil_appendf_auto(expr_buf, __lhs); \
expr_buf->append("] " #_OP " " #_RHS " ["); \
ImGuiTestEngineUtil_appendf_auto(expr_buf, __rhs); \
expr_buf->append("]"); \
if (ImGuiTestEngine_Check(__FILE__, __func__, __LINE__, ImGuiTestCheckFlags_None, __res, expr_buf->c_str())) \
IM_ASSERT(__res); \
if (_RETURN && !__res) \
return; \
} while (0)
#define IM_CHECK_STR_OP(_LHS, _RHS, _OP, _RETURN, _FLAGS) \
do \
{ \
bool __res; \
if (ImGuiTestEngine_CheckStrOp(__FILE__, __func__, __LINE__, _FLAGS, #_OP, #_LHS, _LHS, #_RHS, _RHS, &__res)) \
IM_ASSERT(__res); \
if (_RETURN && !__res) \
return; \
} while (0)
// Scalar compares
#define IM_CHECK_EQ(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, ==, true) // Equal
#define IM_CHECK_NE(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, !=, true) // Not Equal
#define IM_CHECK_LT(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, < , true) // Less Than
#define IM_CHECK_LE(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, <=, true) // Less or Equal
#define IM_CHECK_GT(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, > , true) // Greater Than
#define IM_CHECK_GE(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, >=, true) // Greater or Equal
// Scalar compares, without return on failure
#define IM_CHECK_EQ_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, ==, false) // Equal
#define IM_CHECK_NE_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, !=, false) // Not Equal
#define IM_CHECK_LT_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, < , false) // Less Than
#define IM_CHECK_LE_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, <=, false) // Less or Equal
#define IM_CHECK_GT_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, > , false) // Greater Than
#define IM_CHECK_GE_NO_RET(_LHS, _RHS) IM_CHECK_OP(_LHS, _RHS, >=, false) // Greater or Equal
// String compares
#define IM_CHECK_STR_EQ(_LHS, _RHS) IM_CHECK_STR_OP(_LHS, _RHS, ==, true, ImGuiTestCheckFlags_None)
#define IM_CHECK_STR_NE(_LHS, _RHS) IM_CHECK_STR_OP(_LHS, _RHS, !=, true, ImGuiTestCheckFlags_None)
#define IM_CHECK_STR_EQ_NO_RET(_LHS, _RHS) IM_CHECK_STR_OP(_LHS, _RHS, ==, false, ImGuiTestCheckFlags_None)
#define IM_CHECK_STR_NE_NO_RET(_LHS, _RHS) IM_CHECK_STR_OP(_LHS, _RHS, !=, false, ImGuiTestCheckFlags_None)
#define IM_CHECK_STR_EQ_SILENT(_LHS, _RHS) IM_CHECK_STR_OP(_LHS, _RHS, ==, true, ImGuiTestCheckFlags_SilentSuccess)
// Floating point compares
#define IM_CHECK_FLOAT_EQ_EPS(_LHS, _RHS) IM_CHECK_LE(ImFabs(_LHS - (_RHS)), FLT_EPSILON) // Float Equal
#define IM_CHECK_FLOAT_NEAR(_LHS, _RHS, _EPS) IM_CHECK_LE(ImFabs(_LHS - (_RHS)), _EPS)
#define IM_CHECK_FLOAT_NEAR_NO_RET(_LHS, _RHS, _E) IM_CHECK_LE_NO_RET(ImFabs(_LHS - (_RHS)), _E)
//-------------------------------------------------------------------------
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif