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::ops::{Deref, DerefMut};
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,
AnimationPlaybackRate,
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,
AnimationPlaybackRate,
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),
}
}
}
#[derive(Clone, Debug, Component, PartialEq)]
pub struct AnimationPlaybackRate(f32);
impl Default for AnimationPlaybackRate {
fn default() -> Self {
AnimationPlaybackRate(1.0)
}
}
impl From<f32> for AnimationPlaybackRate {
fn from(value: f32) -> Self {
AnimationPlaybackRate(value)
}
}
impl Deref for AnimationPlaybackRate {
type Target = f32;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for AnimationPlaybackRate {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}