From fdbf146fb5f8034020aee5b0055c85b01035b8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 29 Aug 2015 17:00:23 -0700 Subject: [PATCH] Updated imgui. --- 3rdparty/ocornut-imgui/imgui.cpp | 113 ++++++++++++++---------- 3rdparty/ocornut-imgui/imgui.h | 26 ++++-- 3rdparty/ocornut-imgui/imgui_demo.cpp | 15 +++- 3rdparty/ocornut-imgui/imgui_draw.cpp | 74 ++++++++++++++++ 3rdparty/ocornut-imgui/imgui_internal.h | 10 +++ 5 files changed, 179 insertions(+), 59 deletions(-) diff --git a/3rdparty/ocornut-imgui/imgui.cpp b/3rdparty/ocornut-imgui/imgui.cpp index aa1ddf6e..6c77f77b 100644 --- a/3rdparty/ocornut-imgui/imgui.cpp +++ b/3rdparty/ocornut-imgui/imgui.cpp @@ -620,6 +620,7 @@ ImGuiStyle::ImGuiStyle() DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); @@ -678,6 +679,7 @@ ImGuiIO::ImGuiIO() LogFilename = "imgui_log.txt"; Fonts = &GImDefaultFontAtlas; FontGlobalScale = 1.0f; + DisplayFramebufferScale = ImVec2(1.0f, 1.0f); MousePos = ImVec2(-1,-1); MousePosPrev = ImVec2(-1,-1); MouseDoubleClickTime = 0.30f; @@ -882,45 +884,45 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* } if ((*str & 0xe0) == 0xc0) { - *out_char = 0; + *out_char = 0xFFFD; // will be invalid but not end of string if (in_text_end && in_text_end - (const char*)str < 2) return 0; - if (*str < 0xc2) return 0; + if (*str < 0xc2) return 2; c = (unsigned int)((*str++ & 0x1f) << 6); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 2; c += (*str++ & 0x3f); *out_char = c; return 2; } if ((*str & 0xf0) == 0xe0) { - *out_char = 0; - if (in_text_end && in_text_end - (const char*)str < 3) return 0; - if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 0; - if (*str == 0xed && str[1] > 0x9f) return 0; // str[1] < 0x80 is checked below + *out_char = 0xFFFD; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 3) return 0; + if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; + if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below c = (unsigned int)((*str++ & 0x0f) << 12); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 3; c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 3; c += (*str++ & 0x3f); *out_char = c; return 3; } if ((*str & 0xf8) == 0xf0) { - *out_char = 0; + *out_char = 0xFFFD; // will be invalid but not end of string if (in_text_end && in_text_end - (const char*)str < 4) return 0; - if (*str > 0xf4) return 0; - if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 0; - if (*str == 0xf4 && str[1] > 0x8f) return 0; // str[1] < 0x80 is checked below + if (*str > 0xf4) return 4; + if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; + if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below c = (unsigned int)((*str++ & 0x07) << 18); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 4; c += (unsigned int)((*str++ & 0x3f) << 12); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 4; c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 0; + if ((*str & 0xc0) != 0x80) return 4; c += (*str++ & 0x3f); // utf-8 encodings of values used in surrogate pairs are invalid - if ((c & 0xFFFFF800) == 0xD800) return 0; + if ((c & 0xFFFFF800) == 0xD800) return 4; *out_char = c; return 4; } @@ -1039,6 +1041,12 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e return bytes_count; } +ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) +{ + float s = 1.0f/255.0f; + return ImVec4((in & 0xFF) * s, ((in >> 8) & 0xFF) * s, ((in >> 16) & 0xFF) * s, (in >> 24) * s); +} + ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) { ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f)); @@ -1783,6 +1791,7 @@ void ImGui::NewFrame() IM_ASSERT(g.IO.RenderDrawListsFn != NULL); // Must be implemented IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? + IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid if (!g.Initialized) { @@ -1903,7 +1912,7 @@ void ImGui::NewFrame() bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down]; g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (!mouse_owned_by_application && mouse_any_down) || (g.ActiveId != 0) || (!g.OpenedPopupStack.empty()) || (g.CaptureMouseNextFrame); g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (g.CaptureKeyboardNextFrame); - g.IO.WantInputCharacters = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); + g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); g.MouseCursor = ImGuiMouseCursor_Arrow; g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false; @@ -5074,13 +5083,14 @@ bool ImGui::SmallButton(const char* label) // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) -bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size) +bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; 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); ItemSize(bb); if (!ItemAdd(bb, &id)) @@ -5294,24 +5304,13 @@ void ImGui::LogButtons() LogToClipboard(g.LogAutoExpandMaxDepth); } -bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open) +bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiState& g = *GImGui; - const ImGuiStyle& style = g.Style; - - IM_ASSERT(str_id != NULL || label != NULL); - if (str_id == NULL) - str_id = label; - if (label == NULL) - label = str_id; - const ImGuiID id = window->GetID(str_id); - // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) + ImGuiState& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; + bool opened; if (g.SetNextTreeNodeOpenedCond != 0) { @@ -5338,9 +5337,33 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display } else { - opened = storage->GetInt(id, default_open) != 0; + opened = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; } + // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). + // NB- If we are above max depth we still allow manually opened nodes to be logged. + if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoExpandOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) + opened = true; + + return opened; +} + +bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiState& g = *GImGui; + const ImGuiStyle& style = g.Style; + + IM_ASSERT(str_id != NULL || label != NULL); + if (str_id == NULL) + str_id = label; + if (label == NULL) + label = str_id; + const ImGuiID id = window->GetID(str_id); + // Framed header expand a little outside the default padding const ImVec2 window_padding = window->WindowPadding; const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -5354,24 +5377,22 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display bb.Max.y += style.FramePadding.y * 2; } - // FIXME: we don't provide our width so that it doesn't get feed back into AutoFit. Should manage that better so we can still hover without extending ContentsSize - const ImRect text_bb(bb.Min, bb.Min + ImVec2(g.FontSize + style.FramePadding.x*2*2,0) + label_size); + const float collapser_width = g.FontSize + style.FramePadding.x*2; + const ImRect text_bb(bb.Min, bb.Min + ImVec2(collapser_width + style.FramePadding.x*2*0 + (label_size.x > 0.0f ? label_size.x : 0.0f), label_size.y)); ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y), display_frame ? style.FramePadding.y : 0.0f); - // When logging is enabled, if automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). - // NB- If we are above max depth we still allow manually opened nodes to be logged. - if (g.LogEnabled && !display_frame && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) - opened = true; + const ImRect interact_bb = display_frame ? bb : ImRect(text_bb.Min, text_bb.Max + ImVec2(style.FramePadding.x*2,0.0f)); // FIXME + bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0)); - if (!ItemAdd(bb, &id)) + if (!ItemAdd(interact_bb, &id)) return opened; bool hovered, held; - bool pressed = ButtonBehavior(display_frame ? bb : text_bb, id, &hovered, &held, false); + bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, false); if (pressed) { opened = !opened; - storage->SetInt(id, opened); + window->DC.StateStorage->SetInt(id, opened); } // Render @@ -5387,7 +5408,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display const char log_prefix[] = "\n##"; LogRenderedText(bb.Min + style.FramePadding, log_prefix, log_prefix+3); } - RenderTextClipped(bb.Min + style.FramePadding + ImVec2(g.FontSize + style.FramePadding.x*2,0), bb.Max, label, NULL, &label_size); + RenderTextClipped(bb.Min + style.FramePadding + ImVec2(collapser_width,0), bb.Max, label, NULL, &label_size); if (g.LogEnabled) { const char log_suffix[] = "##"; @@ -5402,7 +5423,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, g.FontSize*0.15f), opened, 0.70f, false); if (g.LogEnabled) LogRenderedText(bb.Min, ">"); - RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x*2,0), label); + RenderText(bb.Min + ImVec2(collapser_width,0), label); } return opened; diff --git a/3rdparty/ocornut-imgui/imgui.h b/3rdparty/ocornut-imgui/imgui.h index f98bb543..f71d0e20 100644 --- a/3rdparty/ocornut-imgui/imgui.h +++ b/3rdparty/ocornut-imgui/imgui.h @@ -114,7 +114,7 @@ namespace ImGui IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging imgui // Window - IMGUI_API bool Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). + IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually. IMGUI_API void End(); IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). @@ -294,7 +294,7 @@ namespace ImGui IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); // Widgets: Trees - IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop + IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop() IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // " IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " @@ -381,6 +381,7 @@ namespace ImGui IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size); // helper to create a child window / scrolling region that looks like a normal widget frame IMGUI_API void EndChildFrame(); + IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); @@ -646,6 +647,7 @@ struct ImGuiStyle ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. ImVec4 Colors[ImGuiCol_COUNT]; IMGUI_API ImGuiStyle(); @@ -675,6 +677,7 @@ struct ImGuiIO ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. float FontGlobalScale; // = 1.0f // Global scale all fonts bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. + ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui. ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize @@ -725,7 +728,7 @@ struct ImGuiIO bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input) bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) - bool WantInputCharacters; // Some text input widget is active, which will read input characters from the InputCharacters array. + bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() @@ -950,7 +953,8 @@ struct ImColor { ImVec4 Value; - ImColor(int r, int g, int b, int a = 255) { Value.x = (float)r / 255.0f; Value.y = (float)g / 255.0f; Value.z = (float)b / 255.0f; Value.w = (float)a / 255.0f; } + ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f/255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; } + ImColor(ImU32 rgba) { float sc = 1.0f/255.0f; Value.x = (float)(rgba&0xFF) * sc; Value.y = (float)((rgba>>8)&0xFF) * sc; Value.z = (float)((rgba>>16)&0xFF) * sc; Value.w = (float)(rgba >> 24) * sc; } ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } ImColor(const ImVec4& col) { Value = col; } operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } @@ -1097,15 +1101,18 @@ struct ImDrawList IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col = 0xFFFFFFFF); IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased); + IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } - inline void PathLineTo(const ImVec2& p) { _Path.push_back(p); } - IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); - IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); - IMGUI_API void PathRect(const ImVec2& a, const ImVec2& b, float rounding = 0.0f, int rounding_corners = 0x0F); + inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); } inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } - inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } + inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } + IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); + IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle + IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); + IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners = 0x0F); // Channels // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) @@ -1140,6 +1147,7 @@ struct ImDrawData // Functions void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! + void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. }; struct ImFontConfig diff --git a/3rdparty/ocornut-imgui/imgui_demo.cpp b/3rdparty/ocornut-imgui/imgui_demo.cpp index 7ae60b2d..48be4a7a 100644 --- a/3rdparty/ocornut-imgui/imgui_demo.cpp +++ b/3rdparty/ocornut-imgui/imgui_demo.cpp @@ -827,7 +827,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Groups")) { - ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items)"); + ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundled the whole group so that you can use functions such as IsItemHovered() on it.)"); ImGui::BeginGroup(); { ImGui::BeginGroup(); @@ -903,7 +903,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Scrolling")) { - ImGui::TextWrapped("Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position."); + ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)"); static bool track = true; static int track_line = 50, scroll_to_px = 200; ImGui::Checkbox("Track", &track); @@ -1343,7 +1343,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); - ImGui::Text("WantInputCharacters: %s", io.WantInputCharacters ? "true" : "false"); + ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false"); ImGui::Button("Hover me\nto enforce\ninputs capture"); if (ImGui::IsItemHovered()) @@ -1392,6 +1392,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes); + ImGui::PushItemWidth(100); + ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); + if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; + ImGui::PopItemWidth(); ImGui::TreePop(); } @@ -1641,6 +1645,9 @@ static void ShowExampleAppCustomRendering(bool* opened) if (canvas_size.y < 50.0f) canvas_size.y = 50.0f; draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0)); draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255)); + + draw_list->AddBezierCurve(ImVec2(canvas_pos.x+20,canvas_pos.y+20), ImVec2(canvas_pos.x+100,canvas_pos.y+20), ImVec2(canvas_pos.x+canvas_size.x-100,canvas_pos.y+canvas_size.y-20), ImVec2(canvas_pos.x+canvas_size.x-20,canvas_pos.y+canvas_size.y-20), ImColor(255,200,0), 5.0f); + bool adding_preview = false; ImGui::InvisibleButton("canvas", canvas_size); if (ImGui::IsItemHovered()) @@ -1667,7 +1674,7 @@ static void ShowExampleAppCustomRendering(bool* opened) } draw_list->PushClipRect(ImVec4(canvas_pos.x, canvas_pos.y, canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.) for (int i = 0; i < points.Size - 1; i += 2) - draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), 0xFF00FFFF); + draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), 0xFF00FFFF, 2.0f); draw_list->PopClipRect(); if (adding_preview) points.pop_back(); diff --git a/3rdparty/ocornut-imgui/imgui_draw.cpp b/3rdparty/ocornut-imgui/imgui_draw.cpp index 0d3e411b..e1a3ea85 100644 --- a/3rdparty/ocornut-imgui/imgui_draw.cpp +++ b/3rdparty/ocornut-imgui/imgui_draw.cpp @@ -639,6 +639,56 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float } } +static void PathBezierToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) +{ + float dx = x4 - x1; + float dy = y4 - y1; + float d2 = ((x2 - x4) * dy - (y2 - y4) * dx); + float d3 = ((x3 - x4) * dy - (y3 - y4) * dx); + d2 = (d2 >= 0) ? d2 : -d2; + d3 = (d3 >= 0) ? d3 : -d3; + if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy)) + { + path->push_back(ImVec2(x4, y4)); + } + else if (level < 10) + { + float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f; + float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f; + float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f; + float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f; + float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f; + float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f; + + PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1); + PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1); + } +} + +void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments) +{ + ImVec2 p1 = _Path.back(); + if (num_segments == 0) + { + // Auto-tessellated + PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0); + } + else + { + float t_step = 1.0f / (float)num_segments; + for (int i_step = 1; i_step <= num_segments; i_step++) + { + float t = t_step * i_step; + float u = 1.0f - t; + float w1 = u*u*u; + float w2 = 3*u*u*t; + float w3 = 3*u*t*t; + float w4 = t*t*t; + _Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y)); + } + } +} + void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) { float r = rounding; @@ -743,6 +793,16 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, PathFill(col); } +void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments) +{ + if ((col >> 24) == 0) + return; + + PathLineTo(pos0); + PathBezierCurveTo(cp0, cp1, pos1, num_segments); + PathStroke(col, false, thickness); +} + void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) { if ((col >> 24) == 0) @@ -833,6 +893,20 @@ void ImDrawData::DeIndexAllBuffers() } } +// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. +void ImDrawData::ScaleClipRects(const ImVec2& scale) +{ + for (int i = 0; i < CmdListsCount; i++) + { + ImDrawList* cmd_list = CmdLists[i]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i]; + cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y); + } + } +} + //----------------------------------------------------------------------------- // ImFontAtlias //----------------------------------------------------------------------------- diff --git a/3rdparty/ocornut-imgui/imgui_internal.h b/3rdparty/ocornut-imgui/imgui_internal.h index 73255bcc..7d45ec95 100644 --- a/3rdparty/ocornut-imgui/imgui_internal.h +++ b/3rdparty/ocornut-imgui/imgui_internal.h @@ -33,6 +33,7 @@ struct ImGuiWindow; typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ +typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ //------------------------------------------------------------------------- // STB libraries @@ -144,6 +145,12 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_AlignTextBaseLine = 1 << 6 }; +enum ImGuiTreeNodeFlags_ +{ + ImGuiTreeNodeFlags_DefaultOpen = 1 << 0, + ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1 +}; + enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ @@ -636,6 +643,7 @@ namespace ImGui IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); + // NB: All position are in absolute pixels coordinates (not window coordinates) IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL); @@ -660,6 +668,8 @@ namespace ImGui IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); + IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging + 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); IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);