pub unsafe trait SystemParamBuilder<P>: Sizedwhere
P: SystemParam,{
// Required method
fn build(
self,
world: &mut World,
meta: &mut SystemMeta,
) -> <P as SystemParam>::State;
// Provided method
fn build_state(self, world: &mut World) -> SystemState<P> { ... }
}
Expand description
A builder that can create a SystemParam
.
fn some_system(param: MyParam) {}
fn build_system(builder: impl SystemParamBuilder<MyParam>) {
let mut world = World::new();
// To build a system, create a tuple of `SystemParamBuilder`s
// with a builder for each parameter.
// Note that the builder for a system must be a tuple,
// even if there is only one parameter.
(builder,)
.build_state(&mut world)
.build_system(some_system);
}
fn build_closure_system_infer(builder: impl SystemParamBuilder<MyParam>) {
let mut world = World::new();
// Closures can be used in addition to named functions.
// If a closure is used, the parameter types must all be inferred
// from the builders, so you cannot use plain `ParamBuilder`.
(builder, ParamBuilder::resource())
.build_state(&mut world)
.build_system(|param, res| {
let param: MyParam = param;
let res: Res<R> = res;
});
}
fn build_closure_system_explicit(builder: impl SystemParamBuilder<MyParam>) {
let mut world = World::new();
// Alternately, you can provide all types in the closure
// parameter list and call `build_any_system()`.
(builder, ParamBuilder)
.build_state(&mut world)
.build_any_system(|param: MyParam, res: Res<R>| {});
}
See the documentation for individual builders for more examples.
§List of Builders
ParamBuilder
can be used for parameters that don’t require any special building.
Using a ParamBuilder
will build the system parameter the same way it would be initialized in an ordinary system.
ParamBuilder
also provides factory methods that return a ParamBuilder
typed as impl SystemParamBuilder<P>
for common system parameters that can be used to guide closure parameter inference.
QueryParamBuilder
can build a Query
to add additional filters,
or to configure the components available to FilteredEntityRef
or FilteredEntityMut
.
You can also use a QueryState
to build a Query
.
LocalBuilder
can build a Local
to supply the initial value for the Local
.
FilteredResourcesParamBuilder
can build a FilteredResources
,
and FilteredResourcesMutParamBuilder
can build a FilteredResourcesMut
,
to configure the resources that can be accessed.
DynParamBuilder
can build a DynSystemParam
to determine the type of the inner parameter,
and to supply any SystemParamBuilder
it needs.
Tuples of builders can build tuples of parameters, one builder for each element. Note that since systems require a tuple as a parameter, the outer builder for a system will always be a tuple.
A Vec
of builders can build a Vec
of parameters, one builder for each element.
A ParamSetBuilder
can build a ParamSet
.
This can wrap either a tuple or a Vec
, one builder for each element.
A custom system param created with #[derive(SystemParam)]
can be buildable if it includes a #[system_param(builder)]
attribute.
See the documentation for SystemParam
derives.
§Safety
The implementor must ensure the following is true.
SystemParamBuilder::build
correctly registers allWorld
accesses used bySystemParam::get_param
with the providedsystem_meta
.- None of the world accesses may conflict with any prior accesses registered
on
system_meta
.
Note that this depends on the implementation of SystemParam::get_param
,
so if Self
is not a local type then you must call SystemParam::init_state
or another SystemParamBuilder::build
Required Methods§
Sourcefn build(
self,
world: &mut World,
meta: &mut SystemMeta,
) -> <P as SystemParam>::State
fn build( self, world: &mut World, meta: &mut SystemMeta, ) -> <P as SystemParam>::State
Registers any World
access used by this SystemParam
and creates a new instance of this param’s State
.
Provided Methods§
Sourcefn build_state(self, world: &mut World) -> SystemState<P>
fn build_state(self, world: &mut World) -> SystemState<P>
Create a SystemState
from a SystemParamBuilder
.
To create a system, call SystemState::build_system
on the result.
Examples found in repository?
79fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
80 let mut rng = ChaCha8Rng::seed_from_u64(42);
81 let mut app = App::default();
82 let world = app.world_mut();
83
84 // register a bunch of components
85 let component_ids: Vec<ComponentId> = (1..=num_components)
86 .map(|i| {
87 world.register_component_with_descriptor(
88 // SAFETY:
89 // * We don't implement a drop function
90 // * u8 is Sync and Send
91 unsafe {
92 ComponentDescriptor::new_with_layout(
93 format!("Component{}", i).to_string(),
94 StorageType::Table,
95 Layout::new::<u8>(),
96 None,
97 true, // is mutable
98 ComponentCloneBehavior::Default,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.gen_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .choose_multiple(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.gen_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .choose_multiple(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.gen_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 println!(
161 "Number of Archetype-Components: {}",
162 world.archetypes().archetype_components_len()
163 );
164
165 // overwrite Update schedule in the app
166 app.add_schedule(schedule);
167 app.add_plugins(MinimalPlugins)
168 .add_plugins(DiagnosticsPlugin)
169 .add_plugins(LogPlugin::default())
170 .add_plugins(FrameTimeDiagnosticsPlugin::default())
171 .add_plugins(LogDiagnosticsPlugin::filtered(vec![DiagnosticPath::new(
172 "fps",
173 )]));
174 app.run();
175}
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl SystemParamBuilder<()> for ()
impl SystemParamBuilder<()> for ()
fn build( self, world: &mut World, meta: &mut SystemMeta, ) -> <() as SystemParam>::State
Source§impl<P, B> SystemParamBuilder<(P₁, P₂, …, Pₙ)> for (B₁, B₂, …, Bₙ)where
P: SystemParam,
B: SystemParamBuilder<P>,
This trait is implemented for tuples up to 17 items long.
impl<P, B> SystemParamBuilder<(P₁, P₂, …, Pₙ)> for (B₁, B₂, …, Bₙ)where
P: SystemParam,
B: SystemParamBuilder<P>,
This trait is implemented for tuples up to 17 items long.