From 5650343ca7e8edcaf391b4e1a7f52a9d90f60b77 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Mon, 2 Mar 2026 10:17:58 +0100 Subject: [PATCH] base: move tween.ts to c --- base/sources/iron.h | 1 + base/sources/iron_tween.c | 119 ++++++++++++++++++++ base/sources/iron_tween.h | 30 ++++++ base/sources/ts/iron.ts | 25 +++++ base/sources/ts/tween.ts | 221 -------------------------------------- 5 files changed, 175 insertions(+), 221 deletions(-) create mode 100644 base/sources/iron_tween.c create mode 100644 base/sources/iron_tween.h delete mode 100644 base/sources/ts/tween.ts diff --git a/base/sources/iron.h b/base/sources/iron.h index d3b239a1..a70e2c0d 100644 --- a/base/sources/iron.h +++ b/base/sources/iron.h @@ -206,6 +206,7 @@ string_t *iron_get_arg(i32 index) { #include "iron_math.h" #include "iron_net.h" +#include "iron_tween.h" #include "kong/dir.h" #include #include diff --git a/base/sources/iron_tween.c b/base/sources/iron_tween.c new file mode 100644 index 00000000..a1ae8654 --- /dev/null +++ b/base/sources/iron_tween.c @@ -0,0 +1,119 @@ +#include "iron_tween.h" + +#include "iron_array.h" +#include "iron_gc.h" +#include +#include + +static any_array_t *_tween_anims = NULL; +static bool _tween_registered = false; + +f32 sys_delta(void); +void sys_notify_on_update(void (*f)(void *data), void *data); + +static void _tween_register(void) { + _tween_registered = true; + _tween_anims = any_array_create(0); + gc_root(_tween_anims); + sys_notify_on_update(tween_update, NULL); +} + +tween_anim_t *tween_to(tween_anim_t *anim) { + if (!_tween_registered) { + _tween_register(); + } + if (anim->target != NULL) { + anim->_from = *anim->target; + } + any_array_push(_tween_anims, anim); + return anim; +} + +tween_anim_t *tween_timer(f32 delay, void (*done)(void *data), void *data) { + tween_anim_t *a = gc_alloc(sizeof(tween_anim_t)); + a->target = NULL; + a->to = 0.0f; + a->duration = 0.0f; + a->delay = delay; + a->ease = EASE_LINEAR; + a->done = done; + a->tick = NULL; + a->done_data = data; + a->_from = 0.0f; + a->_time = 0.0f; + return tween_to(a); +} + +void tween_stop(tween_anim_t *anim) { + array_remove(_tween_anims, anim); +} + +void tween_reset(void) { + gc_unroot(_tween_anims); + _tween_anims = any_array_create(0); + gc_root(_tween_anims); +} + +static f32 _tween_ease_linear(f32 k) { + return k; +} + +static f32 _tween_ease_expo_in(f32 k) { + return k == 0.0f ? 0.0f : powf(2.0f, 10.0f * (k - 1.0f)); +} + +static f32 _tween_ease_expo_out(f32 k) { + return k == 1.0f ? 1.0f : (1.0f - powf(2.0f, -10.0f * k)); +} + +static f32 _tween_ease(ease_t ease, f32 k) { + if (ease == EASE_LINEAR) { + return _tween_ease_linear(k); + } + if (ease == EASE_EXPO_IN) { + return _tween_ease_expo_in(k); + } + if (ease == EASE_EXPO_OUT) { + return _tween_ease_expo_out(k); + } + return 0.0f; +} + +void tween_update(void *unused) { + if (_tween_anims == NULL) { + return; + } + f32 d = sys_delta(); + i32 i = (i32)_tween_anims->length; + while (i-- > 0 && _tween_anims->length > 0) { + tween_anim_t *a = _tween_anims->buffer[i]; + + if (a->delay > 0.0f) { + a->delay -= d; + continue; + } + + a->_time += d; + if (a->_time >= a->duration) { + array_splice(_tween_anims, (uint32_t)i, 1); + i--; + if (a->done != NULL) { + a->done(a->done_data); + } + continue; + } + + f32 k = a->_time / a->duration; + if (k > 1.0f) { + k = 1.0f; + } + + if (a->target != NULL) { + *a->target = a->_from + (a->to - a->_from) * _tween_ease(a->ease, k); + } + + if (a->tick != NULL) { + a->tick(); + } + } +} diff --git a/base/sources/iron_tween.h b/base/sources/iron_tween.h new file mode 100644 index 00000000..723ffcd7 --- /dev/null +++ b/base/sources/iron_tween.h @@ -0,0 +1,30 @@ +#pragma once + +#include "iron_array.h" +#include "iron_global.h" +#include + +typedef enum { + EASE_LINEAR, + EASE_EXPO_IN, + EASE_EXPO_OUT +} ease_t; + +typedef struct tween_anim { + f32 *target; + f32 to; + f32 duration; + f32 delay; + ease_t ease; + void (*done)(void *data); + void (*tick)(void); + void *done_data; + f32 _from; + f32 _time; +} tween_anim_t; + +tween_anim_t *tween_to(tween_anim_t *anim); +tween_anim_t *tween_timer(f32 delay, void (*done)(void *data), void *data); +void tween_stop(tween_anim_t *anim); +void tween_reset(void); +void tween_update(void *unused); diff --git a/base/sources/ts/iron.ts b/base/sources/ts/iron.ts index a648c0ed..3fbf27bd 100644 --- a/base/sources/ts/iron.ts +++ b/base/sources/ts/iron.ts @@ -1042,3 +1042,28 @@ declare let const_data_skydome_vb: gpu_buffer_t; declare let const_data_skydome_ib: gpu_buffer_t; declare function const_data_create_screen_aligned_data(); declare function const_data_create_skydome_data(); + +declare enum ease_t { + LINEAR, + EXPO_IN, + EXPO_OUT, +} + +declare type tween_anim_t = { + target?: f32_ptr; + to?: f32; + duration?: f32; + delay?: f32; + ease?: ease_t; + done?: (data?: any) => void; + tick?: () => void; + done_data?: any; + _from?: f32; + _time?: f32; +}; + +declare function tween_to(anim: tween_anim_t): tween_anim_t; +declare function tween_timer(delay: f32, done: (data?: any) => void, data?: any): tween_anim_t; +declare function tween_stop(anim: tween_anim_t): void; +declare function tween_reset(): void; +declare function tween_update(unused: any): void; diff --git a/base/sources/ts/tween.ts b/base/sources/ts/tween.ts deleted file mode 100644 index 4952ec84..00000000 --- a/base/sources/ts/tween.ts +++ /dev/null @@ -1,221 +0,0 @@ - -let _tween_anims: tween_anim_t[] = []; -let _tween_registered: bool = false; - -function _tween_register() { - _tween_registered = true; - sys_notify_on_update(tween_update); -} - -function tween_to(anim: tween_anim_t): tween_anim_t { - if (!_tween_registered) { - _tween_register(); - } - let f32_target: f32_ptr = anim.target; - if (f32_target != null) { - anim._from = DEREFERENCE(f32_target); - } - array_push(_tween_anims, anim); - return anim; -} - -function tween_timer(delay: f32, done: (data: any) => void, data: any = null): tween_anim_t { - let a: tween_anim_t = {delay : delay, done : done, done_data : data}; - return tween_to(a); -} - -function tween_stop(anim: tween_anim_t) { - array_remove(_tween_anims, anim); -} - -function tween_reset() { - _tween_anims = []; -} - -function tween_update(_: any) { - let d: f32 = sys_delta(); - let i: i32 = _tween_anims.length; - while (i-- > 0 && _tween_anims.length > 0) { - let a: tween_anim_t = _tween_anims[i]; - - if (a.delay > 0) { - a.delay -= d; - continue; - } - - a._time += d; - if (a._time >= a.duration) { - array_splice(_tween_anims, i, 1); - i--; - if (a.done != null) { - a.done(a.done_data); - } - continue; - } - - let k: f32 = a._time / a.duration; - if (k > 1) { - k = 1; - } - - let f32_target: f32_ptr = a.target; - DEREFERENCE(f32_target) = a._from + (a.to - a._from) * _tween_ease(a.ease, k); - - if (a.tick != null) { - a.tick(); - } - } -} - -function _tween_ease_linear(k: f32): f32 { - return k; -} -// function _tween_ease_quad_in(k: f32): f32 { return k * k; } -// function _tween_ease_quad_out(k: f32): f32 { return -k * (k - 2); } -// function _tween_ease_quad_in_out(k: f32): f32 { return (k < 0.5) ? 2 * k * k : -2 * ((k -= 1) * k) + 1; } -function _tween_ease_expo_in(k: f32): f32 { - return k == 0 ? 0 : math_pow(2, 10 * (k - 1)); -} -function _tween_ease_expo_out(k: f32): f32 { - return k == 1 ? 1 : (1 - math_pow(2, -10 * k)); -} -// function _tween_ease_expo_in_out(k: f32): f32 { if (k == 0) { return 0; } if (k == 1) { return 1; } if ((k /= 1 / 2.0) < 1.0) { return 0.5 * math_pow(2, 10 * -// (k - 1)); } return 0.5 * (2 - math_pow(2, -10 * --k)); } function _tween_ease_bounce_in(k: f32): f32 { return 1 - _tween_ease_bounce_out(1 - k); } function -// _tween_ease_bounce_out(k: f32): f32 { if (k < (1 / 2.75)) { return 7.5625 * k * k; } else if (k < (2 / 2.75)) { return 7.5625 * (k -= (1.5 / 2.75)) * k + -// 0.75; } else if (k < (2.5 / 2.75)) { return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; } else { return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; } } -// function _tween_ease_bounce_in_out(k: f32): f32 { return (k < 0.5) ? _tween_ease_bounce_in(k * 2) * 0.5 : _tween_ease_bounce_out(k * 2 - 1) * 0.5 + 0.5; } - -// function _tween_ease_elastic_in(k: f32): f32 { -// let s: f32; -// let a: f32 = 0.1; -// let p: f32 = 0.4; -// if (k == 0) { -// return 0; -// } -// if (k == 1) { -// return 1; -// } -// if (a < 1) { -// a = 1; -// s = p / 4; -// } -// else { -// s = p * math_asin(1 / a) / (2 * math_pi()); -// } -// return -(a * math_pow(2, 10 * (k -= 1)) * math_sin((k - s) * (2 * math_pi()) / p)); -// } - -// function _tween_ease_elastic_out(k: f32): f32 { -// let s: f32; -// let a: f32 = 0.1; -// let p: f32 = 0.4; -// if (k == 0) { -// return 0; -// } -// if (k == 1) { -// return 1; -// } -// if (a < 1) { -// a = 1; -// s = p / 4; -// } -// else { -// s = p * math_asin(1 / a) / (2 * math_pi()); -// } -// return (a * math_pow(2, -10 * k) * math_sin((k - s) * (2 * math_pi()) / p) + 1); -// } - -// function _tween_ease_elastic_in_out(k: f32): f32 { -// let s: i32; -// let a: f32 = 0.1; -// let p: f32 = 0.4; -// if (k == 0) { -// return 0; -// } -// if (k == 1) { -// return 1; -// } -// if (a != 0 || a < 1) { -// a = 1; -// s = p / 4; -// } -// else { -// s = p * math_asin(1 / a) / (2 * math_pi()); -// } -// if ((k *= 2) < 1) { -// return - 0.5 * (a * math_pow(2, 10 * (k -= 1)) * math_sin((k - s) * (2 * math_pi()) / p)); -// } -// return a * math_pow(2, -10 * (k -= 1)) * math_sin((k - s) * (2 * math_pi()) / p) * 0.5 + 1; -// } - -function _tween_ease(ease: ease_t, k: f32): f32 { - if (ease == ease_t.LINEAR) { - return _tween_ease_linear(k); - } - if (ease == ease_t.QUAD_IN) { - // return _tween_ease_quad_in(k); - } - if (ease == ease_t.QUAD_OUT) { - // return _tween_ease_quad_out(k); - } - if (ease == ease_t.QUAD_IN_OUT) { - // return _tween_ease_quad_in_out(k); - } - if (ease == ease_t.EXPO_IN) { - return _tween_ease_expo_in(k); - } - if (ease == ease_t.EXPO_OUT) { - return _tween_ease_expo_out(k); - } - if (ease == ease_t.EXPO_IN_OUT) { - // return _tween_ease_expo_in_out(k); - } - if (ease == ease_t.BOUNCE_IN) { - // return _tween_ease_bounce_in(k); - } - if (ease == ease_t.BOUNCE_OUT) { - // return _tween_ease_bounce_out(k); - } - if (ease == ease_t.BOUNCE_IN_OUT) { - // return _tween_ease_bounce_in_out(k); - } - if (ease == ease_t.ELASTIC_IN) { - // return _tween_ease_elastic_in(k); - } - if (ease == ease_t.ELASTIC_OUT) { - // return _tween_ease_elastic_out(k); - } - if (ease == ease_t.ELASTIC_IN_OUT) { - // return _tween_ease_elastic_in_out(k); - } - return 0.0; -} - -type tween_anim_t = { - target?: any; - to?: f32; - duration?: f32; - delay?: f32; - ease?: ease_t; - done?: (data?: any) => void; - tick?: () => void; - done_data?: any; - _from?: f32; - _time?: f32; -}; - -enum ease_t { - LINEAR, - QUAD_IN, - QUAD_OUT, - QUAD_IN_OUT, - EXPO_IN, - EXPO_OUT, - EXPO_IN_OUT, - BOUNCE_IN, - BOUNCE_OUT, - BOUNCE_IN_OUT, - ELASTIC_IN, - ELASTIC_OUT, - ELASTIC_IN_OUT, -}