diff --git a/AGENTS.md b/AGENTS.md index 5f4eda3..27aa41b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,6 +37,7 @@ testdata/snapshots/ /-.png - Focus: `internal.Ring(e, k.Focus, radius)` for the 2 DIP ring with 2 DIP gap. - State marks (checked, selected, progress) use `OnAccent` on `Accent`, or `AccentText`, never `Accent` alone on dark surfaces (2.44:1). - Ornament color only for dividers, corners, panel titles. No gradients, glow, glass or texture. +- Animated paths: pass coordinates through `internal.Snap(p, v)`. MyGo caches path masks by quarter-pixel keys (ui/path.go); unsnapped motion reuses near-miss masks and breaks snapshots. - Durations: `mujica.Motion(c, theme.StateDuration)`; popups use `theme.PopupDuration`. - Disabled blocks input before handling it (`Disabled(true)`); MyGo dims disabled elements, do not add opacity. - Copy shown by a component comes from `msg(c, key)`; business copy comes from the caller. diff --git a/internal/paint.go b/internal/paint.go index 7e7f951..f1cd9f4 100644 --- a/internal/paint.go +++ b/internal/paint.go @@ -2,6 +2,8 @@ package internal import ( + "math" + "github.com/egoist/mygo/ui" "mujicaui/theme" @@ -33,3 +35,9 @@ func Diamond(cx, cy, s float32) *ui.Path { p.Close() return &p } + +// Snap rounds v to MyGo's quarter-device-pixel path cache grid. +func Snap(p *ui.Painter, v float32) float32 { + g := 4 * p.Scale() + return float32(math.Round(float64(v*g))) / g +} diff --git a/progress.go b/progress.go index c0059af..85d09dc 100644 --- a/progress.go +++ b/progress.go @@ -7,6 +7,7 @@ import ( "github.com/egoist/mygo/ui" + "mujicaui/internal" "mujicaui/theme" ) @@ -112,21 +113,21 @@ func progressRing(c *ui.Context, k theme.Tokens, u float32, acc float64, name, c } stroke := max(3, d/10) ring.Draw(func(p *ui.Painter, r ui.Rect) { - cx, cy, rad := r.X+r.W/2, r.Y+r.H/2, (r.W-stroke)/2 + cx, cy, rad := internal.Snap(p, r.X+r.W/2), internal.Snap(p, r.Y+r.H/2), internal.Snap(p, (r.W-stroke)/2) var track ui.Path track.Circle(cx, cy, rad) p.StrokePath(&track, stroke, k.Border) switch { case !opts.Indeterminate: if shown > 0 { - p.StrokePath(progressArc(cx, cy, rad, 0, shown), stroke, k.AccentText) + p.StrokePath(progressArc(p, cx, cy, rad, 0, shown), stroke, k.AccentText) } case still: p.StrokePath(&track, stroke, k.AccentText.Alpha(0.4)) default: p.AnimationFrame() start := float32(p.Now().UnixMilli()%1200) / 1200 - p.StrokePath(progressArc(cx, cy, rad, start, start+0.25), stroke, k.AccentText) + p.StrokePath(progressArc(p, cx, cy, rad, start, start+0.25), stroke, k.AccentText) } }) if caption != "" && d >= 44 && !opts.Indeterminate { @@ -150,7 +151,7 @@ func progressRing(c *ui.Context, k theme.Tokens, u float32, acc float64, name, c } // progressArc is the arc from turn a to turn b, clockwise from twelve o'clock. -func progressArc(cx, cy, r float32, a, b float32) *ui.Path { +func progressArc(pt *ui.Painter, cx, cy, r float32, a, b float32) *ui.Path { var p ui.Path n := max(2, int(math.Ceil(float64((b-a)*64)))) for i := 0; i <= n; i++ { @@ -158,9 +159,9 @@ func progressArc(cx, cy, r float32, a, b float32) *ui.Path { x := cx + r*float32(math.Sin(2*math.Pi*t)) y := cy - r*float32(math.Cos(2*math.Pi*t)) if i == 0 { - p.MoveTo(x, y) + p.MoveTo(internal.Snap(pt, x), internal.Snap(pt, y)) } else { - p.LineTo(x, y) + p.LineTo(internal.Snap(pt, x), internal.Snap(pt, y)) } } return &p diff --git a/spinner.go b/spinner.go index 1957ba7..2f1e9dd 100644 --- a/spinner.go +++ b/spinner.go @@ -58,11 +58,8 @@ func spinnerMark(c *ui.Context, label string, size float32, color ui.Color, stil a := 2 * math.Pi * (turn + float64(i)/4) x := cx + rad*float32(math.Cos(a)) y := cy + rad*float32(math.Sin(a)) - // Device-pixel centers keep cached shapes rendering alike. - s := p.Scale() - x, y = float32(math.Round(float64(x*s)))/s, float32(math.Round(float64(y*s)))/s alpha := 1 - float32(i)*0.22 - p.FillPath(internal.Diamond(x, y, r.W*0.3), color.Alpha(alpha)) + p.FillPath(internal.Diamond(internal.Snap(p, x), internal.Snap(p, y), internal.Snap(p, r.W*0.3)), color.Alpha(alpha)) } }) } diff --git a/testdata/snapshots/darwin/button-dark.png b/testdata/snapshots/darwin/button-dark.png index 1629bd7..2653916 100644 Binary files a/testdata/snapshots/darwin/button-dark.png and b/testdata/snapshots/darwin/button-dark.png differ diff --git a/testdata/snapshots/darwin/button-light.png b/testdata/snapshots/darwin/button-light.png index 30db253..b85d2e5 100644 Binary files a/testdata/snapshots/darwin/button-light.png and b/testdata/snapshots/darwin/button-light.png differ diff --git a/testdata/snapshots/darwin/loading_overlay-dark.png b/testdata/snapshots/darwin/loading_overlay-dark.png index 881afd8..2d14543 100644 Binary files a/testdata/snapshots/darwin/loading_overlay-dark.png and b/testdata/snapshots/darwin/loading_overlay-dark.png differ diff --git a/testdata/snapshots/darwin/loading_overlay-light.png b/testdata/snapshots/darwin/loading_overlay-light.png index 9596e41..732747f 100644 Binary files a/testdata/snapshots/darwin/loading_overlay-light.png and b/testdata/snapshots/darwin/loading_overlay-light.png differ diff --git a/testdata/snapshots/darwin/progress-dark.png b/testdata/snapshots/darwin/progress-dark.png index 7d428ac..28c32d3 100644 Binary files a/testdata/snapshots/darwin/progress-dark.png and b/testdata/snapshots/darwin/progress-dark.png differ diff --git a/testdata/snapshots/darwin/progress-light.png b/testdata/snapshots/darwin/progress-light.png index 11e5976..ffa4b25 100644 Binary files a/testdata/snapshots/darwin/progress-light.png and b/testdata/snapshots/darwin/progress-light.png differ diff --git a/testdata/snapshots/darwin/spinner-dark.png b/testdata/snapshots/darwin/spinner-dark.png index 3e65cae..6c3d1a1 100644 Binary files a/testdata/snapshots/darwin/spinner-dark.png and b/testdata/snapshots/darwin/spinner-dark.png differ diff --git a/testdata/snapshots/darwin/spinner-light.png b/testdata/snapshots/darwin/spinner-light.png index fa301e6..be8951a 100644 Binary files a/testdata/snapshots/darwin/spinner-light.png and b/testdata/snapshots/darwin/spinner-light.png differ diff --git a/testdata/snapshots/darwin/status_indicator-dark.png b/testdata/snapshots/darwin/status_indicator-dark.png index 3b905a2..40c2973 100644 Binary files a/testdata/snapshots/darwin/status_indicator-dark.png and b/testdata/snapshots/darwin/status_indicator-dark.png differ diff --git a/testdata/snapshots/darwin/status_indicator-light.png b/testdata/snapshots/darwin/status_indicator-light.png index 37db59b..c256f18 100644 Binary files a/testdata/snapshots/darwin/status_indicator-light.png and b/testdata/snapshots/darwin/status_indicator-light.png differ