From b9d0398157e2211959d30acac70f319e2644f8ff Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 24 Nov 2024 16:32:52 -0500 Subject: [PATCH] Format some code, update wgsl-preprocessor crate --- .../lyra-game/src/sprite/animation_sheet.rs | 200 ++++++++++++------ crates/wgsl-preprocessor | 2 +- 2 files changed, 131 insertions(+), 71 deletions(-) diff --git a/crates/lyra-game/src/sprite/animation_sheet.rs b/crates/lyra-game/src/sprite/animation_sheet.rs index 4982cf0..97b5385 100644 --- a/crates/lyra-game/src/sprite/animation_sheet.rs +++ b/crates/lyra-game/src/sprite/animation_sheet.rs @@ -1,7 +1,9 @@ +use std::cell::RefMut; use std::collections::HashMap; +use lyra_ecs::query::filter::Or; use lyra_ecs::query::{Entities, Res, View}; -use lyra_ecs::{Commands, Component}; +use lyra_ecs::{Commands, Component, Entity}; use lyra_math::URect; use lyra_reflect::Reflect; use lyra_resource::{ResHandle, ResourceStorage}; @@ -13,7 +15,7 @@ use crate::DeltaTime; use super::{AtlasSprite, TextureAtlas}; /// A struct describing an animation of a Sprite. -/// +/// /// This is a single animation for a [`TextureAtlas`]. This is used alongside [`AtlasAnimations`] /// to use animations from an atlas. #[derive(Clone, Component, Reflect)] @@ -28,18 +30,18 @@ pub struct SpriteAnimation { impl SpriteAnimation { /// Create an animation from a texture atlas. - /// + /// /// Parameters: /// * `name` - The name of the animation. Used to identify the animation in [`AtlasAnimations`]. /// * `frame_time` - The time per frame of the animation. /// * `atlas` - The texture atlas that this animation is from, used to acquire `self.frames`. /// * `sprites` are the rect indexes in the atlas for this animation. pub fn from_atlas(name: &str, frame_time: f32, atlas: &TextureAtlas, sprites: I) -> Self - where + where I: Iterator, { - let mut frames = vec![];//Vec::with_capacity(sprites.len()); - + let mut frames = vec![]; //Vec::with_capacity(sprites.len()); + for i in sprites { let r = atlas.index_rect(i); frames.push(r); @@ -54,7 +56,7 @@ impl SpriteAnimation { } /// A helper trait that makes it easier to create the animations for an [`AtlasAnimations`] component. -/// +/// /// See [`AtlasAnimations::new`]. pub trait IntoSpriteAnimation { fn into_animation(&self, atlas: &TextureAtlas) -> SpriteAnimation; @@ -81,29 +83,30 @@ pub struct AtlasAnimations { } impl AtlasAnimations { - pub fn from_animations(atlas: ResHandle, animations: Vec) -> Self { - let animations = animations.into_iter() + pub fn from_animations( + atlas: ResHandle, + animations: Vec, + ) -> Self { + let animations = animations + .into_iter() .map(|a| (a.name.clone(), a)) .collect::>(); - Self { - atlas, - animations, - } + Self { atlas, animations } } /// Helper for creating [`AtlasAnimations`]. - /// + /// /// If you already have the [`SpriteAnimation`]s, you can just use /// [`AtlasAnimations::from_animations`] instead of this helper function. - /// + /// /// Example: /// ``` /// let animations = AtlasAnimations::new(atlas, &[ /// // This slice accepts anything that implements `IntoSpriteAnimation`: /// // * tuple of (name: &str, frame_time: f32, frame_indexes: Iterator) /// // * `SpriteAnimation` (will be cloned) - /// + /// /// // The animation is named "soldier_run", with a frame time of 0.1, and the frames /// // 9 to 16 (inclusive) from the atlas. /// ("soldier_run", 0.1, 9..=16), @@ -111,55 +114,70 @@ impl AtlasAnimations { /// ``` pub fn new(atlas: ResHandle, animations: &[A]) -> Self where - A: IntoSpriteAnimation + A: IntoSpriteAnimation, { let animations = { let atlas = atlas.data_ref().unwrap(); - animations.into_iter() + animations + .into_iter() .map(|a| { let a = a.into_animation(&atlas); (a.name.clone(), a) - }) - //.map(|(name, ft, fi)| (name.to_string(), SpriteAnimation::from_atlas(name, *ft, &atlas, fi.clone()))) + }) + //.map(|(name, ft, fi)| (name.to_string(), SpriteAnimation::from_atlas(name, *ft, &atlas, fi.clone()))) .collect::>() }; - Self { - atlas, - animations, - } + Self { atlas, animations } } /// Get the [`ActiveAtlasAnimation`] for an animation with `name`. - /// + /// /// > NOTE: this asserts that the animation exists in self in debug builds (uses `debug_assert`). pub fn get_active(&self, name: &str) -> ActiveAtlasAnimation { - debug_assert!(self.animations.contains_key(name), "The animation with name '{name}' does not exist!"); + debug_assert!( + self.animations.contains_key(name), + "The animation with name '{name}' does not exist!" + ); ActiveAtlasAnimation::new(name) } } +impl lyra_resource::ResourceData for AtlasAnimations { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn dependencies(&self) -> Vec { + vec![self.atlas.untyped_clone()] + } +} + /// The active sprite animation from an [`AtlasAnimations`]. #[derive(Clone, Component, Reflect)] pub struct ActiveAtlasAnimation { /// The name of the active [`SpriteAnimation`]. pub name: String, /// The current frame index in the active [`SpriteAnimation`]. - /// + /// /// This is not the index of the rect in the atlas. pub index: u32, pub paused: bool, /// The time since last animation frame change. - /// + /// /// This is used to detect if enough time has passed for the frame. timer: f32, } impl ActiveAtlasAnimation { ///Create an [`ActiveAtlasAnimation`]. - /// + /// /// The animation will not be paused. pub fn new(name: &str) -> Self { Self { @@ -171,7 +189,7 @@ impl ActiveAtlasAnimation { } /// Create an [`ActiveAtlasAnimation`] that starts at a specific point in the animation. - /// + /// /// The animation will not be paused. pub fn new_at(name: &str, index: u32) -> Self { Self { @@ -183,7 +201,17 @@ impl ActiveAtlasAnimation { } } -pub fn system_sprite_atlas_animation(mut commands: Commands, dt: Res, view: View<(Entities, Option<&mut AtlasSprite>, &AtlasAnimations, &mut ActiveAtlasAnimation)>) -> anyhow::Result<()> { +pub fn system_sprite_atlas_animation( + mut commands: Commands, + dt: Res, + view: View<( + Entities, + Option<&mut AtlasSprite>, + // support animations from assets or non-asset handles. + Or<&AtlasAnimations, &ResHandle>, + &mut ActiveAtlasAnimation, + )>, +) -> anyhow::Result<()> { let dt = **dt; for (en, mut sprite, animations, mut active) in view.iter() { @@ -192,47 +220,79 @@ pub fn system_sprite_atlas_animation(mut commands: Commands, dt: Res, continue; } - if let Some(anim) = animations.animations.get(&active.name) { - if animations.atlas.is_loaded() { - active.timer += dt; - - // Initialize this entity by giving it the first sprite animation frame. - if sprite.is_none() { - // Get the first sprite in the animation. - let rect = anim.frames[active.index as usize]; - let sprite = AtlasSprite { - atlas: animations.atlas.clone(), - sprite: rect, - }; - - commands.insert(en, sprite); - continue; - } - - if active.timer >= anim.frame_time { - active.timer = 0.0; - active.index += 1; - - // wrap the animation around - if active.index as usize >= anim.frames.len() { - active.index = 0; - } - - // Get the sprite for the animation frame - let rect = anim.frames[active.index as usize]; - let new_sprite = AtlasSprite { - atlas: animations.atlas.clone(), - sprite: rect, - }; - - let sprite = sprite.as_mut().unwrap(); - **sprite = new_sprite; - } - } + if let Some(animations) = animations.0 { + system_animation_entity_impl( + &mut commands, + dt, + en, + &mut sprite, + &animations, + &mut active, + ); } else { - error!("Unknown active animation: '{}'", active.name); + let animations = animations.1.unwrap(); + if let Some(animations) = animations.data_ref() { + system_animation_entity_impl( + &mut commands, + dt, + en, + &mut sprite, + &animations, + &mut active, + ); + }; } } Ok(()) -} \ No newline at end of file +} + +fn system_animation_entity_impl( + commands: &mut Commands, + dt: f32, + en: Entity, + sprite: &mut Option>, + animations: &AtlasAnimations, + active: &mut ActiveAtlasAnimation, +) { + if let Some(anim) = animations.animations.get(&active.name) { + if animations.atlas.is_loaded() { + active.timer += dt; + + // Initialize this entity by giving it the first sprite animation frame. + if sprite.is_none() { + // Get the first sprite in the animation. + let rect = anim.frames[active.index as usize]; + let sprite = AtlasSprite { + atlas: animations.atlas.clone(), + sprite: rect, + }; + + commands.insert(en, sprite); + return; + } + + if active.timer >= anim.frame_time { + active.timer = 0.0; + active.index += 1; + + // wrap the animation around + if active.index as usize >= anim.frames.len() { + active.index = 0; + } + + // Get the sprite for the animation frame + let rect = anim.frames[active.index as usize]; + let new_sprite = AtlasSprite { + atlas: animations.atlas.clone(), + sprite: rect, + }; + + let sprite = sprite.as_mut().unwrap(); + **sprite = new_sprite; + } + } + } else { + error!("Unknown active animation: '{}'", active.name); + } +} diff --git a/crates/wgsl-preprocessor b/crates/wgsl-preprocessor index 70daf32..76a1c98 160000 --- a/crates/wgsl-preprocessor +++ b/crates/wgsl-preprocessor @@ -1 +1 @@ -Subproject commit 70daf320827f64b325a77718df07177d74d7ea58 +Subproject commit 76a1c98abd375dbaca694f9728e3d6c105ef3f1b