mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-06 04:58:47 +02:00
AddCircle, AddCircleFilled: Add auto-calculation of circle segment counts (amends)
Tweak default max error value, Changelog, comments, path-fast for 12 segments circles, made LUT store ImU8
This commit is contained in:
@ -349,16 +349,29 @@ ImDrawListSharedData::ImDrawListSharedData()
|
||||
FontSize = 0.0f;
|
||||
CurveTessellationTol = 0.0f;
|
||||
CircleSegmentMaxError = 0.0f;
|
||||
CircleSegmentCountsMaxCircleSegmentError = -FLT_MIN; // Impossible value to force recalculation
|
||||
ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f);
|
||||
InitialFlags = ImDrawListFlags_None;
|
||||
|
||||
// Const data
|
||||
// Lookup tables
|
||||
for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++)
|
||||
{
|
||||
const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12);
|
||||
CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a));
|
||||
}
|
||||
memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by
|
||||
}
|
||||
|
||||
void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error)
|
||||
{
|
||||
if (CircleSegmentMaxError == max_error)
|
||||
return;
|
||||
CircleSegmentMaxError = max_error;
|
||||
for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++)
|
||||
{
|
||||
const float radius = i + 1.0f;
|
||||
const int segment_count = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError);
|
||||
CircleSegmentCounts[i] = (ImU8)ImMin(segment_count, 255);
|
||||
}
|
||||
}
|
||||
|
||||
void ImDrawList::Clear()
|
||||
@ -1085,60 +1098,63 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV
|
||||
PathFillConvex(col);
|
||||
}
|
||||
|
||||
void ImDrawListSharedData::RecalculateCircleSegmentCounts()
|
||||
{
|
||||
for (int i = 0; i < NumCircleSegmentCounts; i++)
|
||||
{
|
||||
const float radius = i + 1.0f;
|
||||
CircleSegmentCounts[i] = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - CircleSegmentMaxError) / radius)), 3, 10000);
|
||||
}
|
||||
|
||||
CircleSegmentCountsMaxCircleSegmentError = CircleSegmentMaxError;
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f))
|
||||
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
|
||||
return;
|
||||
|
||||
// Calculate number of segments if required
|
||||
// Obtain segment count
|
||||
if (num_segments <= 0)
|
||||
{
|
||||
int radius_int = (int)radius;
|
||||
if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts)
|
||||
num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value
|
||||
// Automatic segment count
|
||||
const int radius_idx = (int)radius - 1;
|
||||
if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
|
||||
num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
||||
else
|
||||
num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000);
|
||||
num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Explicit segment count (still clamp to avoid drawing insanely tessellated shapes)
|
||||
num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);
|
||||
}
|
||||
else
|
||||
num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes
|
||||
|
||||
// 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;
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
if (num_segments == 12)
|
||||
PathArcToFast(center, radius - 0.5f, 0, 12);
|
||||
else
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
PathStroke(col, true, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f))
|
||||
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
|
||||
return;
|
||||
|
||||
// Calculate number of segments if required
|
||||
// Obtain segment count
|
||||
if (num_segments <= 0)
|
||||
{
|
||||
int radius_int = (int)radius;
|
||||
if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts)
|
||||
num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value
|
||||
// Automatic segment count
|
||||
const int radius_idx = (int)radius - 1;
|
||||
if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
|
||||
num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
||||
else
|
||||
num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000);
|
||||
num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
|
||||
}
|
||||
else
|
||||
num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes
|
||||
{
|
||||
// Explicit segment count (still clamp to avoid drawing insanely tessellated shapes)
|
||||
num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);
|
||||
}
|
||||
|
||||
// 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;
|
||||
PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);
|
||||
if (num_segments == 12)
|
||||
PathArcToFast(center, radius, 0, 12);
|
||||
else
|
||||
PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);
|
||||
PathFillConvex(col);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user