fix: drag speed on pan
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"image"
|
||||
"testing"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/test"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"galaxy/client/world"
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
scale float32
|
||||
p world.RenderParams
|
||||
|
||||
forced bool
|
||||
updates int
|
||||
refresh int
|
||||
}
|
||||
|
||||
func (e *fakeClient) CanvasScale() float32 { return e.scale }
|
||||
|
||||
func (e *fakeClient) UpdateParams(fn func(p *world.RenderParams)) {
|
||||
fn(&e.p)
|
||||
e.updates++
|
||||
}
|
||||
|
||||
func (e *fakeClient) RequestRefresh() { e.refresh++ }
|
||||
|
||||
func (e *fakeClient) ForceFullRedraw() { e.forced = true }
|
||||
|
||||
func TestPanController_DraggedUpdatesCameraByDeltaPx(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fe := &fakeClient{
|
||||
scale: 1.0, // 1 fyne unit == 1 px for the test
|
||||
p: world.RenderParams{
|
||||
CameraZoom: 1.0,
|
||||
CameraXWorldFp: 5 * world.SCALE,
|
||||
CameraYWorldFp: 5 * world.SCALE,
|
||||
},
|
||||
}
|
||||
|
||||
pc := NewPanController(fe)
|
||||
|
||||
// Drag right by +3 px and down by +2 px.
|
||||
pc.Dragged(&fyne.DragEvent{
|
||||
Dragged: fyne.Delta{DX: 3, DY: 2},
|
||||
})
|
||||
|
||||
require.Equal(t, 1, fe.updates)
|
||||
|
||||
// Map follows pointer => camera moves opposite to pointer delta.
|
||||
require.Equal(t, 5*world.SCALE-3*world.SCALE, fe.p.CameraXWorldFp)
|
||||
require.Equal(t, 5*world.SCALE-2*world.SCALE, fe.p.CameraYWorldFp)
|
||||
}
|
||||
|
||||
func TestPanController_DraggedUsesCanvasScaleByMultiplying(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fe := &fakeClient{
|
||||
scale: 2.0, // 2 px per fyne unit
|
||||
p: world.RenderParams{
|
||||
CameraZoom: 1.0,
|
||||
CameraXWorldFp: 0,
|
||||
CameraYWorldFp: 0,
|
||||
},
|
||||
}
|
||||
|
||||
pc := NewPanController(fe)
|
||||
|
||||
// Dragged.DX=1 fyne unit => 2 px after scaling.
|
||||
pc.Dragged(&fyne.DragEvent{
|
||||
Dragged: fyne.Delta{DX: 1, DY: 0},
|
||||
})
|
||||
|
||||
require.Equal(t, -2*world.SCALE, fe.p.CameraXWorldFp)
|
||||
}
|
||||
|
||||
func TestPanController_DragEndForcesFullRedrawAndRefresh(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fe := &fakeClient{
|
||||
scale: 1.0,
|
||||
p: world.RenderParams{
|
||||
CameraZoom: 1.0,
|
||||
CameraXWorldFp: 0,
|
||||
CameraYWorldFp: 0,
|
||||
},
|
||||
}
|
||||
|
||||
pc := NewPanController(fe)
|
||||
|
||||
// Simulate a drag start.
|
||||
pc.Dragged(&fyne.DragEvent{PointEvent: fyne.PointEvent{Position: fyne.Position{X: 1, Y: 1}}})
|
||||
|
||||
pc.DragEnd()
|
||||
require.True(t, fe.forced)
|
||||
require.Equal(t, 1, fe.refresh)
|
||||
}
|
||||
|
||||
// Optional: demonstrate use of fyne/test package to ensure types are available.
|
||||
// (Not strictly needed, but keeps fyne dependency "active" in tests.)
|
||||
func TestFyneTestDriverIsUsable(t *testing.T) {
|
||||
t.Parallel()
|
||||
_ = test.NewApp()
|
||||
}
|
||||
|
||||
type immediateExecutor struct{}
|
||||
|
||||
func (immediateExecutor) Post(fn func()) {
|
||||
if fn != nil {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
type noopRefresher struct{}
|
||||
|
||||
func (noopRefresher) Refresh() {}
|
||||
|
||||
func newZoomSyncTestClient(t *testing.T, worldW, worldH int, cameraZoom float64) *client {
|
||||
t.Helper()
|
||||
|
||||
w := world.NewWorld(worldW, worldH)
|
||||
e := &client{
|
||||
world: w,
|
||||
drawer: &world.GGDrawer{},
|
||||
wp: &world.RenderParams{
|
||||
CameraZoom: cameraZoom,
|
||||
CameraXWorldFp: w.W / 2,
|
||||
CameraYWorldFp: w.H / 2,
|
||||
Options: &world.RenderOptions{DisableWrapScroll: false},
|
||||
},
|
||||
hits: make([]world.Hit, 5),
|
||||
}
|
||||
|
||||
e.co = NewRasterCoalescer(
|
||||
immediateExecutor{},
|
||||
noopRefresher{},
|
||||
func(wPx, hPx int, _ world.RenderParams) image.Image {
|
||||
return image.NewRGBA(image.Rect(0, 0, wPx, hPx))
|
||||
},
|
||||
)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func TestRenderRasterImage_SyncsCorrectedZoomToBaseParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := newZoomSyncTestClient(t, 10, 10, 1.0)
|
||||
p := *e.wp
|
||||
|
||||
correctedZoom := e.world.CorrectCameraZoom(p.CameraZoom, 100, 100)
|
||||
require.NotEqual(t, p.CameraZoom, correctedZoom)
|
||||
|
||||
_ = e.renderRasterImage(100, 100, p)
|
||||
|
||||
require.Equal(t, correctedZoom, e.wp.CameraZoom)
|
||||
}
|
||||
|
||||
func TestRenderRasterImage_DoesNotOverrideNewerBaseZoom(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := newZoomSyncTestClient(t, 10, 10, 1.0)
|
||||
p := *e.wp
|
||||
|
||||
// Simulate a newer UI update that happened after this render snapshot was taken.
|
||||
e.wp.CameraZoom = 3.0
|
||||
|
||||
_ = e.renderRasterImage(100, 100, p)
|
||||
|
||||
require.Equal(t, 3.0, e.wp.CameraZoom)
|
||||
}
|
||||
|
||||
func TestPanController_Dragged_AfterRenderZoomCorrection_UsesSyncedZoom(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := newZoomSyncTestClient(t, 10, 10, 1.0)
|
||||
|
||||
// Initial render corrects zoom and syncs it into base params.
|
||||
_ = e.renderRasterImage(100, 100, *e.wp)
|
||||
|
||||
syncedZoom := e.wp.CameraZoom
|
||||
require.NotEqual(t, 1.0, syncedZoom)
|
||||
|
||||
zoomFp, err := world.CameraZoomToWorldFixed(syncedZoom)
|
||||
require.NoError(t, err)
|
||||
|
||||
startX := e.wp.CameraXWorldFp
|
||||
pan := NewPanController(e)
|
||||
pan.Dragged(&fyne.DragEvent{
|
||||
Dragged: fyne.Delta{DX: 1, DY: 0},
|
||||
})
|
||||
|
||||
expectedShift := world.PixelSpanToWorldFixed(1, zoomFp)
|
||||
require.Equal(t, startX-expectedShift, e.wp.CameraXWorldFp)
|
||||
}
|
||||
Reference in New Issue
Block a user