use std::collections::HashMap; use std::time::Duration; use bevy::prelude::*; use bevy::reflect::TypePath; use crate::directionality::Directionality; #[derive(Clone, PartialOrd, PartialEq, Debug, Default, Reflect)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AnimationFrames { pub frames: Vec<usize>, pub frame_secs: f32, } impl AnimationFrames { pub fn duration(&self) -> Duration { Duration::from_secs_f32(self.frames.len() as f32 * self.frame_secs) } } #[derive(Clone, Debug, TypePath, PartialEq, Default, Deref, DerefMut, Asset)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] pub struct AnimationSet(pub HashMap<String, AnimationFrames>); #[derive(Copy, Clone, Debug, Component, PartialEq, Eq, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SyncToParent; #[derive(Copy, Clone, Debug, Component, PartialEq, Eq, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AnimationPaused; #[derive(Copy, Clone, Debug, Component, PartialEq, Eq, Default)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] pub struct UserData(pub u128); #[derive(Clone, Debug, Component, PartialEq, Eq, Default)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(untagged, rename_all = "snake_case") )] pub enum AnimationMode { #[default] Loop, Once, IntroLoop { intro: String, r#loop: String, }, } #[derive(Clone, Debug, Component, PartialEq, PartialOrd, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AnimationStatus { pub active_name: String, pub active_step: usize, pub frame_time: f32, } impl From<String> for AnimationStatus { fn from(value: String) -> Self { AnimationStatus { active_name: value, active_step: 0, frame_time: 0.0, } } } impl AnimationStatus { pub fn set_animation(&mut self, name: impl ToString) { self.active_name = name.to_string(); } pub fn start_animation(&mut self, name: impl ToString) { self.active_name = name.to_string(); self.active_step = 0; } pub fn start_or_continue(&mut self, name: impl ToString) { let name = name.to_string(); if self.active_name != name { self.active_name = name; self.active_step = 0; } } } #[derive(Clone, Debug, Bundle, Default)] pub struct DirectionalAnimationBundle { pub animation_handle: Handle<AnimationSet>, pub mode: AnimationMode, pub status: AnimationStatus, pub direction: Directionality, } impl DirectionalAnimationBundle { pub fn new(initial_anim: impl ToString, handle: Handle<AnimationSet>) -> Self { Self { animation_handle: handle, status: AnimationStatus { active_name: initial_anim.to_string(), active_step: 0, frame_time: 0.0, }, mode: AnimationMode::Loop, direction: Directionality::default(), } } pub fn with_direction( initial_anim: impl ToString, handle: Handle<AnimationSet>, direction: Directionality, ) -> Self { Self { animation_handle: handle, status: AnimationStatus { active_name: initial_anim.to_string(), active_step: 0, frame_time: 0.0, }, mode: AnimationMode::Loop, direction, } } } #[derive(Clone, Debug, Bundle, Default)] pub struct SpriteAnimationBundle { pub animation_handle: Handle<AnimationSet>, pub mode: AnimationMode, pub status: AnimationStatus, } impl SpriteAnimationBundle { pub fn new(initial_anim: impl ToString, handle: Handle<AnimationSet>) -> Self { Self { animation_handle: handle, status: AnimationStatus { active_name: initial_anim.to_string(), active_step: 0, frame_time: 0.0, }, mode: AnimationMode::Loop, } } } #[derive(Clone, Debug, Component, PartialEq, PartialOrd, Default, Deref, DerefMut)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] pub struct SimpleAnimation(pub AnimationFrames); impl From<AnimationFrames> for SimpleAnimation { fn from(value: AnimationFrames) -> Self { SimpleAnimation(value) } } #[derive(Copy, Clone, Debug, Component, PartialEq, PartialOrd, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SimpleAnimationStatus { pub active_step: usize, pub frame_time: f32, } #[derive(Clone, Debug, Bundle, PartialEq, PartialOrd, Default)] pub struct SimpleAnimationBundle { pub anim: SimpleAnimation, pub status: SimpleAnimationStatus, } impl SimpleAnimationBundle { pub fn new(frames: Vec<usize>, frame_secs: f32) -> Self { SimpleAnimationBundle { anim: AnimationFrames { frames, frame_secs }.into(), status: SimpleAnimationStatus { active_step: 0, frame_time: 0.0, }, } } } #[derive(Clone, Debug, Component, PartialEq, Eq, Default, Deref, DerefMut)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct OverrideData(pub u128); #[derive(Clone, Debug, Component, PartialEq, Default, Deref, DerefMut)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] pub struct AnimationOverride(pub AnimationStatus); impl AnimationOverride { pub fn new(name: impl ToString) -> Self { AnimationOverride(name.to_string().into()) } } impl From<AnimationStatus> for AnimationOverride { fn from(other: AnimationStatus) -> Self { Self(other) } } impl From<String> for AnimationOverride { fn from(other: String) -> Self { AnimationStatus::from(other).into() } } #[derive(Bundle, Default)] pub struct AnimationOverrideBundle { pub anim: AnimationOverride, pub data: OverrideData, } impl AnimationOverrideBundle { pub fn new(anim: impl Into<AnimationOverride>) -> Self { Self { anim: anim.into(), data: OverrideData(0), } } } #[derive(Clone, Debug, Bundle, Default)] pub struct ChildAnimationBundle { marker: SyncToParent, }