Remove APIs deprecated in 0.13 (#11974)
# Objective We deprecated quite a few APIs in 0.13. 0.13 has shipped already. It should be OK to remove them in 0.14's release. Fixes #4059. Fixes #9011. ## Solution Remove them.
This commit is contained in:
		
							parent
							
								
									f77618eccb
								
							
						
					
					
						commit
						bc82749012
					
				| @ -1,4 +1,4 @@ | ||||
| use bevy_ecs::entity::{Entity, EntityHashMap, EntityHashSet}; | ||||
| use bevy_ecs::entity::{Entity, EntityHashSet}; | ||||
| use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; | ||||
| use rand::{Rng, SeedableRng}; | ||||
| use rand_chacha::ChaCha8Rng; | ||||
|  | ||||
| @ -28,8 +28,6 @@ criterion_group!( | ||||
|     world_query_iter, | ||||
|     world_query_for_each, | ||||
|     world_spawn, | ||||
|     query_get_component_simple, | ||||
|     query_get_component, | ||||
|     query_get, | ||||
|     query_get_many::<2>, | ||||
|     query_get_many::<5>, | ||||
|  | ||||
| @ -2,7 +2,6 @@ use bevy_ecs::{ | ||||
|     bundle::Bundle, | ||||
|     component::Component, | ||||
|     entity::Entity, | ||||
|     prelude::*, | ||||
|     system::{Query, SystemState}, | ||||
|     world::World, | ||||
| }; | ||||
| @ -257,104 +256,6 @@ pub fn world_query_for_each(criterion: &mut Criterion) { | ||||
|     group.finish(); | ||||
| } | ||||
| 
 | ||||
| pub fn query_get_component_simple(criterion: &mut Criterion) { | ||||
|     #[derive(Component)] | ||||
|     struct A(f32); | ||||
| 
 | ||||
|     let mut group = criterion.benchmark_group("query_get_component_simple"); | ||||
|     group.warm_up_time(std::time::Duration::from_millis(500)); | ||||
|     group.measurement_time(std::time::Duration::from_secs(4)); | ||||
| 
 | ||||
|     group.bench_function("unchecked", |bencher| { | ||||
|         let mut world = World::new(); | ||||
| 
 | ||||
|         let entity = world.spawn(A(0.0)).id(); | ||||
|         let mut query = world.query::<&mut A>(); | ||||
| 
 | ||||
|         let world_cell = world.as_unsafe_world_cell(); | ||||
|         bencher.iter(|| { | ||||
|             for _x in 0..100000 { | ||||
|                 let mut a = unsafe { query.get_unchecked(world_cell, entity).unwrap() }; | ||||
|                 a.0 += 1.0; | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
|     group.bench_function("system", |bencher| { | ||||
|         let mut world = World::new(); | ||||
| 
 | ||||
|         let entity = world.spawn(A(0.0)).id(); | ||||
|         fn query_system(In(entity): In<Entity>, mut query: Query<&mut A>) { | ||||
|             for _ in 0..100_000 { | ||||
|                 let mut a = query.get_mut(entity).unwrap(); | ||||
|                 a.0 += 1.0; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let mut system = IntoSystem::into_system(query_system); | ||||
|         system.initialize(&mut world); | ||||
|         system.update_archetype_component_access(world.as_unsafe_world_cell()); | ||||
| 
 | ||||
|         bencher.iter(|| system.run(entity, &mut world)); | ||||
|     }); | ||||
| 
 | ||||
|     group.finish(); | ||||
| } | ||||
| 
 | ||||
| pub fn query_get_component(criterion: &mut Criterion) { | ||||
|     let mut group = criterion.benchmark_group("query_get_component"); | ||||
|     group.warm_up_time(std::time::Duration::from_millis(500)); | ||||
|     group.measurement_time(std::time::Duration::from_secs(4)); | ||||
| 
 | ||||
|     for entity_count in RANGE.map(|i| i * 10_000) { | ||||
|         group.bench_function(format!("{}_entities_table", entity_count), |bencher| { | ||||
|             let mut world = World::default(); | ||||
|             let mut entities: Vec<_> = world | ||||
|                 .spawn_batch((0..entity_count).map(|_| Table::default())) | ||||
|                 .collect(); | ||||
|             entities.shuffle(&mut deterministic_rand()); | ||||
|             let mut query = SystemState::<Query<&Table>>::new(&mut world); | ||||
|             let query = query.get(&world); | ||||
| 
 | ||||
|             bencher.iter(|| { | ||||
|                 let mut count = 0; | ||||
|                 for comp in entities | ||||
|                     .iter() | ||||
|                     .flat_map(|&e| query.get_component::<Table>(e)) | ||||
|                 { | ||||
|                     black_box(comp); | ||||
|                     count += 1; | ||||
|                     black_box(count); | ||||
|                 } | ||||
|                 assert_eq!(black_box(count), entity_count); | ||||
|             }); | ||||
|         }); | ||||
|         group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| { | ||||
|             let mut world = World::default(); | ||||
|             let mut entities: Vec<_> = world | ||||
|                 .spawn_batch((0..entity_count).map(|_| Sparse::default())) | ||||
|                 .collect(); | ||||
|             entities.shuffle(&mut deterministic_rand()); | ||||
|             let mut query = SystemState::<Query<&Sparse>>::new(&mut world); | ||||
|             let query = query.get(&world); | ||||
| 
 | ||||
|             bencher.iter(|| { | ||||
|                 let mut count = 0; | ||||
|                 for comp in entities | ||||
|                     .iter() | ||||
|                     .flat_map(|&e| query.get_component::<Sparse>(e)) | ||||
|                 { | ||||
|                     black_box(comp); | ||||
|                     count += 1; | ||||
|                     black_box(count); | ||||
|                 } | ||||
|                 assert_eq!(black_box(count), entity_count); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     group.finish(); | ||||
| } | ||||
| 
 | ||||
| pub fn query_get(criterion: &mut Criterion) { | ||||
|     let mut group = criterion.benchmark_group("query_get"); | ||||
|     group.warm_up_time(std::time::Duration::from_millis(500)); | ||||
|  | ||||
| @ -121,15 +121,6 @@ pub struct SceneEntityMapper<'m> { | ||||
| } | ||||
| 
 | ||||
| impl<'m> SceneEntityMapper<'m> { | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "please use `EntityMapper::map_entity` instead" | ||||
|     )] | ||||
|     /// Returns the corresponding mapped entity or reserves a new dead entity ID in the current world if it is absent.
 | ||||
|     pub fn get_or_reserve(&mut self, entity: Entity) -> Entity { | ||||
|         self.map_entity(entity) | ||||
|     } | ||||
| 
 | ||||
|     /// Gets a reference to the underlying [`EntityHashMap<Entity>`].
 | ||||
|     pub fn get_map(&'m self) -> &'m EntityHashMap<Entity> { | ||||
|         self.map | ||||
|  | ||||
| @ -21,76 +21,6 @@ pub enum QueryEntityError { | ||||
|     AliasedMutability(Entity), | ||||
| } | ||||
| 
 | ||||
| /// An error that occurs when retrieving a specific [`Entity`]'s component from a [`Query`](crate::system::Query).
 | ||||
| #[derive(Debug, PartialEq, Eq, Error)] | ||||
| pub enum QueryComponentError { | ||||
|     /// The [`Query`](crate::system::Query) does not have read access to the requested component.
 | ||||
|     ///
 | ||||
|     /// This error occurs when the requested component is not included in the original query.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::{prelude::*, query::QueryComponentError};
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Component)]
 | ||||
|     /// # struct OtherComponent;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Component, PartialEq, Debug)]
 | ||||
|     /// # struct RequestedComponent;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Resource)]
 | ||||
|     /// # struct SpecificEntity {
 | ||||
|     /// #     entity: Entity,
 | ||||
|     /// # }
 | ||||
|     /// #
 | ||||
|     /// fn get_missing_read_access_error(query: Query<&OtherComponent>, res: Res<SpecificEntity>) {
 | ||||
|     ///     assert_eq!(
 | ||||
|     ///         query.get_component::<RequestedComponent>(res.entity),
 | ||||
|     ///         Err(QueryComponentError::MissingReadAccess),
 | ||||
|     ///     );
 | ||||
|     ///     println!("query doesn't have read access to RequestedComponent because it does not appear in Query<&OtherComponent>");
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(get_missing_read_access_error);
 | ||||
|     /// ```
 | ||||
|     #[error("This query does not have read access to the requested component")] | ||||
|     MissingReadAccess, | ||||
|     /// The [`Query`](crate::system::Query) does not have write access to the requested component.
 | ||||
|     ///
 | ||||
|     /// This error occurs when the requested component is not included in the original query, or the mutability of the requested component is mismatched with the original query.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::{prelude::*, query::QueryComponentError};
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Component, PartialEq, Debug)]
 | ||||
|     /// # struct RequestedComponent;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Resource)]
 | ||||
|     /// # struct SpecificEntity {
 | ||||
|     /// #     entity: Entity,
 | ||||
|     /// # }
 | ||||
|     /// #
 | ||||
|     /// fn get_missing_write_access_error(mut query: Query<&RequestedComponent>, res: Res<SpecificEntity>) {
 | ||||
|     ///     assert_eq!(
 | ||||
|     ///         query.get_component::<RequestedComponent>(res.entity),
 | ||||
|     ///         Err(QueryComponentError::MissingWriteAccess),
 | ||||
|     ///     );
 | ||||
|     ///     println!("query doesn't have write access to RequestedComponent because it doesn't have &mut in Query<&RequestedComponent>");
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(get_missing_write_access_error);
 | ||||
|     /// ```
 | ||||
|     #[error("This query does not have write access to the requested component")] | ||||
|     MissingWriteAccess, | ||||
|     /// The given [`Entity`] does not have the requested component.
 | ||||
|     #[error("The given entity does not have the requested component")] | ||||
|     MissingComponent, | ||||
|     /// The requested [`Entity`] does not exist.
 | ||||
|     #[error("The requested entity does not exist")] | ||||
|     NoSuchEntity, | ||||
| } | ||||
| 
 | ||||
| /// An error that occurs when evaluating a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) as a single expected result via
 | ||||
| /// [`get_single`](crate::system::Query::get_single) or [`get_single_mut`](crate::system::Query::get_single_mut).
 | ||||
| #[derive(Debug, Error)] | ||||
|  | ||||
| @ -739,7 +739,6 @@ mod tests { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[allow(deprecated)] | ||||
|     #[test] | ||||
|     fn mut_to_immut_query_methods_have_immut_item() { | ||||
|         #[derive(Component)] | ||||
| @ -771,7 +770,6 @@ mod tests { | ||||
|         q.iter().for_each(|_: &Foo| ()); | ||||
| 
 | ||||
|         let _: Option<&Foo> = q.get(e).ok(); | ||||
|         let _: Option<&Foo> = q.get_component(e).ok(); | ||||
|         let _: Option<[&Foo; 1]> = q.get_many([e]).ok(); | ||||
|         let _: Option<&Foo> = q.get_single().ok(); | ||||
|         let _: [&Foo; 1] = q.many([e]); | ||||
|  | ||||
| @ -1,9 +1,8 @@ | ||||
| use crate::{ | ||||
|     archetype::{Archetype, ArchetypeComponentId, ArchetypeGeneration, ArchetypeId}, | ||||
|     change_detection::Mut, | ||||
|     component::{ComponentId, Tick}, | ||||
|     entity::Entity, | ||||
|     prelude::{Component, FromWorld}, | ||||
|     prelude::FromWorld, | ||||
|     query::{ | ||||
|         Access, BatchingStrategy, DebugCheckedUnwrap, FilteredAccess, QueryCombinationIter, | ||||
|         QueryIter, QueryParIter, | ||||
| @ -14,7 +13,7 @@ use crate::{ | ||||
| #[cfg(feature = "trace")] | ||||
| use bevy_utils::tracing::Span; | ||||
| use fixedbitset::FixedBitSet; | ||||
| use std::{any::TypeId, borrow::Borrow, fmt, mem::MaybeUninit, ptr}; | ||||
| use std::{borrow::Borrow, fmt, mem::MaybeUninit, ptr}; | ||||
| 
 | ||||
| use super::{ | ||||
|     NopWorldQuery, QueryBuilder, QueryData, QueryEntityError, QueryFilter, QueryManyIter, | ||||
| @ -646,118 +645,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a shared reference to the component `T` of the given [`Entity`].
 | ||||
|     ///
 | ||||
|     /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead.
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub(crate) fn get_component<'w, T: Component>( | ||||
|         &self, | ||||
|         world: UnsafeWorldCell<'w>, | ||||
|         entity: Entity, | ||||
|     ) -> Result<&'w T, super::QueryComponentError> { | ||||
|         let entity_ref = world | ||||
|             .get_entity(entity) | ||||
|             .ok_or(super::QueryComponentError::NoSuchEntity)?; | ||||
|         let component_id = world | ||||
|             .components() | ||||
|             .get_id(TypeId::of::<T>()) | ||||
|             .ok_or(super::QueryComponentError::MissingComponent)?; | ||||
|         let archetype_component = entity_ref | ||||
|             .archetype() | ||||
|             .get_archetype_component_id(component_id) | ||||
|             .ok_or(super::QueryComponentError::MissingComponent)?; | ||||
|         if self | ||||
|             .archetype_component_access | ||||
|             .has_read(archetype_component) | ||||
|         { | ||||
|             // SAFETY: `world` must have access to the component `T` for this entity,
 | ||||
|             // since it was registered in `self`'s archetype component access set.
 | ||||
|             unsafe { entity_ref.get::<T>() }.ok_or(super::QueryComponentError::MissingComponent) | ||||
|         } else { | ||||
|             Err(super::QueryComponentError::MissingReadAccess) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a shared reference to the component `T` of the given [`Entity`].
 | ||||
|     ///
 | ||||
|     /// # Panics
 | ||||
|     ///
 | ||||
|     /// If given a nonexisting entity or mismatched component, this will panic.
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub(crate) fn component<'w, T: Component>( | ||||
|         &self, | ||||
|         world: UnsafeWorldCell<'w>, | ||||
|         entity: Entity, | ||||
|     ) -> &'w T { | ||||
|         match self.get_component(world, entity) { | ||||
|             Ok(component) => component, | ||||
|             Err(error) => { | ||||
|                 panic!( | ||||
|                     "Cannot get component `{:?}` from {entity:?}: {error}", | ||||
|                     TypeId::of::<T>() | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a mutable reference to the component `T` of the given entity.
 | ||||
|     ///
 | ||||
|     /// In case of a nonexisting entity or mismatched component, a [`QueryComponentError`] is returned instead.
 | ||||
|     ///
 | ||||
|     /// # Safety
 | ||||
|     ///
 | ||||
|     /// This function makes it possible to violate Rust's aliasing guarantees.
 | ||||
|     /// You must make sure this call does not result in multiple mutable references to the same component.
 | ||||
|     ///
 | ||||
|     /// [`QueryComponentError`]: super::QueryComponentError
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use QueryState::get_unchecked_manual and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub unsafe fn get_component_unchecked_mut<'w, T: Component>( | ||||
|         &self, | ||||
|         world: UnsafeWorldCell<'w>, | ||||
|         entity: Entity, | ||||
|         last_run: Tick, | ||||
|         this_run: Tick, | ||||
|     ) -> Result<Mut<'w, T>, super::QueryComponentError> { | ||||
|         let entity_ref = world | ||||
|             .get_entity(entity) | ||||
|             .ok_or(super::QueryComponentError::NoSuchEntity)?; | ||||
|         let component_id = world | ||||
|             .components() | ||||
|             .get_id(TypeId::of::<T>()) | ||||
|             .ok_or(super::QueryComponentError::MissingComponent)?; | ||||
|         let archetype_component = entity_ref | ||||
|             .archetype() | ||||
|             .get_archetype_component_id(component_id) | ||||
|             .ok_or(super::QueryComponentError::MissingComponent)?; | ||||
|         if self | ||||
|             .archetype_component_access | ||||
|             .has_write(archetype_component) | ||||
|         { | ||||
|             // SAFETY: It is the responsibility of the caller to ensure it is sound to get a
 | ||||
|             // mutable reference to this entity's component `T`.
 | ||||
|             let result = unsafe { entity_ref.get_mut_using_ticks::<T>(last_run, this_run) }; | ||||
| 
 | ||||
|             result.ok_or(super::QueryComponentError::MissingComponent) | ||||
|         } else { | ||||
|             Err(super::QueryComponentError::MissingWriteAccess) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Gets the read-only query results for the given [`World`] and array of [`Entity`], where the last change and
 | ||||
|     /// the current change tick are given.
 | ||||
|     ///
 | ||||
| @ -1133,56 +1020,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | ||||
|         QueryCombinationIter::new(world, self, last_run, this_run) | ||||
|     } | ||||
| 
 | ||||
|     /// Runs `func` on each query result for the given [`World`]. This is faster than the equivalent
 | ||||
|     /// `iter()` method, but cannot be chained like a normal [`Iterator`].
 | ||||
|     ///
 | ||||
|     /// This can only be called for read-only queries, see [`Self::for_each_mut`] for write-queries.
 | ||||
|     ///
 | ||||
|     /// Shorthand for `query.iter(world).for_each(..)`.
 | ||||
|     #[inline] | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "QueryState::for_each was not idiomatic Rust and has been moved to query.iter().for_each()" | ||||
|     )] | ||||
|     pub fn for_each<'w, FN: FnMut(ROQueryItem<'w, D>)>(&mut self, world: &'w World, func: FN) { | ||||
|         self.iter(world).for_each(func); | ||||
|     } | ||||
| 
 | ||||
|     /// Runs `func` on each query result for the given [`World`]. This is faster than the equivalent
 | ||||
|     /// `iter_mut()` method, but cannot be chained like a normal [`Iterator`].
 | ||||
|     ///
 | ||||
|     /// Shorthand for `query.iter_mut(world).for_each(..)`.
 | ||||
|     #[inline] | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "QueryState::for_each_mut was not idiomatic Rust and has been moved to query.iter_mut().for_each()" | ||||
|     )] | ||||
|     pub fn for_each_mut<'w, FN: FnMut(D::Item<'w>)>(&mut self, world: &'w mut World, func: FN) { | ||||
|         self.iter_mut(world).for_each(func); | ||||
|     } | ||||
| 
 | ||||
|     /// Runs `func` on each query result for the given [`World`]. This is faster than the equivalent
 | ||||
|     /// `iter()` method, but cannot be chained like a normal [`Iterator`].
 | ||||
|     ///
 | ||||
|     /// # Safety
 | ||||
|     ///
 | ||||
|     /// This does not check for mutable query correctness. To be safe, make sure mutable queries
 | ||||
|     /// have unique access to the components they query.
 | ||||
|     #[inline] | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "QueryState::for_each_unchecked was not idiomatic Rust and has been moved to query.iter_unchecked_manual().for_each()" | ||||
|     )] | ||||
|     pub unsafe fn for_each_unchecked<'w, FN: FnMut(D::Item<'w>)>( | ||||
|         &mut self, | ||||
|         world: UnsafeWorldCell<'w>, | ||||
|         func: FN, | ||||
|     ) { | ||||
|         self.update_archetypes_unsafe_world_cell(world); | ||||
|         self.iter_unchecked_manual(world, world.last_change_tick(), world.change_tick()) | ||||
|             .for_each(func); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a parallel iterator over the query results for the given [`World`].
 | ||||
|     ///
 | ||||
|     /// This can only be called for read-only queries, see [`par_iter_mut`] for write-queries.
 | ||||
|  | ||||
| @ -766,67 +766,6 @@ pub mod common_conditions { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Identical to [`in_state`] - use that instead.
 | ||||
|     ///
 | ||||
|     /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
 | ||||
|     /// if the state machine exists and is currently in `state`.
 | ||||
|     ///
 | ||||
|     /// The condition will return `false` if the state does not exist.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::prelude::*;
 | ||||
|     /// # #[derive(Resource, Default)]
 | ||||
|     /// # struct Counter(u8);
 | ||||
|     /// # let mut app = Schedule::default();
 | ||||
|     /// # let mut world = World::new();
 | ||||
|     /// # world.init_resource::<Counter>();
 | ||||
|     /// #[derive(States, Clone, Copy, Default, Eq, PartialEq, Hash, Debug)]
 | ||||
|     /// enum GameState {
 | ||||
|     ///     #[default]
 | ||||
|     ///     Playing,
 | ||||
|     ///     Paused,
 | ||||
|     /// }
 | ||||
|     ///
 | ||||
|     /// app.add_systems((
 | ||||
|     ///     // `state_exists_and_equals` will only return true if the
 | ||||
|     ///     // given state exists and equals the given value
 | ||||
|     ///     play_system.run_if(state_exists_and_equals(GameState::Playing)),
 | ||||
|     ///     pause_system.run_if(state_exists_and_equals(GameState::Paused)),
 | ||||
|     /// ));
 | ||||
|     ///
 | ||||
|     /// fn play_system(mut counter: ResMut<Counter>) {
 | ||||
|     ///     counter.0 += 1;
 | ||||
|     /// }
 | ||||
|     ///
 | ||||
|     /// fn pause_system(mut counter: ResMut<Counter>) {
 | ||||
|     ///     counter.0 -= 1;
 | ||||
|     /// }
 | ||||
|     ///
 | ||||
|     /// // `GameState` does not yet exists so neither system will run
 | ||||
|     /// app.run(&mut world);
 | ||||
|     /// assert_eq!(world.resource::<Counter>().0, 0);
 | ||||
|     ///
 | ||||
|     /// world.init_resource::<State<GameState>>();
 | ||||
|     ///
 | ||||
|     /// // We default to `GameState::Playing` so `play_system` runs
 | ||||
|     /// app.run(&mut world);
 | ||||
|     /// assert_eq!(world.resource::<Counter>().0, 1);
 | ||||
|     ///
 | ||||
|     /// *world.resource_mut::<State<GameState>>() = State::new(GameState::Paused);
 | ||||
|     ///
 | ||||
|     /// // Now that we are in `GameState::Pause`, `pause_system` will run
 | ||||
|     /// app.run(&mut world);
 | ||||
|     /// assert_eq!(world.resource::<Counter>().0, 0);
 | ||||
|     /// ```
 | ||||
|     #[deprecated(since = "0.13.0", note = "use `in_state` instead.")] | ||||
|     pub fn state_exists_and_equals<S: States>( | ||||
|         state: S, | ||||
|     ) -> impl FnMut(Option<Res<State<S>>>) -> bool + Clone { | ||||
|         in_state(state) | ||||
|     } | ||||
| 
 | ||||
|     /// A [`Condition`](super::Condition)-satisfying system that returns `true`
 | ||||
|     /// if the state machine changed state.
 | ||||
|     ///
 | ||||
|  | ||||
| @ -401,65 +401,6 @@ mod tests { | ||||
|         schedule.run(world); | ||||
|     } | ||||
| 
 | ||||
|     #[allow(deprecated)] | ||||
|     #[test] | ||||
|     fn query_system_gets() { | ||||
|         fn query_system( | ||||
|             mut ran: ResMut<SystemRan>, | ||||
|             entity_query: Query<Entity, With<A>>, | ||||
|             b_query: Query<&B>, | ||||
|             a_c_query: Query<(&A, &C)>, | ||||
|             d_query: Query<&D>, | ||||
|         ) { | ||||
|             let entities = entity_query.iter().collect::<Vec<Entity>>(); | ||||
|             assert!( | ||||
|                 b_query.get_component::<B>(entities[0]).is_err(), | ||||
|                 "entity 0 should not have B" | ||||
|             ); | ||||
|             assert!( | ||||
|                 b_query.get_component::<B>(entities[1]).is_ok(), | ||||
|                 "entity 1 should have B" | ||||
|             ); | ||||
|             assert!( | ||||
|                 b_query.get_component::<A>(entities[1]).is_err(), | ||||
|                 "entity 1 should have A, but b_query shouldn't have access to it" | ||||
|             ); | ||||
|             assert!( | ||||
|                 b_query.get_component::<D>(entities[3]).is_err(), | ||||
|                 "entity 3 should have D, but it shouldn't be accessible from b_query" | ||||
|             ); | ||||
|             assert!( | ||||
|                 b_query.get_component::<C>(entities[2]).is_err(), | ||||
|                 "entity 2 has C, but it shouldn't be accessible from b_query" | ||||
|             ); | ||||
|             assert!( | ||||
|                 a_c_query.get_component::<C>(entities[2]).is_ok(), | ||||
|                 "entity 2 has C, and it should be accessible from a_c_query" | ||||
|             ); | ||||
|             assert!( | ||||
|                 a_c_query.get_component::<D>(entities[3]).is_err(), | ||||
|                 "entity 3 should have D, but it shouldn't be accessible from b_query" | ||||
|             ); | ||||
|             assert!( | ||||
|                 d_query.get_component::<D>(entities[3]).is_ok(), | ||||
|                 "entity 3 should have D" | ||||
|             ); | ||||
| 
 | ||||
|             *ran = SystemRan::Yes; | ||||
|         } | ||||
| 
 | ||||
|         let mut world = World::default(); | ||||
|         world.insert_resource(SystemRan::No); | ||||
|         world.spawn(A); | ||||
|         world.spawn((A, B)); | ||||
|         world.spawn((A, C)); | ||||
|         world.spawn((A, D)); | ||||
| 
 | ||||
|         run_system(&mut world, query_system); | ||||
| 
 | ||||
|         assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn get_many_is_ordered() { | ||||
|         use crate::system::Resource; | ||||
| @ -1561,22 +1502,6 @@ mod tests { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     #[allow(deprecated)] | ||||
|     #[test] | ||||
|     fn readonly_query_get_mut_component_fails() { | ||||
|         use crate::query::QueryComponentError; | ||||
| 
 | ||||
|         let mut world = World::new(); | ||||
|         let entity = world.spawn(W(42u32)).id(); | ||||
|         run_system(&mut world, move |q: Query<&mut W<u32>>| { | ||||
|             let mut rq = q.to_readonly(); | ||||
|             assert_eq!( | ||||
|                 QueryComponentError::MissingWriteAccess, | ||||
|                 rq.get_component_mut::<W<u32>>(entity).unwrap_err(), | ||||
|             ); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     #[should_panic = "Encountered a mismatched World."] | ||||
|     fn query_validates_world_id() { | ||||
| @ -1590,7 +1515,6 @@ mod tests { | ||||
|                 &qstate, | ||||
|                 Tick::new(0), | ||||
|                 Tick::new(0), | ||||
|                 false, | ||||
|             ) | ||||
|         }; | ||||
|         query.iter(); | ||||
|  | ||||
| @ -1,14 +1,14 @@ | ||||
| use crate::{ | ||||
|     component::{Component, Tick}, | ||||
|     component::Tick, | ||||
|     entity::Entity, | ||||
|     query::{ | ||||
|         BatchingStrategy, QueryCombinationIter, QueryData, QueryEntityError, QueryFilter, | ||||
|         QueryIter, QueryManyIter, QueryParIter, QuerySingleError, QueryState, ROQueryItem, | ||||
|         ReadOnlyQueryData, | ||||
|     }, | ||||
|     world::{unsafe_world_cell::UnsafeWorldCell, Mut}, | ||||
|     world::unsafe_world_cell::UnsafeWorldCell, | ||||
| }; | ||||
| use std::{any::TypeId, borrow::Borrow}; | ||||
| use std::borrow::Borrow; | ||||
| 
 | ||||
| /// [System parameter] that provides selective access to the [`Component`] data stored in a [`World`].
 | ||||
| ///
 | ||||
| @ -239,7 +239,7 @@ use std::{any::TypeId, borrow::Borrow}; | ||||
| /// |Query methods|Effect|
 | ||||
| /// |:---:|---|
 | ||||
| /// |[`iter`]\[[`_mut`][`iter_mut`]]|Returns an iterator over all query items.|
 | ||||
| /// |[`for_each`]\[[`_mut`][`for_each_mut`]],<br>[`par_iter`]\[[`_mut`][`par_iter_mut`]]|Runs a specified function for each query item.|
 | ||||
| /// |[[`iter().for_each()`][`for_each`]\[[`iter_mut().for_each()`][`for_each`]],<br>[`par_iter`]\[[`_mut`][`par_iter_mut`]]|Runs a specified function for each query item.|
 | ||||
| /// |[`iter_many`]\[[`_mut`][`iter_many_mut`]]|Iterates or runs a specified function over query items generated by a list of entities.|
 | ||||
| /// |[`iter_combinations`]\[[`_mut`][`iter_combinations_mut`]]|Returns an iterator over all combinations of a specified number of query items.|
 | ||||
| /// |[`get`]\[[`_mut`][`get_mut`]]|Returns the query item for the specified entity.|
 | ||||
| @ -275,7 +275,7 @@ use std::{any::TypeId, borrow::Borrow}; | ||||
| /// |Query operation|Computational complexity|
 | ||||
| /// |:---:|:---:|
 | ||||
| /// |[`iter`]\[[`_mut`][`iter_mut`]]|O(n)|
 | ||||
| /// |[`for_each`]\[[`_mut`][`for_each_mut`]],<br>[`par_iter`]\[[`_mut`][`par_iter_mut`]]|O(n)|
 | ||||
| /// |[[`iter().for_each()`][`for_each`]\[[`iter_mut().for_each()`][`for_each`]],<br>[`par_iter`]\[[`_mut`][`par_iter_mut`]]|O(n)|
 | ||||
| /// |[`iter_many`]\[[`_mut`][`iter_many_mut`]]|O(k)|
 | ||||
| /// |[`iter_combinations`]\[[`_mut`][`iter_combinations_mut`]]|O(<sub>n</sub>C<sub>r</sub>)|
 | ||||
| /// |[`get`]\[[`_mut`][`get_mut`]]|O(1)|
 | ||||
| @ -285,12 +285,34 @@ use std::{any::TypeId, borrow::Borrow}; | ||||
| /// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)|
 | ||||
| /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)|
 | ||||
| ///
 | ||||
| /// `for_each` methods are seen to be generally faster than their `iter` version on worlds with high archetype fragmentation.
 | ||||
| /// As iterators are in general more flexible and better integrated with the rest of the Rust ecosystem,
 | ||||
| /// it is advised to use `iter` methods over `for_each`.
 | ||||
| /// It is strongly advised to only use `for_each` if it tangibly improves performance:
 | ||||
| /// be sure profile or benchmark both before and after the change.
 | ||||
| /// # `Iterator::for_each`
 | ||||
| ///
 | ||||
| /// `for_each` methods are seen to be generally faster than directly iterating through `iter` on worlds with high archetype
 | ||||
| /// fragmentation, and may enable additional optimizations like [autovectorization]. It is strongly advised to only use
 | ||||
| /// [`Iterator::for_each`] if it tangibly improves performance.  *Always* be sure profile or benchmark both before and
 | ||||
| /// after the change!
 | ||||
| ///
 | ||||
| /// ```rust
 | ||||
| /// # use bevy_ecs::prelude::*;
 | ||||
| /// # #[derive(Component)]
 | ||||
| /// # struct ComponentA;
 | ||||
| /// # fn system(
 | ||||
| /// # query: Query<&ComponentA>,
 | ||||
| /// # ) {
 | ||||
| /// // This might be result in better performance...
 | ||||
| /// query.iter().for_each(|component| {
 | ||||
| ///     // do things with the component
 | ||||
| /// });
 | ||||
| /// // ...than this. Always be sure to benchmark to validate the difference!
 | ||||
| /// for component in query.iter() {
 | ||||
| ///     // do things with the component
 | ||||
| /// }
 | ||||
| /// # }
 | ||||
| /// # bevy_ecs::system::assert_system_does_not_conflict(system);
 | ||||
| /// ```
 | ||||
| ///
 | ||||
| /// [`Component`]: crate::component::Component
 | ||||
| /// [autovectorization]: https://en.wikipedia.org/wiki/Automatic_vectorization
 | ||||
| /// [`Added`]: crate::query::Added
 | ||||
| /// [`AnyOf`]: crate::query::AnyOf
 | ||||
| /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient
 | ||||
| @ -298,8 +320,7 @@ use std::{any::TypeId, borrow::Borrow}; | ||||
| /// [components]: crate::component::Component
 | ||||
| /// [entity identifiers]: Entity
 | ||||
| /// [`EntityRef`]: crate::world::EntityRef
 | ||||
| /// [`for_each`]: Self::for_each
 | ||||
| /// [`for_each_mut`]: Self::for_each_mut
 | ||||
| /// [`for_each`]: #iterator-for-each
 | ||||
| /// [`get`]: Self::get
 | ||||
| /// [`get_many`]: Self::get_many
 | ||||
| /// [`get_many_mut`]: Self::get_many_mut
 | ||||
| @ -331,12 +352,6 @@ pub struct Query<'world, 'state, D: QueryData, F: QueryFilter = ()> { | ||||
|     state: &'state QueryState<D, F>, | ||||
|     last_run: Tick, | ||||
|     this_run: Tick, | ||||
|     // SAFETY: This is used to ensure that `get_component_mut::<C>` properly fails when a Query writes C
 | ||||
|     // and gets converted to a read-only query using `to_readonly`. Without checking this, `get_component_mut` relies on
 | ||||
|     // QueryState's archetype_component_access, which will continue allowing write access to C after being cast to
 | ||||
|     // the read-only variant. This whole situation is confusing and error prone. Ideally this is a temporary hack
 | ||||
|     // until we sort out a cleaner alternative.
 | ||||
|     force_read_only_component_access: bool, | ||||
| } | ||||
| 
 | ||||
| impl<D: QueryData, F: QueryFilter> std::fmt::Debug for Query<'_, '_, D, F> { | ||||
| @ -368,12 +383,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|         state: &'s QueryState<D, F>, | ||||
|         last_run: Tick, | ||||
|         this_run: Tick, | ||||
|         force_read_only_component_access: bool, | ||||
|     ) -> Self { | ||||
|         state.validate_world(world.id()); | ||||
| 
 | ||||
|         Self { | ||||
|             force_read_only_component_access, | ||||
|             world, | ||||
|             state, | ||||
|             last_run, | ||||
| @ -389,17 +402,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|     pub fn to_readonly(&self) -> Query<'_, 's, D::ReadOnly, F> { | ||||
|         let new_state = self.state.as_readonly(); | ||||
|         // SAFETY: This is memory safe because it turns the query immutable.
 | ||||
|         unsafe { | ||||
|             Query::new( | ||||
|                 self.world, | ||||
|                 new_state, | ||||
|                 self.last_run, | ||||
|                 self.this_run, | ||||
|                 // SAFETY: this must be set to true or `get_component_mut` will be unsound. See the comments
 | ||||
|                 // on this field for more details
 | ||||
|                 true, | ||||
|             ) | ||||
|         } | ||||
|         unsafe { Query::new(self.world, new_state, self.last_run, self.this_run) } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an [`Iterator`] over the read-only query items.
 | ||||
| @ -424,8 +427,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`iter_mut`](Self::iter_mut) for mutable query items.
 | ||||
|     /// - [`for_each`](Self::for_each) for the closure based alternative.
 | ||||
|     /// [`iter_mut`](Self::iter_mut) for mutable query items.
 | ||||
|     #[inline] | ||||
|     pub fn iter(&self) -> QueryIter<'_, 's, D::ReadOnly, F> { | ||||
|         // SAFETY:
 | ||||
| @ -460,8 +462,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`iter`](Self::iter) for read-only query items.
 | ||||
|     /// - [`for_each_mut`](Self::for_each_mut) for the closure based alternative.
 | ||||
|     /// [`iter`](Self::iter) for read-only query items.
 | ||||
|     #[inline] | ||||
|     pub fn iter_mut(&mut self) -> QueryIter<'_, 's, D, F> { | ||||
|         // SAFETY: `self.world` has permission to access the required components.
 | ||||
| @ -710,89 +711,6 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|             .iter_many_unchecked_manual(entities, self.world, self.last_run, self.this_run) | ||||
|     } | ||||
| 
 | ||||
|     /// Runs `f` on each read-only query item.
 | ||||
|     ///
 | ||||
|     /// Shorthand for `query.iter().for_each(..)`.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it:
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::prelude::*;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Component)]
 | ||||
|     /// # struct Player { name: String }
 | ||||
|     /// #
 | ||||
|     /// fn report_names_system(query: Query<&Player>) {
 | ||||
|     ///     query.for_each(|player| {
 | ||||
|     ///         println!("Say hello to {}!", player.name);
 | ||||
|     ///     });
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(report_names_system);
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`for_each_mut`](Self::for_each_mut) to operate on mutable query items.
 | ||||
|     /// - [`iter`](Self::iter) for the iterator based alternative.
 | ||||
|     #[inline] | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Query::for_each was not idiomatic Rust and has been moved to query.iter().for_each()" | ||||
|     )] | ||||
|     pub fn for_each<'this>(&'this self, f: impl FnMut(ROQueryItem<'this, D>)) { | ||||
|         // SAFETY:
 | ||||
|         // - `self.world` has permission to access the required components.
 | ||||
|         // - The query is read-only, so it can be aliased even if it was originally mutable.
 | ||||
|         unsafe { | ||||
|             self.state | ||||
|                 .as_readonly() | ||||
|                 .iter_unchecked_manual(self.world, self.last_run, self.this_run) | ||||
|                 .for_each(f); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /// Runs `f` on each query item.
 | ||||
|     ///
 | ||||
|     /// Shorthand for `query.iter_mut().for_each(..)`.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it:
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::prelude::*;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Component)]
 | ||||
|     /// # struct Velocity { x: f32, y: f32, z: f32 }
 | ||||
|     /// fn gravity_system(mut query: Query<&mut Velocity>) {
 | ||||
|     ///     const DELTA: f32 = 1.0 / 60.0;
 | ||||
|     ///     query.for_each_mut(|mut velocity| {
 | ||||
|     ///         velocity.y -= 9.8 * DELTA;
 | ||||
|     ///     });
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(gravity_system);
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`for_each`](Self::for_each) to operate on read-only query items.
 | ||||
|     /// - [`iter_mut`](Self::iter_mut) for the iterator based alternative.
 | ||||
|     #[inline] | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Query::for_each_mut was not idiomatic Rust and has been moved to query.iter_mut().for_each()" | ||||
|     )] | ||||
|     pub fn for_each_mut<'a>(&'a mut self, f: impl FnMut(D::Item<'a>)) { | ||||
|         // SAFETY: `self.world` has permission to access the required components.
 | ||||
|         unsafe { | ||||
|             self.state | ||||
|                 .iter_unchecked_manual(self.world, self.last_run, self.this_run) | ||||
|                 .for_each(f); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a parallel iterator over the query results for the given [`World`].
 | ||||
|     ///
 | ||||
|     /// This can only be called for read-only queries, see [`par_iter_mut`] for write-queries.
 | ||||
| @ -1100,183 +1018,6 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|             .get_unchecked_manual(self.world, entity, self.last_run, self.this_run) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a shared reference to the component `T` of the given [`Entity`].
 | ||||
|     ///
 | ||||
|     /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// Here, `get_component` is used to retrieve the `Character` component of the entity specified by the `SelectedCharacter` resource.
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::prelude::*;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Resource)]
 | ||||
|     /// # struct SelectedCharacter { entity: Entity }
 | ||||
|     /// # #[derive(Component)]
 | ||||
|     /// # struct Character { name: String }
 | ||||
|     /// #
 | ||||
|     /// fn print_selected_character_name_system(
 | ||||
|     ///        query: Query<&Character>,
 | ||||
|     ///        selection: Res<SelectedCharacter>
 | ||||
|     /// )
 | ||||
|     /// {
 | ||||
|     ///     if let Ok(selected_character) = query.get_component::<Character>(selection.entity) {
 | ||||
|     ///         println!("{}", selected_character.name);
 | ||||
|     ///     }
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system);
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`component`](Self::component) a panicking version of this function.
 | ||||
|     /// - [`get_component_mut`](Self::get_component_mut) to get a mutable reference of a component.
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub fn get_component<T: Component>( | ||||
|         &self, | ||||
|         entity: Entity, | ||||
|     ) -> Result<&T, crate::query::QueryComponentError> { | ||||
|         self.state.get_component(self.world, entity) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a mutable reference to the component `T` of the given entity.
 | ||||
|     ///
 | ||||
|     /// In case of a nonexisting entity, mismatched component or missing write access, a [`QueryComponentError`] is returned instead.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity specified by the `PoisonedCharacter` resource.
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use bevy_ecs::prelude::*;
 | ||||
|     /// #
 | ||||
|     /// # #[derive(Resource)]
 | ||||
|     /// # struct PoisonedCharacter { character_id: Entity }
 | ||||
|     /// # #[derive(Component)]
 | ||||
|     /// # struct Health(u32);
 | ||||
|     /// #
 | ||||
|     /// fn poison_system(mut query: Query<&mut Health>, poisoned: Res<PoisonedCharacter>) {
 | ||||
|     ///     if let Ok(mut health) = query.get_component_mut::<Health>(poisoned.character_id) {
 | ||||
|     ///         health.0 -= 1;
 | ||||
|     ///     }
 | ||||
|     /// }
 | ||||
|     /// # bevy_ecs::system::assert_is_system(poison_system);
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`component_mut`](Self::component_mut) a panicking version of this function.
 | ||||
|     /// - [`get_component`](Self::get_component) to get a shared reference of a component.
 | ||||
|     ///
 | ||||
|     /// [`QueryComponentError`]: crate::query::QueryComponentError
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get_mut` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub fn get_component_mut<T: Component>( | ||||
|         &mut self, | ||||
|         entity: Entity, | ||||
|     ) -> Result<Mut<'_, T>, crate::query::QueryComponentError> { | ||||
|         // SAFETY: unique access to query (preventing aliased access)
 | ||||
|         unsafe { self.get_component_unchecked_mut(entity) } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a shared reference to the component `T` of the given [`Entity`].
 | ||||
|     ///
 | ||||
|     /// # Panics
 | ||||
|     ///
 | ||||
|     /// Panics in case of a nonexisting entity or mismatched component.
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`get_component`](Self::get_component) a non-panicking version of this function.
 | ||||
|     /// - [`component_mut`](Self::component_mut) to get a mutable reference of a component.
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     #[track_caller] | ||||
|     pub fn component<T: Component>(&self, entity: Entity) -> &T { | ||||
|         self.state.component(self.world, entity) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a mutable reference to the component `T` of the given entity.
 | ||||
|     ///
 | ||||
|     /// # Panics
 | ||||
|     ///
 | ||||
|     /// Panics in case of a nonexisting entity, mismatched component or missing write access.
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`get_component_mut`](Self::get_component_mut) a non-panicking version of this function.
 | ||||
|     /// - [`component`](Self::component) to get a shared reference of a component.
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get_mut` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     #[track_caller] | ||||
|     pub fn component_mut<T: Component>(&mut self, entity: Entity) -> Mut<'_, T> { | ||||
|         match self.get_component_mut(entity) { | ||||
|             Ok(component) => component, | ||||
|             Err(error) => { | ||||
|                 panic!( | ||||
|                     "Cannot get component `{:?}` from {entity:?}: {error}", | ||||
|                     TypeId::of::<T>() | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a mutable reference to the component `T` of the given entity.
 | ||||
|     ///
 | ||||
|     /// In case of a nonexisting entity or mismatched component, a [`QueryComponentError`] is returned instead.
 | ||||
|     ///
 | ||||
|     /// # Safety
 | ||||
|     ///
 | ||||
|     /// This function makes it possible to violate Rust's aliasing guarantees.
 | ||||
|     /// You must make sure this call does not result in multiple mutable references to the same component.
 | ||||
|     ///
 | ||||
|     /// # See also
 | ||||
|     ///
 | ||||
|     /// - [`get_component_mut`](Self::get_component_mut) for the safe version.
 | ||||
|     ///
 | ||||
|     /// [`QueryComponentError`]: crate::query::QueryComponentError
 | ||||
|     #[deprecated(
 | ||||
|         since = "0.13.0", | ||||
|         note = "Please use `get_unchecked` and select for the exact component based on the structure of the exact query as required." | ||||
|     )] | ||||
|     #[allow(deprecated)] | ||||
|     #[inline] | ||||
|     pub unsafe fn get_component_unchecked_mut<T: Component>( | ||||
|         &self, | ||||
|         entity: Entity, | ||||
|     ) -> Result<Mut<'_, T>, crate::query::QueryComponentError> { | ||||
|         // This check is required to ensure soundness in the case of `to_readonly().get_component_mut()`
 | ||||
|         // See the comments on the `force_read_only_component_access` field for more info.
 | ||||
|         if self.force_read_only_component_access { | ||||
|             return Err(crate::query::QueryComponentError::MissingWriteAccess); | ||||
|         } | ||||
| 
 | ||||
|         // SAFETY: The above check ensures we are not a readonly query.
 | ||||
|         // It is the callers responsibility to ensure multiple mutable access is not provided.
 | ||||
|         unsafe { | ||||
|             self.state | ||||
|                 .get_component_unchecked_mut(self.world, entity, self.last_run, self.this_run) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a single read-only query item when there is exactly one entity matching the query.
 | ||||
|     ///
 | ||||
|     /// # Panics
 | ||||
| @ -1566,7 +1307,6 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { | ||||
|             state, | ||||
|             last_run: self.last_run, | ||||
|             this_run: self.this_run, | ||||
|             force_read_only_component_access: self.force_read_only_component_access, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -1684,7 +1424,6 @@ pub struct QueryLens<'w, Q: QueryData, F: QueryFilter = ()> { | ||||
|     state: QueryState<Q, F>, | ||||
|     last_run: Tick, | ||||
|     this_run: Tick, | ||||
|     force_read_only_component_access: bool, | ||||
| } | ||||
| 
 | ||||
| impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { | ||||
| @ -1695,7 +1434,6 @@ impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { | ||||
|             state: &self.state, | ||||
|             last_run: self.last_run, | ||||
|             this_run: self.this_run, | ||||
|             force_read_only_component_access: self.force_read_only_component_access, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -228,7 +228,7 @@ unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Qu | ||||
|         // SAFETY: We have registered all of the query's world accesses,
 | ||||
|         // so the caller ensures that `world` has permission to access any
 | ||||
|         // world data that the query needs.
 | ||||
|         Query::new(world, state, system_meta.last_run, change_tick, false) | ||||
|         Query::new(world, state, system_meta.last_run, change_tick) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -24,20 +24,6 @@ fn main() { | ||||
|             assert_eq!(data, &mut *data2); // oops UB
 | ||||
|         } | ||||
| 
 | ||||
|         #[allow(deprecated)] | ||||
|         { | ||||
|             let data: &Foo = query.get_component::<Foo>(e).unwrap(); | ||||
|             let mut data2: Mut<Foo> = query.get_component_mut(e).unwrap(); | ||||
|             assert_eq!(data, &mut *data2); // oops UB
 | ||||
|         } | ||||
| 
 | ||||
|         #[allow(deprecated)] | ||||
|         { | ||||
|             let mut data2: Mut<Foo> = query.get_component_mut(e).unwrap(); | ||||
|             let data: &Foo = query.get_component::<Foo>(e).unwrap(); | ||||
|             assert_eq!(data, &mut *data2); // oops UB
 | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|             let data: &Foo = query.single(); | ||||
|             let mut data2: Mut<Foo> = query.single_mut(); | ||||
|  | ||||
| @ -19,101 +19,81 @@ error[E0502]: cannot borrow `query` as immutable because it is also borrowed as | ||||
|    |                                    ----- mutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:30:39 | ||||
|   --> tests/ui/query_lifetime_safety.rs:29:39 | ||||
|    | | ||||
| 29 |             let data: &Foo = query.get_component::<Foo>(e).unwrap(); | ||||
| 28 |             let data: &Foo = query.single(); | ||||
|    |                              ----- immutable borrow occurs here | ||||
| 30 |             let mut data2: Mut<Foo> = query.get_component_mut(e).unwrap(); | ||||
|    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||||
| 31 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |             ----------------------------- immutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:37:30 | ||||
|    | | ||||
| 36 |             let mut data2: Mut<Foo> = query.get_component_mut(e).unwrap(); | ||||
|    |                                       ----- mutable borrow occurs here | ||||
| 37 |             let data: &Foo = query.get_component::<Foo>(e).unwrap(); | ||||
|    |                              ^^^^^ immutable borrow occurs here | ||||
| 38 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |                                    ----- mutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:43:39 | ||||
|    | | ||||
| 42 |             let data: &Foo = query.single(); | ||||
|    |                              ----- immutable borrow occurs here | ||||
| 43 |             let mut data2: Mut<Foo> = query.single_mut(); | ||||
| 29 |             let mut data2: Mut<Foo> = query.single_mut(); | ||||
|    |                                       ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||||
| 44 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 30 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |             ----------------------------- immutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:49:30 | ||||
|   --> tests/ui/query_lifetime_safety.rs:35:30 | ||||
|    | | ||||
| 48 |             let mut data2: Mut<Foo> = query.single_mut(); | ||||
| 34 |             let mut data2: Mut<Foo> = query.single_mut(); | ||||
|    |                                       ----- mutable borrow occurs here | ||||
| 49 |             let data: &Foo = query.single(); | ||||
| 35 |             let data: &Foo = query.single(); | ||||
|    |                              ^^^^^ immutable borrow occurs here | ||||
| 50 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 36 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |                                    ----- mutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:55:39 | ||||
|   --> tests/ui/query_lifetime_safety.rs:41:39 | ||||
|    | | ||||
| 54 |             let data: &Foo = query.get_single().unwrap(); | ||||
| 40 |             let data: &Foo = query.get_single().unwrap(); | ||||
|    |                              ----- immutable borrow occurs here | ||||
| 55 |             let mut data2: Mut<Foo> = query.get_single_mut().unwrap(); | ||||
| 41 |             let mut data2: Mut<Foo> = query.get_single_mut().unwrap(); | ||||
|    |                                       ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||||
| 56 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 42 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |             ----------------------------- immutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:61:30 | ||||
|   --> tests/ui/query_lifetime_safety.rs:47:30 | ||||
|    | | ||||
| 60 |             let mut data2: Mut<Foo> = query.get_single_mut().unwrap(); | ||||
| 46 |             let mut data2: Mut<Foo> = query.get_single_mut().unwrap(); | ||||
|    |                                       ----- mutable borrow occurs here | ||||
| 61 |             let data: &Foo = query.get_single().unwrap(); | ||||
| 47 |             let data: &Foo = query.get_single().unwrap(); | ||||
|    |                              ^^^^^ immutable borrow occurs here | ||||
| 62 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 48 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |                                    ----- mutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:67:39 | ||||
|   --> tests/ui/query_lifetime_safety.rs:53:39 | ||||
|    | | ||||
| 66 |             let data: &Foo = query.iter().next().unwrap(); | ||||
| 52 |             let data: &Foo = query.iter().next().unwrap(); | ||||
|    |                              ----- immutable borrow occurs here | ||||
| 67 |             let mut data2: Mut<Foo> = query.iter_mut().next().unwrap(); | ||||
| 53 |             let mut data2: Mut<Foo> = query.iter_mut().next().unwrap(); | ||||
|    |                                       ^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||||
| 68 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 54 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |             ----------------------------- immutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:73:30 | ||||
|   --> tests/ui/query_lifetime_safety.rs:59:30 | ||||
|    | | ||||
| 72 |             let mut data2: Mut<Foo> = query.iter_mut().next().unwrap(); | ||||
| 58 |             let mut data2: Mut<Foo> = query.iter_mut().next().unwrap(); | ||||
|    |                                       ----- mutable borrow occurs here | ||||
| 73 |             let data: &Foo = query.iter().next().unwrap(); | ||||
| 59 |             let data: &Foo = query.iter().next().unwrap(); | ||||
|    |                              ^^^^^ immutable borrow occurs here | ||||
| 74 |             assert_eq!(data, &mut *data2); // oops UB | ||||
| 60 |             assert_eq!(data, &mut *data2); // oops UB | ||||
|    |                                    ----- mutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:81:13 | ||||
|   --> tests/ui/query_lifetime_safety.rs:67:13 | ||||
|    | | ||||
| 80 |             query.iter().for_each(|data| opt_data = Some(data)); | ||||
| 66 |             query.iter().for_each(|data| opt_data = Some(data)); | ||||
|    |             ----- immutable borrow occurs here | ||||
| 81 |             query.iter_mut().for_each(|data| opt_data_2 = Some(data)); | ||||
| 67 |             query.iter_mut().for_each(|data| opt_data_2 = Some(data)); | ||||
|    |             ^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||||
| 82 |             assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB | ||||
| 68 |             assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB | ||||
|    |                        -------- immutable borrow later used here | ||||
| 
 | ||||
| error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable | ||||
|   --> tests/ui/query_lifetime_safety.rs:89:13 | ||||
|   --> tests/ui/query_lifetime_safety.rs:75:13 | ||||
|    | | ||||
| 88 |             query.iter_mut().for_each(|data| opt_data_2 = Some(data)); | ||||
| 74 |             query.iter_mut().for_each(|data| opt_data_2 = Some(data)); | ||||
|    |             ----- mutable borrow occurs here | ||||
| 89 |             query.iter().for_each(|data| opt_data = Some(data)); | ||||
| 75 |             query.iter().for_each(|data| opt_data = Some(data)); | ||||
|    |             ^^^^^ immutable borrow occurs here | ||||
| 90 |             assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB | ||||
| 76 |             assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB | ||||
|    |                                                 ---------- mutable borrow later used here | ||||
|  | ||||
| @ -37,7 +37,7 @@ pub mod prelude { | ||||
|             Projection, | ||||
|         }, | ||||
|         color::Color, | ||||
|         mesh::{morph::MorphWeights, primitives::Meshable, shape, Mesh}, | ||||
|         mesh::{morph::MorphWeights, primitives::Meshable, Mesh}, | ||||
|         render_resource::Shader, | ||||
|         spatial_bundle::SpatialBundle, | ||||
|         texture::{Image, ImagePlugin}, | ||||
|  | ||||
| @ -32,7 +32,7 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; | ||||
| /// with "attribute" values for each vertex.
 | ||||
| ///
 | ||||
| /// Meshes can be automatically generated by a bevy `AssetLoader` (generally by loading a `Gltf` file),
 | ||||
| /// or by converting a primitive [`shape`](crate::mesh::shape) using [`into`](Into).
 | ||||
| /// or by converting a [primitive](bevy_math::primitives) using [`into`](Into).
 | ||||
| /// It is also possible to create one manually.
 | ||||
| /// They can be edited after creation.
 | ||||
| ///
 | ||||
|  | ||||
| @ -2,8 +2,6 @@ | ||||
| mod mesh; | ||||
| pub mod morph; | ||||
| pub mod primitives; | ||||
| /// Generation for some primitive shape meshes.
 | ||||
| pub mod shape; | ||||
| 
 | ||||
| pub use mesh::*; | ||||
| pub use primitives::*; | ||||
|  | ||||
| @ -1,49 +0,0 @@ | ||||
| use crate::mesh::{Capsule3dMeshBuilder, CapsuleUvProfile, Mesh}; | ||||
| 
 | ||||
| /// A cylinder with hemispheres at the top and bottom
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Capsule3d` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Capsule { | ||||
|     /// Radius on the `XZ` plane.
 | ||||
|     pub radius: f32, | ||||
|     /// Number of sections in cylinder between hemispheres.
 | ||||
|     pub rings: usize, | ||||
|     /// Height of the middle cylinder on the `Y` axis, excluding the hemispheres.
 | ||||
|     pub depth: f32, | ||||
|     /// Number of latitudes, distributed by inclination. Must be even.
 | ||||
|     pub latitudes: usize, | ||||
|     /// Number of longitudes, or meridians, distributed by azimuth.
 | ||||
|     pub longitudes: usize, | ||||
|     /// Manner in which UV coordinates are distributed vertically.
 | ||||
|     pub uv_profile: CapsuleUvProfile, | ||||
| } | ||||
| impl Default for Capsule { | ||||
|     fn default() -> Self { | ||||
|         Capsule { | ||||
|             radius: 0.5, | ||||
|             rings: 0, | ||||
|             depth: 1.0, | ||||
|             latitudes: 16, | ||||
|             longitudes: 32, | ||||
|             uv_profile: CapsuleUvProfile::Aspect, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Capsule> for Mesh { | ||||
|     #[allow(clippy::needless_range_loop)] | ||||
|     fn from(capsule: Capsule) -> Self { | ||||
|         Capsule3dMeshBuilder::new( | ||||
|             capsule.radius, | ||||
|             capsule.depth, | ||||
|             capsule.longitudes, | ||||
|             capsule.latitudes, | ||||
|         ) | ||||
|         .rings(capsule.rings) | ||||
|         .uv_profile(capsule.uv_profile) | ||||
|         .build() | ||||
|     } | ||||
| } | ||||
| @ -1,41 +0,0 @@ | ||||
| use crate::mesh::{CylinderMeshBuilder, Mesh}; | ||||
| 
 | ||||
| /// A cylinder which stands on the XZ plane
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Cylinder` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| pub struct Cylinder { | ||||
|     /// Radius in the XZ plane.
 | ||||
|     pub radius: f32, | ||||
|     /// Height of the cylinder in the Y axis.
 | ||||
|     pub height: f32, | ||||
|     /// The number of vertices around each horizontal slice of the cylinder. If you are looking at the cylinder from
 | ||||
|     /// above, this is the number of points you will see on the circle.
 | ||||
|     /// A higher number will make it appear more circular.
 | ||||
|     pub resolution: u32, | ||||
|     /// The number of segments between the two ends. Setting this to 1 will have triangles spanning the full
 | ||||
|     /// height of the cylinder. Setting it to 2 will have two sets of triangles with a horizontal slice in the middle of
 | ||||
|     /// cylinder. Greater numbers increase triangles/slices in the same way.
 | ||||
|     pub segments: u32, | ||||
| } | ||||
| 
 | ||||
| impl Default for Cylinder { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             radius: 0.5, | ||||
|             height: 1.0, | ||||
|             resolution: 16, | ||||
|             segments: 1, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Cylinder> for Mesh { | ||||
|     fn from(c: Cylinder) -> Self { | ||||
|         CylinderMeshBuilder::new(c.radius, c.height, c.resolution) | ||||
|             .segments(c.segments) | ||||
|             .build() | ||||
|     } | ||||
| } | ||||
| @ -1,32 +0,0 @@ | ||||
| use crate::mesh::{IcosphereError, Mesh, Meshable}; | ||||
| use bevy_math::primitives::Sphere; | ||||
| 
 | ||||
| /// A sphere made from a subdivided Icosahedron.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Sphere` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct Icosphere { | ||||
|     /// The radius of the sphere.
 | ||||
|     pub radius: f32, | ||||
|     /// The number of subdivisions applied.
 | ||||
|     pub subdivisions: usize, | ||||
| } | ||||
| 
 | ||||
| impl Default for Icosphere { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             radius: 1.0, | ||||
|             subdivisions: 5, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl TryFrom<Icosphere> for Mesh { | ||||
|     type Error = IcosphereError; | ||||
| 
 | ||||
|     fn try_from(sphere: Icosphere) -> Result<Self, Self::Error> { | ||||
|         Sphere::new(sphere.radius).mesh().ico(sphere.subdivisions) | ||||
|     } | ||||
| } | ||||
| @ -1,306 +0,0 @@ | ||||
| #![allow(deprecated)] | ||||
| 
 | ||||
| use crate::render_asset::RenderAssetUsages; | ||||
| 
 | ||||
| use super::{Indices, Mesh}; | ||||
| use bevy_math::*; | ||||
| 
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Cuboid` primitive for meshing or `Aabb2d` for a bounding volume" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Cube { | ||||
|     pub size: f32, | ||||
| } | ||||
| 
 | ||||
| impl Cube { | ||||
|     pub fn new(size: f32) -> Cube { | ||||
|         Cube { size } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for Cube { | ||||
|     fn default() -> Self { | ||||
|         Cube { size: 1.0 } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Cube> for Mesh { | ||||
|     fn from(cube: Cube) -> Self { | ||||
|         Box::new(cube.size, cube.size, cube.size).into() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// An axis-aligned box defined by its minimum and maximum point.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Cuboid` primitive for meshing or `Aabb3d` for a bounding volume" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Box { | ||||
|     pub min_x: f32, | ||||
|     pub max_x: f32, | ||||
| 
 | ||||
|     pub min_y: f32, | ||||
|     pub max_y: f32, | ||||
| 
 | ||||
|     pub min_z: f32, | ||||
|     pub max_z: f32, | ||||
| } | ||||
| 
 | ||||
| impl Box { | ||||
|     /// Creates a new box centered at the origin with the supplied side lengths.
 | ||||
|     pub fn new(x_length: f32, y_length: f32, z_length: f32) -> Box { | ||||
|         Box { | ||||
|             max_x: x_length / 2.0, | ||||
|             min_x: -x_length / 2.0, | ||||
|             max_y: y_length / 2.0, | ||||
|             min_y: -y_length / 2.0, | ||||
|             max_z: z_length / 2.0, | ||||
|             min_z: -z_length / 2.0, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Creates a new box given the coordinates of two opposing corners.
 | ||||
|     pub fn from_corners(a: Vec3, b: Vec3) -> Box { | ||||
|         let max = a.max(b); | ||||
|         let min = a.min(b); | ||||
|         Box { | ||||
|             max_x: max.x, | ||||
|             min_x: min.x, | ||||
|             max_y: max.y, | ||||
|             min_y: min.y, | ||||
|             max_z: max.z, | ||||
|             min_z: min.z, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for Box { | ||||
|     fn default() -> Self { | ||||
|         Box::new(2.0, 1.0, 1.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Box> for Mesh { | ||||
|     fn from(sp: Box) -> Self { | ||||
|         // suppose Y-up right hand, and camera look from +z to -z
 | ||||
|         let vertices = &[ | ||||
|             // Front
 | ||||
|             ([sp.min_x, sp.min_y, sp.max_z], [0., 0., 1.0], [0., 0.]), | ||||
|             ([sp.max_x, sp.min_y, sp.max_z], [0., 0., 1.0], [1.0, 0.]), | ||||
|             ([sp.max_x, sp.max_y, sp.max_z], [0., 0., 1.0], [1.0, 1.0]), | ||||
|             ([sp.min_x, sp.max_y, sp.max_z], [0., 0., 1.0], [0., 1.0]), | ||||
|             // Back
 | ||||
|             ([sp.min_x, sp.max_y, sp.min_z], [0., 0., -1.0], [1.0, 0.]), | ||||
|             ([sp.max_x, sp.max_y, sp.min_z], [0., 0., -1.0], [0., 0.]), | ||||
|             ([sp.max_x, sp.min_y, sp.min_z], [0., 0., -1.0], [0., 1.0]), | ||||
|             ([sp.min_x, sp.min_y, sp.min_z], [0., 0., -1.0], [1.0, 1.0]), | ||||
|             // Right
 | ||||
|             ([sp.max_x, sp.min_y, sp.min_z], [1.0, 0., 0.], [0., 0.]), | ||||
|             ([sp.max_x, sp.max_y, sp.min_z], [1.0, 0., 0.], [1.0, 0.]), | ||||
|             ([sp.max_x, sp.max_y, sp.max_z], [1.0, 0., 0.], [1.0, 1.0]), | ||||
|             ([sp.max_x, sp.min_y, sp.max_z], [1.0, 0., 0.], [0., 1.0]), | ||||
|             // Left
 | ||||
|             ([sp.min_x, sp.min_y, sp.max_z], [-1.0, 0., 0.], [1.0, 0.]), | ||||
|             ([sp.min_x, sp.max_y, sp.max_z], [-1.0, 0., 0.], [0., 0.]), | ||||
|             ([sp.min_x, sp.max_y, sp.min_z], [-1.0, 0., 0.], [0., 1.0]), | ||||
|             ([sp.min_x, sp.min_y, sp.min_z], [-1.0, 0., 0.], [1.0, 1.0]), | ||||
|             // Top
 | ||||
|             ([sp.max_x, sp.max_y, sp.min_z], [0., 1.0, 0.], [1.0, 0.]), | ||||
|             ([sp.min_x, sp.max_y, sp.min_z], [0., 1.0, 0.], [0., 0.]), | ||||
|             ([sp.min_x, sp.max_y, sp.max_z], [0., 1.0, 0.], [0., 1.0]), | ||||
|             ([sp.max_x, sp.max_y, sp.max_z], [0., 1.0, 0.], [1.0, 1.0]), | ||||
|             // Bottom
 | ||||
|             ([sp.max_x, sp.min_y, sp.max_z], [0., -1.0, 0.], [0., 0.]), | ||||
|             ([sp.min_x, sp.min_y, sp.max_z], [0., -1.0, 0.], [1.0, 0.]), | ||||
|             ([sp.min_x, sp.min_y, sp.min_z], [0., -1.0, 0.], [1.0, 1.0]), | ||||
|             ([sp.max_x, sp.min_y, sp.min_z], [0., -1.0, 0.], [0., 1.0]), | ||||
|         ]; | ||||
| 
 | ||||
|         let positions: Vec<_> = vertices.iter().map(|(p, _, _)| *p).collect(); | ||||
|         let normals: Vec<_> = vertices.iter().map(|(_, n, _)| *n).collect(); | ||||
|         let uvs: Vec<_> = vertices.iter().map(|(_, _, uv)| *uv).collect(); | ||||
| 
 | ||||
|         let indices = Indices::U32(vec![ | ||||
|             0, 1, 2, 2, 3, 0, // front
 | ||||
|             4, 5, 6, 6, 7, 4, // back
 | ||||
|             8, 9, 10, 10, 11, 8, // right
 | ||||
|             12, 13, 14, 14, 15, 12, // left
 | ||||
|             16, 17, 18, 18, 19, 16, // top
 | ||||
|             20, 21, 22, 22, 23, 20, // bottom
 | ||||
|         ]); | ||||
| 
 | ||||
|         Mesh::new( | ||||
|             PrimitiveTopology::TriangleList, | ||||
|             RenderAssetUsages::default(), | ||||
|         ) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) | ||||
|         .with_inserted_indices(indices) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A rectangle on the `XY` plane centered at the origin.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Rectangle` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Quad { | ||||
|     /// Full width and height of the rectangle.
 | ||||
|     pub size: Vec2, | ||||
|     /// Horizontally-flip the texture coordinates of the resulting mesh.
 | ||||
|     pub flip: bool, | ||||
| } | ||||
| 
 | ||||
| impl Default for Quad { | ||||
|     fn default() -> Self { | ||||
|         Quad::new(Vec2::ONE) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Quad { | ||||
|     pub fn new(size: Vec2) -> Self { | ||||
|         Self { size, flip: false } | ||||
|     } | ||||
| 
 | ||||
|     pub fn flipped(size: Vec2) -> Self { | ||||
|         Self { size, flip: true } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Quad> for Mesh { | ||||
|     fn from(quad: Quad) -> Self { | ||||
|         let extent_x = quad.size.x / 2.0; | ||||
|         let extent_y = quad.size.y / 2.0; | ||||
| 
 | ||||
|         let (u_left, u_right) = if quad.flip { (1.0, 0.0) } else { (0.0, 1.0) }; | ||||
|         let vertices = [ | ||||
|             ([-extent_x, -extent_y, 0.0], [0.0, 0.0, 1.0], [u_left, 1.0]), | ||||
|             ([-extent_x, extent_y, 0.0], [0.0, 0.0, 1.0], [u_left, 0.0]), | ||||
|             ([extent_x, extent_y, 0.0], [0.0, 0.0, 1.0], [u_right, 0.0]), | ||||
|             ([extent_x, -extent_y, 0.0], [0.0, 0.0, 1.0], [u_right, 1.0]), | ||||
|         ]; | ||||
| 
 | ||||
|         let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]); | ||||
| 
 | ||||
|         let positions: Vec<_> = vertices.iter().map(|(p, _, _)| *p).collect(); | ||||
|         let normals: Vec<_> = vertices.iter().map(|(_, n, _)| *n).collect(); | ||||
|         let uvs: Vec<_> = vertices.iter().map(|(_, _, uv)| *uv).collect(); | ||||
| 
 | ||||
|         Mesh::new( | ||||
|             PrimitiveTopology::TriangleList, | ||||
|             RenderAssetUsages::default(), | ||||
|         ) | ||||
|         .with_inserted_indices(indices) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A square on the `XZ` plane centered at the origin.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Plane3d` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Plane { | ||||
|     /// The total side length of the square.
 | ||||
|     pub size: f32, | ||||
|     /// The number of subdivisions in the mesh.
 | ||||
|     ///
 | ||||
|     /// 0 - is the original plane geometry, the 4 points in the XZ plane.
 | ||||
|     ///
 | ||||
|     /// 1 - is split by 1 line in the middle of the plane on both the X axis and the Z axis, resulting in a plane with 4 quads / 8 triangles.
 | ||||
|     ///
 | ||||
|     /// 2 - is a plane split by 2 lines on both the X and Z axes, subdividing the plane into 3 equal sections along each axis, resulting in a plane with 9 quads / 18 triangles.
 | ||||
|     ///
 | ||||
|     /// and so on...
 | ||||
|     pub subdivisions: u32, | ||||
| } | ||||
| 
 | ||||
| impl Default for Plane { | ||||
|     fn default() -> Self { | ||||
|         Plane { | ||||
|             size: 1.0, | ||||
|             subdivisions: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Plane { | ||||
|     /// Creates a new plane centered at the origin with the supplied side length and zero subdivisions.
 | ||||
|     pub fn from_size(size: f32) -> Self { | ||||
|         Self { | ||||
|             size, | ||||
|             subdivisions: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Plane> for Mesh { | ||||
|     fn from(plane: Plane) -> Self { | ||||
|         // here this is split in the z and x directions if one ever needs asymmetrical subdivision
 | ||||
|         // two Plane struct fields would need to be added instead of the single subdivisions field
 | ||||
|         let z_vertex_count = plane.subdivisions + 2; | ||||
|         let x_vertex_count = plane.subdivisions + 2; | ||||
|         let num_vertices = (z_vertex_count * x_vertex_count) as usize; | ||||
|         let num_indices = ((z_vertex_count - 1) * (x_vertex_count - 1) * 6) as usize; | ||||
|         let up = Vec3::Y.to_array(); | ||||
| 
 | ||||
|         let mut positions: Vec<[f32; 3]> = Vec::with_capacity(num_vertices); | ||||
|         let mut normals: Vec<[f32; 3]> = Vec::with_capacity(num_vertices); | ||||
|         let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(num_vertices); | ||||
|         let mut indices: Vec<u32> = Vec::with_capacity(num_indices); | ||||
| 
 | ||||
|         for z in 0..z_vertex_count { | ||||
|             for x in 0..x_vertex_count { | ||||
|                 let tx = x as f32 / (x_vertex_count - 1) as f32; | ||||
|                 let tz = z as f32 / (z_vertex_count - 1) as f32; | ||||
|                 positions.push([(-0.5 + tx) * plane.size, 0.0, (-0.5 + tz) * plane.size]); | ||||
|                 normals.push(up); | ||||
|                 uvs.push([tx, tz]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for y in 0..z_vertex_count - 1 { | ||||
|             for x in 0..x_vertex_count - 1 { | ||||
|                 let quad = y * x_vertex_count + x; | ||||
|                 indices.push(quad + x_vertex_count + 1); | ||||
|                 indices.push(quad + 1); | ||||
|                 indices.push(quad + x_vertex_count); | ||||
|                 indices.push(quad); | ||||
|                 indices.push(quad + x_vertex_count); | ||||
|                 indices.push(quad + 1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Mesh::new( | ||||
|             PrimitiveTopology::TriangleList, | ||||
|             RenderAssetUsages::default(), | ||||
|         ) | ||||
|         .with_inserted_indices(Indices::U32(indices)) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) | ||||
|         .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| mod capsule; | ||||
| mod cylinder; | ||||
| mod icosphere; | ||||
| mod regular_polygon; | ||||
| mod torus; | ||||
| mod uvsphere; | ||||
| 
 | ||||
| pub use capsule::Capsule; | ||||
| pub use cylinder::Cylinder; | ||||
| pub use icosphere::Icosphere; | ||||
| pub use regular_polygon::{Circle, RegularPolygon}; | ||||
| pub use torus::Torus; | ||||
| pub use uvsphere::UVSphere; | ||||
| use wgpu::PrimitiveTopology; | ||||
| @ -1,85 +0,0 @@ | ||||
| use crate::mesh::{Mesh, Meshable}; | ||||
| 
 | ||||
| /// A regular polygon in the `XY` plane
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `RegularPolygon` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct RegularPolygon { | ||||
|     /// Circumscribed radius in the `XY` plane.
 | ||||
|     ///
 | ||||
|     /// In other words, the vertices of this polygon will all touch a circle of this radius.
 | ||||
|     pub radius: f32, | ||||
|     /// Number of sides.
 | ||||
|     pub sides: usize, | ||||
| } | ||||
| 
 | ||||
| impl Default for RegularPolygon { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             radius: 0.5, | ||||
|             sides: 6, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl RegularPolygon { | ||||
|     /// Creates a regular polygon in the `XY` plane
 | ||||
|     pub fn new(radius: f32, sides: usize) -> Self { | ||||
|         Self { radius, sides } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<RegularPolygon> for Mesh { | ||||
|     fn from(polygon: RegularPolygon) -> Self { | ||||
|         bevy_math::primitives::RegularPolygon::new(polygon.radius, polygon.sides).mesh() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A circle in the `XY` plane
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Circle` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Circle { | ||||
|     /// Inscribed radius in the `XY` plane.
 | ||||
|     pub radius: f32, | ||||
|     /// The number of vertices used.
 | ||||
|     pub vertices: usize, | ||||
| } | ||||
| 
 | ||||
| impl Default for Circle { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             radius: 0.5, | ||||
|             vertices: 64, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Circle { | ||||
|     /// Creates a circle in the `XY` plane
 | ||||
|     pub fn new(radius: f32) -> Self { | ||||
|         Self { | ||||
|             radius, | ||||
|             ..Default::default() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Circle> for RegularPolygon { | ||||
|     fn from(circle: Circle) -> Self { | ||||
|         Self { | ||||
|             radius: circle.radius, | ||||
|             sides: circle.vertices, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Circle> for Mesh { | ||||
|     fn from(circle: Circle) -> Self { | ||||
|         Mesh::from(RegularPolygon::from(circle)) | ||||
|     } | ||||
| } | ||||
| @ -1,38 +0,0 @@ | ||||
| use crate::mesh::{Mesh, Meshable}; | ||||
| 
 | ||||
| /// A torus (donut) shape.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Torus` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct Torus { | ||||
|     pub radius: f32, | ||||
|     pub ring_radius: f32, | ||||
|     pub subdivisions_segments: usize, | ||||
|     pub subdivisions_sides: usize, | ||||
| } | ||||
| 
 | ||||
| impl Default for Torus { | ||||
|     fn default() -> Self { | ||||
|         Torus { | ||||
|             radius: 1.0, | ||||
|             ring_radius: 0.5, | ||||
|             subdivisions_segments: 32, | ||||
|             subdivisions_sides: 24, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Torus> for Mesh { | ||||
|     fn from(torus: Torus) -> Self { | ||||
|         bevy_math::primitives::Torus { | ||||
|             minor_radius: torus.ring_radius, | ||||
|             major_radius: torus.radius, | ||||
|         } | ||||
|         .mesh() | ||||
|         .minor_resolution(torus.subdivisions_sides) | ||||
|         .major_resolution(torus.subdivisions_segments) | ||||
|         .build() | ||||
|     } | ||||
| } | ||||
| @ -1,37 +0,0 @@ | ||||
| use bevy_math::primitives::Sphere; | ||||
| 
 | ||||
| use crate::mesh::{Mesh, Meshable}; | ||||
| 
 | ||||
| /// A sphere made of sectors and stacks.
 | ||||
| #[deprecated(
 | ||||
|     since = "0.13.0", | ||||
|     note = "please use the `Sphere` primitive in `bevy_math` instead" | ||||
| )] | ||||
| #[allow(clippy::upper_case_acronyms)] | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct UVSphere { | ||||
|     /// The radius of the sphere.
 | ||||
|     pub radius: f32, | ||||
|     /// Longitudinal sectors
 | ||||
|     pub sectors: usize, | ||||
|     /// Latitudinal stacks
 | ||||
|     pub stacks: usize, | ||||
| } | ||||
| 
 | ||||
| impl Default for UVSphere { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             radius: 1.0, | ||||
|             sectors: 36, | ||||
|             stacks: 18, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<UVSphere> for Mesh { | ||||
|     fn from(sphere: UVSphere) -> Self { | ||||
|         Sphere::new(sphere.radius) | ||||
|             .mesh() | ||||
|             .uv(sphere.sectors, sphere.stacks) | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 James Liu
						James Liu