Files
armorpaint/base/sources/ts/iron/anim.ts
T
luboslenco 3b3269f033 Cleanup
2025-08-11 23:08:58 +02:00

257 lines
6.5 KiB
TypeScript

///if arm_anim
type anim_raw_t = {
ext?: any; // anim_object_t
ext_type?: string;
action?: string;
time?: f32;
speed?: f32;
loop?: bool;
frame_index?: i32;
on_complete?: ()=>void;
paused?: bool;
frame_time?: f32;
blend_time?: f32;
blend_current?: f32;
blend_action?: string;
blend_factor?: f32;
last_frame_index?: i32;
marker_events?: map_t<string, (()=>void)[]>;
};
// Lerp
let _anim_m1: mat4_t = mat4_identity();
let _anim_m2: mat4_t = mat4_identity();
let _anim_vpos: vec4_t = vec4_create();
let _anim_vpos2: vec4_t = vec4_create();
let _anim_vscale: vec4_t = vec4_create();
let _anim_vscale2: vec4_t = vec4_create();
let _anim_q1: quat_t = quat_create();
let _anim_q2: quat_t = quat_create();
let _anim_q3: quat_t = quat_create();
let _anim_vp: vec4_t = vec4_create();
let _anim_vs: vec4_t = vec4_create();
function anim_create(): anim_raw_t {
let raw: anim_raw_t = {};
raw.action = "";
raw.time = 0.0;
raw.speed = 1.0;
raw.loop = true;
raw.frame_index = 0;
raw.paused = false;
raw.frame_time = 1 / 60;
raw.blend_time = 0.0;
raw.blend_current = 0.0;
raw.blend_action = "";
raw.blend_factor = 0.0;
raw.last_frame_index = -1;
array_push(scene_animations, raw);
return raw;
}
function anim_play_super(raw: anim_raw_t, action: string = "", on_complete: ()=>void = null, blend_time: f32 = 0.0, speed: f32 = 1.0, loop: bool = true) {
if (blend_time > 0) {
raw.blend_time = blend_time;
raw.blend_current = 0.0;
raw.blend_action = raw.action;
raw.frame_index = 0;
raw.time = 0.0;
}
else {
raw.frame_index = -1;
}
raw.action = action;
raw.on_complete = on_complete;
raw.speed = speed;
raw.loop = loop;
raw.paused = false;
}
function anim_play(raw: anim_raw_t, action: string = "", on_complete: ()=>void = null, blend_time: f32 = 0.0, speed: f32 = 1.0, loop: bool = true) {
if (raw.ext_type == "anim_object_t") {
anim_object_play(raw.ext, action, on_complete, blend_time, speed, loop);
}
else {
anim_play_super(raw, action, on_complete, blend_time, speed, loop);
}
}
function anim_blend_super(raw: anim_raw_t, action1: string, action2: string, factor: f32) {
raw.blend_time = 1.0; // Enable blending
raw.blend_factor = factor;
}
function anim_blend(raw: anim_raw_t, action1: string, action2: string, factor: f32) {
if (raw.ext != null) {
}
else {
anim_blend_super(raw, action1, action2, factor);
}
}
function anim_pause(raw: anim_raw_t) {
raw.paused = true;
}
function anim_resume(raw: anim_raw_t) {
raw.paused = false;
}
function anim_remove(raw: anim_raw_t) {
array_remove(scene_animations, raw);
}
function anim_update_super(raw: anim_raw_t, delta: f32) {
if (raw.paused || raw.speed == 0.0) {
return;
}
raw.time += delta * raw.speed;
if (raw.blend_time > 0 && raw.blend_factor == 0) {
raw.blend_current += delta;
if (raw.blend_current >= raw.blend_time) {
raw.blend_time = 0.0;
}
}
}
function anim_update(raw: anim_raw_t, delta: f32) {
if (raw.ext_type == "anim_object_t") {
anim_object_update(raw.ext, delta);
}
else {
anim_update_super(raw, delta);
}
}
function anim_is_track_end(raw: anim_raw_t, track: track_t): bool {
return raw.speed > 0 ?
raw.frame_index >= track.frames.length - 1 :
raw.frame_index <= 0;
}
function anim_check_frame_index(raw: anim_raw_t, frame_values: u32_array_t): bool {
return raw.speed > 0 ?
((raw.frame_index + 1) < frame_values.length && raw.time > frame_values[raw.frame_index + 1] * raw.frame_time) :
((raw.frame_index - 1) > -1 && raw.time < frame_values[raw.frame_index - 1] * raw.frame_time);
}
function anim_rewind(raw: anim_raw_t, track: track_t) {
raw.frame_index = raw.speed > 0 ? 0 : track.frames.length - 1;
raw.time = track.frames[raw.frame_index] * raw.frame_time;
}
function anim_update_track(raw: anim_raw_t, anim: anim_t) {
if (anim == null) {
return;
}
let track: track_t = anim.tracks[0];
if (raw.frame_index == -1) {
anim_rewind(raw, track);
}
// Move keyframe
let sign: i32 = raw.speed > 0 ? 1 : -1;
while (anim_check_frame_index(raw, track.frames)) {
raw.frame_index += sign;
}
// Marker events
// if (raw.marker_events != null && anim.marker_names != null && raw.frame_index != raw.last_frame_index) {
// for (let i: i32 = 0; i < anim.marker_frames.length; ++i) {
// if (raw.frame_index == anim.marker_frames[i]) {
// let ar: (()=>void)[] = map_get(raw.marker_events, anim.marker_names[i]);
// if (ar != null) {
// for (let i: i32 = 0; i < ar.length; ++i) {
// ar[i]();
// }
// }
// }
// }
// raw.last_frame_index = raw.frame_index;
// }
// End of track
if (anim_is_track_end(raw, track)) {
if (raw.loop || raw.blend_time > 0) {
anim_rewind(raw, track);
}
else {
raw.frame_index -= sign;
raw.paused = true;
}
if (raw.on_complete != null && raw.blend_time == 0) {
raw.on_complete();
}
}
}
function anim_update_anim_sampled(raw: anim_raw_t, anim: anim_t, m: mat4_t) {
if (anim == null) {
return;
}
let track: track_t = anim.tracks[0];
let sign: i32 = raw.speed > 0 ? 1 : -1;
let t: i32 = raw.time;
let ti: i32 = raw.frame_index;
let t1: f32 = track.frames[ti] * raw.frame_time;
let t2: f32 = track.frames[ti + sign] * raw.frame_time;
let s: f32 = (t - t1) / (t2 - t1); // Linear
_anim_m1 = mat4_from_f32_array(track.values, ti * 16); // Offset to 4x4 matrix array
_anim_m2 = mat4_from_f32_array(track.values, (ti + sign) * 16);
// Decompose
mat4_decompose(_anim_m1, _anim_vpos, _anim_q1, _anim_vscale);
mat4_decompose(_anim_m2, _anim_vpos2, _anim_q2, _anim_vscale2);
// Lerp
_anim_vp = vec4_lerp(_anim_vpos, _anim_vpos2, s);
_anim_vs = vec4_lerp(_anim_vscale, _anim_vscale2, s);
_anim_q3 = quat_lerp(_anim_q1, _anim_q2, s);
// Compose
m = mat4_from_quat(_anim_q3);
m = mat4_scale(m, _anim_vs);
m.m30 = _anim_vp.x;
m.m31 = _anim_vp.y;
m.m32 = _anim_vp.z;
}
function anim_set_frame(raw: anim_raw_t, frame: i32) {
raw.time = 0;
raw.frame_index = frame;
anim_update(raw, frame * raw.frame_time);
}
function anim_notify_on_marker(raw: anim_raw_t, name: string, on_marker: ()=>void) {
// if (raw.marker_events == null) {
// raw.marker_events = map_create();
// }
// let ar: (()=>void)[] = map_get(raw.marker_events, name);
// if (ar == null) {
// ar = [];
// map_set(raw.marker_events, name, ar);
// }
// array_push(ar, on_marker);
}
function anim_remove_marker(raw: anim_raw_t, name: string, on_marker: ()=>void) {
array_remove(map_get(raw.marker_events, name), on_marker);
}
function anim_current_frame(raw: anim_raw_t): i32 {
return math_floor(raw.time / raw.frame_time);
}
function anim_total_frames(raw: anim_raw_t): i32 {
return 0;
}
///end