From 3f671bd282b2a3f4815f96b99708d43680e9f8b7 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 | 4 +++- imgui_demo.cpp | 1 + imgui_draw.cpp | 16 +++++++++++++--- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5295ee43..70fb6252 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1070,6 +1070,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. 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. @@ -4297,6 +4298,8 @@ void ImGui::NewFrame() g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; + if (g.Style.TexturedRoundCorners && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_TexturedRoundCorners; // Mark rendering data as invalid to prevent user who may have a handle on it to use it. for (int n = 0; n < g.Viewports.Size; n++) diff --git a/imgui.h b/imgui.h index fe9b0e5b..a1ad71ec 100644 --- a/imgui.h +++ b/imgui.h @@ -1875,6 +1875,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. 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]; @@ -2484,7 +2485,8 @@ enum ImDrawListFlags_ ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles) ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear 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_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 0c7a7bad..5d778bb1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6399,6 +6399,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 e1bc29bf..4c08e289 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1396,6 +1396,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); @@ -1405,6 +1408,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)) { @@ -1414,9 +1420,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. @@ -1773,10 +1777,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 @@ -2432,7 +2442,7 @@ ImFontAtlas::ImFontAtlas() TexGlyphPadding = 1; PackIdMouseCursors = PackIdLines = -1; - RoundCornersMaxSize = 60; + RoundCornersMaxSize = 32; } ImFontAtlas::~ImFontAtlas()