ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle" with a small number of segments (e.g. an hexagon). (#2287) [@baktery]

+ Demo tweaks
This commit is contained in:
omar 2019-01-16 17:47:49 +01:00
parent 06aaf23877
commit 8cbb91261e
4 changed files with 27 additions and 17 deletions

View File

@ -34,6 +34,8 @@ HOW TO UPDATE?
----------------------------------------------------------------------- -----------------------------------------------------------------------
Other Changes: Other Changes:
- ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle"
with a small number of segments (e.g. an hexagon). (#2287) [@baktery]
- Fonts: imgui_freetype: Added support for imgui allocators + custom FreeType only SetAllocatorFunctions. (#2285) [@Vuhdo] - Fonts: imgui_freetype: Added support for imgui allocators + custom FreeType only SetAllocatorFunctions. (#2285) [@Vuhdo]
- Examples: Win32: Using GetForegroundWindow() instead of GetActiveWindow() to be compatible with windows created - Examples: Win32: Using GetForegroundWindow() instead of GetActiveWindow() to be compatible with windows created
in a different thread. (#1951, #2087, #2156, #2232) [many people] in a different thread. (#1951, #2087, #2156, #2232) [many people]

View File

@ -38,7 +38,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
- drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api - drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api
- drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
- drawlist: non-AA strokes have gaps between points (#593, #288), especially RenderCheckmark(). - drawlist: non-AA strokes have gaps between points (#593, #288), glitch especially on RenderCheckmark() and ColorPicker4().
- drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now). - drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now).
- drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302) - drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302)
- drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API). - drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API).

View File

@ -3852,27 +3852,30 @@ static void ShowExampleAppCustomRendering(bool* p_open)
static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
ImGui::ColorEdit3("Color", &col.x); ImGui::ColorEdit4("Color", &col.x);
{ {
const ImVec2 p = ImGui::GetCursorScreenPos(); const ImVec2 p = ImGui::GetCursorScreenPos();
const ImU32 col32 = ImColor(col); const ImU32 col32 = ImColor(col);
float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
for (int n = 0; n < 2; n++) for (int n = 0; n < 2; n++)
{ {
float curr_thickness = (n == 0) ? 1.0f : thickness; // First line uses a thickness of 1.0, second line uses the configurable thickness
draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing; float th = (n == 0) ? 1.0f : thickness;
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6, th); x += sz+spacing; // Hexagon
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, th); x += sz+spacing; // Circle
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing; draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, th); x += sz+spacing;
draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing; draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, th); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, curr_thickness); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, th); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, curr_thickness); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, th); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing; // Diagonal line draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, th); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, curr_thickness); draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, th); x += sz+spacing; // Diagonal line
draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, th);
x = p.x + 4; x = p.x + 4;
y += sz+spacing; y += sz+spacing;
} }
draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6); x += sz+spacing; // Hexagon
draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; // Circle
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;

View File

@ -955,6 +955,9 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, floa
_Path.push_back(centre); _Path.push_back(centre);
return; return;
} }
// Note that we are adding a point at both a_min and a_max.
// If you are trying to draw a full closed circle you don't want the overlapping points!
_Path.reserve(_Path.Size + (num_segments + 1)); _Path.reserve(_Path.Size + (num_segments + 1));
for (int i = 0; i <= num_segments; i++) for (int i = 0; i <= num_segments; i++)
{ {
@ -1138,21 +1141,23 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness) void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
return; return;
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments); PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments - 1);
PathStroke(col, true, thickness); PathStroke(col, true, thickness);
} }
void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments) void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
return; return;
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathArcTo(centre, radius, 0.0f, a_max, num_segments); PathArcTo(centre, radius, 0.0f, a_max, num_segments - 1);
PathFillConvex(col); PathFillConvex(col);
} }