diff --git a/imgui.cpp b/imgui.cpp index 38d8ab4bd..cd8d7f920 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -957,14 +957,6 @@ static void UpdateMouseWheel(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); } -// Test engine hooks (imgui-test) -//#define IMGUI_ENABLE_TEST_ENGINE_HOOKS -#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS -extern void ImGuiTestEngineHook_PreNewFrame(); -extern void ImGuiTestEngineHook_PostNewFrame(); -extern void ImGuiTestEngineHook_ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg); -#endif - //----------------------------------------------------------------------------- // [SECTION] CONTEXT AND MEMORY ALLOCATORS //----------------------------------------------------------------------------- @@ -2607,10 +2599,6 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) { -#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS - ImGuiTestEngineHook_ItemAdd(bb, id, nav_bb_arg); -#endif - ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -2632,6 +2620,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) window->DC.LastItemRect = bb; window->DC.LastItemStatusFlags = 0; +#ifdef IMGUI_ENABLE_TEST_ENGINE + ImGuiTestEngineHook_ItemAdd(id, bb); +#endif + // Clipping test const bool is_clipped = IsClippedEx(bb, id, false); if (is_clipped) @@ -3130,7 +3122,7 @@ void ImGui::NewFrame() IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); ImGuiContext& g = *GImGui; -#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS +#ifdef IMGUI_ENABLE_TEST_ENGINE ImGuiTestEngineHook_PreNewFrame(); #endif @@ -3305,7 +3297,7 @@ void ImGui::NewFrame() SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); Begin("Debug##Default"); -#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS +#ifdef IMGUI_ENABLE_TEST_ENGINE ImGuiTestEngineHook_PostNewFrame(); #endif } diff --git a/imgui_internal.h b/imgui_internal.h index d55261ff6..167f7c4ea 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -314,6 +314,14 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_HoveredRect = 1 << 0, ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, ImGuiItemStatusFlags_Edited = 1 << 2 // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) + +#ifdef IMGUI_ENABLE_TEST_ENGINE + , // [imgui-test only] + ImGuiItemStatusFlags_Openable = 1 << 10, // + ImGuiItemStatusFlags_Opened = 1 << 11, // + ImGuiItemStatusFlags_Checkable = 1 << 12, // + ImGuiItemStatusFlags_Checked = 1 << 13 // +#endif }; // FIXME: this is in development, not exposed/functional as a generic feature yet. @@ -1329,6 +1337,18 @@ IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); +// Test engine hooks (imgui-test) +//#define IMGUI_ENABLE_TEST_ENGINE +#ifdef IMGUI_ENABLE_TEST_ENGINE +extern void ImGuiTestEngineHook_PreNewFrame(); +extern void ImGuiTestEngineHook_PostNewFrame(); +extern void ImGuiTestEngineHook_ItemAdd(ImGuiID id, const ImRect& bb); +extern void ImGuiTestEngineHook_ItemInfo(ImGuiID id, const char* label, int flags); +#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) ImGuiTestEngineHook_ItemInfo(_ID, _LABEL, _FLAGS) // Register status flags +#else +#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) do { } while (0) +#endif + #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d86fcaec2..ab553661d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -913,6 +913,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (label_size.x > 0.0f) RenderText(text_bb.Min, label); + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return pressed; } @@ -4760,6 +4761,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); + bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). @@ -4775,6 +4777,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); + IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } @@ -4784,13 +4787,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0); - if (!(flags & ImGuiTreeNodeFlags_Leaf)) + if (!is_leaf) button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (!(flags & ImGuiTreeNodeFlags_Leaf)) + if (!is_leaf) { bool toggled = false; if (pressed) @@ -4858,7 +4861,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); - else if (!(flags & ImGuiTreeNodeFlags_Leaf)) + else if (!is_leaf) RenderArrow(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); @@ -4867,6 +4870,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } @@ -5650,6 +5654,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (want_close && IsPopupOpen(id)) ClosePopupToLevel(g.CurrentPopupStack.Size); + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); + if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) { // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. @@ -5729,6 +5735,8 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo if (selected) RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } + + IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); return pressed; }