Files
galaxy-game/client/world/renderer_test_helpers_test.go
T
2026-03-07 00:29:06 +03:00

200 lines
5.6 KiB
Go

package world
import (
"testing"
"github.com/stretchr/testify/require"
)
// rendererTestEnv groups the common mutable inputs used by renderer tests.
// The environment stores independent horizontal and vertical margins because
// the expanded canvas geometry is derived separately on each axis.
type rendererTestEnv struct {
world *World
drawer *fakePrimitiveDrawer
// Viewport origin and size in canvas pixel coordinates.
viewportX int
viewportY int
viewportW int
viewportH int
// Independent margins around the viewport in canvas pixels.
marginXPx int
marginYPx int
// Final expanded canvas size in pixels.
// In the default setup:
// canvasW = viewportW + 2*marginXPx
// canvasH = viewportH + 2*marginYPx
canvasW int
canvasH int
// Camera center in fixed-point world coordinates.
cameraX int
cameraY int
// Camera zoom in fixed-point representation, if needed by renderer internals.
zoomFp int
}
// newRendererTestEnv returns a baseline renderer test environment.
// The default margins are derived independently from viewport width and height.
func newRendererTestEnv() *rendererTestEnv {
viewportW := 100
viewportH := 80
marginXPx := viewportW / 4
marginYPx := viewportH / 4
return &rendererTestEnv{
world: NewWorld(10, 10),
drawer: &fakePrimitiveDrawer{},
viewportX: marginXPx,
viewportY: marginYPx,
viewportW: viewportW,
viewportH: viewportH,
marginXPx: marginXPx,
marginYPx: marginYPx,
canvasW: viewportW + 2*marginXPx,
canvasH: viewportH + 2*marginYPx,
cameraX: 5 * SCALE,
cameraY: 5 * SCALE,
zoomFp: SCALE,
}
}
// setViewport resets viewport-dependent fields and recomputes margins
// using the default test formula:
//
// marginXPx = viewportW / 4
// marginYPx = viewportH / 4
func (env *rendererTestEnv) setViewport(viewportW, viewportH int) {
env.viewportW = viewportW
env.viewportH = viewportH
env.marginXPx = viewportW / 4
env.marginYPx = viewportH / 4
env.viewportX = env.marginXPx
env.viewportY = env.marginYPx
env.canvasW = env.viewportW + 2*env.marginXPx
env.canvasH = env.viewportH + 2*env.marginYPx
}
// setViewportAndMargins overrides viewport and margins explicitly.
// This is useful for edge cases where the expanded canvas geometry
// must be controlled exactly.
func (env *rendererTestEnv) setViewportAndMargins(viewportW, viewportH, marginXPx, marginYPx int) {
env.viewportW = viewportW
env.viewportH = viewportH
env.marginXPx = marginXPx
env.marginYPx = marginYPx
env.viewportX = env.marginXPx
env.viewportY = env.marginYPx
env.canvasW = env.viewportW + 2*env.marginXPx
env.canvasH = env.viewportH + 2*env.marginYPx
}
// viewportRect returns the viewport rectangle in canvas pixel coordinates.
func (env *rendererTestEnv) viewportRect() (x, y, w, h float64) {
return float64(env.viewportX), float64(env.viewportY), float64(env.viewportW), float64(env.viewportH)
}
// canvasRect returns the full expanded canvas rectangle in canvas pixel coordinates.
func (env *rendererTestEnv) canvasRect() (x, y, w, h float64) {
return 0, 0, float64(env.canvasW), float64(env.canvasH)
}
// worldMustAddPoint adds a point to the test world and fails the test on error.
func worldMustAddPoint(t *testing.T, w *World, x, y float64) {
t.Helper()
_, err := w.AddPoint(x, y)
require.NoError(t, err)
}
// worldMustAddCircle adds a circle to the test world and fails the test on error.
func worldMustAddCircle(t *testing.T, w *World, x, y, r float64) {
t.Helper()
_, err := w.AddCircle(x, y, r)
require.NoError(t, err)
}
// worldMustAddLine adds a line to the test world and fails the test on error.
func worldMustAddLine(t *testing.T, w *World, x1, y1, x2, y2 float64) {
t.Helper()
_, err := w.AddLine(x1, y1, x2, y2)
require.NoError(t, err)
}
// requireNoDrawerCommands asserts that the renderer produced no drawing commands.
func requireNoDrawerCommands(t *testing.T, d *fakePrimitiveDrawer) {
t.Helper()
require.Empty(t, d.Commands())
}
// requireStrokeCommandAt returns a command and asserts that it is Stroke.
func requireStrokeCommandAt(t *testing.T, d *fakePrimitiveDrawer, index int) fakeDrawerCommand {
t.Helper()
cmd := requireDrawerCommandAt(t, d, index)
requireCommandName(t, cmd, "Stroke")
return cmd
}
// requireFillCommandAt returns a command and asserts that it is Fill.
func requireFillCommandAt(t *testing.T, d *fakePrimitiveDrawer, index int) fakeDrawerCommand {
t.Helper()
cmd := requireDrawerCommandAt(t, d, index)
requireCommandName(t, cmd, "Fill")
return cmd
}
// requireAddPointCommandAt returns a command and asserts that it is AddPoint.
func requireAddPointCommandAt(t *testing.T, d *fakePrimitiveDrawer, index int) fakeDrawerCommand {
t.Helper()
cmd := requireDrawerCommandAt(t, d, index)
requireCommandName(t, cmd, "AddPoint")
return cmd
}
// requireAddLineCommandAt returns a command and asserts that it is AddLine.
func requireAddLineCommandAt(t *testing.T, d *fakePrimitiveDrawer, index int) fakeDrawerCommand {
t.Helper()
cmd := requireDrawerCommandAt(t, d, index)
requireCommandName(t, cmd, "AddLine")
return cmd
}
// requireAddCircleCommandAt returns a command and asserts that it is AddCircle.
func requireAddCircleCommandAt(t *testing.T, d *fakePrimitiveDrawer, index int) fakeDrawerCommand {
t.Helper()
cmd := requireDrawerCommandAt(t, d, index)
requireCommandName(t, cmd, "AddCircle")
return cmd
}
// requireSingleClipRectOnCommand asserts that the command was issued under exactly one clip rect.
func requireSingleClipRectOnCommand(t *testing.T, cmd fakeDrawerCommand, x, y, w, h float64) {
t.Helper()
requireCommandClipRects(t, cmd, fakeClipRect{
X: x,
Y: y,
W: w,
H: h,
})
}