nightshade 0.13.2

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::sprite_animator::components::LoopMode;
use crate::ecs::world::{SPRITE, SPRITE_ANIMATOR, World};

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

    let entities: Vec<_> = world
        .sprite2d
        .query_entities(SPRITE_ANIMATOR | SPRITE)
        .collect();

    for entity in entities {
        let (uv_min, uv_max, texture_index) = {
            let Some(animator) = world.sprite2d.get_sprite_animator_mut(entity) else {
                continue;
            };

            if !animator.playing || animator.frames.is_empty() {
                continue;
            }

            animator.elapsed += delta_time * animator.speed;

            let frame_duration = animator.frames[animator.current_frame].duration;
            if animator.elapsed >= frame_duration {
                animator.elapsed -= frame_duration;

                match animator.loop_mode {
                    LoopMode::Once => {
                        if animator.current_frame + 1 < animator.frames.len() {
                            animator.current_frame += 1;
                        } else {
                            animator.playing = false;
                        }
                    }
                    LoopMode::Loop => {
                        animator.current_frame =
                            (animator.current_frame + 1) % animator.frames.len();
                    }
                    LoopMode::PingPong => {
                        if animator.ping_pong_forward {
                            if animator.current_frame + 1 < animator.frames.len() {
                                animator.current_frame += 1;
                            } else {
                                animator.ping_pong_forward = false;
                                if animator.current_frame > 0 {
                                    animator.current_frame -= 1;
                                }
                            }
                        } else if animator.current_frame > 0 {
                            animator.current_frame -= 1;
                        } else {
                            animator.ping_pong_forward = true;
                            animator.current_frame += 1;
                        }
                    }
                }
            }

            let frame = &animator.frames[animator.current_frame];
            (frame.uv_min, frame.uv_max, frame.texture_index)
        };

        if let Some(sprite) = world.sprite2d.get_sprite_mut(entity) {
            sprite.uv_min = uv_min;
            sprite.uv_max = uv_max;
            if let Some(texture_index) = texture_index {
                sprite.texture_index = texture_index;
                sprite.texture_index2 = texture_index;
            }
        }
    }
}