ecs: use Mut<T> tracking pointer everywhere
This commit is contained in:
		
							parent
							
								
									bf164a5936
								
							
						
					
					
						commit
						19fe299f5a
					
				@ -38,7 +38,7 @@ impl Timer {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn timer_system(time: Res<Time>, mut query: Query<&mut Timer>) {
 | 
					pub fn timer_system(time: Res<Time>, mut query: Query<&mut Timer>) {
 | 
				
			||||||
    for timer in &mut query.iter() {
 | 
					    for mut timer in &mut query.iter() {
 | 
				
			||||||
        timer.tick(time.delta_seconds);
 | 
					        timer.tick(time.delta_seconds);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -68,7 +68,7 @@ fn iterate_100k(b: &mut Bencher) {
 | 
				
			|||||||
        world.spawn((Position(-(i as f32)), Velocity(i as f32)));
 | 
					        world.spawn((Position(-(i as f32)), Velocity(i as f32)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    b.iter(|| {
 | 
					    b.iter(|| {
 | 
				
			||||||
        for (pos, vel) in &mut world.query::<(&mut Position, &Velocity)>() {
 | 
					        for (mut pos, vel) in &mut world.query::<(&mut Position, &Velocity)>() {
 | 
				
			||||||
            pos.0 += vel.0;
 | 
					            pos.0 += vel.0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ pub use borrow::{EntityRef, Ref, RefMut};
 | 
				
			|||||||
pub use bundle::{Bundle, DynamicBundle, MissingComponent};
 | 
					pub use bundle::{Bundle, DynamicBundle, MissingComponent};
 | 
				
			||||||
pub use entities::{Entity, Location, NoSuchEntity};
 | 
					pub use entities::{Entity, Location, NoSuchEntity};
 | 
				
			||||||
pub use entity_builder::{BuiltEntity, EntityBuilder};
 | 
					pub use entity_builder::{BuiltEntity, EntityBuilder};
 | 
				
			||||||
pub use query::{Access, BatchedIter, Query, QueryBorrow, QueryIter, With, Without};
 | 
					pub use query::{Access, BatchedIter, Query, QueryBorrow, QueryIter, With, Without, Mut, Changed};
 | 
				
			||||||
pub use query_one::QueryOne;
 | 
					pub use query_one::QueryOne;
 | 
				
			||||||
pub use world::{ArchetypesGeneration, Component, ComponentError, Iter, SpawnBatchIter, World};
 | 
					pub use world::{ArchetypesGeneration, Component, ComponentError, Iter, SpawnBatchIter, World};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// modified by Bevy contributors
 | 
					// modified by Bevy contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use core::{marker::PhantomData, ptr::NonNull};
 | 
					use core::{marker::PhantomData, ptr::NonNull, ops::{Deref, DerefMut}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{archetype::Archetype, Component, Entity};
 | 
					use crate::{archetype::Archetype, Component, Entity};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,40 +140,7 @@ impl<'a, T: Component> Fetch<'a> for FetchRead<T> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'a, T: Component> Query for &'a mut T {
 | 
					impl<'a, T: Component> Query for &'a mut T {
 | 
				
			||||||
    type Fetch = FetchWrite<T>;
 | 
					    type Fetch = FetchMut<T>;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[doc(hidden)]
 | 
					 | 
				
			||||||
pub struct FetchWrite<T>(NonNull<T>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component> Fetch<'a> for FetchWrite<T> {
 | 
					 | 
				
			||||||
    type Item = &'a mut T;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn access(archetype: &Archetype) -> Option<Access> {
 | 
					 | 
				
			||||||
        if archetype.has::<T>() {
 | 
					 | 
				
			||||||
            Some(Access::Write)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn borrow(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        archetype.borrow_mut::<T>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
 | 
					 | 
				
			||||||
        archetype
 | 
					 | 
				
			||||||
            .get::<T>()
 | 
					 | 
				
			||||||
            .map(|x| Self(NonNull::new_unchecked(x.as_ptr().add(offset))))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn release(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        archetype.release_mut::<T>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unsafe fn next(&mut self) -> &'a mut T {
 | 
					 | 
				
			||||||
        let x = self.0.as_ptr();
 | 
					 | 
				
			||||||
        self.0 = NonNull::new_unchecked(x.add(1));
 | 
					 | 
				
			||||||
        &mut *x
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: Query> Query for Option<T> {
 | 
					impl<T: Query> Query for Option<T> {
 | 
				
			||||||
@ -665,8 +632,129 @@ macro_rules! tuple_impl {
 | 
				
			|||||||
//smaller_tuples_too!(tuple_impl, B, A);
 | 
					//smaller_tuples_too!(tuple_impl, B, A);
 | 
				
			||||||
smaller_tuples_too!(tuple_impl, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A);
 | 
					smaller_tuples_too!(tuple_impl, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Unique borrow of an entity's component
 | 
				
			||||||
 | 
					pub struct Mut<'a, T: Component> {
 | 
				
			||||||
 | 
					    value: &'a mut T,
 | 
				
			||||||
 | 
					    modified: &'a mut bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsafe impl<T: Component> Send for Mut<'_, T> {}
 | 
				
			||||||
 | 
					unsafe impl<T: Component> Sync for Mut<'_, T> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> Deref for Mut<'a, T> {
 | 
				
			||||||
 | 
					    type Target = T;
 | 
				
			||||||
 | 
					    fn deref(&self) -> &T {
 | 
				
			||||||
 | 
					        self.value
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> DerefMut for Mut<'a, T> {
 | 
				
			||||||
 | 
					    fn deref_mut(&mut self) -> &mut T {
 | 
				
			||||||
 | 
					        *self.modified = true;
 | 
				
			||||||
 | 
					        self.value
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> Query for Mut<'a, T> {
 | 
				
			||||||
 | 
					    type Fetch = FetchMut<T>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#[doc(hidden)]
 | 
				
			||||||
 | 
					pub struct FetchMut<T>(NonNull<T>, NonNull<bool>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> Fetch<'a> for FetchMut<T> {
 | 
				
			||||||
 | 
					    type Item = Mut<'a, T>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn access(archetype: &Archetype) -> Option<Access> {
 | 
				
			||||||
 | 
					        if archetype.has::<T>() {
 | 
				
			||||||
 | 
					            Some(Access::Write)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn borrow(archetype: &Archetype) {
 | 
				
			||||||
 | 
					        archetype.borrow_mut::<T>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
 | 
				
			||||||
 | 
					        archetype
 | 
				
			||||||
 | 
					            .get_with_modified::<T>()
 | 
				
			||||||
 | 
					            .map(|(components, modified)| {
 | 
				
			||||||
 | 
					                Self(
 | 
				
			||||||
 | 
					                    NonNull::new_unchecked(components.as_ptr().add(offset)),
 | 
				
			||||||
 | 
					                    NonNull::new_unchecked(modified.as_ptr().add(offset)),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn release(archetype: &Archetype) {
 | 
				
			||||||
 | 
					        archetype.release_mut::<T>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe fn next(&mut self) -> Mut<'a, T> {
 | 
				
			||||||
 | 
					        let component = self.0.as_ptr();
 | 
				
			||||||
 | 
					        let modified = self.1.as_ptr();
 | 
				
			||||||
 | 
					        self.0 = NonNull::new_unchecked(component.add(1));
 | 
				
			||||||
 | 
					        self.1 = NonNull::new_unchecked(modified.add(1));
 | 
				
			||||||
 | 
					        Mut {
 | 
				
			||||||
 | 
					            value: &mut *component,
 | 
				
			||||||
 | 
					            modified: &mut *modified,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[allow(missing_docs)]
 | 
				
			||||||
 | 
					pub struct Changed<T, Q>(PhantomData<(Q, fn(T))>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: Component, Q: Query> Query for Changed<T, Q> {
 | 
				
			||||||
 | 
					    type Fetch = FetchChanged<T, Q::Fetch>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[doc(hidden)]
 | 
				
			||||||
 | 
					pub struct FetchChanged<T, F>(F, PhantomData<fn(T)>, NonNull<bool>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchChanged<T, F> {
 | 
				
			||||||
 | 
					    type Item = F::Item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn access(archetype: &Archetype) -> Option<Access> {
 | 
				
			||||||
 | 
					        if archetype.has::<T>() {
 | 
				
			||||||
 | 
					            F::access(archetype)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn borrow(archetype: &Archetype) {
 | 
				
			||||||
 | 
					        F::borrow(archetype)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
 | 
				
			||||||
 | 
					        if !archetype.has::<T>() {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Some(Self(
 | 
				
			||||||
 | 
					            F::get(archetype, offset)?,
 | 
				
			||||||
 | 
					            PhantomData,
 | 
				
			||||||
 | 
					            NonNull::new_unchecked(archetype.get_modified::<T>()?.as_ptr().add(offset)),
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn release(archetype: &Archetype) {
 | 
				
			||||||
 | 
					        F::release(archetype)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe fn should_skip(&self) -> bool {
 | 
				
			||||||
 | 
					        // skip if the current item wasn't changed
 | 
				
			||||||
 | 
					        !*self.2.as_ref() || self.0.should_skip()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe fn next(&mut self) -> F::Item {
 | 
				
			||||||
 | 
					        self.2 = NonNull::new_unchecked(self.2.as_ptr().add(1));
 | 
				
			||||||
 | 
					        self.0.next()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use crate::{Entity, World, Mut, Changed};
 | 
				
			||||||
 | 
					    use std::{vec::Vec, vec};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
@ -675,4 +763,98 @@ mod tests {
 | 
				
			|||||||
        assert!(Access::Read > Access::Iterate);
 | 
					        assert!(Access::Read > Access::Iterate);
 | 
				
			||||||
        assert!(Some(Access::Iterate) > None);
 | 
					        assert!(Some(Access::Iterate) > None);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					
 | 
				
			||||||
 | 
					    struct A(usize);
 | 
				
			||||||
 | 
					    struct B(usize);
 | 
				
			||||||
 | 
					    struct C;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn modified_trackers() {
 | 
				
			||||||
 | 
					        let mut world = World::default();
 | 
				
			||||||
 | 
					        let e1 = world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					        let e2 = world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					        let e3 = world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					        world.spawn((A(0), B));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i, mut a) in world.query::<Mut<A>>().iter().enumerate() {
 | 
				
			||||||
 | 
					            if i % 2 == 0 {
 | 
				
			||||||
 | 
					                a.0 += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn get_changed_a(world: &World) -> Vec<Entity> {
 | 
				
			||||||
 | 
					            world
 | 
				
			||||||
 | 
					                .query::<Changed<A, Entity>>()
 | 
				
			||||||
 | 
					                .iter()
 | 
				
			||||||
 | 
					                .collect::<Vec<Entity>>()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(get_changed_a(&world), vec![e1, e3]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ensure changing an entity's archetypes also moves its modified state
 | 
				
			||||||
 | 
					        world.insert(e1, (C,)).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(get_changed_a(&world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // spawning a new A entity should not change existing modified state
 | 
				
			||||||
 | 
					        world.insert(e1, (A(0), B)).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            get_changed_a(&world),
 | 
				
			||||||
 | 
					            vec![e3, e1],
 | 
				
			||||||
 | 
					            "changed entities list should not change"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // removing an unchanged entity should not change modified state
 | 
				
			||||||
 | 
					        world.despawn(e2).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            get_changed_a(&world),
 | 
				
			||||||
 | 
					            vec![e3, e1],
 | 
				
			||||||
 | 
					            "changed entities list should not change"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // removing a changed entity should remove it from enumeration
 | 
				
			||||||
 | 
					        world.despawn(e1).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            get_changed_a(&world),
 | 
				
			||||||
 | 
					            vec![e3],
 | 
				
			||||||
 | 
					            "e1 should no longer be returned"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        world.clear_trackers();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(world
 | 
				
			||||||
 | 
					            .query::<Changed<A, Entity>>()
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .collect::<Vec<Entity>>()
 | 
				
			||||||
 | 
					            .is_empty());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn nested_changed_query() {
 | 
				
			||||||
 | 
					        let mut world = World::default();
 | 
				
			||||||
 | 
					        world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					        let e2 = world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					        world.spawn((A(0), B(0)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for mut a in world.query::<Mut<A>>().iter() {
 | 
				
			||||||
 | 
					            a.0 += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for mut b in world.query::<Mut<B>>().iter().skip(1).take(1) {
 | 
				
			||||||
 | 
					            b.0 += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let a_b_changed = world
 | 
				
			||||||
 | 
					            .query::<Changed<A, Changed<B, Entity>>>()
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .collect::<Vec<Entity>>();
 | 
				
			||||||
 | 
					        assert_eq!(a_b_changed, vec![e2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let a_b_changed_tuple = world
 | 
				
			||||||
 | 
					            .query::<(Changed<A, Entity>, Changed<B, &B>)>()
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(|(e, _b)| e)
 | 
				
			||||||
 | 
					            .collect::<Vec<Entity>>();
 | 
				
			||||||
 | 
					        assert_eq!(a_b_changed_tuple, vec![e2]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -6,7 +6,7 @@ mod world;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub use resource::*;
 | 
					pub use resource::*;
 | 
				
			||||||
pub use schedule::*;
 | 
					pub use schedule::*;
 | 
				
			||||||
pub use system::{*, Query};
 | 
					pub use system::{Query, *};
 | 
				
			||||||
pub use world::*;
 | 
					pub use world::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod prelude {
 | 
					pub mod prelude {
 | 
				
			||||||
@ -15,7 +15,7 @@ pub mod prelude {
 | 
				
			|||||||
        system::{
 | 
					        system::{
 | 
				
			||||||
            Commands, IntoForEachSystem, IntoQuerySystem, IntoThreadLocalSystem, Query, System,
 | 
					            Commands, IntoForEachSystem, IntoQuerySystem, IntoThreadLocalSystem, Query, System,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        world::{WorldBuilderSource, Track},
 | 
					        world::WorldBuilderSource,
 | 
				
			||||||
        Bundle, Component, Entity, Ref, RefMut, With, Without, World,
 | 
					        Bundle, Component, Entity, Ref, RefMut, With, Without, World,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,224 +0,0 @@
 | 
				
			|||||||
use crate::{Archetype, Component, HecsQuery};
 | 
					 | 
				
			||||||
use hecs::{Access, Fetch};
 | 
					 | 
				
			||||||
use std::{
 | 
					 | 
				
			||||||
    marker::PhantomData,
 | 
					 | 
				
			||||||
    ops::{Deref, DerefMut},
 | 
					 | 
				
			||||||
    ptr::NonNull,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Unique borrow of an entity's component
 | 
					 | 
				
			||||||
pub struct Track<'a, T: Component> {
 | 
					 | 
				
			||||||
    value: &'a mut T,
 | 
					 | 
				
			||||||
    modified: &'a mut bool,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
unsafe impl<T: Component> Send for Track<'_, T> {}
 | 
					 | 
				
			||||||
unsafe impl<T: Component> Sync for Track<'_, T> {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component> Deref for Track<'a, T> {
 | 
					 | 
				
			||||||
    type Target = T;
 | 
					 | 
				
			||||||
    fn deref(&self) -> &T {
 | 
					 | 
				
			||||||
        self.value
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component> DerefMut for Track<'a, T> {
 | 
					 | 
				
			||||||
    fn deref_mut(&mut self) -> &mut T {
 | 
					 | 
				
			||||||
        *self.modified = true;
 | 
					 | 
				
			||||||
        self.value
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component> HecsQuery for Track<'a, T> {
 | 
					 | 
				
			||||||
    type Fetch = FetchTrack<T>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#[doc(hidden)]
 | 
					 | 
				
			||||||
pub struct FetchTrack<T>(NonNull<T>, NonNull<bool>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component> Fetch<'a> for FetchTrack<T> {
 | 
					 | 
				
			||||||
    type Item = Track<'a, T>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn access(archetype: &Archetype) -> Option<Access> {
 | 
					 | 
				
			||||||
        if archetype.has::<T>() {
 | 
					 | 
				
			||||||
            Some(Access::Write)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn borrow(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        archetype.borrow_mut::<T>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
 | 
					 | 
				
			||||||
        archetype
 | 
					 | 
				
			||||||
            .get_with_modified::<T>()
 | 
					 | 
				
			||||||
            .map(|(components, modified)| {
 | 
					 | 
				
			||||||
                Self(
 | 
					 | 
				
			||||||
                    NonNull::new_unchecked(components.as_ptr().add(offset)),
 | 
					 | 
				
			||||||
                    NonNull::new_unchecked(modified.as_ptr().add(offset)),
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn release(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        archetype.release_mut::<T>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unsafe fn next(&mut self) -> Track<'a, T> {
 | 
					 | 
				
			||||||
        let component = self.0.as_ptr();
 | 
					 | 
				
			||||||
        let modified = self.1.as_ptr();
 | 
					 | 
				
			||||||
        self.0 = NonNull::new_unchecked(component.add(1));
 | 
					 | 
				
			||||||
        self.1 = NonNull::new_unchecked(modified.add(1));
 | 
					 | 
				
			||||||
        Track {
 | 
					 | 
				
			||||||
            value: &mut *component,
 | 
					 | 
				
			||||||
            modified: &mut *modified,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct Changed<T, Q>(PhantomData<(Q, fn(T))>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T: Component, Q: HecsQuery> HecsQuery for Changed<T, Q> {
 | 
					 | 
				
			||||||
    type Fetch = FetchChanged<T, Q::Fetch>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[doc(hidden)]
 | 
					 | 
				
			||||||
pub struct FetchChanged<T, F>(F, PhantomData<fn(T)>, NonNull<bool>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchChanged<T, F> {
 | 
					 | 
				
			||||||
    type Item = F::Item;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn access(archetype: &Archetype) -> Option<Access> {
 | 
					 | 
				
			||||||
        if archetype.has::<T>() {
 | 
					 | 
				
			||||||
            F::access(archetype)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn borrow(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        F::borrow(archetype)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
 | 
					 | 
				
			||||||
        if !archetype.has::<T>() {
 | 
					 | 
				
			||||||
            return None;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Some(Self(
 | 
					 | 
				
			||||||
            F::get(archetype, offset)?,
 | 
					 | 
				
			||||||
            PhantomData,
 | 
					 | 
				
			||||||
            NonNull::new_unchecked(archetype.get_modified::<T>()?.as_ptr().add(offset)),
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn release(archetype: &Archetype) {
 | 
					 | 
				
			||||||
        F::release(archetype)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unsafe fn should_skip(&self) -> bool {
 | 
					 | 
				
			||||||
        // skip if the current item wasn't changed
 | 
					 | 
				
			||||||
        !*self.2.as_ref() || self.0.should_skip()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unsafe fn next(&mut self) -> F::Item {
 | 
					 | 
				
			||||||
        self.2 = NonNull::new_unchecked(self.2.as_ptr().add(1));
 | 
					 | 
				
			||||||
        self.0.next()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(test)]
 | 
					 | 
				
			||||||
mod tests {
 | 
					 | 
				
			||||||
    use crate::{Changed, Track};
 | 
					 | 
				
			||||||
    use hecs::{Entity, World};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    struct A(usize);
 | 
					 | 
				
			||||||
    struct B(usize);
 | 
					 | 
				
			||||||
    struct C;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn modified_trackers() {
 | 
					 | 
				
			||||||
        let mut world = World::default();
 | 
					 | 
				
			||||||
        let e1 = world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
        let e2 = world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
        let e3 = world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
        world.spawn((A(0), B));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (i, mut a) in world.query::<Track<A>>().iter().enumerate() {
 | 
					 | 
				
			||||||
            if i % 2 == 0 {
 | 
					 | 
				
			||||||
                a.0 += 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fn get_changed_a(world: &World) -> Vec<Entity> {
 | 
					 | 
				
			||||||
            world
 | 
					 | 
				
			||||||
                .query::<Changed<A, Entity>>()
 | 
					 | 
				
			||||||
                .iter()
 | 
					 | 
				
			||||||
                .collect::<Vec<Entity>>()
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert_eq!(get_changed_a(&world), vec![e1, e3]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // ensure changing an entity's archetypes also moves its modified state
 | 
					 | 
				
			||||||
        world.insert(e1, (C,)).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert_eq!(get_changed_a(&world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // spawning a new A entity should not change existing modified state
 | 
					 | 
				
			||||||
        world.insert(e1, (A(0), B)).unwrap();
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            get_changed_a(&world),
 | 
					 | 
				
			||||||
            vec![e3, e1],
 | 
					 | 
				
			||||||
            "changed entities list should not change"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // removing an unchanged entity should not change modified state
 | 
					 | 
				
			||||||
        world.despawn(e2).unwrap();
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            get_changed_a(&world),
 | 
					 | 
				
			||||||
            vec![e3, e1],
 | 
					 | 
				
			||||||
            "changed entities list should not change"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // removing a changed entity should remove it from enumeration
 | 
					 | 
				
			||||||
        world.despawn(e1).unwrap();
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            get_changed_a(&world),
 | 
					 | 
				
			||||||
            vec![e3],
 | 
					 | 
				
			||||||
            "e1 should no longer be returned"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        world.clear_trackers();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert!(world
 | 
					 | 
				
			||||||
            .query::<Changed<A, Entity>>()
 | 
					 | 
				
			||||||
            .iter()
 | 
					 | 
				
			||||||
            .collect::<Vec<Entity>>()
 | 
					 | 
				
			||||||
            .is_empty());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn nested_changed_query() {
 | 
					 | 
				
			||||||
        let mut world = World::default();
 | 
					 | 
				
			||||||
        world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
        let e2 = world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
        world.spawn((A(0), B(0)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for mut a in world.query::<Track<A>>().iter() {
 | 
					 | 
				
			||||||
            a.0 += 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for mut b in world.query::<Track<B>>().iter().skip(1).take(1) {
 | 
					 | 
				
			||||||
            b.0 += 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let a_b_changed = world
 | 
					 | 
				
			||||||
            .query::<Changed<A, Changed<B, Entity>>>()
 | 
					 | 
				
			||||||
            .iter()
 | 
					 | 
				
			||||||
            .collect::<Vec<Entity>>();
 | 
					 | 
				
			||||||
        assert_eq!(a_b_changed, vec![e2]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let a_b_changed_tuple = world
 | 
					 | 
				
			||||||
            .query::<(Changed<A, Entity>, Changed<B, &B>)>()
 | 
					 | 
				
			||||||
            .iter()
 | 
					 | 
				
			||||||
            .map(|(e, _b)| e)
 | 
					 | 
				
			||||||
            .collect::<Vec<Entity>>();
 | 
					 | 
				
			||||||
        assert_eq!(a_b_changed_tuple, vec![e2]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +1,3 @@
 | 
				
			|||||||
mod component;
 | 
					 | 
				
			||||||
mod world_builder;
 | 
					mod world_builder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use world_builder::*;
 | 
					pub use world_builder::*;
 | 
				
			||||||
pub use component::*;
 | 
					 | 
				
			||||||
@ -62,7 +62,7 @@ pub fn camera_system<T: CameraProjection + Component>(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (mut camera, camera_projection) in &mut query.iter() {
 | 
					    for (mut camera, mut camera_projection) in &mut query.iter() {
 | 
				
			||||||
        if let Some(window) = match camera.window {
 | 
					        if let Some(window) = match camera.window {
 | 
				
			||||||
            WindowReference::Id(id) => {
 | 
					            WindowReference::Id(id) => {
 | 
				
			||||||
                if changed_window_ids.contains(&id) {
 | 
					                if changed_window_ids.contains(&id) {
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ pub fn visible_entities_system(
 | 
				
			|||||||
    mut draw_query: Query<(Entity, &Draw)>,
 | 
					    mut draw_query: Query<(Entity, &Draw)>,
 | 
				
			||||||
    draw_transform_query: Query<(&Draw, &Transform)>,
 | 
					    draw_transform_query: Query<(&Draw, &Transform)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (_camera, camera_transform, visible_entities) in &mut camera_query.iter() {
 | 
					    for (_camera, camera_transform, mut visible_entities) in &mut camera_query.iter() {
 | 
				
			||||||
        visible_entities.value.clear();
 | 
					        visible_entities.value.clear();
 | 
				
			||||||
        let camera_position = camera_transform.value.w_axis().truncate();
 | 
					        let camera_position = camera_transform.value.w_axis().truncate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -392,7 +392,7 @@ pub trait Drawable {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn clear_draw_system(mut query: Query<&mut Draw>) {
 | 
					pub fn clear_draw_system(mut query: Query<&mut Draw>) {
 | 
				
			||||||
    for draw in &mut query.iter() {
 | 
					    for mut draw in &mut query.iter() {
 | 
				
			||||||
        draw.clear_render_commands();
 | 
					        draw.clear_render_commands();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -479,7 +479,7 @@ pub fn mesh_resource_provider_system(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
 | 
					    // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
 | 
				
			||||||
    for (handle, render_pipelines) in &mut query.iter() {
 | 
					    for (handle, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
        if let Some(mesh) = meshes.get(&handle) {
 | 
					        if let Some(mesh) = meshes.get(&handle) {
 | 
				
			||||||
            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
					            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
				
			||||||
                render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
 | 
					                render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
 | 
				
			||||||
 | 
				
			|||||||
@ -438,7 +438,7 @@ fn render_resources_node_system<T: RenderResources>(
 | 
				
			|||||||
        .uniform_buffer_arrays
 | 
					        .uniform_buffer_arrays
 | 
				
			||||||
        .update_staging_buffer(render_resource_context);
 | 
					        .update_staging_buffer(render_resource_context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uniforms, draw, render_pipelines) in &mut query.iter() {
 | 
					    for (uniforms, draw, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
        if !draw.is_visible {
 | 
					        if !draw.is_visible {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -456,7 +456,7 @@ fn render_resources_node_system<T: RenderResources>(
 | 
				
			|||||||
            staging_buffer,
 | 
					            staging_buffer,
 | 
				
			||||||
            0..state.uniform_buffer_arrays.staging_buffer_size as u64,
 | 
					            0..state.uniform_buffer_arrays.staging_buffer_size as u64,
 | 
				
			||||||
            &mut |mut staging_buffer, _render_resource_context| {
 | 
					            &mut |mut staging_buffer, _render_resource_context| {
 | 
				
			||||||
                for (uniforms, draw, render_pipelines) in &mut query.iter() {
 | 
					                for (uniforms, draw, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
                    if !draw.is_visible {
 | 
					                    if !draw.is_visible {
 | 
				
			||||||
                        return;
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -479,7 +479,7 @@ fn render_resources_node_system<T: RenderResources>(
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // TODO: can we just remove this?
 | 
					        // TODO: can we just remove this?
 | 
				
			||||||
        let mut staging_buffer: [u8; 0] = [];
 | 
					        let mut staging_buffer: [u8; 0] = [];
 | 
				
			||||||
        for (uniforms, draw, render_pipelines) in &mut query.iter() {
 | 
					        for (uniforms, draw, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
            if !draw.is_visible {
 | 
					            if !draw.is_visible {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -657,7 +657,7 @@ fn asset_render_resources_node_system<T: RenderResources>(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (asset_handle, _draw, render_pipelines) in &mut query.iter() {
 | 
					    for (asset_handle, _draw, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
        if let Some(asset_bindings) = asset_render_resource_bindings.get(*asset_handle) {
 | 
					        if let Some(asset_bindings) = asset_render_resource_bindings.get(*asset_handle) {
 | 
				
			||||||
            render_pipelines.bindings.extend(asset_bindings);
 | 
					            render_pipelines.bindings.extend(asset_bindings);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -59,7 +59,7 @@ pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines)>)
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    T: ShaderDefs + Send + Sync + 'static,
 | 
					    T: ShaderDefs + Send + Sync + 'static,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (shader_defs, render_pipelines) in &mut query.iter() {
 | 
					    for (shader_defs, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
        for shader_def in shader_defs.iter_shader_defs() {
 | 
					        for shader_def in shader_defs.iter_shader_defs() {
 | 
				
			||||||
            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
					            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
				
			||||||
                render_pipeline
 | 
					                render_pipeline
 | 
				
			||||||
@ -73,7 +73,7 @@ where
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
 | 
					pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
 | 
				
			||||||
    for render_pipelines in &mut query.iter() {
 | 
					    for mut render_pipelines in &mut query.iter() {
 | 
				
			||||||
        for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
					        for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
				
			||||||
            render_pipeline
 | 
					            render_pipeline
 | 
				
			||||||
                .specialization
 | 
					                .specialization
 | 
				
			||||||
@ -90,7 +90,7 @@ pub fn asset_shader_defs_system<T>(
 | 
				
			|||||||
) where
 | 
					) where
 | 
				
			||||||
    T: ShaderDefs + Send + Sync + 'static,
 | 
					    T: ShaderDefs + Send + Sync + 'static,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (asset_handle, render_pipelines) in &mut query.iter() {
 | 
					    for (asset_handle, mut render_pipelines) in &mut query.iter() {
 | 
				
			||||||
        let shader_defs = assets.get(&asset_handle).unwrap();
 | 
					        let shader_defs = assets.get(&asset_handle).unwrap();
 | 
				
			||||||
        for shader_def in shader_defs.iter_shader_defs() {
 | 
					        for shader_def in shader_defs.iter_shader_defs() {
 | 
				
			||||||
            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
					            for render_pipeline in render_pipelines.pipelines.iter_mut() {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@ pub fn sprite_system(
 | 
				
			|||||||
    textures: Res<Assets<Texture>>,
 | 
					    textures: Res<Assets<Texture>>,
 | 
				
			||||||
    mut query: Query<(&mut Sprite, &Handle<ColorMaterial>)>,
 | 
					    mut query: Query<(&mut Sprite, &Handle<ColorMaterial>)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (sprite, handle) in &mut query.iter() {
 | 
					    for (mut sprite, handle) in &mut query.iter() {
 | 
				
			||||||
        let material = materials.get(&handle).unwrap();
 | 
					        let material = materials.get(&handle).unwrap();
 | 
				
			||||||
        if let Some(texture_handle) = material.texture {
 | 
					        if let Some(texture_handle) = material.texture {
 | 
				
			||||||
            if let Some(texture) = textures.get(&texture_handle) {
 | 
					            if let Some(texture) = textures.get(&texture_handle) {
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@ pub fn parent_update_system(
 | 
				
			|||||||
    let mut children_additions = HashMap::<Entity, SmallVec<[Entity; 8]>>::with_capacity(16);
 | 
					    let mut children_additions = HashMap::<Entity, SmallVec<[Entity; 8]>>::with_capacity(16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Entities with a changed Parent (that also have a PreviousParent, even if None)
 | 
					    // Entities with a changed Parent (that also have a PreviousParent, even if None)
 | 
				
			||||||
    for (entity, parent, previous_parent) in &mut changed_parent_query.iter() {
 | 
					    for (entity, parent, mut previous_parent) in &mut changed_parent_query.iter() {
 | 
				
			||||||
        log::trace!("Parent changed for {:?}", entity);
 | 
					        log::trace!("Parent changed for {:?}", entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If the `PreviousParent` is not None.
 | 
					        // If the `PreviousParent` is not None.
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ pub fn local_transform_translation_system(
 | 
				
			|||||||
        >,
 | 
					        >,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation) in &mut query.iter() {
 | 
					    for (mut local, translation) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_translation(translation.0));
 | 
					        *local = LocalTransform(Mat4::from_translation(translation.0));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -26,7 +26,7 @@ pub fn local_transform_rotation_system(
 | 
				
			|||||||
        >,
 | 
					        >,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, rotation) in &mut query.iter() {
 | 
					    for (mut local, rotation) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_quat(rotation.0));
 | 
					        *local = LocalTransform(Mat4::from_quat(rotation.0));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -39,7 +39,7 @@ pub fn local_transform_scale_system(
 | 
				
			|||||||
        >,
 | 
					        >,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, scale) in &mut query.iter() {
 | 
					    for (mut local, scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
 | 
					        *local = LocalTransform(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -52,7 +52,7 @@ pub fn local_transform_non_uniform_scale_system(
 | 
				
			|||||||
        >,
 | 
					        >,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut local, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale(non_uniform_scale.0));
 | 
					        *local = LocalTransform(Mat4::from_scale(non_uniform_scale.0));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -62,7 +62,7 @@ pub fn local_transform_translation_rotation_system(
 | 
				
			|||||||
        Without<Scale, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation)>>,
 | 
					        Without<Scale, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation, rotation) in &mut query.iter() {
 | 
					    for (mut local, translation, rotation) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_rotation_translation(rotation.0, translation.0));
 | 
					        *local = LocalTransform(Mat4::from_rotation_translation(rotation.0, translation.0));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -72,7 +72,7 @@ pub fn local_transform_translation_scale_system(
 | 
				
			|||||||
        Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Scale)>>,
 | 
					        Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Scale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation, scale) in &mut query.iter() {
 | 
					    for (mut local, translation, scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            Vec3::new(scale.0, scale.0, scale.0),
 | 
					            Vec3::new(scale.0, scale.0, scale.0),
 | 
				
			||||||
            Quat::default(),
 | 
					            Quat::default(),
 | 
				
			||||||
@ -86,7 +86,7 @@ pub fn local_transform_translation_non_uniform_scale_system(
 | 
				
			|||||||
        Without<Rotation, Without<Scale, (&mut LocalTransform, &Translation, &NonUniformScale)>>,
 | 
					        Without<Rotation, Without<Scale, (&mut LocalTransform, &Translation, &NonUniformScale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut local, translation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            non_uniform_scale.0,
 | 
					            non_uniform_scale.0,
 | 
				
			||||||
            Quat::default(),
 | 
					            Quat::default(),
 | 
				
			||||||
@ -100,7 +100,7 @@ pub fn local_transform_rotation_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<NonUniformScale, (&mut LocalTransform, &Rotation, &Scale)>>,
 | 
					        Without<Translation, Without<NonUniformScale, (&mut LocalTransform, &Rotation, &Scale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, rotation, scale) in &mut query.iter() {
 | 
					    for (mut local, rotation, scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            Vec3::new(scale.0, scale.0, scale.0),
 | 
					            Vec3::new(scale.0, scale.0, scale.0),
 | 
				
			||||||
            rotation.0,
 | 
					            rotation.0,
 | 
				
			||||||
@ -114,7 +114,7 @@ pub fn local_transform_rotation_non_uniform_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<Scale, (&mut LocalTransform, &Rotation, &NonUniformScale)>>,
 | 
					        Without<Translation, Without<Scale, (&mut LocalTransform, &Rotation, &NonUniformScale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, rotation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut local, rotation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            non_uniform_scale.0,
 | 
					            non_uniform_scale.0,
 | 
				
			||||||
            rotation.0,
 | 
					            rotation.0,
 | 
				
			||||||
@ -128,7 +128,7 @@ pub fn local_transform_translation_rotation_scale_system(
 | 
				
			|||||||
        Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation, &Scale)>,
 | 
					        Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation, &Scale)>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation, rotation, scale) in &mut query.iter() {
 | 
					    for (mut local, translation, rotation, scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            Vec3::new(scale.0, scale.0, scale.0),
 | 
					            Vec3::new(scale.0, scale.0, scale.0),
 | 
				
			||||||
            rotation.0,
 | 
					            rotation.0,
 | 
				
			||||||
@ -150,7 +150,7 @@ pub fn local_transform_translation_rotation_non_uniform_scale_system(
 | 
				
			|||||||
        >,
 | 
					        >,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (local, translation, rotation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut local, translation, rotation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
					        *local = LocalTransform(Mat4::from_scale_rotation_translation(
 | 
				
			||||||
            non_uniform_scale.0,
 | 
					            non_uniform_scale.0,
 | 
				
			||||||
            rotation.0,
 | 
					            rotation.0,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ pub fn transform_translation_system(
 | 
				
			|||||||
        Without<Rotation, Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation)>>>,
 | 
					        Without<Rotation, Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation)>>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation) in &mut query.iter() {
 | 
					    for (mut transform, translation) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -24,7 +24,7 @@ pub fn transform_rotation_system(
 | 
				
			|||||||
        Without<Translation, Without<Scale, Without<NonUniformScale, (&mut Transform, &Rotation)>>>,
 | 
					        Without<Translation, Without<Scale, Without<NonUniformScale, (&mut Transform, &Rotation)>>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, rotation) in &mut query.iter() {
 | 
					    for (mut transform, rotation) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -38,7 +38,7 @@ pub fn transform_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<Rotation, Without<NonUniformScale, (&mut Transform, &Scale)>>>,
 | 
					        Without<Translation, Without<Rotation, Without<NonUniformScale, (&mut Transform, &Scale)>>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, scale) in &mut query.iter() {
 | 
					    for (mut transform, scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -52,7 +52,7 @@ pub fn transform_non_uniform_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<Rotation, Without<Scale, (&mut Transform, &NonUniformScale)>>>,
 | 
					        Without<Translation, Without<Rotation, Without<Scale, (&mut Transform, &NonUniformScale)>>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut transform, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -66,7 +66,7 @@ pub fn transform_translation_rotation_system(
 | 
				
			|||||||
        Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation, &Rotation)>>,
 | 
					        Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation, &Rotation)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation, rotation) in &mut query.iter() {
 | 
					    for (mut transform, translation, rotation) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -80,7 +80,7 @@ pub fn transform_translation_scale_system(
 | 
				
			|||||||
        Without<Rotation, Without<NonUniformScale, (&mut Transform, &Translation, &Scale)>>,
 | 
					        Without<Rotation, Without<NonUniformScale, (&mut Transform, &Translation, &Scale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation, scale) in &mut query.iter() {
 | 
					    for (mut transform, translation, scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -98,7 +98,7 @@ pub fn transform_translation_non_uniform_scale_system(
 | 
				
			|||||||
        Without<Rotation, Without<Scale, (&mut Transform, &Translation, &NonUniformScale)>>,
 | 
					        Without<Rotation, Without<Scale, (&mut Transform, &Translation, &NonUniformScale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut transform, translation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -116,7 +116,7 @@ pub fn transform_rotation_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<NonUniformScale, (&mut Transform, &Rotation, &Scale)>>,
 | 
					        Without<Translation, Without<NonUniformScale, (&mut Transform, &Rotation, &Scale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, rotation, scale) in &mut query.iter() {
 | 
					    for (mut transform, rotation, scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -134,7 +134,7 @@ pub fn transform_rotation_non_uniform_scale_system(
 | 
				
			|||||||
        Without<Translation, Without<Scale, (&mut Transform, &Rotation, &NonUniformScale)>>,
 | 
					        Without<Translation, Without<Scale, (&mut Transform, &Rotation, &NonUniformScale)>>,
 | 
				
			||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, rotation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut transform, rotation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -150,7 +150,7 @@ pub fn transform_rotation_non_uniform_scale_system(
 | 
				
			|||||||
pub fn transform_translation_rotation_scale_system(
 | 
					pub fn transform_translation_rotation_scale_system(
 | 
				
			||||||
    mut query: Query<Without<NonUniformScale, (&mut Transform, &Translation, &Rotation, &Scale)>>,
 | 
					    mut query: Query<Without<NonUniformScale, (&mut Transform, &Translation, &Rotation, &Scale)>>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation, rotation, scale) in &mut query.iter() {
 | 
					    for (mut transform, translation, rotation, scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -166,7 +166,7 @@ pub fn transform_translation_rotation_scale_system(
 | 
				
			|||||||
pub fn transform_translation_rotation_non_uniform_scale_system(
 | 
					pub fn transform_translation_rotation_non_uniform_scale_system(
 | 
				
			||||||
    mut query: Query<Without<Scale, (&mut Transform, &Translation, &Rotation, &NonUniformScale)>>,
 | 
					    mut query: Query<Without<Scale, (&mut Transform, &Translation, &Rotation, &NonUniformScale)>>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, translation, rotation, non_uniform_scale) in &mut query.iter() {
 | 
					    for (mut transform, translation, rotation, non_uniform_scale) in &mut query.iter() {
 | 
				
			||||||
        if !transform.sync {
 | 
					        if !transform.sync {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ fn animate_sprite_system(
 | 
				
			|||||||
    texture_atlases: Res<Assets<TextureAtlas>>,
 | 
					    texture_atlases: Res<Assets<TextureAtlas>>,
 | 
				
			||||||
    mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle<TextureAtlas>)>,
 | 
					    mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle<TextureAtlas>)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (timer, sprite, texture_atlas_handle) in &mut query.iter() {
 | 
					    for (mut timer, mut sprite, texture_atlas_handle) in &mut query.iter() {
 | 
				
			||||||
        if timer.finished {
 | 
					        if timer.finished {
 | 
				
			||||||
            let texture_atlas = texture_atlases.get(&texture_atlas_handle).unwrap();
 | 
					            let texture_atlas = texture_atlases.get(&texture_atlas_handle).unwrap();
 | 
				
			||||||
            sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;
 | 
					            sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ fn main() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// rotates the parent, which will result in the child also rotating
 | 
					/// rotates the parent, which will result in the child also rotating
 | 
				
			||||||
fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Rotation)>) {
 | 
					fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Rotation)>) {
 | 
				
			||||||
    for (_rotator, rotation) in &mut query.iter() {
 | 
					    for (_rotator, mut rotation) in &mut query.iter() {
 | 
				
			||||||
        rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
 | 
					        rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ fn move_cubes(
 | 
				
			|||||||
    mut materials: ResMut<Assets<StandardMaterial>>,
 | 
					    mut materials: ResMut<Assets<StandardMaterial>>,
 | 
				
			||||||
    mut query: Query<(&mut Translation, &Handle<StandardMaterial>)>,
 | 
					    mut query: Query<(&mut Translation, &Handle<StandardMaterial>)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (translation, material_handle) in &mut query.iter() {
 | 
					    for (mut translation, material_handle) in &mut query.iter() {
 | 
				
			||||||
        let material = materials.get_mut(&material_handle).unwrap();
 | 
					        let material = materials.get_mut(&material_handle).unwrap();
 | 
				
			||||||
        translation.0 += Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds;
 | 
					        translation.0 += Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds;
 | 
				
			||||||
        material.albedo += Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
 | 
					        material.albedo += Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ fn new_round_system(game_rules: Res<GameRules>, mut game_state: ResMut<GameState
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// This system updates the score for each entity with the "Player" and "Score" component.
 | 
					// This system updates the score for each entity with the "Player" and "Score" component.
 | 
				
			||||||
fn score_system(mut query: Query<(&Player, &mut Score)>) {
 | 
					fn score_system(mut query: Query<(&Player, &mut Score)>) {
 | 
				
			||||||
    for (player, score) in &mut query.iter() {
 | 
					    for (player, mut score) in &mut query.iter() {
 | 
				
			||||||
        let scored_a_point = random::<bool>();
 | 
					        let scored_a_point = random::<bool>();
 | 
				
			||||||
        if scored_a_point {
 | 
					        if scored_a_point {
 | 
				
			||||||
            score.value += 1;
 | 
					            score.value += 1;
 | 
				
			||||||
 | 
				
			|||||||
@ -159,7 +159,7 @@ fn paddle_movement_system(
 | 
				
			|||||||
    keyboard_input: Res<Input<KeyCode>>,
 | 
					    keyboard_input: Res<Input<KeyCode>>,
 | 
				
			||||||
    mut query: Query<(&Paddle, &mut Translation)>,
 | 
					    mut query: Query<(&Paddle, &mut Translation)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (paddle, translation) in &mut query.iter() {
 | 
					    for (paddle, mut translation) in &mut query.iter() {
 | 
				
			||||||
        let mut direction = 0.0;
 | 
					        let mut direction = 0.0;
 | 
				
			||||||
        if keyboard_input.pressed(KeyCode::Left) {
 | 
					        if keyboard_input.pressed(KeyCode::Left) {
 | 
				
			||||||
            direction -= 1.0;
 | 
					            direction -= 1.0;
 | 
				
			||||||
@ -174,7 +174,7 @@ fn paddle_movement_system(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn ball_movement_system(time: Res<Time>, mut ball_query: Query<(&Ball, &mut Translation)>) {
 | 
					fn ball_movement_system(time: Res<Time>, mut ball_query: Query<(&Ball, &mut Translation)>) {
 | 
				
			||||||
    for (ball, translation) in &mut ball_query.iter() {
 | 
					    for (ball, mut translation) in &mut ball_query.iter() {
 | 
				
			||||||
        translation.0 += ball.velocity * time.delta_seconds;
 | 
					        translation.0 += ball.velocity * time.delta_seconds;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -193,7 +193,7 @@ fn ball_collision_system(
 | 
				
			|||||||
    mut brick_query: Query<(Entity, &Brick, &Translation, &Sprite)>,
 | 
					    mut brick_query: Query<(Entity, &Brick, &Translation, &Sprite)>,
 | 
				
			||||||
    mut wall_query: Query<(&Wall, &Translation, &Sprite)>,
 | 
					    mut wall_query: Query<(&Wall, &Translation, &Sprite)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (ball, translation, sprite) in &mut ball_query.iter() {
 | 
					    for (mut ball, translation, sprite) in &mut ball_query.iter() {
 | 
				
			||||||
        let ball_position = translation.0;
 | 
					        let ball_position = translation.0;
 | 
				
			||||||
        let ball_size = sprite.size;
 | 
					        let ball_size = sprite.size;
 | 
				
			||||||
        let velocity = &mut ball.velocity;
 | 
					        let velocity = &mut ball.velocity;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ fn main() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&mut Label>) {
 | 
					fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&mut Label>) {
 | 
				
			||||||
    for label in &mut query.iter() {
 | 
					    for mut label in &mut query.iter() {
 | 
				
			||||||
        if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
 | 
					        if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
 | 
				
			||||||
            if let Some(average) = fps.average() {
 | 
					            if let Some(average) = fps.average() {
 | 
				
			||||||
                label.text = format!("FPS: {:.2}", average);
 | 
					                label.text = format!("FPS: {:.2}", average);
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ fn placement_system(
 | 
				
			|||||||
    materials: Res<Assets<ColorMaterial>>,
 | 
					    materials: Res<Assets<ColorMaterial>>,
 | 
				
			||||||
    mut query: Query<(&mut Node, &Handle<ColorMaterial>)>,
 | 
					    mut query: Query<(&mut Node, &Handle<ColorMaterial>)>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (node, material_handle) in &mut query.iter() {
 | 
					    for (mut node, material_handle) in &mut query.iter() {
 | 
				
			||||||
        let material = materials.get(&material_handle).unwrap();
 | 
					        let material = materials.get(&material_handle).unwrap();
 | 
				
			||||||
        if material.color.r > 0.2 {
 | 
					        if material.color.r > 0.2 {
 | 
				
			||||||
            node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
 | 
					            node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user