feat: hit on primitives

This commit is contained in:
IliaDenisov
2026-03-07 19:28:22 +02:00
parent e4b956232f
commit c076347d70
21 changed files with 1167 additions and 165 deletions
+98
View File
@@ -1,6 +1,7 @@
package world
import (
"image/color"
"testing"
"github.com/stretchr/testify/require"
@@ -197,3 +198,100 @@ func TestCircles_NoWrap_DoesNotDuplicateAcrossEdges(t *testing.T) {
// Center must be at (9,9) only, no (-1,*) or (*,-1).
require.Equal(t, []float64{9, 9, 2}, cmds[0].Args)
}
func TestRender_CircleTransparentFill_UsesStrokeNotFill(t *testing.T) {
t.Parallel()
w := NewWorld(10, 10)
w.resetGrid(2 * SCALE)
sw := 4.0
circleStyle := w.AddStyleCircle(StyleOverride{
FillColor: color.RGBA{A: 0}, // explicitly transparent
StrokeColor: color.RGBA{R: 255, G: 255, B: 255, A: 255},
StrokeWidthPx: &sw,
})
_, err := w.AddCircle(5, 5, 2, CircleWithStyleID(circleStyle), CircleWithPriority(100))
require.NoError(t, err)
for _, obj := range w.objects {
w.indexObject(obj)
}
params := RenderParams{
ViewportWidthPx: 10,
ViewportHeightPx: 10,
MarginXPx: 0,
MarginYPx: 0,
CameraXWorldFp: 5 * SCALE,
CameraYWorldFp: 5 * SCALE,
CameraZoom: 1.0,
Options: &RenderOptions{
BackgroundColor: color.RGBA{A: 255},
},
}
d := &fakePrimitiveDrawer{}
require.NoError(t, w.Render(d, params))
cmds := d.Commands()
iAdd := indexOfFirstName(cmds, "AddCircle")
require.NotEqual(t, -1, iAdd)
// After AddCircle we must see Stroke (not Fill).
iFill := indexOfFirstNameInRange(cmds, "Fill", iAdd+1, min(iAdd+6, len(cmds)))
iStroke := indexOfFirstNameInRange(cmds, "Stroke", iAdd+1, min(iAdd+6, len(cmds)))
require.Equal(t, -1, iFill, "transparent fill must not trigger Fill()")
require.NotEqual(t, -1, iStroke, "transparent fill must trigger Stroke() when stroke is visible")
}
func TestRender_CircleFillAndStroke_DrawsFillThenStroke(t *testing.T) {
t.Parallel()
w := NewWorld(10, 10)
w.resetGrid(2 * SCALE)
sw := 2.0
styleID := w.AddStyleCircle(StyleOverride{
FillColor: color.RGBA{R: 10, G: 20, B: 30, A: 255},
StrokeColor: color.RGBA{R: 255, G: 255, B: 255, A: 255},
StrokeWidthPx: &sw,
})
_, err := w.AddCircle(5, 5, 2, CircleWithStyleID(styleID), CircleWithPriority(100))
require.NoError(t, err)
for _, obj := range w.objects {
w.indexObject(obj)
}
params := RenderParams{
ViewportWidthPx: 10,
ViewportHeightPx: 10,
MarginXPx: 0,
MarginYPx: 0,
CameraXWorldFp: 5 * SCALE,
CameraYWorldFp: 5 * SCALE,
CameraZoom: 1.0,
Options: &RenderOptions{
BackgroundColor: color.RGBA{A: 255},
},
}
d := &fakePrimitiveDrawer{}
require.NoError(t, w.Render(d, params))
cmds := d.Commands()
iAdd := indexOfFirstName(cmds, "AddCircle")
require.NotEqual(t, -1, iAdd)
iFill := indexOfFirstNameInRange(cmds, "Fill", iAdd+1, min(iAdd+10, len(cmds)))
iStroke := indexOfFirstNameInRange(cmds, "Stroke", iAdd+1, min(iAdd+10, len(cmds)))
require.NotEqual(t, -1, iFill, "expected Fill() for visible fill")
require.NotEqual(t, -1, iStroke, "expected Stroke() for visible stroke")
require.Less(t, iFill, iStroke, "Stroke must be last when both are visible")
}