From cb9d412ad8837d97fce4a9d904e1787253d6c625 Mon Sep 17 00:00:00 2001 From: Ben Carter Date: Fri, 29 Nov 2019 15:35:23 +0900 Subject: [PATCH] Texture-based round corners: Adding style/drawlist flags for rounded corner textures --- imgui.cpp | 3 +++ imgui.h | 2 ++ imgui_demo.cpp | 1 + imgui_draw.cpp | 16 +++++++++++++--- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d639e83e..d2642aa5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1263,6 +1263,7 @@ ImGuiStyle::ImGuiStyle() AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.). + TexturedRoundCorners = true; // Enable using textures instead of strokes to draw rounded corners/circles where possible. CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. @@ -4634,6 +4635,8 @@ static void SetupDrawListSharedData() g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; + if (g.Style.TexturedRoundCorners && !(g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedRoundCorners)) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_TexturedRoundCorners; } void ImGui::NewFrame() diff --git a/imgui.h b/imgui.h index cf1c45ac..b9a23663 100644 --- a/imgui.h +++ b/imgui.h @@ -2079,6 +2079,7 @@ struct ImGuiStyle bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). + bool TexturedRoundCorners; // Enable using textures instead of strokes to draw rounded corners/circles where possible. float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. ImVec4 Colors[ImGuiCol_COUNT]; @@ -2752,6 +2753,7 @@ enum ImDrawListFlags_ ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. + ImDrawListFlags_TexturedRoundCorners = 1 << 4, // Enable using textures instead of strokes to draw rounded corners/circles where possible. }; // Draw command list diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6716c8fd..e2d67708 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7029,6 +7029,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering)."); ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); + ImGui::Checkbox("Rounded corner textures", &style.TexturedRoundCorners); ImGui::PushItemWidth(ImGui::GetFontSize() * 8); ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f"); if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 28f764e9..97a9fc10 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1404,6 +1404,9 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th // We are using the textures generated by ImFontAtlasBuildRenderRoundCornersTexData() inline bool AddRoundCornerRect(ImDrawList* draw_list, const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawFlags flags, bool fill) { + if (!(draw_list->Flags & ImDrawListFlags_TexturedRoundCorners)) // Disabled by the draw list flags + return false; + #if 1 flags = FixRectCornerFlags(flags); rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f); @@ -1413,6 +1416,9 @@ inline bool AddRoundCornerRect(ImDrawList* draw_list, const ImVec2& a, const ImV const ImDrawListSharedData* data = draw_list->_Data; const int rad = (int)rounding; + if (data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners) // No data in font + return false; + if ((rad <= 0) || // Zero radius causes issues with the [rad - 1] UV lookup below (rad > data->Font->ContainerAtlas->RoundCornersMaxSize)) { @@ -1422,9 +1428,7 @@ inline bool AddRoundCornerRect(ImDrawList* draw_list, const ImVec2& a, const ImV // Debug command to force this render path to only execute when shift is held if (!ImGui::GetIO().KeyShift) - { return false; - } ImTextureID tex_id = data->Font->ContainerAtlas->TexID; IM_ASSERT(tex_id == draw_list->_TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. @@ -1781,10 +1785,16 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV // (in which case the caller should try the regular circle drawing code) inline bool AddRoundCornerCircle(ImDrawList* draw_list, const ImVec2& center, float radius, ImU32 col, bool fill) { + if (!(draw_list->Flags & ImDrawListFlags_TexturedRoundCorners)) // Disabled by the draw list flags + return false; + const ImDrawListSharedData* data = draw_list->_Data; ImTextureID tex_id = data->Font->ContainerAtlas->TexID; IM_ASSERT(tex_id == draw_list->_TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. + if (data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners) // No data in font + return false; + const int rad = (int)radius; if (rad < 1 || rad > data->Font->ContainerAtlas->RoundCornersMaxSize) // Radius 0 will cause issues with the UV lookup below return false; // We can't handle this @@ -2840,7 +2850,7 @@ ImFontAtlas::ImFontAtlas() TexGlyphPadding = 1; PackIdMouseCursors = PackIdLines = -1; - RoundCornersMaxSize = 60; + RoundCornersMaxSize = 32; } ImFontAtlas::~ImFontAtlas()