# 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) }