ludic.anim: animset_choice names the playing choice's clip as the set does, animset_can says whether the rig carries any of a state's clips (a one-shot with none is not asked for)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a22b8a572b
commit
a87f20c66e
6 changed files with 35 additions and 3 deletions
|
|
@ -68,7 +68,9 @@ and transitions (from a state or `"*"`, with a fade; with `@frame when: fn() ->
|
||||||
own the frame it answers true). The code binds an `AnimPlayer` to a set and a rig
|
own the frame it answers true). The code binds an `AnimPlayer` to a set and a rig
|
||||||
(`animset_bind`), sets parameters (`animset_param`), asks for a state (`animset_request`, taken once
|
(`animset_bind`), sets parameters (`animset_param`), asks for a state (`animset_request`, taken once
|
||||||
however often it is asked) and ticks it into a skin (`animset_tick`). A one-shot (`loop: false`)
|
however often it is asked) and ticks it into a skin (`animset_tick`). A one-shot (`loop: false`)
|
||||||
holds its last pose and hands on to `next`. Clip names are made once per rig; a tick makes nothing.
|
holds its last pose and hands on to `next`. `animset_choice` names the playing choice's clip as the set
|
||||||
|
does ("sit_seat", no rig), and `animset_can(key)` says whether the rig carries any of a state's clips, so a
|
||||||
|
one-shot with none yet is not asked for. Clip names are made once per rig; a tick makes nothing.
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@ export function animset_request(pl: AnimPlayer, key: string) -> void {
|
||||||
pl.want = i
|
pl.want = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# the state is in the set and the rig carries one of its clips: a one-shot with none is not asked for
|
||||||
|
export function animset_can(pl: AnimPlayer, key: string) -> bool {
|
||||||
|
if pl.set < 0 or pl.clips == null { return false }
|
||||||
|
let i = as_state(AnimSets[pl.set], key)
|
||||||
|
if i < 0 { return false }
|
||||||
|
let d = AnimSets[pl.set].states[i]
|
||||||
|
if d.choices == null { return false }
|
||||||
|
for c in 0 .. len(d.choices) { if pl.clips[pl.base[i] + c] != null { return true } }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
function as_param_at(pl: AnimPlayer, name: string) -> int {
|
function as_param_at(pl: AnimPlayer, name: string) -> int {
|
||||||
if pl.set < 0 { return -1 }
|
if pl.set < 0 { return -1 }
|
||||||
let s = AnimSets[pl.set]
|
let s = AnimSets[pl.set]
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,16 @@ export property AnimPlayer {
|
||||||
mix: float = 1.0
|
mix: float = 1.0
|
||||||
fade: float = 0.2
|
fade: float = 0.2
|
||||||
rate: float = 1.0
|
rate: float = 1.0
|
||||||
|
pick: int = -1 # which of the state's choices plays
|
||||||
}
|
}
|
||||||
|
|
||||||
export function animset_clip(pl: AnimPlayer) -> Clip { return pl.clip }
|
export function animset_clip(pl: AnimPlayer) -> Clip { return pl.clip }
|
||||||
export function animset_time(pl: AnimPlayer) -> float { return pl.t }
|
export function animset_time(pl: AnimPlayer) -> float { return pl.t }
|
||||||
export function animset_rate(pl: AnimPlayer) -> float { return pl.rate }
|
export function animset_rate(pl: AnimPlayer) -> float { return pl.rate }
|
||||||
|
# the playing choice's clip as the set names it, without the rig ("sit_seat"); "" before a tick
|
||||||
|
export function animset_choice(pl: AnimPlayer) -> string {
|
||||||
|
if pl.set < 0 or pl.pick < 0 { return "" }
|
||||||
|
return AnimSets[pl.set].states[pl.state].choices[pl.pick].clip
|
||||||
|
}
|
||||||
export function animset_ready(pl: AnimPlayer) -> bool { return pl.ready }
|
export function animset_ready(pl: AnimPlayer) -> bool { return pl.ready }
|
||||||
export function animset_bound(pl: AnimPlayer, set: int, rig: string) -> bool { return pl.set == set and pl.rig == rig and pl.names != null }
|
export function animset_bound(pl: AnimPlayer, set: int, rig: string) -> bool { return pl.set == set and pl.rig == rig and pl.names != null }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export function animset_tick(anim_st: mut AnimState, pl: AnimPlayer, sk: Skin, d
|
||||||
let d = AnimSets[pl.set].states[pl.state]
|
let d = AnimSets[pl.set].states[pl.state]
|
||||||
let k = as_pick(pl, d)
|
let k = as_pick(pl, d)
|
||||||
if k < 0 { return false }
|
if k < 0 { return false }
|
||||||
|
pl.pick = k
|
||||||
pl.rate = as_rate(pl, d, d.choices[k])
|
pl.rate = as_rate(pl, d, d.choices[k])
|
||||||
as_switch(pl, d, pl.clips[pl.base[pl.state] + k])
|
as_switch(pl, d, pl.clips[pl.base[pl.state] + k])
|
||||||
let adv = dt * pl.rate
|
let adv = dt * pl.rate
|
||||||
|
|
|
||||||
|
|
@ -113,4 +113,15 @@ program AnimSetTest {
|
||||||
}
|
}
|
||||||
expect(playing(pl) == "rig_idle")
|
expect(playing(pl) == "rig_idle")
|
||||||
}
|
}
|
||||||
|
test "the playing choice is named as the set names it; a state the rig has no clip for cannot be asked" (anim_st: mut AnimState, render3d_st: mut Render3dState) {
|
||||||
|
let sk = skin(render3d_st)
|
||||||
|
let pl = rig(anim_st)
|
||||||
|
expect(animset_choice(pl) == "")
|
||||||
|
animset_param(pl, "speed", 1.0)
|
||||||
|
animset_tick(anim_st, pl, sk, 0.016)
|
||||||
|
expect(animset_choice(pl) == "walk")
|
||||||
|
expect(animset_can(pl, "wave"))
|
||||||
|
expect(not animset_can(pl, "bow"))
|
||||||
|
expect(not animset_can(pl, "nope"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# sets.lres - the test's one set: a ground state picking by speed bands, a one-shot that hands back,
|
# sets.lres - the test's one set: a ground state picking by speed bands, a one-shot that hands back,
|
||||||
# and a hop the code never asks for, taken when toy_hops says so
|
# a hop the code never asks for, taken when toy_hops says so, and a bow no rig carries
|
||||||
toy {
|
toy {
|
||||||
entry: "ground"
|
entry: "ground"
|
||||||
params: ["speed"]
|
params: ["speed"]
|
||||||
|
|
@ -14,7 +14,8 @@ toy {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ key: "wave", loop: false, next: "ground", choices: [{ clip: "wave" }] },
|
{ key: "wave", loop: false, next: "ground", choices: [{ clip: "wave" }] },
|
||||||
{ key: "hop", choices: [{ clip: "hop" }] }
|
{ key: "hop", choices: [{ clip: "hop" }] },
|
||||||
|
{ key: "bow", loop: false, next: "ground", choices: [{ clip: "bow" }] }
|
||||||
]
|
]
|
||||||
transitions: [{ from: "ground", to: "hop", blend: 0.1, when: fn toy_hops }]
|
transitions: [{ from: "ground", to: "hop", blend: 0.1, when: fn toy_hops }]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue