Files
aego/modules/tween/scriptfield_test.go

112 lines
3.1 KiB
Go

package tween
import (
"testing"
"aego/contracts/scriptfields"
"aego/core/mathx"
"aego/engine"
"aego/scene"
"aego/script/abi"
"aego/script/vm"
)
type fakeFields struct {
node scene.NodeHandle
kinds map[string]abi.Kind
vals map[string]vm.Value
}
func (f *fakeFields) ResolveField(node scene.NodeHandle, script, field string) (scriptfields.Ref, bool) {
k, ok := f.kinds[field]
if !ok || node != f.node || (script != "Mover" && script != "game.Mover") {
return scriptfields.Ref{}, false
}
return scriptfields.Ref{Node: node, Script: "game.Mover", Field: field, Kind: k}, true
}
func (f *fakeFields) LoadField(ref *scriptfields.Ref) (vm.Value, bool) {
v, ok := f.vals[ref.Field]
return v, ok
}
func (f *fakeFields) StoreField(ref *scriptfields.Ref, v vm.Value) bool {
if _, ok := f.vals[ref.Field]; !ok {
return false
}
f.vals[ref.Field] = v
return true
}
func scriptSetup(t *testing.T) (*Service, *fakeFields, scene.NodeHandle) {
t.Helper()
s := newScene(t)
h := s.Create(s.Root(), "n")
s.Flush()
f := &fakeFields{
node: h,
kinds: map[string]abi.Kind{"Speed": abi.Float, "Vel": abi.Vec2, "Hits": abi.Int, "Name": abi.String},
vals: map[string]vm.Value{"Speed": vm.Float(0), "Vel": vm.Vec(1, 1, 0, 0), "Hits": vm.Int(0), "Name": {}},
}
w := engine.NewWorld("t")
w.SetService(scriptfields.ServiceID, scriptfields.Fields(f))
return NewService(s, w), f, h
}
func TestScriptFieldTargets(t *testing.T) {
svc, f, h := scriptSetup(t)
if _, err := svc.ToFloat(h, "script/Mover.Speed", 4, 0.25, Options{}); err != nil {
t.Fatal(err)
}
if _, err := svc.ToFloat(h, "script/game.Mover.Vel.y", -3, 0.25, Options{}); err != nil {
t.Fatal(err)
}
if _, err := svc.ToFloat(h, "script/Mover.Hits", 3, 0.25, Options{}); err != nil {
t.Fatal(err)
}
steps(svc, 8)
if v := f.vals["Hits"].Int(); v != 2 {
t.Fatalf("an int script field rounds the halfway value, got %d", v)
}
steps(svc, 8)
if v := f.vals["Speed"].Float(); v != 4 {
t.Fatalf("Speed %v", v)
}
if v := f.vals["Vel"]; v.Lane(0) != 1 || v.Lane(1) != -3 || v.Lane(2) != 0 || v.Lane(3) != 0 {
t.Fatalf("Vel lanes %v %v %v %v", v.Lane(0), v.Lane(1), v.Lane(2), v.Lane(3))
}
if f.vals["Hits"].Int() != 3 {
t.Fatal("int end value")
}
}
func TestScriptFieldErrors(t *testing.T) {
svc, f, h := scriptSetup(t)
if _, err := svc.ToFloat(h, "script/Mover.Name", 1, 1, Options{}); err == nil {
t.Fatal("a string script field must not tween")
}
if _, err := svc.ToFloat(h, "script/Other.Speed", 1, 1, Options{}); err == nil {
t.Fatal("unknown script accepted")
}
if _, err := svc.ToVec2(h, "script/Mover.Speed", mathx.Vec2{}, 1, Options{}); err == nil {
t.Fatal("a Vec2 tween on a float field must fail")
}
tw, err := svc.ToFloat(h, "script/Mover.Speed", 4, 1, Options{})
if err != nil {
t.Fatal(err)
}
steps(svc, 4)
delete(f.vals, "Speed")
steps(svc, 1)
if !svc.Done(tw) {
t.Fatal("a tween whose script field is gone must stop")
}
}
func TestScriptFieldsWithoutScripts(t *testing.T) {
svc, _, h := setup(t)
if _, err := svc.ToFloat(h, "script/Mover.Speed", 1, 1, Options{}); err == nil {
t.Fatal("script targets need the script runtime")
}
}