Add documentation to ParamSet (#6998)
				
					
				
			# Objective Fixes #4729. Continuation of #4854. ## Solution Add documentation to `ParamSet` and its methods. Includes examples suggested by community members in the original PR. Co-authored-by: Nanox19435 <50684926+Nanox19435@users.noreply.github.com> Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									ca87830450
								
							
						
					
					
						commit
						fa2b5f2b36
					
				@ -222,7 +222,17 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
 | 
				
			|||||||
    for (i, param) in params.iter().enumerate() {
 | 
					    for (i, param) in params.iter().enumerate() {
 | 
				
			||||||
        let fn_name = Ident::new(&format!("p{i}"), Span::call_site());
 | 
					        let fn_name = Ident::new(&format!("p{i}"), Span::call_site());
 | 
				
			||||||
        let index = Index::from(i);
 | 
					        let index = Index::from(i);
 | 
				
			||||||
 | 
					        let ordinal = match i {
 | 
				
			||||||
 | 
					            1 => "1st".to_owned(),
 | 
				
			||||||
 | 
					            2 => "2nd".to_owned(),
 | 
				
			||||||
 | 
					            3 => "3rd".to_owned(),
 | 
				
			||||||
 | 
					            x => format!("{x}th"),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let comment =
 | 
				
			||||||
 | 
					            format!("Gets exclusive access to the {ordinal} parameter in this [`ParamSet`].");
 | 
				
			||||||
        param_fn_muts.push(quote! {
 | 
					        param_fn_muts.push(quote! {
 | 
				
			||||||
 | 
					            #[doc = #comment]
 | 
				
			||||||
 | 
					            /// No other parameters may be accessed while this one is active.
 | 
				
			||||||
            pub fn #fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, #param> {
 | 
					            pub fn #fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, #param> {
 | 
				
			||||||
                // SAFETY: systems run without conflicts with other systems.
 | 
					                // SAFETY: systems run without conflicts with other systems.
 | 
				
			||||||
                // Conflicting params in ParamSet are not accessible at the same time
 | 
					                // Conflicting params in ParamSet are not accessible at the same time
 | 
				
			||||||
 | 
				
			|||||||
@ -239,6 +239,114 @@ fn assert_component_access_compatibility(
 | 
				
			|||||||
           query_type, filter_type, system_name, accesses);
 | 
					           query_type, filter_type, system_name, accesses);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as
 | 
				
			||||||
 | 
					/// two queries that reference the same mutable data or an event reader and writer of the same type.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,
 | 
				
			||||||
 | 
					/// according to the order they are defined in the `ParamSet`. This ensures that there's either
 | 
				
			||||||
 | 
					/// only one mutable reference to a parameter at a time or any number of immutable references.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// # Examples
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// The following system mutably accesses the same component two times,
 | 
				
			||||||
 | 
					/// which is not allowed due to rust's mutability rules.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```should_panic
 | 
				
			||||||
 | 
					/// # use bevy_ecs::prelude::*;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Health;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Enemy;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Ally;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// // This will panic at runtime when the system gets initialized.
 | 
				
			||||||
 | 
					/// fn bad_system(
 | 
				
			||||||
 | 
					///     mut enemies: Query<&mut Health, With<Enemy>>,
 | 
				
			||||||
 | 
					///     mut allies: Query<&mut Health, With<Ally>>,
 | 
				
			||||||
 | 
					/// ) {
 | 
				
			||||||
 | 
					///     // ...
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # let mut bad_system_system = bevy_ecs::system::IntoSystem::into_system(bad_system);
 | 
				
			||||||
 | 
					/// # let mut world = World::new();
 | 
				
			||||||
 | 
					/// # bad_system_system.initialize(&mut world);
 | 
				
			||||||
 | 
					/// # bad_system_system.run((), &mut world);
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Conflicing `SystemParam`s like these can be placed in a `ParamSet`,
 | 
				
			||||||
 | 
					/// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// # use bevy_ecs::prelude::*;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Health;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Enemy;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # #[derive(Component)]
 | 
				
			||||||
 | 
					/// # struct Ally;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// // Given the following system
 | 
				
			||||||
 | 
					/// fn fancy_system(
 | 
				
			||||||
 | 
					///     mut set: ParamSet<(
 | 
				
			||||||
 | 
					///         Query<&mut Health, With<Enemy>>,
 | 
				
			||||||
 | 
					///         Query<&mut Health, With<Ally>>,
 | 
				
			||||||
 | 
					///     )>
 | 
				
			||||||
 | 
					/// ) {
 | 
				
			||||||
 | 
					///     // This will access the first `SystemParam`.
 | 
				
			||||||
 | 
					///     for mut health in set.p0().iter_mut() {
 | 
				
			||||||
 | 
					///         // Do your fancy stuff here...
 | 
				
			||||||
 | 
					///     }
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///     // The second `SystemParam`.
 | 
				
			||||||
 | 
					///     // This would fail to compile if the previous parameter was still borrowed.
 | 
				
			||||||
 | 
					///     for mut health in set.p1().iter_mut() {
 | 
				
			||||||
 | 
					///         // Do even fancier stuff here...
 | 
				
			||||||
 | 
					///     }
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// # bevy_ecs::system::assert_is_system(fancy_system);
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// # use bevy_ecs::prelude::*;
 | 
				
			||||||
 | 
					/// #
 | 
				
			||||||
 | 
					/// # struct MyEvent;
 | 
				
			||||||
 | 
					/// # impl MyEvent {
 | 
				
			||||||
 | 
					/// #   pub fn new() -> Self { Self }
 | 
				
			||||||
 | 
					/// # }
 | 
				
			||||||
 | 
					/// fn event_system(
 | 
				
			||||||
 | 
					///     mut set: ParamSet<(
 | 
				
			||||||
 | 
					///         // `EventReader`s and `EventWriter`s conflict with each other,
 | 
				
			||||||
 | 
					///         // since they both access the event queue resource for `MyEvent`.
 | 
				
			||||||
 | 
					///         EventReader<MyEvent>,
 | 
				
			||||||
 | 
					///         EventWriter<MyEvent>,
 | 
				
			||||||
 | 
					///         // `&World` reads the entire world, so a `ParamSet` is the only way
 | 
				
			||||||
 | 
					///         // that it can be used in the same system as any mutable accesses.
 | 
				
			||||||
 | 
					///         &World,
 | 
				
			||||||
 | 
					///     )>,
 | 
				
			||||||
 | 
					/// ) {
 | 
				
			||||||
 | 
					///     for event in set.p0().iter() {
 | 
				
			||||||
 | 
					///         // ...
 | 
				
			||||||
 | 
					///         # let _event = event;
 | 
				
			||||||
 | 
					///     }
 | 
				
			||||||
 | 
					///     set.p1().send(MyEvent::new());
 | 
				
			||||||
 | 
					///     
 | 
				
			||||||
 | 
					///     let entities = set.p2().entities();
 | 
				
			||||||
 | 
					///     // ...
 | 
				
			||||||
 | 
					///     # let _entities = entities;
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// # bevy_ecs::system::assert_is_system(event_system);
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
pub struct ParamSet<'w, 's, T: SystemParam> {
 | 
					pub struct ParamSet<'w, 's, T: SystemParam> {
 | 
				
			||||||
    param_states: &'s mut T::State,
 | 
					    param_states: &'s mut T::State,
 | 
				
			||||||
    world: &'w World,
 | 
					    world: &'w World,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user