use nalgebra_glm::Vec2;
#[derive(Debug, Clone, Copy, PartialEq, Default, serde::Serialize, serde::Deserialize)]
pub enum LoopMode {
Once,
#[default]
Loop,
PingPong,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SpriteFrame {
pub uv_min: Vec2,
pub uv_max: Vec2,
pub duration: f32,
pub texture_index: Option<u32>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SpriteAnimator {
pub frames: Vec<SpriteFrame>,
pub current_frame: usize,
pub elapsed: f32,
pub loop_mode: LoopMode,
pub playing: bool,
pub speed: f32,
pub ping_pong_forward: bool,
}
impl Default for SpriteAnimator {
fn default() -> Self {
Self {
frames: Vec::new(),
current_frame: 0,
elapsed: 0.0,
loop_mode: LoopMode::Loop,
playing: true,
speed: 1.0,
ping_pong_forward: true,
}
}
}
impl SpriteAnimator {
pub fn from_grid(columns: u32, rows: u32, frame_count: u32, frame_duration: f32) -> Self {
let mut frames = Vec::with_capacity(frame_count as usize);
let cell_width = 1.0 / columns as f32;
let cell_height = 1.0 / rows as f32;
for index in 0..frame_count {
let column = index % columns;
let row = index / columns;
frames.push(SpriteFrame {
uv_min: Vec2::new(column as f32 * cell_width, row as f32 * cell_height),
uv_max: Vec2::new(
(column + 1) as f32 * cell_width,
(row + 1) as f32 * cell_height,
),
duration: frame_duration,
texture_index: None,
});
}
Self {
frames,
playing: true,
..Default::default()
}
}
pub fn with_loop_mode(mut self, mode: LoopMode) -> Self {
self.loop_mode = mode;
self
}
pub fn with_speed(mut self, speed: f32) -> Self {
self.speed = speed;
self
}
pub fn play(&mut self) {
self.playing = true;
}
pub fn pause(&mut self) {
self.playing = false;
}
pub fn reset(&mut self) {
self.current_frame = 0;
self.elapsed = 0.0;
self.ping_pong_forward = true;
}
}