Format some code, update wgsl-preprocessor crate

This commit is contained in:
SeanOMik 2024-11-24 16:32:52 -05:00
parent cb4cf9a48f
commit b9d0398157
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
2 changed files with 131 additions and 71 deletions

View File

@ -1,7 +1,9 @@
use std::cell::RefMut;
use std::collections::HashMap; use std::collections::HashMap;
use lyra_ecs::query::filter::Or;
use lyra_ecs::query::{Entities, Res, View}; use lyra_ecs::query::{Entities, Res, View};
use lyra_ecs::{Commands, Component}; use lyra_ecs::{Commands, Component, Entity};
use lyra_math::URect; use lyra_math::URect;
use lyra_reflect::Reflect; use lyra_reflect::Reflect;
use lyra_resource::{ResHandle, ResourceStorage}; use lyra_resource::{ResHandle, ResourceStorage};
@ -13,7 +15,7 @@ use crate::DeltaTime;
use super::{AtlasSprite, TextureAtlas}; use super::{AtlasSprite, TextureAtlas};
/// A struct describing an animation of a Sprite. /// A struct describing an animation of a Sprite.
/// ///
/// This is a single animation for a [`TextureAtlas`]. This is used alongside [`AtlasAnimations`] /// This is a single animation for a [`TextureAtlas`]. This is used alongside [`AtlasAnimations`]
/// to use animations from an atlas. /// to use animations from an atlas.
#[derive(Clone, Component, Reflect)] #[derive(Clone, Component, Reflect)]
@ -28,18 +30,18 @@ pub struct SpriteAnimation {
impl SpriteAnimation { impl SpriteAnimation {
/// Create an animation from a texture atlas. /// Create an animation from a texture atlas.
/// ///
/// Parameters: /// Parameters:
/// * `name` - The name of the animation. Used to identify the animation in [`AtlasAnimations`]. /// * `name` - The name of the animation. Used to identify the animation in [`AtlasAnimations`].
/// * `frame_time` - The time per frame of the animation. /// * `frame_time` - The time per frame of the animation.
/// * `atlas` - The texture atlas that this animation is from, used to acquire `self.frames`. /// * `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. /// * `sprites` are the rect indexes in the atlas for this animation.
pub fn from_atlas<I>(name: &str, frame_time: f32, atlas: &TextureAtlas, sprites: I) -> Self pub fn from_atlas<I>(name: &str, frame_time: f32, atlas: &TextureAtlas, sprites: I) -> Self
where where
I: Iterator<Item = u32>, I: Iterator<Item = u32>,
{ {
let mut frames = vec![];//Vec::with_capacity(sprites.len()); let mut frames = vec![]; //Vec::with_capacity(sprites.len());
for i in sprites { for i in sprites {
let r = atlas.index_rect(i); let r = atlas.index_rect(i);
frames.push(r); frames.push(r);
@ -54,7 +56,7 @@ impl SpriteAnimation {
} }
/// A helper trait that makes it easier to create the animations for an [`AtlasAnimations`] component. /// A helper trait that makes it easier to create the animations for an [`AtlasAnimations`] component.
/// ///
/// See [`AtlasAnimations::new`]. /// See [`AtlasAnimations::new`].
pub trait IntoSpriteAnimation { pub trait IntoSpriteAnimation {
fn into_animation(&self, atlas: &TextureAtlas) -> SpriteAnimation; fn into_animation(&self, atlas: &TextureAtlas) -> SpriteAnimation;
@ -81,29 +83,30 @@ pub struct AtlasAnimations {
} }
impl AtlasAnimations { impl AtlasAnimations {
pub fn from_animations(atlas: ResHandle<TextureAtlas>, animations: Vec<SpriteAnimation>) -> Self { pub fn from_animations(
let animations = animations.into_iter() atlas: ResHandle<TextureAtlas>,
animations: Vec<SpriteAnimation>,
) -> Self {
let animations = animations
.into_iter()
.map(|a| (a.name.clone(), a)) .map(|a| (a.name.clone(), a))
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
Self { Self { atlas, animations }
atlas,
animations,
}
} }
/// Helper for creating [`AtlasAnimations`]. /// Helper for creating [`AtlasAnimations`].
/// ///
/// If you already have the [`SpriteAnimation`]s, you can just use /// If you already have the [`SpriteAnimation`]s, you can just use
/// [`AtlasAnimations::from_animations`] instead of this helper function. /// [`AtlasAnimations::from_animations`] instead of this helper function.
/// ///
/// Example: /// Example:
/// ``` /// ```
/// let animations = AtlasAnimations::new(atlas, &[ /// let animations = AtlasAnimations::new(atlas, &[
/// // This slice accepts anything that implements `IntoSpriteAnimation`: /// // This slice accepts anything that implements `IntoSpriteAnimation`:
/// // * tuple of (name: &str, frame_time: f32, frame_indexes: Iterator<Item = u32>) /// // * tuple of (name: &str, frame_time: f32, frame_indexes: Iterator<Item = u32>)
/// // * `SpriteAnimation` (will be cloned) /// // * `SpriteAnimation` (will be cloned)
/// ///
/// // The animation is named "soldier_run", with a frame time of 0.1, and the frames /// // The animation is named "soldier_run", with a frame time of 0.1, and the frames
/// // 9 to 16 (inclusive) from the atlas. /// // 9 to 16 (inclusive) from the atlas.
/// ("soldier_run", 0.1, 9..=16), /// ("soldier_run", 0.1, 9..=16),
@ -111,55 +114,70 @@ impl AtlasAnimations {
/// ``` /// ```
pub fn new<A>(atlas: ResHandle<TextureAtlas>, animations: &[A]) -> Self pub fn new<A>(atlas: ResHandle<TextureAtlas>, animations: &[A]) -> Self
where where
A: IntoSpriteAnimation A: IntoSpriteAnimation,
{ {
let animations = { let animations = {
let atlas = atlas.data_ref().unwrap(); let atlas = atlas.data_ref().unwrap();
animations.into_iter() animations
.into_iter()
.map(|a| { .map(|a| {
let a = a.into_animation(&atlas); let a = a.into_animation(&atlas);
(a.name.clone(), a) (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::<HashMap<_, _>>() .collect::<HashMap<_, _>>()
}; };
Self { Self { atlas, animations }
atlas,
animations,
}
} }
/// Get the [`ActiveAtlasAnimation`] for an animation with `name`. /// Get the [`ActiveAtlasAnimation`] for an animation with `name`.
/// ///
/// > NOTE: this asserts that the animation exists in self in debug builds (uses `debug_assert`). /// > NOTE: this asserts that the animation exists in self in debug builds (uses `debug_assert`).
pub fn get_active(&self, name: &str) -> ActiveAtlasAnimation { 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) 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<lyra_resource::UntypedResHandle> {
vec![self.atlas.untyped_clone()]
}
}
/// The active sprite animation from an [`AtlasAnimations`]. /// The active sprite animation from an [`AtlasAnimations`].
#[derive(Clone, Component, Reflect)] #[derive(Clone, Component, Reflect)]
pub struct ActiveAtlasAnimation { pub struct ActiveAtlasAnimation {
/// The name of the active [`SpriteAnimation`]. /// The name of the active [`SpriteAnimation`].
pub name: String, pub name: String,
/// The current frame index in the active [`SpriteAnimation`]. /// The current frame index in the active [`SpriteAnimation`].
/// ///
/// This is not the index of the rect in the atlas. /// This is not the index of the rect in the atlas.
pub index: u32, pub index: u32,
pub paused: bool, pub paused: bool,
/// The time since last animation frame change. /// The time since last animation frame change.
/// ///
/// This is used to detect if enough time has passed for the frame. /// This is used to detect if enough time has passed for the frame.
timer: f32, timer: f32,
} }
impl ActiveAtlasAnimation { impl ActiveAtlasAnimation {
///Create an [`ActiveAtlasAnimation`]. ///Create an [`ActiveAtlasAnimation`].
/// ///
/// The animation will not be paused. /// The animation will not be paused.
pub fn new(name: &str) -> Self { pub fn new(name: &str) -> Self {
Self { Self {
@ -171,7 +189,7 @@ impl ActiveAtlasAnimation {
} }
/// Create an [`ActiveAtlasAnimation`] that starts at a specific point in the animation. /// Create an [`ActiveAtlasAnimation`] that starts at a specific point in the animation.
/// ///
/// The animation will not be paused. /// The animation will not be paused.
pub fn new_at(name: &str, index: u32) -> Self { pub fn new_at(name: &str, index: u32) -> Self {
Self { Self {
@ -183,7 +201,17 @@ impl ActiveAtlasAnimation {
} }
} }
pub fn system_sprite_atlas_animation(mut commands: Commands, dt: Res<DeltaTime>, view: View<(Entities, Option<&mut AtlasSprite>, &AtlasAnimations, &mut ActiveAtlasAnimation)>) -> anyhow::Result<()> { pub fn system_sprite_atlas_animation(
mut commands: Commands,
dt: Res<DeltaTime>,
view: View<(
Entities,
Option<&mut AtlasSprite>,
// support animations from assets or non-asset handles.
Or<&AtlasAnimations, &ResHandle<AtlasAnimations>>,
&mut ActiveAtlasAnimation,
)>,
) -> anyhow::Result<()> {
let dt = **dt; let dt = **dt;
for (en, mut sprite, animations, mut active) in view.iter() { 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<DeltaTime>,
continue; continue;
} }
if let Some(anim) = animations.animations.get(&active.name) { if let Some(animations) = animations.0 {
if animations.atlas.is_loaded() { system_animation_entity_impl(
active.timer += dt; &mut commands,
dt,
// Initialize this entity by giving it the first sprite animation frame. en,
if sprite.is_none() { &mut sprite,
// Get the first sprite in the animation. &animations,
let rect = anim.frames[active.index as usize]; &mut active,
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;
}
}
} else { } 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(()) Ok(())
} }
fn system_animation_entity_impl(
commands: &mut Commands,
dt: f32,
en: Entity,
sprite: &mut Option<RefMut<AtlasSprite>>,
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);
}
}

@ -1 +1 @@
Subproject commit 70daf320827f64b325a77718df07177d74d7ea58 Subproject commit 76a1c98abd375dbaca694f9728e3d6c105ef3f1b