Skip to content

Commit

Permalink
Merge pull request #22 from mirsella/optional_3d
Browse files Browse the repository at this point in the history
add a plugin option to disable 3d systems
  • Loading branch information
merwaaan authored Nov 20, 2024
2 parents e61a77e + be3bae4 commit 27c7f8e
Show file tree
Hide file tree
Showing 19 changed files with 149 additions and 68 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn main() {
.add_plugins(DefaultPlugins)
// Add the plugin to enable animations.
// This makes the AnimationLibrary resource available to your systems.
.add_plugins(SpritesheetAnimationPlugin)
.add_plugins(SpritesheetAnimationPlugin::default())
.add_systems(Startup, setup)
.run();
}
Expand Down
9 changes: 3 additions & 6 deletions benches/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn create_app() -> App {
.into(),
..default()
}),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.finish();
app
Expand Down Expand Up @@ -71,10 +71,7 @@ fn playback(bencher: Bencher, (animation_count, sprite_count): (usize, usize)) {

let mut rng = rand::thread_rng();
for _ in 0..sprite_count {
create_sprite(
&mut app,
animation_ids.iter().choose(&mut rng).unwrap().clone(),
);
create_sprite(&mut app, *animation_ids.iter().choose(&mut rng).unwrap());
}

let mut time = Time::new_with(());
Expand All @@ -83,7 +80,7 @@ fn playback(bencher: Bencher, (animation_count, sprite_count): (usize, usize)) {
Res<AnimationLibrary>,
ResMut<Animator>,
EventWriter<AnimationEvent>,
Query<(Entity, &mut SpritesheetAnimation, &mut TextureAtlas)>,
Query<(Entity, &mut SpritesheetAnimation, Option<&mut TextureAtlas>)>,
)> = SystemState::new(app.world_mut());

bencher.bench_local(|| {
Expand Down
2 changes: 1 addition & 1 deletion examples/3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, (update_on_keypress, orbit, draw_gizmos))
Expand Down
2 changes: 1 addition & 1 deletion examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
.add_plugins(DefaultPlugins)
// Add the plugin to enable animations.
// This makes the AnimationLibrary resource available to your systems.
.add_plugins(SpritesheetAnimationPlugin)
.add_plugins(SpritesheetAnimationPlugin::default())
.add_systems(Startup, (setup, spawn_sprite.after(setup)))
.run();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/character.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, control_character)
Expand Down
2 changes: 1 addition & 1 deletion examples/composition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, show_triggered_events)
Expand Down
57 changes: 57 additions & 0 deletions examples/headless.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This example shows how to use this plugin in a bevy app without bevy_render.
//
// For example for a headless server with MinimalPlugins, while still using the animations events.

#[path = "./common/mod.rs"]
pub mod common;

use bevy::prelude::*;
use bevy_spritesheet_animation::prelude::*;

fn main() {
App::new()
.add_plugins((
MinimalPlugins,
SpritesheetAnimationPlugin { enable_3d: false },
))
.add_systems(Startup, setup)
.add_systems(Update, handle_animations_events)
.run();
}

fn setup(mut commands: Commands, mut library: ResMut<AnimationLibrary>) {
commands.spawn(Camera2dBundle::default());

// Create a clip that references some frames from a spritesheet

let spritesheet = Spritesheet::new(8, 8);

let clip = Clip::from_frames(spritesheet.row(3));

let clip_id = library.register_clip(clip);

// Create an animation that uses the clip

let animation = Animation::from_clip(clip_id);

let animation_id = library.register_animation(animation);

// Name the animation to retrieve it from other systems

library.name_animation(animation_id, "walk").unwrap();

// Spawn a sprite with Bevy's built-in SpriteBundle

commands.spawn((
// We dont even need a TextureAtlas since its only used for bevy_render (and we aren't rendering anything)

// Add a SpritesheetAnimation component that references our animation
SpritesheetAnimation::from_id(animation_id),
));
}

