From 0b1fecb792ffe00313b43a01f4dadb41e69850e7 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 12:36:16 +0100 Subject: [PATCH] Horizontal mouse wheel: renamed io.MouseHorizWheel to io.MouseWheelH. Reorganized the code in NewFrame(). Examples: Updated GLFW+GL and SDL+GL accordingly. (#1463) --- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 13 ++-- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 13 ++-- .../imgui_impl_sdl_gl2.cpp | 21 +++---- .../imgui_impl_sdl_gl3.cpp | 21 +++---- imgui.cpp | 60 +++++++++---------- imgui.h | 4 +- 6 files changed, 59 insertions(+), 73 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 2b7efc146..8dcd71e9f 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -31,8 +31,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -137,8 +136,8 @@ void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel += (float)yoffset; + g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel.y += (float)yoffset; } void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -297,9 +296,9 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseHorizWheel = g_MouseHorizWheel; - io.MouseWheel = g_MouseWheel; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 8808d8bb1..79a62531f 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -25,8 +25,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -158,8 +157,8 @@ void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel += (float)yoffset; + g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel.y += (float)yoffset; } void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -409,9 +408,9 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseHorizWheel = g_MouseHorizWheel; - io.MouseWheel = g_MouseWheel; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index e1adbe86a..d55af2b7f 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -24,8 +24,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -133,14 +132,10 @@ bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) - g_MouseHorizWheel = 1; - if (event->wheel.x < 0) - g_MouseHorizWheel = -1; - if (event->wheel.y > 0) - g_MouseWheel = 1; - if (event->wheel.y < 0) - g_MouseWheel = -1; + if (event->wheel.x > 0) g_MouseWheel.x = +1; + if (event->wheel.x < 0) g_MouseWheel.x = -1; + if (event->wheel.y > 0) g_MouseWheel.y = +1; + if (event->wheel.y < 0) g_MouseWheel.y = -1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -279,13 +274,13 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel; - io.MouseHorizWheel = g_MouseHorizWheel; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseWheel = g_MouseHorizWheel = 0.0f; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 264ac64b0..0a07cd082 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -19,8 +19,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -155,14 +154,10 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) - g_MouseHorizWheel = 1; - if (event->wheel.x < 0) - g_MouseHorizWheel = -1; - if (event->wheel.y > 0) - g_MouseWheel = 1; - if (event->wheel.y < 0) - g_MouseWheel = -1; + if (event->wheel.x > 0) g_MouseWheel.x = +1; + if (event->wheel.x < 0) g_MouseWheel.x = -1; + if (event->wheel.y > 0) g_MouseWheel.y = +1; + if (event->wheel.y < 0) g_MouseWheel.y = -1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -390,13 +385,13 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel; - io.MouseHorizWheel = g_MouseHorizWheel; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/imgui.cpp b/imgui.cpp index 781e1ff3e..0020c2c1b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2483,47 +2483,45 @@ void ImGui::NewFrame() if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) g.HoveredWindow = g.HoveredRootWindow = NULL; - // Scale & Scrolling - if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) + // Mouse wheel scrolling, scale + if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f)) { + // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). ImGuiWindow* window = g.HoveredWindow; - if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) - { - // Zoom / Scale window - const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - const float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; + ImGuiWindow* scroll_window = window; + while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) + scroll_window = scroll_window->ParentWindow; + const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs); - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - window->Pos += offset; - window->PosFloat += offset; - window->Size *= scale; - window->SizeFull *= scale; - } - else if (!g.IO.KeyCtrl) + if (g.IO.MouseWheel != 0.0f) { - // Mouse wheel Scrolling - // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). - ImGuiWindow* scroll_window = window; - while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) - scroll_window = scroll_window->ParentWindow; - - if (!(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs)) + if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { + // Zoom / Scale window + const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + const float scale = new_font_scale / window->FontWindowScale; + window->FontWindowScale = new_font_scale; + + const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + window->Pos += offset; + window->PosFloat += offset; + window->Size *= scale; + window->SizeFull *= scale; + } + else if (!g.IO.KeyCtrl && scroll_allowed) + { + // Mouse wheel vertical scrolling float scroll_amount = 5 * scroll_window->CalcFontSize(); scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f); SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount); } } - } - - // Horizontal wheel scrolling; for consistency, only allowed if Ctrl is not pressed. - if (g.HoveredWindow && g.IO.MouseHorizWheel != 0.0f && !g.HoveredWindow->Collapsed) - { - ImGuiWindow* window = g.HoveredWindow; - if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + if (g.IO.MouseWheelH != 0.0f && scroll_allowed) { - SetWindowScrollX(window, window->Scroll.x - g.IO.MouseHorizWheel * 10.f); + // Mouse wheel horizontal scrolling (for hardware that supports it) + float scroll_amount = scroll_window->CalcFontSize(); + if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheelH * scroll_amount); } } @@ -3040,7 +3038,7 @@ void ImGui::EndFrame() g.Windows.swap(g.WindowsSortBuffer); // Clear Input data for next frame - g.IO.MouseWheel = 0.0f; + g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); g.FrameCountEnded = g.FrameCount; diff --git a/imgui.h b/imgui.h index 01fe3f777..f8d36ba41 100644 --- a/imgui.h +++ b/imgui.h @@ -930,8 +930,8 @@ struct ImGuiIO ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - float MouseHorizWheel; // Horizontal mouse wheel + float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back ends. bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift