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

228 lines
5.8 KiB
TypeScript

///if arm_anim
type anim_object_t = {
base?: anim_raw_t;
object?: object_t;
oactions?: scene_t[];
oaction?: obj_t;
};
function anim_object_create(object: object_t, oactions: scene_t[]): anim_object_t {
let raw: anim_object_t = {};
raw.base = anim_create();
raw.base.ext = raw;
raw.base.ext_type = "anim_object_t";
raw.object = object;
raw.oactions = oactions;
anim_object_play(raw);
return raw;
}
function anim_object_get_action(raw: anim_object_t, action: string): obj_t {
for (let i: i32 = 0; i < raw.oactions.length; ++i) {
let a: scene_t = raw.oactions[i];
if (a != null && a.objects[0].name == action) {
return a.objects[0];
}
}
return null;
}
function anim_object_update_object_anim(raw: anim_object_t) {
anim_object_update_transform_anim(raw, raw.oaction.anim, raw.object.transform);
transform_build_matrix(raw.object.transform);
}
function anim_object_interpolate_linear(t: f32, t1: f32, t2: f32, v1: f32, v2: f32): f32 {
let s: f32 = (t - t1) / (t2 - t1);
return (1.0 - s) * v1 + s * v2;
}
function anim_object_check_frame_index_t(raw: anim_object_t, frame_values: u32_array_t, t: f32): bool {
return raw.base.speed > 0 ?
raw.base.frame_index < frame_values.length - 2 && t > frame_values[raw.base.frame_index + 1] * raw.base.frame_time :
raw.base.frame_index > 1 && t > frame_values[raw.base.frame_index - 1] * raw.base.frame_time;
}
function anim_object_update_transform_anim(raw: anim_object_t, anim: anim_t, transform: transform_t) {
if (anim == null) {
return;
}
let total: i32 = anim.end * raw.base.frame_time - anim.begin * raw.base.frame_time;
if (anim.has_delta) {
let t: transform_t = transform;
if (vec4_isnan(t.dloc)) {
t.dloc = vec4_create();
t.drot = quat_create();
t.dscale = vec4_create();
}
t.dloc = vec4_create(0, 0, 0);
t.dscale = vec4_create(0, 0, 0);
t._deuler_x = t._deuler_y = t._deuler_z = 0.0;
}
for (let i: i32 = 0; i < anim.tracks.length; ++i) {
let track: track_t = anim.tracks[i];
if (raw.base.frame_index == -1) {
anim_rewind(raw.base, track);
}
let sign: i32 = raw.base.speed > 0 ? 1 : -1;
// End of current time range
let t: f32 = raw.base.time + anim.begin * raw.base.frame_time;
while (anim_object_check_frame_index_t(raw, track.frames, t)) {
raw.base.frame_index += sign;
}
// No data for raw track at current time
if (raw.base.frame_index >= track.frames.length) {
continue;
}
// End of track
if (raw.base.time > total) {
if (raw.base.on_complete != null) {
raw.base.on_complete();
}
if (raw.base.loop) {
anim_rewind(raw.base, track);
}
else {
raw.base.frame_index -= sign;
raw.base.paused = true;
}
return;
}
let ti: i32 = raw.base.frame_index;
let t1: f32 = track.frames[ti] * raw.base.frame_time;
let t2: f32 = track.frames[ti + sign] * raw.base.frame_time;
let v1: f32 = track.values[ti];
let v2: f32 = track.values[ti + sign];
let value: f32 = anim_object_interpolate_linear(t, t1, t2, v1, v2);
let target: string = track.target;
if (target == "xloc") {
transform.loc.x = value;
}
else if (target == "yloc") {
transform.loc.y = value;
}
else if (target == "zloc") {
transform.loc.z = value;
}
else if (target == "xrot") {
transform_set_rot(transform, value, transform._euler_y, transform._euler_z);
}
else if (target == "yrot") {
transform_set_rot(transform, transform._euler_x, value, transform._euler_z);
}
else if (target == "zrot") {
transform_set_rot(transform, transform._euler_x, transform._euler_y, value);
}
else if (target == "qwrot") {
transform.rot.w = value;
}
else if (target == "qxrot") {
transform.rot.x = value;
}
else if (target == "qyrot") {
transform.rot.y = value;
}
else if (target == "qzrot") {
transform.rot.z = value;
}
else if (target == "xscl") {
transform.scale.x = value;
}
else if (target == "yscl") {
transform.scale.y = value;
}
else if (target == "zscl") {
transform.scale.z = value;
}
// Delta
else if (target == "dxloc") {
transform.dloc.x = value;
}
else if (target == "dyloc") {
transform.dloc.y = value;
}
else if (target == "dzloc") {
transform.dloc.z = value;
}
else if (target == "dxrot") {
transform._deuler_x = value;
}
else if (target == "dyrot") {
transform._deuler_y = value;
}
else if (target == "dzrot") {
transform._deuler_z = value;
}
else if (target == "dqwrot") {
transform.drot.w = value;
}
else if (target == "dqxrot") {
transform.drot.x = value;
}
else if (target == "dqyrot") {
transform.drot.y = value;
}
else if (target == "dqzrot") {
transform.drot.z = value;
}
else if (target == "dxscl") {
transform.dscale.x = value;
}
else if (target == "dyscl") {
transform.dscale.y = value;
}
else if (target == "dzscl") {
transform.dscale.z = value;
}
}
}
function anim_object_play(raw: anim_object_t, action: string = "", on_complete: ()=>void = null, blend_time: f32 = 0.0, speed: f32 = 1.0, loop: bool = true) {
anim_play_super(raw.base, action, on_complete, blend_time, speed, loop);
if (raw.base.action == "" && raw.oactions[0] != null) {
raw.base.action = raw.oactions[0].objects[0].name;
}
raw.oaction = anim_object_get_action(raw, raw.base.action);
}
function anim_object_update(raw: anim_object_t, delta: f32) {
if (!raw.object.visible || raw.object.culled || raw.oaction == null) {
return;
}
anim_update_super(raw.base, delta);
if (raw.base.paused) {
return;
}
anim_object_update_object_anim(raw);
}
function anim_object_is_track_end(raw: anim_object_t, track: track_t): bool {
return raw.base.speed > 0 ?
raw.base.frame_index >= track.frames.length - 2 :
raw.base.frame_index <= 0;
}
function anim_object_total_frames(raw: anim_object_t): i32 {
if (raw.oaction == null || raw.oaction.anim == null) {
return 0;
}
return raw.oaction.anim.end - raw.oaction.anim.begin;
}
///end