fn handle_animations_events(mut events: EventReader<AnimationEvent>) {
for event in events.read() {
dbg!(event);
}
}
2 changes: 1 addition & 1 deletion examples/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, keyboard)
Expand Down
2 changes: 1 addition & 1 deletion examples/stress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
SpritesheetAnimationPlugin::default(),
bevy::diagnostic::FrameTimeDiagnosticsPlugin,
PerfUiPlugin,
))
Expand Down
46 changes: 23 additions & 23 deletions src/animator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
pub mod cache;
mod iterator;

use self::{iterator::AnimationIterator, iterator::IteratorFrame};
use crate::{
animation::AnimationId,
components::spritesheet_animation::{AnimationProgress, SpritesheetAnimation},
events::AnimationEvent,
library::AnimationLibrary,
};
use bevy::time::Time;
use bevy::{
ecs::{
entity::Entity,
Expand All @@ -10,19 +18,9 @@ use bevy::{
},
reflect::prelude::*,
sprite::TextureAtlas,
time::Time,
};
use iterator::AnimationIteratorEvent;
use std::collections::HashMap;

use crate::{
animation::AnimationId,
components::spritesheet_animation::{AnimationProgress, SpritesheetAnimation},
events::AnimationEvent,
library::AnimationLibrary,
};

use self::{iterator::AnimationIterator, iterator::IteratorFrame};
use std::{collections::HashMap, time::Duration};

#[derive(Debug, Reflect)]
#[reflect(Debug)]
Expand All @@ -35,7 +33,7 @@ struct AnimationInstance {
current_frame: Option<(IteratorFrame, AnimationProgress)>,

/// Time accumulated since the last frame
accumulated_time: u32,
accumulated_time: Duration,
}

/// The animator is responsible for playing animations as time advances.
Expand All @@ -54,7 +52,7 @@ impl Animator {
time: &Time,
library: &AnimationLibrary,
event_writer: &mut EventWriter<AnimationEvent>,
query: &mut Query<(Entity, &mut SpritesheetAnimation, &mut TextureAtlas)>,
query: &mut Query<(Entity, &mut SpritesheetAnimation, Option<&mut TextureAtlas>)>,
) {
// Clear outdated animation instances associated to entities that do not have the component anymore

Expand Down Expand Up @@ -94,7 +92,7 @@ impl Animator {
&mut iterator,
&mut entity_animation,
&entity,
&mut entity_atlas,
entity_atlas.as_deref_mut(),
event_writer,
);

Expand All @@ -104,7 +102,7 @@ impl Animator {
animation_id: entity_animation.animation_id,
iterator,
current_frame: first_frame,
accumulated_time: 0,
accumulated_time: Duration::ZERO,
},
);
}
Expand All @@ -124,12 +122,12 @@ impl Animator {
&mut animation_instance.iterator,
&mut entity_animation,
&entity,
&mut entity_atlas,
entity_atlas.as_deref_mut(),
event_writer,
)
.inspect(|new_frame| {
animation_instance.current_frame = Some(new_frame.clone());
animation_instance.accumulated_time = 0;
animation_instance.accumulated_time = Duration::ZERO;
});
} else {
// Restore to the last valid progress if invalid
Expand All @@ -152,7 +150,7 @@ impl Animator {
// Update the animation

animation_instance.accumulated_time +=
(time.delta_seconds() * entity_animation.speed_factor * 1000.0) as u32;
Duration::from_secs_f32(time.delta_seconds() * entity_animation.speed_factor);

while let Some(current_frame) = animation_instance
.current_frame
Expand All @@ -169,7 +167,7 @@ impl Animator {
&mut animation_instance.iterator,
&mut entity_animation,
&entity,
&mut entity_atlas,
entity_atlas.as_deref_mut(),
event_writer,
)
.or_else(|| {
Expand Down Expand Up @@ -211,17 +209,19 @@ impl Animator {
iterator: &mut AnimationIterator,
animation: &mut SpritesheetAnimation,
entity: &Entity,
atlas: &mut TextureAtlas,
maybe_atlas: Option<&mut TextureAtlas>,
event_writer: &mut EventWriter<AnimationEvent>,
) -> Option<(IteratorFrame, AnimationProgress)> {
let maybe_frame = iterator.next();

if let Some((frame, progress)) = &maybe_frame {
// Update the sprite

if atlas.index != frame.atlas_index {
// prevents needless "Changed" events
atlas.index = frame.atlas_index;
if let Some(atlas) = maybe_atlas {
if atlas.index != frame.atlas_index {
// prevents needless "Changed" events
atlas.index = frame.atlas_index;
}
}

animation.progress = *progress;
Expand Down
20 changes: 10 additions & 10 deletions src/animator/cache.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use bevy::{log::warn, reflect::prelude::*};

use crate::{
animation::{AnimationDirection, AnimationDuration, AnimationId, AnimationRepeat},
clip::{Clip, ClipId},
Expand All @@ -8,13 +6,15 @@ use crate::{
library::AnimationLibrary,
CRATE_NAME,
};
use bevy::{log::warn, reflect::prelude::*};
use std::time::Duration;

/// A pre-computed frame of animation, ready to be played back.
#[derive(Debug, Clone, Reflect)]
#[reflect(Debug)]
pub struct CacheFrame {
pub atlas_index: usize,
pub duration: u32,
pub duration: Duration,
pub clip_id: ClipId,
pub clip_repetition: usize,
pub events: Vec<AnimationCacheEvent>,
Expand Down Expand Up @@ -242,7 +242,7 @@ impl ClipData {
#[derive(Clone)]
struct Frame {
atlas_index: usize,
duration: u32,
duration: Duration,
markers: Vec<AnimationMarkerId>,
}

Expand Down Expand Up @@ -271,12 +271,12 @@ impl ClipRepetitionFrames {

Frame {
atlas_index: *frame_atlas_index,
duration: frame_duration_ms,
duration: Duration::from_millis(frame_duration_ms as u64),
markers,
}
})
// Filter out frames with no duration
.filter(|frame| frame.duration > 0)
.filter(|frame| !frame.duration.is_zero())
.collect(),
}
}
Expand Down Expand Up @@ -502,7 +502,7 @@ impl AnimationFrames {
}
}

fn apply_easing(frame_durations: Vec<&mut u32>, easing: Easing) {
fn apply_easing(frame_durations: Vec<&mut Duration>, easing: Easing) {
// Linear easing: there's nothing to do

if matches!(easing, Easing::Linear) {
Expand All @@ -511,7 +511,7 @@ fn apply_easing(frame_durations: Vec<&mut u32>, easing: Easing) {

// If the total duration is zero, exit early to prevent arithmetic errors

let total_duration_ms: u32 = frame_durations.iter().map(|f| **f).sum();
let total_duration_ms: u32 = frame_durations.iter().map(|d| d.as_millis() as u32).sum();

if total_duration_ms == 0 {
warn!("{CRATE_NAME}: zero duration, cannot apply easing");
Expand All @@ -537,11 +537,11 @@ fn apply_easing(frame_durations: Vec<&mut u32>, easing: Easing) {

let eased_duration = (eased_time - previous_eased_time) as u32;

accumulated_time += *frame_duration;
accumulated_time += frame_duration.as_millis();
previous_eased_time = eased_time;

// Update the frame

*frame_duration = eased_duration;
*frame_duration = Duration::from_millis(eased_duration as u64);
}
}
4 changes: 2 additions & 2 deletions src/animator/iterator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{sync::Arc, time::Duration};

use bevy::{log::warn, reflect::prelude::*};

Expand All @@ -14,7 +14,7 @@ use super::cache::{AnimationCache, AnimationCacheEvent, CacheFrame};
#[reflect(Debug)]
pub struct IteratorFrame {
pub atlas_index: usize,
pub duration: u32,
pub duration: Duration,
pub clip_id: ClipId,
pub clip_repetition: usize,
pub animation_repetition: usize,
Expand Down
Loading

0 comments on commit 27c7f8e

Please sign in to comment.