diff --git a/core/math/ease/ease.odin b/core/math/ease/ease.odin index 0fe59f9d2..f4310b639 100644 --- a/core/math/ease/ease.odin +++ b/core/math/ease/ease.odin @@ -1,3 +1,4 @@ +// easing procedures and flux easing used for animations package ease import "core:math" @@ -335,9 +336,8 @@ Flux_Tween :: struct($T: typeid) { diff: T, goal: T, - // using ticks for timing instead - delay_tick_start: time.Tick, - delay: time.Duration, + delay: f64, // in seconds + delay_delta: f64, duration: time.Duration, progress: f64, @@ -379,7 +379,7 @@ flux_to :: proc( goal: f32, type: Ease = .Quadratic_Out, duration: time.Duration = time.Second, - delay: time.Duration = 0, + delay: f64 = 0, ) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) { if res, ok := &flux.values[value]; ok { tween = res @@ -393,7 +393,6 @@ flux_to :: proc( goal = goal, duration = duration, delay = delay, - delay_tick_start = time.tick_now(), type = type, data = value, } @@ -416,17 +415,24 @@ flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where i // deletes tween from the map after completion flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) { size := len(flux.values) - now := time.tick_now() + dt := dt for key, tween in &flux.values { - if tween.delay != 0 { - diff := time.tick_diff(tween.delay_tick_start, now) + delay_remainder := f64(0) - // when diff reached delay, stop delaying - if diff > tween.delay { + if tween.delay > 0 { + // Update delay + tween.delay -= dt + + if tween.delay < 0 { + // We finished the delay, but in doing so consumed part of this frame's `dt` budget. + // Keep track of it so we can apply it to this tween without affecting others. + delay_remainder = tween.delay + // We're done with this delay. tween.delay = 0 } } else { + // We either had no delay, or the delay has been consumed. if !tween.inited { flux_tween_init(&tween, tween.duration) @@ -435,7 +441,10 @@ flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float } } - tween.progress += tween.rate * dt + // If part of the `dt` budget was consumed this frame, then `delay_remainder` will be + // that remainder, a negative value. Adding it to `dt` applies what's left of the `dt` + // to the tween so it advances properly, instead of too much or little. + tween.progress += tween.rate * (dt + delay_remainder) x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress) tween.value^ = tween.start + tween.diff * T(x) @@ -463,4 +472,14 @@ flux_stop :: proc(flux: ^Flux_Map($T), key: ^f32) -> bool where intrinsics.type_ } return false +} + +// returns the amount of time left for the tween animation, if the key exists in the map +// returns 0 if the tween doesnt exist on the map +flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 { + if tween, ok := flux.values[key]; ok { + return ((1 - tween.progress) * tween.rate) + tween.delay + } else { + return 0 + } } \ No newline at end of file