From 6d7677534f80d0bc501f093ae606f6277cc57e6e Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 9 Nov 2018 14:31:14 +0100 Subject: [PATCH 1/6] Internals: SliderBehavior: Using axis indexing. --- imgui_widgets.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e8a47b3b..963ada41 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2081,20 +2081,20 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; + const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); const bool is_power = (power != 1.0f) && is_decimal; const float grab_padding = 2.0f; - const float slider_sz = is_horizontal ? (bb.GetWidth() - grab_padding * 2.0f) : (bb.GetHeight() - grab_padding * 2.0f); + const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f; float grab_sz = style.GrabMinSize; SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max); if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit grab_sz = ImMin(grab_sz, slider_sz); const float slider_usable_sz = slider_sz - grab_sz; - const float slider_usable_pos_min = (is_horizontal ? bb.Min.x : bb.Min.y) + grab_padding + grab_sz*0.5f; - const float slider_usable_pos_max = (is_horizontal ? bb.Max.x : bb.Max.y) - grab_padding - grab_sz*0.5f; + const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz*0.5f; + const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz*0.5f; // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f float linear_zero_pos; // 0.0->1.0f @@ -2125,9 +2125,9 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ } else { - const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + const float mouse_abs_pos = g.IO.MousePos[axis]; clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; - if (!is_horizontal) + if (axis == ImGuiAxis_Y) clicked_t = 1.0f - clicked_t; set_new_value = true; } @@ -2135,7 +2135,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ else if (g.ActiveIdSource == ImGuiInputSource_Nav) { const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); - float delta = is_horizontal ? delta2.x : -delta2.y; + float delta = (axis == ImGuiAxis_X) ? delta2.x : -delta2.y; if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) { ClearActiveID(); @@ -2227,10 +2227,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ // Output grab position so it can be displayed by the caller float grab_t = SliderCalcRatioFromValueT(data_type, *v, v_min, v_max, power, linear_zero_pos); - if (!is_horizontal) + if (axis == ImGuiAxis_Y) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); - if (is_horizontal) + if (axis == ImGuiAxis_X) *out_grab_bb = ImRect(grab_pos - grab_sz*0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz*0.5f, bb.Max.y - grab_padding); else *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f); From 6c1ae6cc71c6c6b9c0b5c19e1a793e15e8f0cde2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 9 Nov 2018 14:41:40 +0100 Subject: [PATCH 2/6] Internals: DragBehavior: Added support for ImGuiDragFlags_Vertical to implement a vertical drag widget (no frontend function provided). --- imgui_internal.h | 11 +++++++++-- imgui_widgets.cpp | 27 ++++++++++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index bac04ae6..b31aed4b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -63,6 +63,7 @@ typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for Separator() - internal typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for SliderBehavior() +typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior() //------------------------------------------------------------------------- // STB libraries @@ -249,6 +250,12 @@ enum ImGuiSliderFlags_ ImGuiSliderFlags_Vertical = 1 << 0 }; +enum ImGuiDragFlags_ +{ + ImGuiDragFlags_None = 0, + ImGuiDragFlags_Vertical = 1 << 0 +}; + enum ImGuiColumnsFlags_ { // Default: 0 @@ -1246,7 +1253,7 @@ namespace ImGui // Widgets low-level behaviors IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); - IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power); + IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); @@ -1256,7 +1263,7 @@ namespace ImGui // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). // e.g. " extern template IMGUI_API float RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, float v); " - template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, const T v_min, const T v_max, const char* format, float power); + template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, const T v_min, const T v_max, const char* format, float power, ImGuiDragFlags flags); template IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, const T v_min, const T v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); template IMGUI_API float SliderCalcRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float power, float linear_zero_pos); template IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 963ada41..580bfc4e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1706,9 +1706,10 @@ TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, // This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) template -bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power) +bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiDragFlags flags) { ImGuiContext& g = *GImGui; + const ImGuiAxis axis = (flags & ImGuiDragFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); const bool has_min_max = (v_min != v_max); @@ -1720,7 +1721,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const float adjust_delta = 0.0f; if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f) { - adjust_delta = g.IO.MouseDelta.x; + adjust_delta = g.IO.MouseDelta[axis]; if (g.IO.KeyAlt) adjust_delta *= 1.0f / 100.0f; if (g.IO.KeyShift) @@ -1729,11 +1730,15 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const else if (g.ActiveIdSource == ImGuiInputSource_Nav) { int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0; - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f).x; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis]; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; + // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter. + if (axis == ImGuiAxis_Y) + adjust_delta = -adjust_delta; + // Clear current value on activation // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. bool is_just_activated = g.ActiveIdIsJustActivated; @@ -1804,7 +1809,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const return true; } -bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags) { ImGuiContext& g = *GImGui; if (g.ActiveId == id) @@ -1819,12 +1824,12 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_s switch (data_type) { - case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power); - case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power); - case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power); - case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power); - case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power); - case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power); + case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power, flags); + case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power, flags); + case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power, flags); + case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power, flags); + case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power, flags); + case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power, flags); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); @@ -1889,7 +1894,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa // Actual drag behavior ItemSize(total_bb, style.FramePadding.y); - const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power); + const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None); if (value_changed) MarkItemEdited(id); From 5b1394c5ac351a1317e42fb45a066f441740a7af Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 9 Nov 2018 15:02:19 +0100 Subject: [PATCH 3/6] Update README.md --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 50ae7819..ecedfe66 100644 --- a/docs/README.md +++ b/docs/README.md @@ -109,7 +109,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ _NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ Languages: (third-party bindings) -- C: [cimgui](https://github.com/cimgui/cimgui) (new 2018 auto-generated version!) +- C: [cimgui](https://github.com/cimgui/cimgui) (2018: now auto-generated! you can use its json output to generate bindings for other languages) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) - D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) @@ -126,12 +126,11 @@ Languages: (third-party bindings) - Swift [swift-imgui](https://github.com/mnmly/Swift-imgui) Frameworks: -- Renderers: DirectX 9, DirectX 10, DirectX 11, DirectX 12, Metal, OpenGL2, OpenGL3+/ES2/ES3, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Renderers: DirectX 9/10/11/12, Metal, OpenGL2, OpenGL3+/ES2/ES3, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Platform: GLFW, SDL, Win32, OSX, Freeglut: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Framework: Allegro 5, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336) - Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) -- Unmerged PR: ORX: [#1843](https://github.com/ocornut/imgui/pull/1843) - Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) - Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551) - Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI) @@ -140,6 +139,7 @@ Frameworks: - Ogre: [ogreimgui](https://bitbucket.org/LMCrashy/ogreimgui/src) - OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui) - OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) +- ORX: [pr #1843](https://github.com/ocornut/imgui/pull/1843) - LÖVE+Lua: [love-imgui](https://github.com/slages/love-imgui) - Magnum: [magnum-imgui](https://github.com/lecopivo/magnum-imgui), [MagnumImguiPort](https://github.com/lecopivo/MagnumImguiPort) - NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) From 19b4fcdacb71b3901e8f5831f37218c6afff3aca Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Nov 2018 11:23:15 +0100 Subject: [PATCH 4/6] Made IsWindowFocused() work outside of NewFrame()-EndFrame() and added comments about how ImGuiFocusedFlags_AnyWindow should NOT be used in place of io.WantCaptureMouse. (#2185) --- imgui.cpp | 2 +- imgui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index da8ac5bc..54fac2cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5642,11 +5642,11 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() if (flags & ImGuiFocusedFlags_AnyWindow) return g.NavWindow != NULL; + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) { case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: diff --git a/imgui.h b/imgui.h index 90cde630..24f24ff0 100644 --- a/imgui.h +++ b/imgui.h @@ -732,7 +732,7 @@ enum ImGuiFocusedFlags_ ImGuiFocusedFlags_None = 0, ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) - ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused + ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use ImGui::GetIO().WantCaptureMouse instead. ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows }; From f52f0a52771f9609267e9ad67d4f2835e0df0072 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Nov 2018 18:54:02 +0100 Subject: [PATCH 5/6] Examples: OpenGL3: Added support for GL 4.5's glClipControl(GL_UPPER_LEFT). (#2186) --- docs/CHANGELOG.txt | 1 + examples/imgui_impl_opengl3.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b0409bf9..9126cfd1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -79,6 +79,7 @@ Other Changes: - Examples: DirectX10, DirectX11: Removed seemingly unnecessary calls to invalidate and recreate device objects in the WM_SIZE handler. (#2088) [@ice1000] - Examples: GLFW: User previously installed GLFW callbacks are now saved and chain-called by the default callbacks. (#1759) +- Examples: OpenGL3: Added support for GL 4.5's glClipControl(GL_UPPER_LEFT). (#2186) - Examples: OpenGL3+GLFW: Fixed error condition when using the GLAD loader. (#2157) [@blackball] - Examples: OpenGL3+GLFW/SDL: Made main.cpp compile with IMGUI_IMPL_OPENGL_LOADER_CUSTOM (may be missing init). (#2178) [@doug-moen] diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 2a031004..18b62f86 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT). // 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used. // 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES". // 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. @@ -162,6 +163,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + bool clip_origin_lower_left = true; +#ifdef GL_CLIP_ORIGIN + GLenum last_clip_origin; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) + clip_origin_lower_left = (last_clip_origin == GL_LOWER_LEFT); +#endif // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); @@ -234,7 +240,10 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) { // Apply scissor/clipping rectangle - glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); + if (clip_origin_lower_left) + glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); + else + glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) // Bind texture, Draw glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); From aa668c410a020e6cb40dbdd66620df1f8c7daa3c Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Nov 2018 13:53:53 +0100 Subject: [PATCH 6/6] Nav: Fixed an assert in certain circumstance (mostly when using popups) when mouse positions stop being valid. (#2168) + adding a else block to make NavCalcPreferredRefPos() more explicit. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 25 ++++++++++++++++--------- imgui_internal.h | 4 +++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9126cfd1..c7603717 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Other Changes: accidental alteration of window position. We now round the provided size. (#2067) - Nav, Focus: Fixed ImGuiWindowFlags_NoBringToFrontOnFocus windows not being restoring focus properly after the main menu bar or last focused window is deactivated. +- Nav: Fixed an assert in certain circumstance (mostly when using popups) when mouse positions stop being valid. (#2168) - DragFloat: Fixed a situation where dragging with value rounding enabled or with a power curve erroneously wrapped the value to one of the min/max edge. (#2024, #708, #320, #2075). - DragFloat: Disabled using power curve when one edge is FLT_MAX (broken in 1.61). (#2024) diff --git a/imgui.cpp b/imgui.cpp index 54fac2cb..c6452b97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2966,7 +2966,7 @@ static void ImGui::UpdateMouseInputs() // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well) if (IsMousePosValid(&g.IO.MousePos)) - g.IO.MousePos = ImFloor(g.IO.MousePos); + g.IO.MousePos = g.LastValidMousePos = ImFloor(g.IO.MousePos); // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) @@ -6415,8 +6415,8 @@ void ImGui::OpenPopupEx(ImGuiID id) popup_ref.ParentWindow = parent_window; popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenParentId = parent_window->IDStack.back(); - popup_ref.OpenMousePos = g.IO.MousePos; popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); + popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos; //printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id); if (g.OpenPopupStack.Size < current_stack_size + 1) @@ -7093,13 +7093,20 @@ static ImVec2 ImGui::NavCalcPreferredRefPos() { ImGuiContext& g = *GImGui; if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) - return ImFloor(g.IO.MousePos); - - // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item - const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; - ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); - ImRect visible_rect = GetViewportRect(); - return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. + { + // Mouse (we need a fallback in case the mouse becomes invalid after being used) + if (IsMousePosValid(&g.IO.MousePos)) + return g.IO.MousePos; + return g.LastValidMousePos; + } + else + { + // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item. + const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; + ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); + ImRect visible_rect = GetViewportRect(); + return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. + } } float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) diff --git a/imgui_internal.h b/imgui_internal.h index b31aed4b..f3385d85 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -687,8 +687,9 @@ struct ImGuiContext ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. + ImVec2 LastValidMousePos; ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. - ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() + ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector FontStack; // Stack for PushFont()/PopFont() ImVector OpenPopupStack; // Which popups are open (persistent) @@ -833,6 +834,7 @@ struct ImGuiContext ActiveIdSource = ImGuiInputSource_None; LastActiveId = 0; LastActiveIdTimer = 0.0f; + LastValidMousePos = ImVec2(0.0f, 0.0f); MovingWindow = NULL; NextTreeNodeOpenVal = false; NextTreeNodeOpenCond = 0;