nightshade 0.13.3

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::tween::components::{TweenLoopMode, TweenState, TweenValue};
use crate::ecs::world::{TWEEN, World};

pub fn tween_system(world: &mut World) {
    let delta_time = world.resources.window.timing.delta_time;

    let entities: Vec<_> = world.core.query_entities(TWEEN).collect();

    for entity in entities {
        let Some(tween) = world.core.get_tween_mut(entity) else {
            continue;
        };

        for track in &mut tween.tracks {
            if track.state != TweenState::Playing {
                continue;
            }

            if track.delay_remaining > 0.0 {
                track.delay_remaining -= delta_time * track.speed;
                if track.delay_remaining > 0.0 {
                    continue;
                }
                track.delay_remaining = 0.0;
            }

            track.elapsed += delta_time * track.speed;

            if track.elapsed >= track.duration {
                match track.loop_mode {
                    TweenLoopMode::Once => {
                        track.elapsed = track.duration;
                        track.state = TweenState::Completed;
                    }
                    TweenLoopMode::Loop => {
                        track.elapsed -= track.duration;
                    }
                    TweenLoopMode::PingPong => {
                        track.elapsed -= track.duration;
                        track.ping_pong_forward = !track.ping_pong_forward;
                    }
                }
            }

            let raw_progress = if track.duration > 0.0 {
                (track.elapsed / track.duration).clamp(0.0, 1.0)
            } else {
                1.0
            };

            let directed_progress = if track.ping_pong_forward {
                raw_progress
            } else {
                1.0 - raw_progress
            };

            let eased = track.easing.evaluate(directed_progress);
            track.current = TweenValue::lerp(&track.from, &track.to, eased);
        }
    }
}