From 842e88a8e3dcbd775390732fe5a0c7f65a7b62a3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 15:47:08 +0200 Subject: [PATCH 1/7] Examples: Avoid using ImColor() to not tempt newcomers into looking at it --- examples/allegro5_example/main.cpp | 2 +- examples/directx10_example/main.cpp | 6 +++--- examples/directx11_example/main.cpp | 6 +++--- examples/directx9_example/main.cpp | 6 +++--- examples/marmalade_example/main.cpp | 2 +- examples/opengl2_example/main.cpp | 2 +- examples/opengl3_example/main.cpp | 2 +- examples/sdl_opengl2_example/main.cpp | 2 +- examples/sdl_opengl3_example/main.cpp | 2 +- examples/vulkan_example/main.cpp | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 9f8a6c35..2b161d37 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -37,7 +37,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop bool running = true; diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 90add036..88472e5b 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -137,7 +137,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_col = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop MSG msg; @@ -158,7 +158,7 @@ int main(int, char**) static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_col); + ImGui::ColorEdit3("clear color", (float*)&clear_color); if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); @@ -180,7 +180,7 @@ int main(int, char**) } // Rendering - g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_col); + g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); g_pSwapChain->Present(1, 0); // Present with vsync diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 76bab951..ab563403 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -140,7 +140,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_col = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop MSG msg; @@ -161,7 +161,7 @@ int main(int, char**) static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_col); + ImGui::ColorEdit3("clear color", (float*)&clear_color); if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); @@ -183,7 +183,7 @@ int main(int, char**) } // Rendering - g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_col); + g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); g_pSwapChain->Present(1, 0); // Present with vsync diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index f9791b73..85f34eee 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -89,7 +89,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_col = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop MSG msg; @@ -112,7 +112,7 @@ int main(int, char**) static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_col); + ImGui::ColorEdit3("clear color", (float*)&clear_color); if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); @@ -137,7 +137,7 @@ int main(int, char**) g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); - D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_col.x*255.0f), (int)(clear_col.y*255.0f), (int)(clear_col.z*255.0f), (int)(clear_col.w*255.0f)); + D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f)); g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0); if (g_pd3dDevice->BeginScene() >= 0) { diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 57b7f0b6..ebc812f1 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -29,7 +29,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop while (true) diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 5674a4bc..c676953f 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -36,7 +36,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop while (!glfwWindowShouldClose(window)) diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 0de9b0a0..d3ac2cc2 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -44,7 +44,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop while (!glfwWindowShouldClose(window)) diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 4db6f0f9..fb5f3fb5 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -42,7 +42,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop bool done = false; diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 30b14e72..19e3f861 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -45,7 +45,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop bool done = false; diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 7ed9ea12..64c0f08c 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -664,7 +664,7 @@ int main(int, char**) bool show_test_window = true; bool show_another_window = false; - ImVec4 clear_color = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before. // Hence we must render once and increase the g_FrameIndex without presenting, which we do before entering the render loop. From e87ad328e4a43b880693e3ccdaf3cf4bf6aa106c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 16:07:47 +0200 Subject: [PATCH 2/7] Moved implementation of Hovered-related functions next to each others + comments, before I attempt to work on them. No functional change here. --- imgui.cpp | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d8a308bd..99abdf97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1947,11 +1947,13 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return false; //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] - // Setting LastItemHoveredAndUsable for IsItemHovered(). This is a sensible default, but widgets are free to override it. + // Setting LastItemHoveredAndUsable for public facing IsItemHovered(). This is a sensible default, but widgets are free to override it. + // FIXME: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. if (IsMouseHoveringRect(bb.Min, bb.Max)) { - // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) - // So that clicking on items with no active id such as Text() still returns true with IsItemHovered() + // Matching the behavior of internal IsHovered() but: + // - we are always setting LastItemHoveredRect, which is returned by IsItemRectHovered(), so the order of tests is tweaked to be different. + // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) window->DC.LastItemHoveredRect = true; if (g.HoveredRootWindow == window->RootWindow) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) @@ -1962,18 +1964,19 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return true; } -bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) +bool ImGui::IsItemHovered() { - ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); - if (!bb.Overlaps(window->ClipRect)) - if (!id || *id != g.ActiveId) - if (clip_even_when_logged || !g.LogEnabled) - return true; - return false; + return window->DC.LastItemHoveredAndUsable; } -// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. +bool ImGui::IsItemRectHovered() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.LastItemHoveredRect; +} + +// [Internal] The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { ImGuiContext& g = *GImGui; @@ -1988,6 +1991,17 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) return false; } +bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindowRead(); + if (!bb.Overlaps(window->ClipRect)) + if (!id || *id != g.ActiveId) + if (clip_even_when_logged || !g.LogEnabled) + return true; + return false; +} + bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop) { ImGuiContext& g = *GImGui; @@ -3323,18 +3337,6 @@ void ImGui::CaptureMouseFromApp(bool capture) GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0; } -bool ImGui::IsItemHovered() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredAndUsable; -} - -bool ImGui::IsItemRectHovered() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredRect; -} - bool ImGui::IsItemActive() { ImGuiContext& g = *GImGui; From 99c7622a1bd747b068db97a6e1c8e2cd06e39037 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 16:20:53 +0200 Subject: [PATCH 3/7] ItemAdd(), not performing computation for IsItemRectHovered() which does them itself, allowing us in the next commit to optimize ItemAdd() and make its logic more consistent with IsHovered(). --- imgui.cpp | 15 ++++++++------- imgui_demo.cpp | 4 ++-- imgui_internal.h | 3 +-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 99abdf97..555cea14 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1942,19 +1942,17 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) ImGuiWindow* window = g.CurrentWindow; window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; + window->DC.LastItemHoveredAndUsable = false; if (IsClippedEx(bb, id, false)) return false; //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // Setting LastItemHoveredAndUsable for public facing IsItemHovered(). This is a sensible default, but widgets are free to override it. - // FIXME: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. + // FIXME-OPT: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of internal IsHovered() but: - // - we are always setting LastItemHoveredRect, which is returned by IsItemRectHovered(), so the order of tests is tweaked to be different. // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) - window->DC.LastItemHoveredRect = true; if (g.HoveredRootWindow == window->RootWindow) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) if (IsWindowContentHoverable(window)) @@ -1973,7 +1971,7 @@ bool ImGui::IsItemHovered() bool ImGui::IsItemRectHovered() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredRect; + return IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max); } // [Internal] The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. @@ -10020,13 +10018,16 @@ void ImGui::EndGroup() ItemAdd(group_bb, NULL); } - // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will function on the entire group. + // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will be functional on the entire group. // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context. const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow); if (active_id_within_group) window->DC.LastItemId = g.ActiveId; if (active_id_within_group && g.HoveredId == g.ActiveId) - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = true; + { + window->DC.LastItemHoveredAndUsable = true; + window->DC.LastItemRect = group_bb; + } window->DC.GroupStack.pop_back(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 81e89db5..d846faa1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1126,11 +1126,11 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Button("CCC"); ImGui::Button("DDD"); ImGui::EndGroup(); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("Group hovered"); ImGui::SameLine(); ImGui::Button("EEE"); ImGui::EndGroup(); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("First group hovered"); } // Capture the group size and create widgets using the same size ImVec2 size = ImGui::GetItemRectSize(); diff --git a/imgui_internal.h b/imgui_internal.h index b12b3c05..b204b602 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -601,7 +601,6 @@ struct IMGUI_API ImGuiDrawContext ImGuiID LastItemId; ImRect LastItemRect; bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) - bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -642,7 +641,7 @@ struct IMGUI_API ImGuiDrawContext TreeDepth = 0; LastItemId = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); - LastItemHoveredAndUsable = LastItemHoveredRect = false; + LastItemHoveredAndUsable = false; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; From c075786d8b7e682f26d11b5b4a629fdf608fe28d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 16:29:46 +0200 Subject: [PATCH 4/7] ItemAdd(): re-ordering the tests, submission should now be faster. --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 555cea14..25d463fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1947,13 +1947,13 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return false; //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] - // Setting LastItemHoveredAndUsable for public facing IsItemHovered(). This is a sensible default, but widgets are free to override it. + // Set up for public-facing IsItemHovered(). We store the result in DC.LastItemHoveredAndUsable. + // This is roughly matching the behavior of internal IsHovered() + // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) // FIXME-OPT: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. - if (IsMouseHoveringRect(bb.Min, bb.Max)) + if (g.HoveredRootWindow == window->RootWindow) { - // Matching the behavior of internal IsHovered() but: - // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) - if (g.HoveredRootWindow == window->RootWindow) + if (IsMouseHoveringRect(bb.Min, bb.Max)) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) if (IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; From 344d48be31e1fae98c9f7cb6d96b6d77d29abec0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 16:49:25 +0200 Subject: [PATCH 5/7] IsItemHovered(), ItemAdd(): Fixed seemingly unnecessary comparaison of root windows, makes IsItemHovered() more consistent with internal IsHovered(). Original test was added in 6e99688fa74b3de5694a8e021619cc1ade51ee03 should not have been using RootWindow in the first place. The difference between public-facing and internal versions would only be noticeable with overlapped child windows, which doesn't really happen anyway --- imgui.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 25d463fd..2bce31de 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1948,16 +1948,14 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // Set up for public-facing IsItemHovered(). We store the result in DC.LastItemHoveredAndUsable. - // This is roughly matching the behavior of internal IsHovered() + // This is roughly matching the behavior of internal-facing IsHovered() // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) // FIXME-OPT: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. - if (g.HoveredRootWindow == window->RootWindow) - { + if (g.HoveredWindow == window) if (IsMouseHoveringRect(bb.Min, bb.Max)) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) if (IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; - } return true; } @@ -1982,9 +1980,10 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { ImGuiWindow* window = GetCurrentWindowRead(); if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) - if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) - return true; + if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) + if (IsMouseHoveringRect(bb.Min, bb.Max)) + if (IsWindowContentHoverable(g.HoveredRootWindow)) + return true; } return false; } From 19e22baa065dab7c99694d14fc46d713e5c4f449 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 17:06:07 +0200 Subject: [PATCH 6/7] ItemAdd(): more re-ordering of tests to match IsHovered() + comments --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2bce31de..25dd1ce5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1950,10 +1950,11 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) // Set up for public-facing IsItemHovered(). We store the result in DC.LastItemHoveredAndUsable. // This is roughly matching the behavior of internal-facing IsHovered() // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) + // - we don't expose the flatten_child feature that IsHovered() has, which is only used by the window resizing widget (may rework this) // FIXME-OPT: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. if (g.HoveredWindow == window) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) + if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) + if (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; From 0adcddac39ab6aad6f2c745f2d51c767c5673191 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 17:21:50 +0200 Subject: [PATCH 7/7] IsItemHovered(), ItemAdd(): finishing cleaning up, moved the code to IsItemHovered() so ItemAdd() is more lightweight and the two IsXXXHovered functions are now very similar, making their differences less confusing. --- imgui.cpp | 36 +++++++++++++++--------------------- imgui_internal.h | 2 -- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 25dd1ce5..c9b7031f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1942,29 +1942,27 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) ImGuiWindow* window = g.CurrentWindow; window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; - window->DC.LastItemHoveredAndUsable = false; if (IsClippedEx(bb, id, false)) return false; //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] - // Set up for public-facing IsItemHovered(). We store the result in DC.LastItemHoveredAndUsable. - // This is roughly matching the behavior of internal-facing IsHovered() - // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) - // - we don't expose the flatten_child feature that IsHovered() has, which is only used by the window resizing widget (may rework this) - // FIXME-OPT: Consider moving this code to IsItemHovered() so it's only evaluated if users needs it. - if (g.HoveredWindow == window) - if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(window)) - window->DC.LastItemHoveredAndUsable = true; - return true; } +// This is roughly matching the behavior of internal-facing IsHovered() +// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) +// - we don't expose the flatten_child feature that IsHovered() has, which is only used by the window resizing widget (may rework this) bool ImGui::IsItemHovered() { - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredAndUsable; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.HoveredWindow == window) + if (g.ActiveId == 0 || g.ActiveId == window->DC.LastItemId || g.ActiveIdAllowOverlap || g.ActiveId == window->MoveId) + if (IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) + if (IsWindowContentHoverable(window)) + return true; + + return false; } bool ImGui::IsItemRectHovered() @@ -1973,13 +1971,13 @@ bool ImGui::IsItemRectHovered() return IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max); } -// [Internal] The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. +// Internal facing IsHovered() differs slightly from IsItemHovered(). bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { ImGuiContext& g = *GImGui; if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow* window = g.CurrentWindow; if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) if (IsMouseHoveringRect(bb.Min, bb.Max)) @@ -10023,11 +10021,7 @@ void ImGui::EndGroup() const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow); if (active_id_within_group) window->DC.LastItemId = g.ActiveId; - if (active_id_within_group && g.HoveredId == g.ActiveId) - { - window->DC.LastItemHoveredAndUsable = true; - window->DC.LastItemRect = group_bb; - } + window->DC.LastItemRect = group_bb; window->DC.GroupStack.pop_back(); diff --git a/imgui_internal.h b/imgui_internal.h index b204b602..a1192be9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -600,7 +600,6 @@ struct IMGUI_API ImGuiDrawContext int TreeDepth; ImGuiID LastItemId; ImRect LastItemRect; - bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -641,7 +640,6 @@ struct IMGUI_API ImGuiDrawContext TreeDepth = 0; LastItemId = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); - LastItemHoveredAndUsable = false; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL;