///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_tvoid)[]>; }; // 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