Skip to content

Commit

Permalink
Fix arc segment fuckery when it's near full
Browse files Browse the repository at this point in the history
  • Loading branch information
WorkingRobot committed Nov 24, 2023
1 parent fd80536 commit 1fe8db7
Showing 1 changed file with 30 additions and 27 deletions.
57 changes: 30 additions & 27 deletions Craftimizer/ImGuiUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,21 @@ private static Vector2 UnitCircle(float theta)
private static float Lerp(float a, float b, float t) =>
MathF.FusedMultiplyAdd(b - a, t, a);

private static void ArcSegment(Vector2 o, Vector2 prev, Vector2 cur, Vector2? next, float radius, float ratio, uint color)
private readonly record struct ArcEdge(float Angle, Vector2 Point)
{
public ArcEdge(float angle) : this(angle, UnitCircle(angle)) { }
}

private static void ArcSegment(Vector2 o, ArcEdge prev, ArcEdge cur, ArcEdge? next, float radius, float ratio, uint color)
{
var d = ImGui.GetWindowDrawList();

d.PathLineTo(o + cur * radius);
d.PathLineTo(o + prev * radius);
d.PathLineTo(o + prev * radius * ratio);
d.PathLineTo(o + cur * radius * ratio);
d.PathLineTo(o + cur.Point * radius);
d.PathLineTo(o + prev.Point * radius);
d.PathLineTo(o + prev.Point * radius * ratio);
d.PathLineTo(o + cur.Point * radius * ratio);
if (next is { } nextValue)
d.PathLineTo(o + nextValue * radius);
d.PathLineTo(o + nextValue.Point * radius);
d.PathFillConvex(color);
}

Expand All @@ -164,24 +169,25 @@ public static void Arc(float startAngle, float endAngle, float radius, float rat
if (startAngle > endAngle)
(startAngle, endAngle) = (endAngle, startAngle);

// Origin of circle
var offset = ImGui.GetCursorScreenPos() + new Vector2(radius);

// Number of segments to draw
var segments = ImGui.GetWindowDrawList()._CalcCircleAutoSegmentCount(radius);
// Angle between each segment
var incrementAngle = MathF.Tau / segments;
// Whether the arc is a full circle (no background or all background)
var isFullCircle = (endAngle - startAngle) % MathF.Tau == 0;

var prevA = startAngle;
var prev = UnitCircle(prevA);
var end = new ArcEdge(endAngle);
var prev = new ArcEdge(startAngle);
for (var i = 1; i <= segments; ++i)
{
var a = startAngle + incrementAngle * i;
var cur = UnitCircle(a);

var nextA = a + incrementAngle;
var next = UnitCircle(nextA);
var cur = new ArcEdge(startAngle + incrementAngle * i);
var next = new ArcEdge(startAngle + incrementAngle * (i + 1));

// full segment is background
if (prevA >= endAngle)
if (prev.Angle >= end.Angle)
{
// don't overlap with the first segment
if (i == segments && !isFullCircle)
Expand All @@ -190,39 +196,36 @@ public static void Arc(float startAngle, float endAngle, float radius, float rat
ArcSegment(offset, prev, cur, next, radius, ratio, backgroundColor);
}
// segment is partially filled
else if (a > endAngle && !isFullCircle)
else if (cur.Angle > end.Angle && !isFullCircle)
{
// we split the drawing in two
var end = UnitCircle(endAngle);
ArcSegment(offset, prev, end, null, radius, ratio, filledColor);
ArcSegment(offset, end, cur, next, radius, ratio, backgroundColor);
// set the previous segment to endAngle
a = endAngle;
if (i == segments)
ArcSegment(offset, end, cur, null, radius, ratio, backgroundColor);
else
ArcSegment(offset, end, cur, next, radius, ratio, backgroundColor);
// set the previous segment to end
cur = end;
}
// full segment is filled
else
{
// if the next segment will be partially filled, the next segment will be the endAngle
if (nextA > endAngle && !isFullCircle)
{
var end = UnitCircle(endAngle);
// if the next segment will be partially filled, the next segment will be the end
if (next.Angle > end.Angle && !isFullCircle)
ArcSegment(offset, prev, cur, end, radius, ratio, filledColor);
}
else
ArcSegment(offset, prev, cur, next, radius, ratio, filledColor);
}
prevA = a;
prev = cur;
}

if (addDummy)
ImGui.Dummy(new Vector2(radius * 2));
}

public static void ArcProgress(float value, float radiusInner, float radiusOuter, uint backgroundColor, uint filledColor)
public static void ArcProgress(float value, float radius, float ratio, uint backgroundColor, uint filledColor)
{
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radiusInner, radiusOuter, backgroundColor, filledColor);
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radius, ratio, backgroundColor, filledColor);
}

public sealed class ViolinData
Expand Down

0 comments on commit 1fe8db7

Please sign in to comment.