Skip to content
Snippets Groups Projects
Verified Commit ed708608 authored by Louis's avatar Louis :fire:
Browse files

Upgrade to Bevy 0.10

parent 38082690
No related branches found
No related tags found
No related merge requests found
...@@ -25,10 +25,10 @@ bevy_text = ["bevy/bevy_text", "bevy/bevy_render"] ...@@ -25,10 +25,10 @@ bevy_text = ["bevy/bevy_text", "bevy/bevy_render"]
[dependencies] [dependencies]
interpolation = "0.2" interpolation = "0.2"
bevy = { version = "0.9", default-features = false } bevy = { version = "0.10", default-features = false }
[dev-dependencies] [dev-dependencies]
bevy-inspector-egui = "0.14" bevy-inspector-egui = "0.18.0"
[[example]] [[example]]
name = "menu" name = "menu"
...@@ -61,7 +61,7 @@ required-features = [ "bevy_text", "bevy/bevy_winit" ] ...@@ -61,7 +61,7 @@ required-features = [ "bevy_text", "bevy/bevy_winit" ]
[[example]] [[example]]
name = "sequence" name = "sequence"
required-features = [ "bevy/bevy_winit" ] required-features = [ "bevy/bevy_winit" ]
#
[workspace] #[workspace]
resolver = "2" #resolver = "2"
members = [".", "benchmarks/"] #members = [".", "benchmarks/"]
...@@ -38,32 +38,34 @@ use crate::{tweenable::ComponentTarget, Animator, AnimatorState, TweenCompleted} ...@@ -38,32 +38,34 @@ use crate::{tweenable::ComponentTarget, Animator, AnimatorState, TweenCompleted}
pub struct TweeningPlugin; pub struct TweeningPlugin;
impl Plugin for TweeningPlugin { impl Plugin for TweeningPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<TweenCompleted>().add_system( app.add_event::<TweenCompleted>().add_system(
component_animator_system::<Transform>.label(AnimationSystem::AnimationUpdate), component_animator_system::<Transform>.in_set(AnimationSystem::AnimationUpdate),
); );
#[cfg(feature = "bevy_ui")] #[cfg(feature = "bevy_ui")]
app.add_system(component_animator_system::<Style>.label(AnimationSystem::AnimationUpdate)); app.add_system(component_animator_system::<Style>.in_set(AnimationSystem::AnimationUpdate));
#[cfg(feature = "bevy_sprite")] #[cfg(feature = "bevy_sprite")]
app.add_system(component_animator_system::<Sprite>.label(AnimationSystem::AnimationUpdate)); app.add_system(
component_animator_system::<Sprite>.in_set(AnimationSystem::AnimationUpdate),
#[cfg(all(feature = "bevy_sprite", feature = "bevy_asset"))] );
app.add_system(
asset_animator_system::<ColorMaterial>.label(AnimationSystem::AnimationUpdate), #[cfg(all(feature = "bevy_sprite", feature = "bevy_asset"))]
); app.add_system(
asset_animator_system::<ColorMaterial>.in_set(AnimationSystem::AnimationUpdate),
#[cfg(feature = "bevy_text")] );
app.add_system(component_animator_system::<Text>.label(AnimationSystem::AnimationUpdate));
} #[cfg(feature = "bevy_text")]
app.add_system(component_animator_system::<Text>.in_set(AnimationSystem::AnimationUpdate));
}
} }
/// Label enum for the systems relating to animations /// Label enum for the systems relating to animations
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, SystemLabel)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, SystemSet)]
pub enum AnimationSystem { pub enum AnimationSystem {
/// Ticks animations /// Ticks animations
AnimationUpdate, AnimationUpdate,
} }
/// Animator system for components. /// Animator system for components.
...@@ -71,23 +73,23 @@ pub enum AnimationSystem { ...@@ -71,23 +73,23 @@ pub enum AnimationSystem {
/// This system extracts all components of type `T` with an `Animator<T>` /// This system extracts all components of type `T` with an `Animator<T>`
/// attached to the same entity, and tick the animator to animate the component. /// attached to the same entity, and tick the animator to animate the component.
pub fn component_animator_system<T: Component>( pub fn component_animator_system<T: Component>(
time: Res<Time>, time: Res<Time>,
mut query: Query<(Entity, &mut T, &mut Animator<T>)>, mut query: Query<(Entity, &mut T, &mut Animator<T>)>,
events: ResMut<Events<TweenCompleted>>, events: ResMut<Events<TweenCompleted>>,
) { ) {
let mut events: Mut<Events<TweenCompleted>> = events.into(); let mut events: Mut<Events<TweenCompleted>> = events.into();
for (entity, target, mut animator) in query.iter_mut() { for (entity, target, mut animator) in query.iter_mut() {
if animator.state != AnimatorState::Paused { if animator.state != AnimatorState::Paused {
let speed = animator.speed(); let speed = animator.speed();
let mut target = ComponentTarget::new(target); let mut target = ComponentTarget::new(target);
animator.tweenable_mut().tick( animator.tweenable_mut().tick(
time.delta().mul_f32(speed), time.delta().mul_f32(speed),
&mut target, &mut target,
entity, entity,
&mut events, &mut events,
); );
} }
} }
} }
/// Animator system for assets. /// Animator system for assets.
...@@ -98,166 +100,166 @@ pub fn component_animator_system<T: Component>( ...@@ -98,166 +100,166 @@ pub fn component_animator_system<T: Component>(
/// This requires the `bevy_asset` feature (enabled by default). /// This requires the `bevy_asset` feature (enabled by default).
#[cfg(feature = "bevy_asset")] #[cfg(feature = "bevy_asset")]
pub fn asset_animator_system<T: Asset>( pub fn asset_animator_system<T: Asset>(
time: Res<Time>, time: Res<Time>,
assets: ResMut<Assets<T>>, assets: ResMut<Assets<T>>,
mut query: Query<(Entity, &mut AssetAnimator<T>)>, mut query: Query<(Entity, &mut AssetAnimator<T>)>,
events: ResMut<Events<TweenCompleted>>, events: ResMut<Events<TweenCompleted>>,
) { ) {
let mut events: Mut<Events<TweenCompleted>> = events.into(); let mut events: Mut<Events<TweenCompleted>> = events.into();
let mut target = AssetTarget::new(assets); let mut target = AssetTarget::new(assets);
for (entity, mut animator) in query.iter_mut() { for (entity, mut animator) in query.iter_mut() {
if animator.state != AnimatorState::Paused { if animator.state != AnimatorState::Paused {
target.handle = animator.handle().clone(); target.handle = animator.handle().clone();
if !target.is_valid() { if !target.is_valid() {
continue; continue;
} }
let speed = animator.speed(); let speed = animator.speed();
animator.tweenable_mut().tick( animator.tweenable_mut().tick(
time.delta().mul_f32(speed), time.delta().mul_f32(speed),
&mut target, &mut target,
entity, entity,
&mut events, &mut events,
); );
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use bevy::prelude::{Events, IntoSystem, System, Transform, World}; use bevy::prelude::{Events, IntoSystem, System, Transform, World};
use crate::{lens::TransformPositionLens, *}; use crate::{lens::TransformPositionLens, *};
/// A simple isolated test environment with a [`World`] and a single /// A simple isolated test environment with a [`World`] and a single
/// [`Entity`] in it. /// [`Entity`] in it.
struct TestEnv { struct TestEnv {
world: World, world: World,
entity: Entity, entity: Entity,
} }
impl TestEnv { impl TestEnv {
/// Create a new test environment containing a single entity with a /// Create a new test environment containing a single entity with a
/// [`Transform`], and add the given animator on that same entity. /// [`Transform`], and add the given animator on that same entity.
pub fn new<T: Component>(animator: T) -> Self { pub fn new<T: Component>(animator: T) -> Self {
let mut world = World::new(); let mut world = World::new();
world.init_resource::<Events<TweenCompleted>>(); world.init_resource::<Events<TweenCompleted>>();
let mut time = Time::default(); let mut time = Time::default();
time.update(); time.update();
world.insert_resource(time); world.insert_resource(time);
let entity = world.spawn((Transform::default(), animator)).id(); let entity = world.spawn((Transform::default(), animator)).id();
Self { world, entity } Self { world, entity }
} }
/// Get the test world. /// Get the test world.
pub fn world_mut(&mut self) -> &mut World { pub fn world_mut(&mut self) -> &mut World {
&mut self.world &mut self.world
} }
/// Tick the test environment, updating the simulation time and ticking /// Tick the test environment, updating the simulation time and ticking
/// the given system. /// the given system.
pub fn tick(&mut self, duration: Duration, system: &mut dyn System<In = (), Out = ()>) { pub fn tick(&mut self, duration: Duration, system: &mut dyn System<In = (), Out = ()>) {
// Simulate time passing by updating the simulation time resource // Simulate time passing by updating the simulation time resource
{ {
let mut time = self.world.resource_mut::<Time>(); let mut time = self.world.resource_mut::<Time>();
let last_update = time.last_update().unwrap(); let last_update = time.last_update().unwrap();
time.update_with_instant(last_update + duration); time.update_with_instant(last_update + duration);
} }
// Reset world-related change detection // Reset world-related change detection
self.world.clear_trackers(); self.world.clear_trackers();
assert!(!self.transform().is_changed()); assert!(!self.transform().is_changed());
// Tick system // Tick system
system.run((), &mut self.world); system.run((), &mut self.world);
// Update events after system ticked, in case system emitted some events // Update events after system ticked, in case system emitted some events
let mut events = self.world.resource_mut::<Events<TweenCompleted>>(); let mut events = self.world.resource_mut::<Events<TweenCompleted>>();
events.update(); events.update();
} }
/// Get the animator for the transform. /// Get the animator for the transform.
pub fn animator(&self) -> &Animator<Transform> { pub fn animator(&self) -> &Animator<Transform> {
self.world self.world
.entity(self.entity) .entity(self.entity)
.get::<Animator<Transform>>() .get::<Animator<Transform>>()
.unwrap() .unwrap()
} }
/// Get the transform component. /// Get the transform component.
pub fn transform(&mut self) -> Mut<Transform> { pub fn transform(&mut self) -> Mut<Transform> {
self.world.get_mut::<Transform>(self.entity).unwrap() self.world.get_mut::<Transform>(self.entity).unwrap()
} }
/// Get the emitted event count since last tick. /// Get the emitted event count since last tick.
pub fn event_count(&self) -> usize { pub fn event_count(&self) -> usize {
let events = self.world.resource::<Events<TweenCompleted>>(); let events = self.world.resource::<Events<TweenCompleted>>();
events.get_reader().len(events) events.get_reader().len(events)
} }
} }
#[test] #[test]
fn change_detect_component() { fn change_detect_component() {
let tween = Tween::new( let tween = Tween::new(
EaseMethod::Linear, EaseMethod::Linear,
Duration::from_secs(1), Duration::from_secs(1),
TransformPositionLens { TransformPositionLens {
start: Vec3::ZERO, start: Vec3::ZERO,
end: Vec3::ONE, end: Vec3::ONE,
}, },
) )
.with_completed_event(0); .with_completed_event(0);
let mut env = TestEnv::new(Animator::new(tween)); let mut env = TestEnv::new(Animator::new(tween));
// After being inserted, components are always considered changed // After being inserted, components are always considered changed
let transform = env.transform(); let transform = env.transform();
assert!(transform.is_changed()); assert!(transform.is_changed());
//fn nit() {} //fn nit() {}
//let mut system = IntoSystem::into_system(nit); //let mut system = IntoSystem::into_system(nit);
let mut system = IntoSystem::into_system(component_animator_system::<Transform>); let mut system = IntoSystem::into_system(component_animator_system::<Transform>);
system.initialize(env.world_mut()); system.initialize(env.world_mut());
env.tick(Duration::ZERO, &mut system); env.tick(Duration::ZERO, &mut system);
let animator = env.animator(); let animator = env.animator();
assert_eq!(animator.state, AnimatorState::Playing); assert_eq!(animator.state, AnimatorState::Playing);
assert_eq!(animator.tweenable().times_completed(), 0); assert_eq!(animator.tweenable().times_completed(), 0);
let transform = env.transform(); let transform = env.transform();
assert!(transform.is_changed()); assert!(transform.is_changed());
assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5)); assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
env.tick(Duration::from_millis(500), &mut system); env.tick(Duration::from_millis(500), &mut system);
assert_eq!(env.event_count(), 0); assert_eq!(env.event_count(), 0);
let animator = env.animator(); let animator = env.animator();
assert_eq!(animator.state, AnimatorState::Playing); assert_eq!(animator.state, AnimatorState::Playing);
assert_eq!(animator.tweenable().times_completed(), 0); assert_eq!(animator.tweenable().times_completed(), 0);
let transform = env.transform(); let transform = env.transform();
assert!(transform.is_changed()); assert!(transform.is_changed());
assert!(transform.translation.abs_diff_eq(Vec3::splat(0.5), 1e-5)); assert!(transform.translation.abs_diff_eq(Vec3::splat(0.5), 1e-5));
env.tick(Duration::from_millis(500), &mut system); env.tick(Duration::from_millis(500), &mut system);
assert_eq!(env.event_count(), 1); assert_eq!(env.event_count(), 1);
let animator = env.animator(); let animator = env.animator();
assert_eq!(animator.state, AnimatorState::Playing); assert_eq!(animator.state, AnimatorState::Playing);
assert_eq!(animator.tweenable().times_completed(), 1); assert_eq!(animator.tweenable().times_completed(), 1);
let transform = env.transform(); let transform = env.transform();
assert!(transform.is_changed()); assert!(transform.is_changed());
assert!(transform.translation.abs_diff_eq(Vec3::ONE, 1e-5)); assert!(transform.translation.abs_diff_eq(Vec3::ONE, 1e-5));
env.tick(Duration::from_millis(100), &mut system); env.tick(Duration::from_millis(100), &mut system);
assert_eq!(env.event_count(), 0); assert_eq!(env.event_count(), 0);
let animator = env.animator(); let animator = env.animator();
assert_eq!(animator.state, AnimatorState::Playing); assert_eq!(animator.state, AnimatorState::Playing);
assert_eq!(animator.tweenable().times_completed(), 1); assert_eq!(animator.tweenable().times_completed(), 1);
let transform = env.transform(); let transform = env.transform();
assert!(!transform.is_changed()); assert!(!transform.is_changed());
assert!(transform.translation.abs_diff_eq(Vec3::ONE, 1e-5)); assert!(transform.translation.abs_diff_eq(Vec3::ONE, 1e-5));
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment