themes and styles

This commit is contained in:
IliaDenisov
2026-03-08 15:31:17 +02:00
parent e37a67bc99
commit 1c2fc30127
39 changed files with 2693 additions and 199 deletions
@@ -0,0 +1,90 @@
package world
import (
"image"
"image/color"
"testing"
"github.com/stretchr/testify/require"
)
type pointRadiusTheme struct {
id string
radius float64
}
func (t pointRadiusTheme) ID() string { return t.id }
func (t pointRadiusTheme) Name() string { return t.id }
func (t pointRadiusTheme) BackgroundColor() color.Color { return color.RGBA{A: 255} }
func (t pointRadiusTheme) BackgroundImage() image.Image { return nil }
func (t pointRadiusTheme) BackgroundTileMode() BackgroundTileMode { return BackgroundTileNone }
func (t pointRadiusTheme) BackgroundScaleMode() BackgroundScaleMode { return BackgroundScaleNone }
func (t pointRadiusTheme) BackgroundAnchorMode() BackgroundAnchorMode { return BackgroundAnchorWorld }
func (t pointRadiusTheme) PointStyle() Style {
return Style{FillColor: color.RGBA{A: 255}, PointRadiusPx: t.radius}
}
func (t pointRadiusTheme) LineStyle() Style {
return Style{StrokeColor: color.RGBA{A: 255}, StrokeWidthPx: 1}
}
func (t pointRadiusTheme) CircleStyle() Style {
return Style{FillColor: color.RGBA{A: 255}, StrokeColor: color.RGBA{A: 255}, StrokeWidthPx: 1}
}
func (t pointRadiusTheme) PointClassOverride(PointClassID) (StyleOverride, bool) {
return StyleOverride{}, false
}
func (t pointRadiusTheme) LineClassOverride(LineClassID) (StyleOverride, bool) {
return StyleOverride{}, false
}
func (t pointRadiusTheme) CircleClassOverride(CircleClassID) (StyleOverride, bool) {
return StyleOverride{}, false
}
func TestRender_ThemeChange_AppliesWithoutReindex_UsesLatestObjectStyles(t *testing.T) {
t.Parallel()
w := NewWorld(10, 10)
// Build index once.
w.IndexOnViewportChange(100, 100, 1.0)
// Theme A: point radius 2
w.SetTheme(pointRadiusTheme{id: "A", radius: 2})
_, err := w.AddPoint(5, 5)
require.NoError(t, err)
// Ensure the point is actually present in grid (it will be, because Add triggers rebuild via index state).
// Render once.
params := RenderParams{
ViewportWidthPx: 100,
ViewportHeightPx: 100,
MarginXPx: 0,
MarginYPx: 0,
CameraXWorldFp: 5 * SCALE,
CameraYWorldFp: 5 * SCALE,
CameraZoom: 1.0,
}
d1 := &fakePrimitiveDrawer{}
require.NoError(t, w.Render(d1, params))
p1 := d1.CommandsByName("AddPoint")
require.NotEmpty(t, p1)
r1 := p1[0].Args[2]
require.Equal(t, 2.0, r1)
// Theme B: point radius 7. Change theme, but DO NOT reindex.
w.SetTheme(pointRadiusTheme{id: "B", radius: 7})
d2 := &fakePrimitiveDrawer{}
require.NoError(t, w.Render(d2, params))
p2 := d2.CommandsByName("AddPoint")
require.NotEmpty(t, p2)
r2 := p2[0].Args[2]
require.Equal(t, 7.0, r2)
}