Files

196 lines
4.5 KiB
Go

package tween
import (
"unsafe"
"aego/core/curve"
"aego/core/rewind"
)
var _ rewind.Keyframer = (*Service)(nil)
type tweenKey struct {
tweens []slot[tween]
tfree []uint32
ckeys []curve.Key
ckn []int32
timers []slot[timer]
mfree []uint32
actions []slot[action]
afree []uint32
steps []actStep
stn []int32
tn int
mn int
an int
}
func (k *tweenKey) Size() int {
return len(k.tweens)*int(unsafe.Sizeof(slot[tween]{})) + len(k.timers)*int(unsafe.Sizeof(slot[timer]{})) +
len(k.actions)*int(unsafe.Sizeof(slot[action]{})) + len(k.ckeys)*int(unsafe.Sizeof(curve.Key{})) +
len(k.steps)*int(unsafe.Sizeof(actStep{})) + 4*(len(k.tfree)+len(k.mfree)+len(k.afree)+len(k.ckn)+len(k.stn))
}
func fitSlots[T any](s []slot[T], n int) []slot[T] {
if cap(s) < n {
out := make([]slot[T], n)
copy(out, s[:cap(s)])
return out
}
return s[:n]
}
func (s *Service) Capture(reuse rewind.Key) rewind.Key {
k, _ := reuse.(*tweenKey)
if k == nil {
k = &tweenKey{}
}
k.tweens = append(k.tweens[:0], s.tweens.s...)
k.ckeys, k.ckn = k.ckeys[:0], k.ckn[:0]
for i := range k.tweens {
cv := &k.tweens[i].v.cv
k.ckn = append(k.ckn, int32(len(cv.Keys)))
k.ckeys = append(k.ckeys, cv.Keys...)
cv.Keys = nil
}
k.tfree, k.tn = append(k.tfree[:0], s.tweens.free...), s.tweens.n
k.timers = append(k.timers[:0], s.timers.s...)
k.mfree, k.mn = append(k.mfree[:0], s.timers.free...), s.timers.n
k.actions = append(k.actions[:0], s.actions.s...)
k.steps, k.stn = k.steps[:0], k.stn[:0]
for i := range k.actions {
a := &k.actions[i].v
k.stn = append(k.stn, int32(len(a.steps)))
k.steps = append(k.steps, a.steps...)
a.steps = nil
}
k.afree, k.an = append(k.afree[:0], s.actions.free...), s.actions.n
return k
}
func (s *Service) Restore(key rewind.Key) {
k := key.(*tweenKey)
ts := fitSlots(s.tweens.s, len(k.tweens))
off := 0
for i := range k.tweens {
prev := ts[i].v.cv.Keys
ts[i] = k.tweens[i]
n := int(k.ckn[i])
ts[i].v.cv.Keys = append(prev[:0], k.ckeys[off:off+n]...)
off += n
}
s.tweens = pool[tween]{s: ts, free: append(s.tweens.free[:0], k.tfree...), n: k.tn}
s.timers = pool[timer]{s: append(s.timers.s[:0], k.timers...), free: append(s.timers.free[:0], k.mfree...), n: k.mn}
as := fitSlots(s.actions.s, len(k.actions))
off = 0
for i := range k.actions {
prev := as[i].v.steps
as[i] = k.actions[i]
n := int(k.stn[i])
as[i].v.steps = append(prev[:0], k.steps[off:off+n]...)
off += n
}
s.actions = pool[action]{s: as, free: append(s.actions.free[:0], k.afree...), n: k.an}
}
func hashFree(h *rewind.Hasher, free []uint32, n int) {
h.Int(len(free))
for _, f := range free {
h.U32(f)
}
h.Int(n)
}
func hashTarget(h *rewind.Hasher, t *target) {
h.U64(uint64(t.own))
h.U64(uint64(t.typ))
h.U64(uint64(t.off))
h.U64(uint64(t.kind))
h.U64(uint64(t.part))
h.Bool(t.three)
h.U64(uint64(t.shape))
h.I64(int64(t.lane))
h.U32(uint32(t.ref.Instance))
h.String(t.ref.Field)
h.Int(t.ref.Slot)
}
func (s *Service) Hash(h *rewind.Hasher) {
h.String("tween")
h.Int(len(s.tweens.s))
for i := range s.tweens.s {
e := &s.tweens.s[i]
h.U32(e.gen)
h.Bool(e.live)
if !e.live {
continue
}
t := &e.v
h.U32(t.node.Index)
h.U32(t.node.Gen)
hashTarget(h, &t.tgt)
for j := range 4 {
h.F32(t.from[j])
h.F32(t.to[j])
}
h.F32(t.dur)
h.F32(t.t)
h.F32(t.delay)
h.I64(int64(t.legs))
h.U64(uint64(t.ease))
h.Int(len(t.cv.Keys))
for _, b := range [...]bool{t.hasCurve, t.ping, t.rev, t.started, t.unscaled, t.held, t.moved} {
h.Bool(b)
}
h.U64(t.act.Key())
}
hashFree(h, s.tweens.free, s.tweens.n)
h.Int(len(s.timers.s))
for i := range s.timers.s {
e := &s.timers.s[i]
h.U32(e.gen)
h.Bool(e.live)
if !e.live {
continue
}
t := &e.v
h.F32(t.dur)
h.F32(t.left)
h.I64(int64(t.legs))
h.I64(int64(t.repeat))
h.U32(t.count)
h.U32(t.owner.Index)
h.U32(t.owner.Gen)
for _, b := range [...]bool{t.paused, t.unscaled, t.keep, t.done, t.held, t.moved} {
h.Bool(b)
}
h.U64(t.act.Key())
}
hashFree(h, s.timers.free, s.timers.n)
h.Int(len(s.actions.s))
for i := range s.actions.s {
e := &s.actions.s[i]
h.U32(e.gen)
h.Bool(e.live)
if !e.live {
continue
}
a := &e.v
h.Bool(a.parallel)
h.Bool(a.started)
h.Bool(a.held)
h.Int(a.cur)
h.Int(a.left)
h.U32(a.owner.Index)
h.U32(a.owner.Gen)
h.U64(a.parent.Key())
h.Int(len(a.steps))
for _, st := range a.steps {
h.U64(uint64(st.kind))
h.U64(st.h.Key())
h.Bool(st.done)
}
}
hashFree(h, s.actions.free, s.actions.n)
}