use crate::directionality::Directionality; use bevy_asset::{Asset, Handle}; use bevy_ecs::bundle::Bundle; use bevy_ecs::component::Component; use bevy_reflect::{Reflect, TypePath}; use bevy_sprite::Sprite; use std::collections::HashMap; use std::time::Duration; macro_rules! dr { ($type: ident -> $output: ty) => { impl ::std::ops::Deref for $type { type Target = $output; fn deref(&self) -> &Self::Target { &self.0 } } impl ::std::ops::DerefMut for $type { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } }; } #[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, Asset)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] pub struct AnimationSet(pub HashMap<String, AnimationFrames>); dr!(AnimationSet -> HashMap<String, AnimationFrames>); #[derive(Clone, Debug, Component, PartialEq, Default)] pub struct AnimationHandle(pub Handle<AnimationSet>); dr!(AnimationHandle -> Handle<AnimationSet>); #[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)] #[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 Default for AnimationStatus { fn default() -> Self { Self { active_name: String::from("idle"), active_step: 0, frame_time: 0.0, } } } 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 new(name: impl ToString) -> Self { AnimationStatus { active_name: name.to_string(), active_step: 0, frame_time: 0.0, } } 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(Component)] #[require(AnimationHandle, AnimationStatus, AnimationMode, Sprite)] pub struct SpriteAnimation; pub fn create_sprite_animation( handle: Handle<AnimationSet>, initial_anim: impl ToString, ) -> impl Bundle { ( SpriteAnimation, AnimationHandle(handle), AnimationStatus::new(initial_anim), ) } #[derive(Component)] #[require( AnimationHandle, AnimationStatus, AnimationMode, Directionality, Sprite )] pub struct DirectionalAnimation; pub fn create_directional_animation( handle: Handle<AnimationSet>, initial_anim: impl ToString, ) -> impl Bundle { ( DirectionalAnimation, AnimationHandle(handle), AnimationStatus::new(initial_anim), ) } #[derive(Component)] #[require(Sprite, SyncToParent)] pub struct ChildAnimation; pub fn create_child_animation() -> impl Bundle { (ChildAnimation,) } #[derive(Clone, Debug, Component, PartialEq, PartialOrd, Default)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] #[require(SimpleAnimationStatus)] pub struct SimpleAnimation(pub AnimationFrames); dr!(SimpleAnimation -> 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, } impl SimpleAnimation { pub fn new(frames: Vec<usize>, frame_secs: f32) -> Self { AnimationFrames { frames, frame_secs }.into() } } #[derive(Clone, Debug, Component, PartialEq, Eq, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct OverrideData(pub u128); dr!(OverrideData -> u128); #[derive(Clone, Debug, Component, PartialEq, Default)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent) )] #[require(OverrideData)] pub struct AnimationOverride(pub AnimationStatus); dr!(AnimationOverride -> 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), } } }