53 lines
2 KiB
Text
53 lines
2 KiB
Text
# set_tick.ludic - a frame of a player: follow the graph, pick the clip, cross-fade on a change,
|
|
# advance both clips by the same step and play them into the skin (ludic.anim)
|
|
export function animset_tick(anim_st: mut AnimState, pl: AnimPlayer, sk: Skin, dt: float) -> bool {
|
|
if not pl.ready or sk == null { return false }
|
|
as_follow(pl)
|
|
let d = AnimSets[pl.set].states[pl.state]
|
|
let k = as_pick(pl, d)
|
|
if k < 0 { return false }
|
|
pl.pick = k
|
|
pl.rate = as_rate(pl, d, d.choices[k])
|
|
as_switch(pl, d, pl.clips[pl.base[pl.state] + k])
|
|
let adv = dt * pl.rate
|
|
pl.t = pl.t + adv
|
|
pl.pt = pl.pt + adv
|
|
as_one_shot(pl, d)
|
|
if pl.mix < 1.0 { pl.mix = Math.min(1.0, pl.mix + dt / pl.fade) }
|
|
# anim_play blends TOWARD its second clip, so the weight is how much of the old one is left
|
|
return anim_play(anim_st, sk, pl.clip, pl.t, pl.prev, pl.pt, 1.0 - pl.mix)
|
|
}
|
|
|
|
# a new clip fades in from the old one. Within a state it carries the PHASE across: two leg cycles
|
|
# restarted at zero put the far leg forward for the length of the fade, which reads as a stumble.
|
|
function as_switch(pl: AnimPlayer, d: AnimStateDef, want: Clip) -> void {
|
|
var fade = d.blend
|
|
if pl.fade_next > 0.0 { fade = pl.fade_next }
|
|
pl.fade_next = -1.0
|
|
if pl.clip == null {
|
|
pl.clip = want
|
|
pl.t = 0.0
|
|
pl.prev = null
|
|
pl.mix = 1.0
|
|
return
|
|
}
|
|
if want == pl.clip { return }
|
|
var ph = 0.0
|
|
if d.keep_phase and not pl.fresh and pl.clip.dur > 0.0 { ph = pl.t % pl.clip.dur / pl.clip.dur }
|
|
pl.prev = pl.clip
|
|
pl.pt = pl.t
|
|
pl.clip = want
|
|
pl.t = ph * want.dur
|
|
pl.fade = fade
|
|
pl.mix = 0.0
|
|
if not (fade > 0.0) { pl.mix = 1.0 }
|
|
}
|
|
|
|
# a clip that does not loop holds its last pose, and hands over to its `next` state when played
|
|
function as_one_shot(pl: AnimPlayer, d: AnimStateDef) -> void {
|
|
if d.loop or pl.clip.dur <= 0.0 or pl.t < pl.clip.dur { return }
|
|
pl.t = pl.clip.dur * 0.999
|
|
if d.next == "" { return }
|
|
let i = as_state(AnimSets[pl.set], d.next)
|
|
if i >= 0 { pl.want = i }
|
|
}
|