diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7b04314e..9e00ae82 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,7 @@ - When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). - When fixing a warning or compilation problem, please post the compiler log and specify the version and OS you are using. - Try to attach screenshots to clarify the context and demonstrate the feature at a glance. +- Make sure your code follows the coding style already used in imgui (spaces instead of tabs, "local_variable", "FunctionName", "MemberName", etc.). - Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. - You can read [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md) for more details. diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3961fe67..4c80e655 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -47,14 +47,17 @@ Other Changes: - Nav: Added a CTRL+TAB window list and changed the highlight system accordingly. This is designed to allow CTRL+TAB between Tabs in the future. (#787) - Window: Allow menu and popups windows from ignoring the style.WindowMinSize values so short menus/popups are not padded. (#1909) - Window: Added global io.OptResizeWindowsFromEdges option to enable resizing windows from their edges and from the lower-left corner. (#1495) + - Window: Collapse button shows hovering highlight + clicking and dragging on it allows to drag the window as well. - Drag and Drop: Fixed an incorrect assert when dropping a source that is submitted after the target (bug introduced with 1.62 changes related to the addition of IsItemDeactivated()). (#1875, #143) - Drag and Drop: Fixed ImGuiDragDropFlags_SourceNoDisableHover to affect hovering state prior to calling IsItemHovered() + fixed description. (#143) - Drag and Drop: Calling BeginTooltip() between a BeginDragSource()/EndDragSource() or BeginDropTarget()/EndDropTarget() uses adjusted tooltip settings matching the one created when calling BeginDragSource() without the ImGuiDragDropFlags_SourceNoPreviewTooltip flag. (#143) + - Drag and Drop: Payload stays available and under the mouse if the source stops being submitted, however the tooltip is replaced by "...". (#1725) - IsItemHovered(): Added ImGuiHoveredFlags_AllowWhenDisabled flag to query hovered status on disabled items. (#1940, #211) - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. + - Made assertion more clear when trying to call Begin() outside of the NewFrame()..EndFrame() scope. (#1987) - Fixed horizontal mouse wheel not forwarding the request to the parent window if ImGuiWindowFlags_NoScrollWithMouse is set. (#1463, #1380, #1502) - Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) - OS/Windows: Fixed missing ImmReleaseContext() call in the default Win32 IME handler. (#1932) [@vby] @@ -65,7 +68,8 @@ Other Changes: - Examples: OSX: Added early raw OSX platform backend. (#1873) [@pagghiu, @itamago, @ocornut] - Examples: Added mac OSX & iOS + Metal example in example_apple_metal/. (#1929, #1873) [@warrenm] - Examples: Added mac OSX + OpenGL2 example in example_apple_opengl2/. (#1873) - - Examples: OpenGL3: Added shaders more versions of GLSL. (#1938, #1900, #1513, #1466, etc.) + - Examples: OpenGL3: Added shaders more versions of GLSL. (#1938, #1941, #1900, #1513, #1466, etc.) + - Examples: OpenGL3: Tweaked the imgui_impl_opengl3.cpp to work as-is with Emscripten + WebGL 2.0. (#1941). [@o-micron] - Examples: OpenGL3: Made the example app default to GL 3.0 + GLSL 130 (instead of GL 3.2 + GLSL 150) unless on Mac. - Examples: OpenGL3: Added error output when shaders fail to compile/link. - Examples: DirectX10, DirectX11: Fixed unreleased resources in Init and Shutdown functions. (#1944) diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index caece5cd..e827d34a 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. // 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link. // 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. @@ -39,7 +40,7 @@ // 3.2 150 "#version 150" // 3.3 330 // 4.0 400 -// 4.1 410 +// 4.1 410 "#version 410 core" // 4.2 420 // 4.3 430 // ES 2.0 100 "#version 100" @@ -59,10 +60,18 @@ #include // intptr_t #endif -#include // This example is using gl3w to access OpenGL functions. You may use another OpenGL loader/header such as: glew, glext, glad, glLoadGen, etc. +#ifdef __EMSCRIPTEN__ +#include // Use GL ES 3 +#else +// About OpenGL function loaders: +// Modern OpenGL requires individual functions to be loaded manually. Helper libraries are often used for this purpose. +// Here we are using gl3w.h, which requires a call to gl3wInit(). +// You may use another any other loader/header of your choice, such as glew, glext, glad, glLoadGen, etc. +#include //#include //#include //#include +#endif // OpenGL Data static char g_GlslVersionString[32] = ""; @@ -128,7 +137,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); +#ifdef GL_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); +#endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); @@ -149,7 +160,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); +#ifdef GL_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. @@ -168,8 +181,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - if (glBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. - +#ifdef GL_SAMPLER_BINDING + glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. +#endif // Recreate the VAO every time // (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.) GLuint vao_handle = 0; @@ -225,7 +239,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Restore modified GL state glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); - if (glBindSampler) glBindSampler(0, last_sampler); +#ifdef GL_SAMPLER_BINDING + glBindSampler(0, last_sampler); +#endif glActiveTexture(last_active_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); @@ -235,7 +251,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); +#ifdef GL_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); +#endif glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } @@ -354,6 +372,35 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" "}\n"; + const GLchar* vertex_shader_glsl_300_es = + "precision mediump float;\n" + "layout (location = 0) in vec2 Position;\n" + "layout (location = 1) in vec2 UV;\n" + "layout (location = 2) in vec4 Color;\n" + "uniform mat4 ProjMtx;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* vertex_shader_glsl_410_core = + "layout (location = 0) in vec2 Position;\n" + "layout (location = 1) in vec2 UV;\n" + "layout (location = 2) in vec4 Color;\n" + "uniform mat4 ProjMtx;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + const GLchar* fragment_shader_glsl_120 = "#ifdef GL_ES\n" " precision mediump float;\n" @@ -376,6 +423,27 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; + const GLchar* fragment_shader_glsl_300_es = + "precision mediump float;\n" + "uniform sampler2D Texture;\n" + "in vec2 Frag_UV;\n" + "in vec4 Frag_Color;\n" + "layout (location = 0) out vec4 Out_Color;\n" + "void main()\n" + "{\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + "}\n"; + + const GLchar* fragment_shader_glsl_410_core = + "in vec2 Frag_UV;\n" + "in vec4 Frag_Color;\n" + "uniform sampler2D Texture;\n" + "layout (location = 0) out vec4 Out_Color;\n" + "void main()\n" + "{\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + "}\n"; + // Select shaders matching our GLSL versions const GLchar* vertex_shader = NULL; const GLchar* fragment_shader = NULL; @@ -384,6 +452,16 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() vertex_shader = vertex_shader_glsl_120; fragment_shader = fragment_shader_glsl_120; } + else if (glsl_version == 410) + { + vertex_shader = vertex_shader_glsl_410_core; + fragment_shader = fragment_shader_glsl_410_core; + } + else if (glsl_version == 300) + { + vertex_shader = vertex_shader_glsl_300_es; + fragment_shader = fragment_shader_glsl_300_es; + } else { vertex_shader = vertex_shader_glsl_130; diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index a0d78b07..f16308f0 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -10,6 +10,11 @@ // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// About OpenGL function loaders: +// Modern OpenGL requires individual functions to be loaded manually. Helper libraries are often used for this purpose. +// Here we are using gl3w.h, which requires a call to gl3wInit(). +// You may use another any other loader/header of your choice, such as glew, glext, glad, glLoadGen, etc. + // About GLSL version: // The 'glsl_version' initialization parameter defaults to "#version 130" if NULL. // Only override if your GL version doesn't handle this GLSL version (see table at the top of imgui_impl_opengl3.cpp). Keep NULL if unsure! diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index 0052fdf0..4b0347a9 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -16,7 +16,7 @@ // 2018-07-07: Initial version. // Data -static clock_t g_Time = 0; +static CFAbsoluteTime g_Time = 0.0; // Functions bool ImGui_ImplOSX_Init() @@ -95,10 +95,10 @@ void ImGui_ImplOSX_NewFrame(NSView* view) io.DisplayFramebufferScale = ImVec2(dpi, dpi); // Setup time step - if (g_Time == 0) - g_Time = clock(); - clock_t current_time = clock(); - io.DeltaTime = (double)(current_time - g_Time) / CLOCKS_PER_SEC; + if (g_Time == 0.0) + g_Time = CFAbsoluteTimeGetCurrent(); + CFAbsoluteTime current_time = CFAbsoluteTimeGetCurrent(); + io.DeltaTime = current_time - g_Time; g_Time = current_time; } diff --git a/imgui.cpp b/imgui.cpp index badfd14b..9da49f55 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1271,9 +1271,13 @@ static const char* ImAtoi(const char* src, TYPE* output) // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. // B) When buf==NULL vsnprintf() will return the output size. #ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS + +#if defined(_MSC_VER) && !defined(vsnprintf) +#define vsnprintf _vsnprintf +#endif + int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) { - IM_ASSERT(fmt != NULL); va_list args; va_start(args, fmt); int w = vsnprintf(buf, buf_size, fmt, args); @@ -1288,7 +1292,6 @@ int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) { - IM_ASSERT(fmt != NULL); int w = vsnprintf(buf, buf_size, fmt, args); if (buf == NULL) return w; @@ -1940,8 +1943,12 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const // On some platform vsnprintf() takes va_list by reference and modifies it. // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. #ifndef va_copy +#if defined(__GNUC__) || defined(__clang__) +#define va_copy(dest, src) __builtin_va_copy(dest, src) +#else #define va_copy(dest, src) (dest = src) #endif +#endif // Helper: Text buffer for logging/accumulating text void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) @@ -2305,7 +2312,8 @@ void ImGui::SetHoveredID(ImGuiID id) ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; - g.HoveredIdTimer = (id != 0 && g.HoveredIdPreviousFrame == id) ? (g.HoveredIdTimer + g.IO.DeltaTime) : 0.0f; + if (id != 0 && g.HoveredIdPreviousFrame != id) + g.HoveredIdTimer = 0.0f; } ImGuiID ImGui::GetHoveredID() @@ -4357,6 +4365,7 @@ void ImGui::NewFrame() } g.Time += g.IO.DeltaTime; + g.FrameScopeActive = true; g.FrameCount += 1; g.TooltipOverrideCount = 0; g.WindowsActiveCount = 0; @@ -4382,9 +4391,15 @@ void ImGui::NewFrame() viewport->DrawDataP.Clear(); } + // Drag and drop keep the source ID alive so even if the source disappear our state is consistent + if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) + KeepAliveID(g.DragDropPayload.SourceId); + // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) g.HoveredIdTimer = 0.0f; + if (g.HoveredId) + g.HoveredIdTimer += g.IO.DeltaTime; g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; @@ -4401,13 +4416,7 @@ void ImGui::NewFrame() if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) g.ScalarAsInputTextId = 0; - // Elapse drag & drop payload - if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) - { - ClearDragDrop(); - g.DragDropPayloadBufHeap.clear(); - memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); - } + // Drag and drop g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdCurr = 0; g.DragDropAcceptIdCurrRectSurface = FLT_MAX; @@ -4943,9 +4952,10 @@ void ImGui::PopClipRect() void ImGui::EndFrame() { ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.Initialized); if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times. return; + IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()"); // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) if (g.PlatformIO.Platform_SetImeInputPos && g.PlatformImePosViewport != NULL && ImLengthSqr(g.PlatformImePos - g.PlatformImeLastPos) > 0.0001f) @@ -4986,6 +4996,22 @@ void ImGui::EndFrame() SetCurrentViewport(NULL, NULL); + // Drag and Drop: Elapse payload at the end of the frame if mouse has been released + if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount && !IsMouseDown(g.DragDropMouseButton)) + { + ClearDragDrop(); + g.DragDropPayloadBufHeap.clear(); + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); + } + + // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. + if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount) + { + g.DragDropWithinSourceOrTarget = true; + SetTooltip("..."); + g.DragDropWithinSourceOrTarget = false; + } + // Initiate moving window if (g.ActiveId == 0 && g.HoveredId == 0) { @@ -5061,13 +5087,14 @@ void ImGui::EndFrame() memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); + g.FrameScopeActive = false; g.FrameCountEnded = g.FrameCount; } void ImGui::Render() { ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.Initialized); if (g.FrameCountEnded != g.FrameCount) ImGui::EndFrame(); @@ -5954,7 +5981,11 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ void ImGui::SetTooltipV(const char* fmt, va_list args) { - BeginTooltipEx(0, true); + ImGuiContext& g = *GImGui; + if (g.DragDropWithinSourceOrTarget) + BeginTooltip(); + else + BeginTooltipEx(0, true); TextV(fmt, args); EndTooltip(); } @@ -7084,7 +7115,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; IM_ASSERT(name != NULL); // Window name required - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.FrameScopeActive); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet // Find or create @@ -7659,7 +7690,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Collapse button if (!(flags & ImGuiWindowFlags_NoCollapse)) - if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos + style.FramePadding)) + if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos)) window->CollapseToggleWanted = true; // Defer collapsing to next frame as we are too far in the Begin() function // Close button @@ -9330,6 +9361,9 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) if (window->SkipItems) return false; + // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size. + IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f); + const ImGuiID id = window->GetID(str_id); ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); @@ -9378,17 +9412,21 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize)); + ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); ItemAdd(bb, id); - bool ret = ButtonBehavior(bb, id, NULL, NULL, ImGuiButtonFlags_None); - RenderNavHighlight(bb, id); - RenderArrow(bb.Min, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); + + ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + if (hovered || held) + window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, col, 9); + RenderArrow(bb.Min + g.Style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); // Switch to moving the window after mouse is moved beyond the initial drag threshold if (IsItemActive() && IsMouseDragging()) StartMouseMovingWindow(window); - return ret; + return pressed; } void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) @@ -9780,9 +9818,10 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. ImGuiContext& g = *GImGui; - float button_sz = g.FontSize * 0.5f; ImGuiItemHoveredDataBackup last_item_backup; - if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) + float button_radius = g.FontSize * 0.5f; + ImVec2 button_center = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_radius, window->DC.LastItemRect.GetCenter().y); + if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), button_center, button_radius)) *p_open = false; last_item_backup.Restore(); } @@ -13853,7 +13892,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl // Paint colors over existing vertices ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); - ShadeVertsLinearColorGradientKeepAlpha(draw_list->VtxBuffer.Data + vert_start_idx, draw_list->VtxBuffer.Data + vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); + ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); } // Render Cursor + preview on Hue Wheel @@ -14682,6 +14721,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button; } + g.DragDropSourceFrameCount = g.FrameCount; g.DragDropWithinSourceOrTarget = true; if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) @@ -14850,7 +14890,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop // FIXME-DRAG: Settle on a proper default visuals for drop target. r.Expand(3.5f); bool push_clip_rect = !window->ClipRect.Contains(r); - if (push_clip_rect) window->DrawList->PushClipRect(r.Min, r.Max); + if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1)); window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f); if (push_clip_rect) window->DrawList->PopClipRect(); } diff --git a/imgui.h b/imgui.h index b37a2615..e2495b0b 100644 --- a/imgui.h +++ b/imgui.h @@ -122,11 +122,15 @@ typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); typedef signed int ImS32; // 32-bit signed integer == int typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors) #if defined(_MSC_VER) && !defined(__clang__) -typedef signed __int64 ImS64; // 64-bit signed integer -typedef unsigned __int64 ImU64; // 64-bit unsigned integer +typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio) +typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio) +#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) +#include +typedef int64_t ImS64; // 64-bit signed integer (pre C++11) +typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11) #else -typedef signed long long ImS64; // 64-bit signed integer -typedef unsigned long long ImU64; // 64-bit unsigned integer +typedef signed long long ImS64; // 64-bit signed integer (post C++11) +typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) #endif // 2D vector (often used to store positions, sizes, etc.) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 37ae91d3..bad1a4c5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -36,7 +36,8 @@ #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf +#define snprintf _snprintf +#define vsnprintf _vsnprintf #endif #ifdef __clang__ #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. @@ -1035,7 +1036,7 @@ void ImGui::ShowDemoWindow(bool* p_open) const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2; const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2; const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f; - const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000, f64_hi_a = +1000000000000000; + const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0; // State static ImS32 s32_v = -1; @@ -1534,10 +1535,26 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::PopItemWidth(); // Dummy - ImVec2 sz(30,30); - ImGui::Button("A", sz); ImGui::SameLine(); - ImGui::Dummy(sz); ImGui::SameLine(); - ImGui::Button("B", sz); + ImVec2 button_sz(40,40); + ImGui::Button("A", button_sz); ImGui::SameLine(); + ImGui::Dummy(button_sz); ImGui::SameLine(); + ImGui::Button("B", button_sz); + + // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually) + ImGui::Text("Manually wrapping:"); + ImGuiStyle& style = ImGui::GetStyle(); + int buttons_count = 20; + float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x; + for (int n = 0; n < buttons_count; n++) + { + ImGui::PushID(n); + ImGui::Button("Box", button_sz); + float last_button_x2 = ImGui::GetItemRectMax().x; + float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line + if (n + 1 < buttons_count && next_button_x2 < window_visible_x2) + ImGui::SameLine(); + ImGui::PopID(); + } ImGui::TreePop(); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bf5558d4..2f45c9d7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1210,7 +1210,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, c PathRect(a, b, rounding, rounding_corners); PathFillConvex(col); int vert_end_idx = VtxBuffer.Size; - ImGui::ShadeVertsLinearUV(VtxBuffer.Data + vert_start_idx, VtxBuffer.Data + vert_end_idx, a, b, uv_a, uv_b, true); + ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, a, b, uv_a, uv_b, true); if (push_texture_id) PopTextureID(); @@ -1258,10 +1258,12 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale) //----------------------------------------------------------------------------- // Generic linear color gradient, write to RGB fields, leave A untouched. -void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) +void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) { ImVec2 gradient_extent = gradient_p1 - gradient_p0; float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); + ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; + ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) { float d = ImDot(vert->pos - gradient_p0, gradient_extent); @@ -1274,7 +1276,7 @@ void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDra } // Distribute UV over (a, b) rectangle -void ImGui::ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp) +void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp) { const ImVec2 size = b - a; const ImVec2 uv_size = uv_b - uv_a; @@ -1282,11 +1284,12 @@ void ImGui::ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, con size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); + ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; + ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; if (clamp) { const ImVec2 min = ImMin(uv_a, uv_b); const ImVec2 max = ImMax(uv_a, uv_b); - for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max); } @@ -1545,7 +1548,8 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, GetGlyphRangesDefault()); + const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); + ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges); font->DisplayOffset.y = 1.0f; return font; } @@ -2342,6 +2346,8 @@ void ImFont::GrowIndex(int new_size) IndexLookup.resize(new_size, (unsigned short)-1); } +// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. +// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) { Glyphs.resize(Glyphs.Size + 1); diff --git a/imgui_internal.h b/imgui_internal.h index a9b9e6d0..902f1ded 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -556,7 +556,7 @@ struct ImDrawDataBuilder enum ImGuiViewportFlagsPrivate_ { - ImGuiViewportFlags_CanHostOtherWindows = 1 << 10, // Normal viewports are associated to a single window. The main viewport can host multiple windows. + ImGuiViewportFlags_CanHostOtherWindows = 1 << 10 // Normal viewports are associated to a single window. The main viewport can host multiple windows. }; // ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) @@ -644,6 +644,7 @@ struct ImGuiNextWindowData struct ImGuiContext { bool Initialized; + bool FrameScopeActive; // Set by NewFrame(), cleared by EndFrame()/Render() bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; ImGuiPlatformIO PlatformIO; @@ -753,6 +754,7 @@ struct ImGuiContext bool DragDropActive; bool DragDropWithinSourceOrTarget; ImGuiDragDropFlags DragDropSourceFlags; + int DragDropSourceFrameCount; int DragDropMouseButton; ImGuiPayload DragDropPayload; ImRect DragDropTargetRect; @@ -808,6 +810,7 @@ struct ImGuiContext ImGuiContext(ImFontAtlas* shared_font_atlas) { Initialized = false; + FrameScopeActive = false; Font = NULL; FontSize = FontBaseSize = 0.0f; FontAtlasOwnedByContext = shared_font_atlas ? false : true; @@ -878,6 +881,7 @@ struct ImGuiContext DragDropActive = DragDropWithinSourceOrTarget = false; DragDropSourceFlags = 0; + DragDropSourceFrameCount = -1; DragDropMouseButton = -1; DragDropTargetId = 0; DragDropAcceptFlags = 0; @@ -1269,8 +1273,8 @@ namespace ImGui IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); // Shade functions (write over already created vertices) - IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); - IMGUI_API void ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); + IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); + IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); } // namespace ImGui