bevy_hui 0.7.0

pseudo Html templating ui crate for the bevy-engine.
Documentation
use bevy::{math::UVec2, prelude::{Component, ImageNode, Query, Res}, reflect::Reflect, time::{Time, Timer}};

use crate::styles::HtmlStyle;

#[derive(Debug, Clone, Reflect, PartialEq)]
#[reflect]
pub struct Atlas {
    pub size: UVec2,
    pub columns: u32,
    pub rows: u32,
    pub padding: Option<UVec2>,
    pub offset: Option<UVec2>,
}

impl Default for Atlas {
    fn default() -> Self {
        Atlas { size: [0,0].into(), columns: 0, rows: 0, padding: None, offset: None }
    }
}

#[derive(Debug, Default, Reflect, PartialEq, Clone, Component)]
#[reflect]
pub enum AnimationDirection {
    #[default]
    Forward,
    Reverse,
    AlternateForward,
    AlternateReverse,
}

#[derive(Component)]
pub struct ActiveAnimation {
    pub timer: Timer,
    pub frame: usize,
    pub iterations: i64,
    pub duration: f32,
    pub direction: AnimationDirection,
}

pub fn run_animations(
    time: Res<Time>,
    mut query: Query<(&mut ActiveAnimation, &mut ImageNode, &HtmlStyle)>,
) {
    for (mut active_animation, mut node, style) in query.iter_mut() {
        if active_animation.iterations == 0 {
            continue;
        }

        if style.computed.duration > 0.0 {
            active_animation.duration = active_animation.duration - time.delta_secs();

            if active_animation.duration <= 0.0 {
                continue;
            }
        }

        active_animation.timer.tick(time.delta());

        if style.computed.frames.len() == 1 {
            continue;
        }

        if active_animation.timer.is_finished() {
            let atlas = node.texture_atlas.as_mut().unwrap();
            let atlas_details = style.computed.atlas.as_ref().unwrap();

            if style.computed.frames.len() == 0 {
                let frame_count = (atlas_details.columns * atlas_details.rows) as usize;

                match active_animation.direction {
                    AnimationDirection::Forward => {
                        if atlas.index == frame_count - 1 {
                            if style.computed.direction == AnimationDirection::AlternateForward || style.computed.direction == AnimationDirection::AlternateReverse{
                                active_animation.direction = AnimationDirection::Reverse;
                                active_animation.frame = frame_count - 2;
                            } else {
                                active_animation.frame = 0;
                            }
                            active_animation.iterations = active_animation.iterations - 1;
                        } else {
                            active_animation.frame = active_animation.frame + 1;
                        }
                    }
                    AnimationDirection::Reverse => {
                        if atlas.index == 0 {
                            if style.computed.direction == AnimationDirection::AlternateForward || style.computed.direction == AnimationDirection::AlternateReverse{
                                active_animation.direction = AnimationDirection::Forward;
                                active_animation.frame = 1;
                            } else {
                                active_animation.frame = frame_count - 1;
                            }
                            active_animation.iterations = active_animation.iterations - 1;
                        } else {
                            active_animation.frame = active_animation.frame - 1;
                        }
                    }
                    _ => (),
                }

                node.texture_atlas.as_mut().unwrap().index = active_animation.frame;
            } else {
                let frame_count = style.computed.frames.len();

                match active_animation.direction {
                    AnimationDirection::Forward => {
                        if active_animation.frame == frame_count - 1 {
                            if style.computed.direction == AnimationDirection::AlternateForward || style.computed.direction == AnimationDirection::AlternateReverse{
                                active_animation.direction = AnimationDirection::Reverse;
                                active_animation.frame = frame_count - 2;
                            } else {
                                active_animation.frame = 0;
                            }
                            active_animation.iterations = active_animation.iterations - 1;
                        } else {
                            active_animation.frame = active_animation.frame + 1;
                        }
                    },
                    AnimationDirection::Reverse => {
                        if active_animation.frame == 0 {
                            if style.computed.direction == AnimationDirection::AlternateForward || style.computed.direction == AnimationDirection::AlternateReverse{
                                active_animation.direction = AnimationDirection::Forward;
                                active_animation.frame = 1;
                            } else {
                                active_animation.frame = frame_count - 1;
                            }
                            active_animation.iterations = active_animation.iterations - 1;
                        } else {
                            active_animation.frame = active_animation.frame - 1;
                        }
                    }
                    _ => (),
                }

                node.texture_atlas.as_mut().unwrap().index = style.computed.frames[active_animation.frame] as usize;
            }
        }
    }
}