81 lines
2.8 KiB
Text
81 lines
2.8 KiB
Text
# set_pick.ludic - the code's side: a parameter set, a state asked for; and the choice a state
|
|
# makes from them. Nothing here makes anything: it runs every frame.
|
|
export function animset_param(pl: AnimPlayer, name: string, v: float) -> void {
|
|
let i = as_param_at(pl, name)
|
|
if i >= 0 { pl.vals[i] = v }
|
|
}
|
|
|
|
# a state by name, taken once: the code may ask every frame, and a `when` edge that moved the
|
|
# player on since is not undone by the same request again
|
|
export function animset_request(pl: AnimPlayer, key: string) -> void {
|
|
if pl.set < 0 or key == pl.asked { return }
|
|
let i = as_state(AnimSets[pl.set], key)
|
|
if i < 0 { return }
|
|
let v = as_via(pl, key)
|
|
pl.asked = key
|
|
pl.want = i
|
|
if v >= 0 { pl.want = v }
|
|
}
|
|
|
|
# the one-shot a request goes by: a `via` edge from where the code last asked (or "*") to this state,
|
|
# whose clip the rig carries; -1 for none
|
|
function as_via(pl: AnimPlayer, key: string) -> int {
|
|
let s = AnimSets[pl.set]
|
|
if s.transitions == null { return -1 }
|
|
for i in 0 .. len(s.transitions) {
|
|
let tr = s.transitions[i]
|
|
if tr.via != "" and tr.to == key and (tr.from == "*" or tr.from == pl.asked) and animset_can(pl, tr.via) { return as_state(s, tr.via) }
|
|
}
|
|
return -1
|
|
}
|
|
|
|
# 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 {
|
|
if pl.set < 0 { return -1 }
|
|
let s = AnimSets[pl.set]
|
|
if s.params == null { return -1 }
|
|
for i in 0 .. len(s.params) { if s.params[i] == name { return i } }
|
|
return -1
|
|
}
|
|
|
|
function as_value(pl: AnimPlayer, name: string) -> float {
|
|
let i = as_param_at(pl, name)
|
|
if i < 0 { return 0.0 }
|
|
return pl.vals[i]
|
|
}
|
|
|
|
function as_holds(pl: AnimPlayer, c: AnimChoice) -> bool {
|
|
if c.need == null { return true }
|
|
for k in 0 .. len(c.need) {
|
|
let n = c.need[k]
|
|
let v = as_value(pl, n.param)
|
|
if not (v > n.over and v < n.under) { return false }
|
|
}
|
|
return true
|
|
}
|
|
|
|
# the state's first choice that holds and whose clip the rig has; -1 none
|
|
function as_pick(pl: AnimPlayer, d: AnimStateDef) -> int {
|
|
if d.choices == null { return -1 }
|
|
let b = pl.base[pl.state]
|
|
for c in 0 .. len(d.choices) {
|
|
if pl.clips[b + c] != null and as_holds(pl, d.choices[c]) { return c }
|
|
}
|
|
return -1
|
|
}
|
|
|
|
function as_rate(pl: AnimPlayer, d: AnimStateDef, c: AnimChoice) -> float {
|
|
var r = c.rate
|
|
if c.rate_by != "" and c.ground > 0.0 { r = as_value(pl, c.rate_by) / c.ground }
|
|
return Math.clamp(r, d.rate_min, d.rate_max)
|
|
}
|