Newer
Older
AnimationOverride, AnimationPaused, AnimationSet, AnimationStatus, OverrideData,
SimpleAnimation, SimpleAnimationStatus, SyncToParent,
use crate::directionality::Directionality;
use bevy::asset::Assets;
use bevy::prelude::{
Commands, Entity, EventWriter, Handle, Parent, Query, Res, Time, With, Without,
};
pub struct AnimationComponents {
handle: &'static Handle<AnimationSet>,
status: &'static mut AnimationStatus,
pub struct DirectionalAnimationComponents {
handle: &'static Handle<AnimationSet>,
direction: &'static Directionality,
status: &'static mut AnimationStatus,
pub struct OverrideAnimationComponents {
handle: &'static Handle<AnimationSet>,
data: Option<&'static OverrideData>,
status: &'static mut AnimationOverride,
pub struct SimpleAnimationComponents {
anim: &'static SimpleAnimation,
status: &'static mut SimpleAnimationStatus,
pub struct OnlyAnimations {
_status: With<AnimationStatus>,
_override: Without<AnimationOverride>,
_direction: Without<Directionality>,
_paused: Without<AnimationPaused>,
}
pub struct OnlyDirectionalAnimations {
_status: With<AnimationStatus>,
_direction: With<Directionality>,
_override: Without<AnimationOverride>,
_paused: Without<AnimationPaused>,
}
pub struct OnlyOverrideAnimations {
_override: With<AnimationOverride>,
_direction: Without<Directionality>,
_paused: Without<AnimationPaused>,
}
pub struct OnlyDirectionalOverrideAnimations {
_override: With<AnimationOverride>,
_direction: With<Directionality>,
_paused: Without<AnimationPaused>,
}
macro_rules! get_current_anim {
($anims: expr, $handle: expr, $name: expr) => {
match $anims.get($handle) {
Some(active) => match active.get(&$name) {
Some(inner) => inner,
None => continue,
},
None => continue,
};
($anims: expr, $handle: expr, $name: expr, $($also: expr),+) => {
match $anims.get($handle) {
Some(active) => match active.get(&$name)$(.or_else(|| active.get(&$also)))+ {
Some(inner) => inner,
None => continue,
},
None => continue,
}
};
}
macro_rules! tick_animation {
($delta: expr, $anim: expr, $status: expr, $atlas: expr) => {{
let current_frame = $atlas.index;
let mut has_looped = false;
$status.frame_time += $delta.as_secs_f32();
while $status.frame_time >= $anim.frame_secs {
$status.frame_time = ($status.frame_time - $anim.frame_secs).max(0.0);
let next_frame = $status.active_step.saturating_add(1);
$status.active_step = if next_frame >= $anim.frames.len() {
has_looped = true;
0
} else {
next_frame
};
}
if current_frame != $anim.frames[$status.active_step] {
has_looped
}};
}
pub fn play_animations(
time: Res<Time>,
mut anim_query: Query<AnimationComponents, OnlyAnimations>,
animations: Res<Assets<AnimationSet>>,
) {
let delta = time.delta();
for AnimationComponentsItem {
mut status,
handle,
} in &mut anim_query
{
let anim = get_current_anim!(animations, handle, status.active_name);
pub fn play_directional_animations(
time: Res<Time>,
mut anim_query: Query<DirectionalAnimationComponents, OnlyDirectionalAnimations>,
animations: Res<Assets<AnimationSet>>,
) {
let delta = time.delta();
for DirectionalAnimationComponentsItem {
mut status,
handle,
direction,
} in &mut anim_query
{
let anim = get_current_anim!(
animations,
handle,
format!("{}_{}", status.active_name, direction),
status.active_name
);
pub fn play_override_animation(
time: Res<Time>,
mut commands: Commands,
mut anim_query: Query<(Entity, OverrideAnimationComponents), OnlyOverrideAnimations>,
animations: Res<Assets<AnimationSet>>,
mut events: EventWriter<AnimationCompleted>,
) {
let delta = time.delta();
for (
entity,
OverrideAnimationComponentsItem {
mut status,
handle,
data,
},
) in &mut anim_query
{
let anim = get_current_anim!(animations, handle, status.active_name);
if looped {
commands
.entity(entity)
.remove::<(AnimationOverride, OverrideData)>();
if let Some(data) = data {
events.send(AnimationCompleted {
entity,
user_data: **data,
});
pub fn play_simple_animation(
time: Res<Time>,
mut anim_query: Query<SimpleAnimationComponents, Without<AnimationPaused>>,
) {
let delta = time.delta();
for SimpleAnimationComponentsItem {
mut status,
anim,
} in &mut anim_query
{
pub fn sync_child_animation(
mut children: Query<(&Parent, &mut TextureAtlas), With<SyncToParent>>,
parents: Query<&TextureAtlas, Without<SyncToParent>>,
) {
for (parent, mut child_sprite) in &mut children {
if let Ok(parent_sprite) = parents.get(**parent) {
if parent_sprite.index != child_sprite.index {
child_sprite.index = parent_sprite.index;