diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e36f6c4..3779658 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,6 +72,7 @@ jobs: - "unstable-load-from-file, ron" - "bevy-07" - "bevy-app-07" + - "bevy-sprite-07" steps: - uses: actions/checkout@v3 diff --git a/Cargo.toml b/Cargo.toml index d375d50..927a556 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,20 +16,20 @@ all-features = true [features] default = [] unstable-load-from-file = ["serde", "anyhow", "bevy_utils"] -bevy-07 = ["bevy-app-07"] +bevy-07 = ["bevy-app-07", "bevy-sprite-07"] [dependencies] # Private dependencies (do not leak into the public API) yaml = { package = "serde_yaml", version = "0.8.25", default-features = false, optional = true } ron = { version = "0.7.1", default-features = false, optional = true } -# Private dependencies (Present in the public API) +# Public dependencies (Present in the public API) bevy_core = { version = "0.7.0", default-features = false } bevy_ecs = { version = "0.7.0", default-features = false } -bevy-app-07 = { package = "bevy_app",version = "0.7.0", default-features = false, optional = true } bevy_reflect = { version = "0.7.0", default-features = false } -bevy_sprite = { version = "0.7.0", default-features = false } bevy_asset = { version = "0.7.0", default-features = false } +bevy-app-07 = { package = "bevy_app",version = "0.7.0", default-features = false, optional = true } +bevy-sprite-07 = { package = "bevy_sprite", version = "0.7.0", default-features = false, optional = true } bevy_utils = { version = "0.7.0", default-features = false, optional = true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } anyhow = { version = "1.0", default-features = false, optional = true } diff --git a/src/lib.rs b/src/lib.rs index 28a19c3..24c2540 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,8 +256,17 @@ pub fn maintenance_systems() -> SystemSet { } /// System set that animate the sprite-sheets +#[must_use] +#[allow(unused_mut)] pub fn animation_systems() -> SystemSet { - SystemSet::new().with_system(state::animate) + let mut set = SystemSet::new(); + + #[cfg(feature = "bevy-sprite-07")] + { + set = set.with_system(state::animate::); + } + + set } #[cfg(test)] diff --git a/src/state.rs b/src/state.rs index 4e27e7a..91decae 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,10 +1,8 @@ -use std::ops::DerefMut; -use std::time::Duration; +use std::{ops::DerefMut, time::Duration}; use bevy_asset::{Assets, Handle}; use bevy_core::prelude::*; use bevy_ecs::prelude::*; -use bevy_sprite::prelude::*; use crate::{animation::Mode, Play, PlaySpeedMultiplier, SpriteSheetAnimation}; @@ -32,6 +30,10 @@ pub struct SpriteSheetAnimationState { going_backward: bool, } +pub trait SpriteState { + fn set_current_index(&mut self, index: usize); +} + impl SpriteSheetAnimationState { /// Reset animation state /// @@ -53,14 +55,14 @@ impl SpriteSheetAnimationState { /// Returns true if the animation has ended fn update( &mut self, - mut sprite: impl DerefMut, + sprite: &mut impl SpriteState, animation: &SpriteSheetAnimation, delta: Duration, ) -> bool { debug_assert!(animation.has_frames()); let mut frame = animation.frames[self.current_frame % animation.frames.len()]; - sprite.index = frame.index; + sprite.set_current_index(frame.index); self.elapsed_in_frame += delta; while self.elapsed_in_frame >= frame.duration { @@ -99,7 +101,7 @@ impl SpriteSheetAnimationState { self.elapsed_in_frame -= frame.duration; frame = animation.frames[self.current_frame]; - sprite.index = frame.index; + sprite.set_current_index(frame.index); } false @@ -136,21 +138,23 @@ pub(crate) fn remove( } } -type AnimationSystemQuery<'a> = ( +#[allow(dead_code)] +type AnimationSystemQuery<'a, T> = ( Entity, - &'a mut TextureAtlasSprite, + &'a mut T, &'a Handle, &'a mut SpriteSheetAnimationState, Option<&'a PlaySpeedMultiplier>, ); -pub(crate) fn animate( +#[allow(dead_code)] +pub(crate) fn animate( mut commands: Commands<'_, '_>, time: Res<'_, Time>, animation_defs: Res<'_, Assets>, - mut animations: Query<'_, '_, AnimationSystemQuery<'_>, With>, + mut animations: Query<'_, '_, AnimationSystemQuery<'_, T>, With>, ) { - for (entity, sprite, animation, mut state, speed_multiplier) in + for (entity, mut sprite, animation, mut state, speed_multiplier) in animations.iter_mut().filter_map( |(entity, sprite, anim_handle, state, optional_speed_multiplier)| { animation_defs @@ -165,29 +169,52 @@ pub(crate) fn animate( .unwrap_or_default() .transform(time.delta()); - if state.update(sprite, animation, delta) { + if state.update(&mut sprite, animation, delta) { commands.entity(entity).remove::(); } } } +impl<'w, T: SpriteState> SpriteState for Mut<'w, T> { + fn set_current_index(&mut self, index: usize) { + self.deref_mut().set_current_index(index); + } +} + +#[cfg(feature = "bevy-sprite-07")] +impl SpriteState for bevy_sprite_07::TextureAtlasSprite { + fn set_current_index(&mut self, index: usize) { + self.index = index; + } +} + #[cfg(test)] mod tests { use super::*; + struct TextureAtlasSprite { + index: usize, + } + + impl SpriteState for TextureAtlasSprite { + fn set_current_index(&mut self, index: usize) { + self.index = index; + } + } + #[fixture] fn sprite() -> TextureAtlasSprite { - TextureAtlasSprite::new(0) + TextureAtlasSprite { index: 0 } } #[fixture] fn sprite_at_second_frame() -> TextureAtlasSprite { - TextureAtlasSprite::new(1) + TextureAtlasSprite { index: 1 } } #[fixture] fn sprite_at_third_frame() -> TextureAtlasSprite { - TextureAtlasSprite::new(2) + TextureAtlasSprite { index: 2 } } #[fixture]