pub struct Commands<'w, 's> { /* private fields */ }
Expand description
A Command
queue to perform structural changes to the World
.
Since each command requires exclusive access to the World
,
all queued commands are automatically applied in sequence
when the ApplyDeferred
system runs (see ApplyDeferred
documentation for more details).
Each command can be used to modify the World
in arbitrary ways:
- spawning or despawning entities
- inserting components on new or existing entities
- inserting resources
- etc.
For a version of Commands
that works in parallel contexts (such as
within Query::par_iter
) see
ParallelCommands
§Usage
Add mut commands: Commands
as a function argument to your system to get a
copy of this struct that will be applied the next time a copy of ApplyDeferred
runs.
Commands are almost always used as a SystemParam
.
fn my_system(mut commands: Commands) {
// ...
}
§Implementing
Each built-in command is implemented as a separate method, e.g. Commands::spawn
.
In addition to the pre-defined command methods, you can add commands with any arbitrary
behavior using Commands::queue
, which accepts any type implementing Command
.
Since closures and other functions implement this trait automatically, this allows one-shot, anonymous custom commands.
// NOTE: type inference fails here, so annotations are required on the closure.
commands.queue(|w: &mut World| {
// Mutate the world however you want...
});
§Error handling
A Command
can return a Result
,
which will be passed to an error handler if the Result
is an error.
The default error handler panics. It can be configured via
the DefaultErrorHandler
resource.
Alternatively, you can customize the error handler for a specific command
by calling Commands::queue_handled
.
The error
module provides some simple error handlers for convenience.
Implementations§
Source§impl<'w, 's> Commands<'w, 's>
impl<'w, 's> Commands<'w, 's>
Sourcepub fn new(queue: &'s mut CommandQueue, world: &'w World) -> Commands<'w, 's>
pub fn new(queue: &'s mut CommandQueue, world: &'w World) -> Commands<'w, 's>
Returns a new Commands
instance from a CommandQueue
and a World
.
Sourcepub fn new_from_entities(
queue: &'s mut CommandQueue,
entities: &'w Entities,
) -> Commands<'w, 's>
pub fn new_from_entities( queue: &'s mut CommandQueue, entities: &'w Entities, ) -> Commands<'w, 's>
Returns a new Commands
instance from a CommandQueue
and an Entities
reference.
Sourcepub fn reborrow(&mut self) -> Commands<'w, '_>
pub fn reborrow(&mut self) -> Commands<'w, '_>
Returns a Commands
with a smaller lifetime.
This is useful if you have &mut Commands
but need Commands
.
§Example
fn my_system(mut commands: Commands) {
// We do our initialization in a separate function,
// which expects an owned `Commands`.
do_initialization(commands.reborrow());
// Since we only reborrowed the commands instead of moving them, we can still use them.
commands.spawn_empty();
}
Sourcepub fn append(&mut self, other: &mut CommandQueue)
pub fn append(&mut self, other: &mut CommandQueue)
Take all commands from other
and append them to self
, leaving other
empty.
Examples found in repository?
110fn handle_tasks(
111 mut commands: Commands,
112 mut transform_tasks: Query<(Entity, &mut ComputeTransform)>,
113) {
114 for (entity, mut task) in &mut transform_tasks {
115 if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) {
116 // append the returned command queue to have it execute later
117 commands.append(&mut commands_queue);
118 // Task is complete, so remove task component from entity
119 commands.entity(entity).remove::<ComputeTransform>();
120 }
121 }
122}
Sourcepub fn spawn_empty(&mut self) -> EntityCommands<'_>
pub fn spawn_empty(&mut self) -> EntityCommands<'_>
Spawns a new empty Entity
and returns its corresponding EntityCommands
.
§Example
#[derive(Component)]
struct Label(&'static str);
#[derive(Component)]
struct Strength(u32);
#[derive(Component)]
struct Agility(u32);
fn example_system(mut commands: Commands) {
// Create a new empty entity.
commands.spawn_empty();
// Create another empty entity.
commands.spawn_empty()
// Add a new component bundle to the entity.
.insert((Strength(1), Agility(2)))
// Add a single component to the entity.
.insert(Label("hello world"));
}
§See also
spawn
to spawn an entity with components.spawn_batch
to spawn many entities with the same combination of components.
Examples found in repository?
53fn spawn_tasks(mut commands: Commands) {
54 let thread_pool = AsyncComputeTaskPool::get();
55 for x in 0..NUM_CUBES {
56 for y in 0..NUM_CUBES {
57 for z in 0..NUM_CUBES {
58 // Spawn new task on the AsyncComputeTaskPool; the task will be
59 // executed in the background, and the Task future returned by
60 // spawn() can be used to poll for the result
61 let entity = commands.spawn_empty().id();
62 let task = thread_pool.spawn(async move {
63 let duration = Duration::from_secs_f32(rand::rng().random_range(0.05..5.0));
64
65 // Pretend this is a time-intensive function. :)
66 Delay::new(duration).await;
67
68 // Such hard work, all done!
69 let transform = Transform::from_xyz(x as f32, y as f32, z as f32);
70 let mut command_queue = CommandQueue::default();
71
72 // we use a raw command queue to pass a FnOnce(&mut World) back to be
73 // applied in a deferred manner.
74 command_queue.push(move |world: &mut World| {
75 let (box_mesh_handle, box_material_handle) = {
76 let mut system_state = SystemState::<(
77 Res<BoxMeshHandle>,
78 Res<BoxMaterialHandle>,
79 )>::new(world);
80 let (box_mesh_handle, box_material_handle) =
81 system_state.get_mut(world);
82
83 (box_mesh_handle.clone(), box_material_handle.clone())
84 };
85
86 world
87 .entity_mut(entity)
88 // Add our new `Mesh3d` and `MeshMaterial3d` to our tagged entity
89 .insert((
90 Mesh3d(box_mesh_handle),
91 MeshMaterial3d(box_material_handle),
92 transform,
93 ));
94 });
95
96 command_queue
97 });
98
99 // Add our new task as a component
100 commands.entity(entity).insert(ComputeTransform(task));
101 }
102 }
103 }
104}
More examples
354fn spawn_tree(
355 parent_map: &[usize],
356 commands: &mut Commands,
357 update_filter: &UpdateFilter,
358 root_transform: Transform,
359) -> InsertResult {
360 // total count (# of nodes + root)
361 let count = parent_map.len() + 1;
362
363 #[derive(Default, Clone, Copy)]
364 struct NodeInfo {
365 child_count: u32,
366 depth: u32,
367 }
368
369 // node index -> entity lookup list
370 let mut ents: Vec<Entity> = Vec::with_capacity(count);
371 let mut node_info: Vec<NodeInfo> = vec![default(); count];
372 for (i, &parent_idx) in parent_map.iter().enumerate() {
373 // assert spawn order (parent must be processed before child)
374 assert!(parent_idx <= i, "invalid spawn order");
375 node_info[parent_idx].child_count += 1;
376 }
377
378 // insert root
379 ents.push(commands.spawn(root_transform).id());
380
381 let mut result = InsertResult::default();
382 let mut rng = rand::rng();
383 // used to count through the number of children (used only for visual layout)
384 let mut child_idx: Vec<u16> = vec![0; count];
385
386 // insert children
387 for (current_idx, &parent_idx) in parent_map.iter().enumerate() {
388 let current_idx = current_idx + 1;
389
390 // separation factor to visually separate children (0..1)
391 let sep = child_idx[parent_idx] as f32 / node_info[parent_idx].child_count as f32;
392 child_idx[parent_idx] += 1;
393
394 // calculate and set depth
395 // this works because it's guaranteed that we have already iterated over the parent
396 let depth = node_info[parent_idx].depth + 1;
397 let info = &mut node_info[current_idx];
398 info.depth = depth;
399
400 // update max depth of tree
401 result.maximum_depth = result.maximum_depth.max(depth.try_into().unwrap());
402
403 // insert child
404 let child_entity = {
405 let mut cmd = commands.spawn_empty();
406
407 // check whether or not to update this node
408 let update = (rng.random::<f32>() <= update_filter.probability)
409 && (depth >= update_filter.min_depth && depth <= update_filter.max_depth);
410
411 if update {
412 cmd.insert(UpdateValue(sep));
413 result.active_nodes += 1;
414 }
415
416 let transform = {
417 let mut translation = Vec3::ZERO;
418 // use the same placement fn as the `update` system
419 // this way the entities won't be all at (0, 0, 0) when they don't have an `Update` component
420 set_translation(&mut translation, sep);
421 Transform::from_translation(translation)
422 };
423
424 // only insert the components necessary for the transform propagation
425 cmd.insert(transform);
426
427 cmd.id()
428 };
429
430 commands.entity(ents[parent_idx]).add_child(child_entity);
431
432 ents.push(child_entity);
433 }
434
435 result.inserted_nodes = ents.len();
436 result
437}
Sourcepub fn spawn<T>(&mut self, bundle: T) -> EntityCommands<'_>where
T: Bundle,
pub fn spawn<T>(&mut self, bundle: T) -> EntityCommands<'_>where
T: Bundle,
Spawns a new Entity
with the given components
and returns the entity’s corresponding EntityCommands
.
To spawn many entities with the same combination of components,
spawn_batch
can be used for better performance.
§Example
#[derive(Component)]
struct ComponentA(u32);
#[derive(Component)]
struct ComponentB(u32);
#[derive(Bundle)]
struct ExampleBundle {
a: ComponentA,
b: ComponentB,
}
fn example_system(mut commands: Commands) {
// Create a new entity with a single component.
commands.spawn(ComponentA(1));
// Create a new entity with two components using a "tuple bundle".
commands.spawn((ComponentA(2), ComponentB(1)));
// Create a new entity with a component bundle.
commands.spawn(ExampleBundle {
a: ComponentA(3),
b: ComponentB(2),
});
}
§See also
spawn_empty
to spawn an entity without any components.spawn_batch
to spawn many entities with the same combination of components.
Examples found in repository?
43fn setup(mut commands: Commands) {
44 commands.spawn(Camera2d);
45}
46
47mod splash {
48 use bevy::prelude::*;
49
50 use super::GameState;
51
52 // This plugin will display a splash screen with Bevy logo for 1 second before switching to the menu
53 pub fn splash_plugin(app: &mut App) {
54 // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash`
55 app
56 // When entering the state, spawn everything needed for this screen
57 .add_systems(OnEnter(GameState::Splash), splash_setup)
58 // While in this state, run the `countdown` system
59 .add_systems(Update, countdown.run_if(in_state(GameState::Splash)));
60 }
61
62 // Tag component used to tag entities added on the splash screen
63 #[derive(Component)]
64 struct OnSplashScreen;
65
66 // Newtype to use a `Timer` for this screen as a resource
67 #[derive(Resource, Deref, DerefMut)]
68 struct SplashTimer(Timer);
69
70 fn splash_setup(mut commands: Commands, asset_server: Res<AssetServer>) {
71 let icon = asset_server.load("branding/icon.png");
72 // Display the logo
73 commands.spawn((
74 // This entity will be despawned when exiting the state
75 DespawnOnExit(GameState::Splash),
76 Node {
77 align_items: AlignItems::Center,
78 justify_content: JustifyContent::Center,
79 width: percent(100),
80 height: percent(100),
81 ..default()
82 },
83 OnSplashScreen,
84 children![(
85 ImageNode::new(icon),
86 Node {
87 // This will set the logo to be 200px wide, and auto adjust its height
88 width: px(200),
89 ..default()
90 },
91 )],
92 ));
93 // Insert the timer as a resource
94 commands.insert_resource(SplashTimer(Timer::from_seconds(1.0, TimerMode::Once)));
95 }
96
97 // Tick the timer, and change state when finished
98 fn countdown(
99 mut game_state: ResMut<NextState<GameState>>,
100 time: Res<Time>,
101 mut timer: ResMut<SplashTimer>,
102 ) {
103 if timer.tick(time.delta()).is_finished() {
104 game_state.set(GameState::Menu);
105 }
106 }
107}
108
109mod game {
110 use bevy::{
111 color::palettes::basic::{BLUE, LIME},
112 prelude::*,
113 };
114
115 use super::{DisplayQuality, GameState, Volume, TEXT_COLOR};
116
117 // This plugin will contain the game. In this case, it's just be a screen that will
118 // display the current settings for 5 seconds before returning to the menu
119 pub fn game_plugin(app: &mut App) {
120 app.add_systems(OnEnter(GameState::Game), game_setup)
121 .add_systems(Update, game.run_if(in_state(GameState::Game)));
122 }
123
124 // Tag component used to tag entities added on the game screen
125 #[derive(Component)]
126 struct OnGameScreen;
127
128 #[derive(Resource, Deref, DerefMut)]
129 struct GameTimer(Timer);
130
131 fn game_setup(
132 mut commands: Commands,
133 display_quality: Res<DisplayQuality>,
134 volume: Res<Volume>,
135 ) {
136 commands.spawn((
137 DespawnOnExit(GameState::Game),
138 Node {
139 width: percent(100),
140 height: percent(100),
141 // center children
142 align_items: AlignItems::Center,
143 justify_content: JustifyContent::Center,
144 ..default()
145 },
146 OnGameScreen,
147 children![(
148 Node {
149 // This will display its children in a column, from top to bottom
150 flex_direction: FlexDirection::Column,
151 // `align_items` will align children on the cross axis. Here the main axis is
152 // vertical (column), so the cross axis is horizontal. This will center the
153 // children
154 align_items: AlignItems::Center,
155 ..default()
156 },
157 BackgroundColor(Color::BLACK),
158 children![
159 (
160 Text::new("Will be back to the menu shortly..."),
161 TextFont {
162 font_size: 67.0,
163 ..default()
164 },
165 TextColor(TEXT_COLOR),
166 Node {
167 margin: UiRect::all(px(50)),
168 ..default()
169 },
170 ),
171 (
172 Text::default(),
173 Node {
174 margin: UiRect::all(px(50)),
175 ..default()
176 },
177 children![
178 (
179 TextSpan(format!("quality: {:?}", *display_quality)),
180 TextFont {
181 font_size: 50.0,
182 ..default()
183 },
184 TextColor(BLUE.into()),
185 ),
186 (
187 TextSpan::new(" - "),
188 TextFont {
189 font_size: 50.0,
190 ..default()
191 },
192 TextColor(TEXT_COLOR),
193 ),
194 (
195 TextSpan(format!("volume: {:?}", *volume)),
196 TextFont {
197 font_size: 50.0,
198 ..default()
199 },
200 TextColor(LIME.into()),
201 ),
202 ]
203 ),
204 ]
205 )],
206 ));
207 // Spawn a 5 seconds timer to trigger going back to the menu
208 commands.insert_resource(GameTimer(Timer::from_seconds(5.0, TimerMode::Once)));
209 }
210
211 // Tick the timer, and change state when finished
212 fn game(
213 time: Res<Time>,
214 mut game_state: ResMut<NextState<GameState>>,
215 mut timer: ResMut<GameTimer>,
216 ) {
217 if timer.tick(time.delta()).is_finished() {
218 game_state.set(GameState::Menu);
219 }
220 }
221}
222
223mod menu {
224 use bevy::{
225 app::AppExit,
226 color::palettes::css::CRIMSON,
227 ecs::spawn::{SpawnIter, SpawnWith},
228 prelude::*,
229 };
230
231 use super::{DisplayQuality, GameState, Volume, TEXT_COLOR};
232
233 // This plugin manages the menu, with 5 different screens:
234 // - a main menu with "New Game", "Settings", "Quit"
235 // - a settings menu with two submenus and a back button
236 // - two settings screen with a setting that can be set and a back button
237 pub fn menu_plugin(app: &mut App) {
238 app
239 // At start, the menu is not enabled. This will be changed in `menu_setup` when
240 // entering the `GameState::Menu` state.
241 // Current screen in the menu is handled by an independent state from `GameState`
242 .init_state::<MenuState>()
243 .add_systems(OnEnter(GameState::Menu), menu_setup)
244 // Systems to handle the main menu screen
245 .add_systems(OnEnter(MenuState::Main), main_menu_setup)
246 // Systems to handle the settings menu screen
247 .add_systems(OnEnter(MenuState::Settings), settings_menu_setup)
248 // Systems to handle the display settings screen
249 .add_systems(
250 OnEnter(MenuState::SettingsDisplay),
251 display_settings_menu_setup,
252 )
253 .add_systems(
254 Update,
255 (setting_button::<DisplayQuality>.run_if(in_state(MenuState::SettingsDisplay)),),
256 )
257 // Systems to handle the sound settings screen
258 .add_systems(OnEnter(MenuState::SettingsSound), sound_settings_menu_setup)
259 .add_systems(
260 Update,
261 setting_button::<Volume>.run_if(in_state(MenuState::SettingsSound)),
262 )
263 // Common systems to all screens that handles buttons behavior
264 .add_systems(
265 Update,
266 (menu_action, button_system).run_if(in_state(GameState::Menu)),
267 );
268 }
269
270 // State used for the current menu screen
271 #[derive(Clone, Copy, Default, Eq, PartialEq, Debug, Hash, States)]
272 enum MenuState {
273 Main,
274 Settings,
275 SettingsDisplay,
276 SettingsSound,
277 #[default]
278 Disabled,
279 }
280
281 // Tag component used to tag entities added on the main menu screen
282 #[derive(Component)]
283 struct OnMainMenuScreen;
284
285 // Tag component used to tag entities added on the settings menu screen
286 #[derive(Component)]
287 struct OnSettingsMenuScreen;
288
289 // Tag component used to tag entities added on the display settings menu screen
290 #[derive(Component)]
291 struct OnDisplaySettingsMenuScreen;
292
293 // Tag component used to tag entities added on the sound settings menu screen
294 #[derive(Component)]
295 struct OnSoundSettingsMenuScreen;
296
297 const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
298 const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
299 const HOVERED_PRESSED_BUTTON: Color = Color::srgb(0.25, 0.65, 0.25);
300 const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
301
302 // Tag component used to mark which setting is currently selected
303 #[derive(Component)]
304 struct SelectedOption;
305
306 // All actions that can be triggered from a button click
307 #[derive(Component)]
308 enum MenuButtonAction {
309 Play,
310 Settings,
311 SettingsDisplay,
312 SettingsSound,
313 BackToMainMenu,
314 BackToSettings,
315 Quit,
316 }
317
318 // This system handles changing all buttons color based on mouse interaction
319 fn button_system(
320 mut interaction_query: Query<
321 (&Interaction, &mut BackgroundColor, Option<&SelectedOption>),
322 (Changed<Interaction>, With<Button>),
323 >,
324 ) {
325 for (interaction, mut background_color, selected) in &mut interaction_query {
326 *background_color = match (*interaction, selected) {
327 (Interaction::Pressed, _) | (Interaction::None, Some(_)) => PRESSED_BUTTON.into(),
328 (Interaction::Hovered, Some(_)) => HOVERED_PRESSED_BUTTON.into(),
329 (Interaction::Hovered, None) => HOVERED_BUTTON.into(),
330 (Interaction::None, None) => NORMAL_BUTTON.into(),
331 }
332 }
333 }
334
335 // This system updates the settings when a new value for a setting is selected, and marks
336 // the button as the one currently selected
337 fn setting_button<T: Resource + Component + PartialEq + Copy>(
338 interaction_query: Query<(&Interaction, &T, Entity), (Changed<Interaction>, With<Button>)>,
339 selected_query: Single<(Entity, &mut BackgroundColor), With<SelectedOption>>,
340 mut commands: Commands,
341 mut setting: ResMut<T>,
342 ) {
343 let (previous_button, mut previous_button_color) = selected_query.into_inner();
344 for (interaction, button_setting, entity) in &interaction_query {
345 if *interaction == Interaction::Pressed && *setting != *button_setting {
346 *previous_button_color = NORMAL_BUTTON.into();
347 commands.entity(previous_button).remove::<SelectedOption>();
348 commands.entity(entity).insert(SelectedOption);
349 *setting = *button_setting;
350 }
351 }
352 }
353
354 fn menu_setup(mut menu_state: ResMut<NextState<MenuState>>) {
355 menu_state.set(MenuState::Main);
356 }
357
358 fn main_menu_setup(mut commands: Commands, asset_server: Res<AssetServer>) {
359 // Common style for all buttons on the screen
360 let button_node = Node {
361 width: px(300),
362 height: px(65),
363 margin: UiRect::all(px(20)),
364 justify_content: JustifyContent::Center,
365 align_items: AlignItems::Center,
366 ..default()
367 };
368 let button_icon_node = Node {
369 width: px(30),
370 // This takes the icons out of the flexbox flow, to be positioned exactly
371 position_type: PositionType::Absolute,
372 // The icon will be close to the left border of the button
373 left: px(10),
374 ..default()
375 };
376 let button_text_font = TextFont {
377 font_size: 33.0,
378 ..default()
379 };
380
381 let right_icon = asset_server.load("textures/Game Icons/right.png");
382 let wrench_icon = asset_server.load("textures/Game Icons/wrench.png");
383 let exit_icon = asset_server.load("textures/Game Icons/exitRight.png");
384
385 commands.spawn((
386 DespawnOnExit(MenuState::Main),
387 Node {
388 width: percent(100),
389 height: percent(100),
390 align_items: AlignItems::Center,
391 justify_content: JustifyContent::Center,
392 ..default()
393 },
394 OnMainMenuScreen,
395 children![(
396 Node {
397 flex_direction: FlexDirection::Column,
398 align_items: AlignItems::Center,
399 ..default()
400 },
401 BackgroundColor(CRIMSON.into()),
402 children![
403 // Display the game name
404 (
405 Text::new("Bevy Game Menu UI"),
406 TextFont {
407 font_size: 67.0,
408 ..default()
409 },
410 TextColor(TEXT_COLOR),
411 Node {
412 margin: UiRect::all(px(50)),
413 ..default()
414 },
415 ),
416 // Display three buttons for each action available from the main menu:
417 // - new game
418 // - settings
419 // - quit
420 (
421 Button,
422 button_node.clone(),
423 BackgroundColor(NORMAL_BUTTON),
424 MenuButtonAction::Play,
425 children![
426 (ImageNode::new(right_icon), button_icon_node.clone()),
427 (
428 Text::new("New Game"),
429 button_text_font.clone(),
430 TextColor(TEXT_COLOR),
431 ),
432 ]
433 ),
434 (
435 Button,
436 button_node.clone(),
437 BackgroundColor(NORMAL_BUTTON),
438 MenuButtonAction::Settings,
439 children![
440 (ImageNode::new(wrench_icon), button_icon_node.clone()),
441 (
442 Text::new("Settings"),
443 button_text_font.clone(),
444 TextColor(TEXT_COLOR),
445 ),
446 ]
447 ),
448 (
449 Button,
450 button_node,
451 BackgroundColor(NORMAL_BUTTON),
452 MenuButtonAction::Quit,
453 children![
454 (ImageNode::new(exit_icon), button_icon_node),
455 (Text::new("Quit"), button_text_font, TextColor(TEXT_COLOR),),
456 ]
457 ),
458 ]
459 )],
460 ));
461 }
462
463 fn settings_menu_setup(mut commands: Commands) {
464 let button_node = Node {
465 width: px(200),
466 height: px(65),
467 margin: UiRect::all(px(20)),
468 justify_content: JustifyContent::Center,
469 align_items: AlignItems::Center,
470 ..default()
471 };
472
473 let button_text_style = (
474 TextFont {
475 font_size: 33.0,
476 ..default()
477 },
478 TextColor(TEXT_COLOR),
479 );
480
481 commands.spawn((
482 DespawnOnExit(MenuState::Settings),
483 Node {
484 width: percent(100),
485 height: percent(100),
486 align_items: AlignItems::Center,
487 justify_content: JustifyContent::Center,
488 ..default()
489 },
490 OnSettingsMenuScreen,
491 children![(
492 Node {
493 flex_direction: FlexDirection::Column,
494 align_items: AlignItems::Center,
495 ..default()
496 },
497 BackgroundColor(CRIMSON.into()),
498 Children::spawn(SpawnIter(
499 [
500 (MenuButtonAction::SettingsDisplay, "Display"),
501 (MenuButtonAction::SettingsSound, "Sound"),
502 (MenuButtonAction::BackToMainMenu, "Back"),
503 ]
504 .into_iter()
505 .map(move |(action, text)| {
506 (
507 Button,
508 button_node.clone(),
509 BackgroundColor(NORMAL_BUTTON),
510 action,
511 children![(Text::new(text), button_text_style.clone())],
512 )
513 })
514 ))
515 )],
516 ));
517 }
518
519 fn display_settings_menu_setup(mut commands: Commands, display_quality: Res<DisplayQuality>) {
520 fn button_node() -> Node {
521 Node {
522 width: px(200),
523 height: px(65),
524 margin: UiRect::all(px(20)),
525 justify_content: JustifyContent::Center,
526 align_items: AlignItems::Center,
527 ..default()
528 }
529 }
530 fn button_text_style() -> impl Bundle {
531 (
532 TextFont {
533 font_size: 33.0,
534 ..default()
535 },
536 TextColor(TEXT_COLOR),
537 )
538 }
539
540 let display_quality = *display_quality;
541 commands.spawn((
542 DespawnOnExit(MenuState::SettingsDisplay),
543 Node {
544 width: percent(100),
545 height: percent(100),
546 align_items: AlignItems::Center,
547 justify_content: JustifyContent::Center,
548 ..default()
549 },
550 OnDisplaySettingsMenuScreen,
551 children![(
552 Node {
553 flex_direction: FlexDirection::Column,
554 align_items: AlignItems::Center,
555 ..default()
556 },
557 BackgroundColor(CRIMSON.into()),
558 children![
559 // Create a new `Node`, this time not setting its `flex_direction`. It will
560 // use the default value, `FlexDirection::Row`, from left to right.
561 (
562 Node {
563 align_items: AlignItems::Center,
564 ..default()
565 },
566 BackgroundColor(CRIMSON.into()),
567 Children::spawn((
568 // Display a label for the current setting
569 Spawn((Text::new("Display Quality"), button_text_style())),
570 SpawnWith(move |parent: &mut ChildSpawner| {
571 for quality_setting in [
572 DisplayQuality::Low,
573 DisplayQuality::Medium,
574 DisplayQuality::High,
575 ] {
576 let mut entity = parent.spawn((
577 Button,
578 Node {
579 width: px(150),
580 height: px(65),
581 ..button_node()
582 },
583 BackgroundColor(NORMAL_BUTTON),
584 quality_setting,
585 children![(
586 Text::new(format!("{quality_setting:?}")),
587 button_text_style(),
588 )],
589 ));
590 if display_quality == quality_setting {
591 entity.insert(SelectedOption);
592 }
593 }
594 })
595 ))
596 ),
597 // Display the back button to return to the settings screen
598 (
599 Button,
600 button_node(),
601 BackgroundColor(NORMAL_BUTTON),
602 MenuButtonAction::BackToSettings,
603 children![(Text::new("Back"), button_text_style())]
604 )
605 ]
606 )],
607 ));
608 }
609
610 fn sound_settings_menu_setup(mut commands: Commands, volume: Res<Volume>) {
611 let button_node = Node {
612 width: px(200),
613 height: px(65),
614 margin: UiRect::all(px(20)),
615 justify_content: JustifyContent::Center,
616 align_items: AlignItems::Center,
617 ..default()
618 };
619 let button_text_style = (
620 TextFont {
621 font_size: 33.0,
622 ..default()
623 },
624 TextColor(TEXT_COLOR),
625 );
626
627 let volume = *volume;
628 let button_node_clone = button_node.clone();
629 commands.spawn((
630 DespawnOnExit(MenuState::SettingsSound),
631 Node {
632 width: percent(100),
633 height: percent(100),
634 align_items: AlignItems::Center,
635 justify_content: JustifyContent::Center,
636 ..default()
637 },
638 OnSoundSettingsMenuScreen,
639 children![(
640 Node {
641 flex_direction: FlexDirection::Column,
642 align_items: AlignItems::Center,
643 ..default()
644 },
645 BackgroundColor(CRIMSON.into()),
646 children![
647 (
648 Node {
649 align_items: AlignItems::Center,
650 ..default()
651 },
652 BackgroundColor(CRIMSON.into()),
653 Children::spawn((
654 Spawn((Text::new("Volume"), button_text_style.clone())),
655 SpawnWith(move |parent: &mut ChildSpawner| {
656 for volume_setting in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] {
657 let mut entity = parent.spawn((
658 Button,
659 Node {
660 width: px(30),
661 height: px(65),
662 ..button_node_clone.clone()
663 },
664 BackgroundColor(NORMAL_BUTTON),
665 Volume(volume_setting),
666 ));
667 if volume == Volume(volume_setting) {
668 entity.insert(SelectedOption);
669 }
670 }
671 })
672 ))
673 ),
674 (
675 Button,
676 button_node,
677 BackgroundColor(NORMAL_BUTTON),
678 MenuButtonAction::BackToSettings,
679 children![(Text::new("Back"), button_text_style)]
680 )
681 ]
682 )],
683 ));
684 }
More examples
221fn setup(mut commands: Commands) {
222 commands.spawn(Camera2d);
223}
224
225fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
226 commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
227 info!("Setup game");
228}
229
230fn teardown_game(mut commands: Commands, player: Single<Entity, With<Sprite>>) {
231 commands.entity(*player).despawn();
232 info!("Teardown game");
233}
234
235#[derive(Resource)]
236struct MenuData {
237 pub button_entity: Entity,
238}
239
240const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
241const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
242const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
243
244fn setup_menu(mut commands: Commands) {
245 let button_entity = commands
246 .spawn((
247 Node {
248 // center button
249 width: percent(100),
250 height: percent(100),
251 justify_content: JustifyContent::Center,
252 align_items: AlignItems::Center,
253 ..default()
254 },
255 children![(
256 Button,
257 Node {
258 width: px(150),
259 height: px(65),
260 // horizontally center child text
261 justify_content: JustifyContent::Center,
262 // vertically center child text
263 align_items: AlignItems::Center,
264 ..default()
265 },
266 BackgroundColor(NORMAL_BUTTON),
267 children![(
268 Text::new("Play"),
269 TextFont {
270 font_size: 33.0,
271 ..default()
272 },
273 TextColor(Color::srgb(0.9, 0.9, 0.9)),
274 )]
275 )],
276 ))
277 .id();
278 commands.insert_resource(MenuData { button_entity });
279}
48fn setup(mut commands: Commands) {
49 commands.spawn(Camera2d);
50}
51
52fn setup_menu(mut commands: Commands) {
53 let button_entity = commands
54 .spawn((
55 Node {
56 // center button
57 width: percent(100),
58 height: percent(100),
59 justify_content: JustifyContent::Center,
60 align_items: AlignItems::Center,
61 ..default()
62 },
63 children![(
64 Button,
65 Node {
66 width: px(150),
67 height: px(65),
68 // horizontally center child text
69 justify_content: JustifyContent::Center,
70 // vertically center child text
71 align_items: AlignItems::Center,
72 ..default()
73 },
74 BackgroundColor(NORMAL_BUTTON),
75 children![(
76 Text::new("Play"),
77 TextFont {
78 font_size: 33.0,
79 ..default()
80 },
81 TextColor(Color::srgb(0.9, 0.9, 0.9)),
82 )],
83 )],
84 ))
85 .id();
86 commands.insert_resource(MenuData { button_entity });
87}
88
89fn menu(
90 mut next_state: ResMut<NextState<AppState>>,
91 mut interaction_query: Query<
92 (&Interaction, &mut BackgroundColor),
93 (Changed<Interaction>, With<Button>),
94 >,
95) {
96 for (interaction, mut color) in &mut interaction_query {
97 match *interaction {
98 Interaction::Pressed => {
99 *color = PRESSED_BUTTON.into();
100 next_state.set(AppState::InGame);
101 }
102 Interaction::Hovered => {
103 *color = HOVERED_BUTTON.into();
104 }
105 Interaction::None => {
106 *color = NORMAL_BUTTON.into();
107 }
108 }
109 }
110}
111
112fn cleanup_menu(mut commands: Commands, menu_data: Res<MenuData>) {
113 commands.entity(menu_data.button_entity).despawn();
114}
115
116fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
117 commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
118}
13fn setup_camera(mut commands: Commands) {
14 commands.spawn(Camera2d);
15}
16
17fn setup_sprites(mut commands: Commands, asset_server: Res<AssetServer>) {
18 let square = asset_server.load("textures/slice_square_2.png");
19 let banner = asset_server.load("branding/banner.png");
20
21 let rects = [
22 Rect {
23 size: Vec2::new(100., 225.),
24 text: "Stretched".to_string(),
25 transform: Transform::from_translation(Vec3::new(-570., 230., 0.)),
26 texture: square.clone(),
27 image_mode: SpriteImageMode::Auto,
28 },
29 Rect {
30 size: Vec2::new(100., 225.),
31 text: "Fill Center".to_string(),
32 transform: Transform::from_translation(Vec3::new(-450., 230., 0.)),
33 texture: square.clone(),
34 image_mode: SpriteImageMode::Scale(ScalingMode::FillCenter),
35 },
36 Rect {
37 size: Vec2::new(100., 225.),
38 text: "Fill Start".to_string(),
39 transform: Transform::from_translation(Vec3::new(-330., 230., 0.)),
40 texture: square.clone(),
41 image_mode: SpriteImageMode::Scale(ScalingMode::FillStart),
42 },
43 Rect {
44 size: Vec2::new(100., 225.),
45 text: "Fill End".to_string(),
46 transform: Transform::from_translation(Vec3::new(-210., 230., 0.)),
47 texture: square.clone(),
48 image_mode: SpriteImageMode::Scale(ScalingMode::FillEnd),
49 },
50 Rect {
51 size: Vec2::new(300., 100.),
52 text: "Fill Start Horizontal".to_string(),
53 transform: Transform::from_translation(Vec3::new(10., 290., 0.)),
54 texture: square.clone(),
55 image_mode: SpriteImageMode::Scale(ScalingMode::FillStart),
56 },
57 Rect {
58 size: Vec2::new(300., 100.),
59 text: "Fill End Horizontal".to_string(),
60 transform: Transform::from_translation(Vec3::new(10., 155., 0.)),
61 texture: square.clone(),
62 image_mode: SpriteImageMode::Scale(ScalingMode::FillEnd),
63 },
64 Rect {
65 size: Vec2::new(200., 200.),
66 text: "Fill Center".to_string(),
67 transform: Transform::from_translation(Vec3::new(280., 230., 0.)),
68 texture: banner.clone(),
69 image_mode: SpriteImageMode::Scale(ScalingMode::FillCenter),
70 },
71 Rect {
72 size: Vec2::new(200., 100.),
73 text: "Fill Center".to_string(),
74 transform: Transform::from_translation(Vec3::new(500., 230., 0.)),
75 texture: square.clone(),
76 image_mode: SpriteImageMode::Scale(ScalingMode::FillCenter),
77 },
78 Rect {
79 size: Vec2::new(100., 100.),
80 text: "Stretched".to_string(),
81 transform: Transform::from_translation(Vec3::new(-570., -40., 0.)),
82 texture: banner.clone(),
83 image_mode: SpriteImageMode::Auto,
84 },
85 Rect {
86 size: Vec2::new(200., 200.),
87 text: "Fit Center".to_string(),
88 transform: Transform::from_translation(Vec3::new(-400., -40., 0.)),
89 texture: banner.clone(),
90 image_mode: SpriteImageMode::Scale(ScalingMode::FitCenter),
91 },
92 Rect {
93 size: Vec2::new(200., 200.),
94 text: "Fit Start".to_string(),
95 transform: Transform::from_translation(Vec3::new(-180., -40., 0.)),
96 texture: banner.clone(),
97 image_mode: SpriteImageMode::Scale(ScalingMode::FitStart),
98 },
99 Rect {
100 size: Vec2::new(200., 200.),
101 text: "Fit End".to_string(),
102 transform: Transform::from_translation(Vec3::new(40., -40., 0.)),
103 texture: banner.clone(),
104 image_mode: SpriteImageMode::Scale(ScalingMode::FitEnd),
105 },
106 Rect {
107 size: Vec2::new(100., 200.),
108 text: "Fit Center".to_string(),
109 transform: Transform::from_translation(Vec3::new(210., -40., 0.)),
110 texture: banner.clone(),
111 image_mode: SpriteImageMode::Scale(ScalingMode::FitCenter),
112 },
113 ];
114
115 for rect in rects {
116 commands.spawn((
117 Sprite {
118 image: rect.texture,
119 custom_size: Some(rect.size),
120 image_mode: rect.image_mode,
121 ..default()
122 },
123 rect.transform,
124 children![(
125 Text2d::new(rect.text),
126 TextLayout::new_with_justify(Justify::Center),
127 TextFont::from_font_size(15.),
128 Transform::from_xyz(0., -0.5 * rect.size.y - 10., 0.),
129 bevy::sprite::Anchor::TOP_CENTER,
130 )],
131 ));
132 }
133}
134
135fn setup_texture_atlas(
136 mut commands: Commands,
137 asset_server: Res<AssetServer>,
138 mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
139) {
140 let gabe = asset_server.load("textures/rpg/chars/gabe/gabe-idle-run.png");
141 let animation_indices_gabe = AnimationIndices { first: 0, last: 6 };
142 let gabe_atlas = TextureAtlas {
143 layout: texture_atlas_layouts.add(TextureAtlasLayout::from_grid(
144 UVec2::splat(24),
145 7,
146 1,
147 None,
148 None,
149 )),
150 index: animation_indices_gabe.first,
151 };
152
153 let sprite_sheets = [
154 SpriteSheet {
155 size: Vec2::new(120., 50.),
156 text: "Stretched".to_string(),
157 transform: Transform::from_translation(Vec3::new(-570., -200., 0.)),
158 texture: gabe.clone(),
159 image_mode: SpriteImageMode::Auto,
160 atlas: gabe_atlas.clone(),
161 indices: animation_indices_gabe.clone(),
162 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
163 },
164 SpriteSheet {
165 size: Vec2::new(120., 50.),
166 text: "Fill Center".to_string(),
167 transform: Transform::from_translation(Vec3::new(-570., -300., 0.)),
168 texture: gabe.clone(),
169 image_mode: SpriteImageMode::Scale(ScalingMode::FillCenter),
170 atlas: gabe_atlas.clone(),
171 indices: animation_indices_gabe.clone(),
172 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
173 },
174 SpriteSheet {
175 size: Vec2::new(120., 50.),
176 text: "Fill Start".to_string(),
177 transform: Transform::from_translation(Vec3::new(-430., -200., 0.)),
178 texture: gabe.clone(),
179 image_mode: SpriteImageMode::Scale(ScalingMode::FillStart),
180 atlas: gabe_atlas.clone(),
181 indices: animation_indices_gabe.clone(),
182 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
183 },
184 SpriteSheet {
185 size: Vec2::new(120., 50.),
186 text: "Fill End".to_string(),
187 transform: Transform::from_translation(Vec3::new(-430., -300., 0.)),
188 texture: gabe.clone(),
189 image_mode: SpriteImageMode::Scale(ScalingMode::FillEnd),
190 atlas: gabe_atlas.clone(),
191 indices: animation_indices_gabe.clone(),
192 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
193 },
194 SpriteSheet {
195 size: Vec2::new(50., 120.),
196 text: "Fill Center".to_string(),
197 transform: Transform::from_translation(Vec3::new(-300., -250., 0.)),
198 texture: gabe.clone(),
199 image_mode: SpriteImageMode::Scale(ScalingMode::FillCenter),
200 atlas: gabe_atlas.clone(),
201 indices: animation_indices_gabe.clone(),
202 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
203 },
204 SpriteSheet {
205 size: Vec2::new(50., 120.),
206 text: "Fill Start".to_string(),
207 transform: Transform::from_translation(Vec3::new(-190., -250., 0.)),
208 texture: gabe.clone(),
209 image_mode: SpriteImageMode::Scale(ScalingMode::FillStart),
210 atlas: gabe_atlas.clone(),
211 indices: animation_indices_gabe.clone(),
212 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
213 },
214 SpriteSheet {
215 size: Vec2::new(50., 120.),
216 text: "Fill End".to_string(),
217 transform: Transform::from_translation(Vec3::new(-90., -250., 0.)),
218 texture: gabe.clone(),
219 image_mode: SpriteImageMode::Scale(ScalingMode::FillEnd),
220 atlas: gabe_atlas.clone(),
221 indices: animation_indices_gabe.clone(),
222 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
223 },
224 SpriteSheet {
225 size: Vec2::new(120., 50.),
226 text: "Fit Center".to_string(),
227 transform: Transform::from_translation(Vec3::new(20., -200., 0.)),
228 texture: gabe.clone(),
229 image_mode: SpriteImageMode::Scale(ScalingMode::FitCenter),
230 atlas: gabe_atlas.clone(),
231 indices: animation_indices_gabe.clone(),
232 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
233 },
234 SpriteSheet {
235 size: Vec2::new(120., 50.),
236 text: "Fit Start".to_string(),
237 transform: Transform::from_translation(Vec3::new(20., -300., 0.)),
238 texture: gabe.clone(),
239 image_mode: SpriteImageMode::Scale(ScalingMode::FitStart),
240 atlas: gabe_atlas.clone(),
241 indices: animation_indices_gabe.clone(),
242 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
243 },
244 SpriteSheet {
245 size: Vec2::new(120., 50.),
246 text: "Fit End".to_string(),
247 transform: Transform::from_translation(Vec3::new(160., -200., 0.)),
248 texture: gabe.clone(),
249 image_mode: SpriteImageMode::Scale(ScalingMode::FitEnd),
250 atlas: gabe_atlas.clone(),
251 indices: animation_indices_gabe.clone(),
252 timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
253 },
254 ];
255
256 for sprite_sheet in sprite_sheets {
257 commands.spawn((
258 Sprite {
259 image_mode: sprite_sheet.image_mode,
260 custom_size: Some(sprite_sheet.size),
261 ..Sprite::from_atlas_image(sprite_sheet.texture.clone(), sprite_sheet.atlas.clone())
262 },
263 sprite_sheet.indices,
264 sprite_sheet.timer,
265 sprite_sheet.transform,
266 children![(
267 Text2d::new(sprite_sheet.text),
268 TextLayout::new_with_justify(Justify::Center),
269 TextFont::from_font_size(15.),
270 Transform::from_xyz(0., -0.5 * sprite_sheet.size.y - 10., 0.),
271 bevy::sprite::Anchor::TOP_CENTER,
272 )],
273 ));
274 }
275}
- examples/window/window_resizing.rs
- examples/state/computed_states.rs
- examples/state/sub_states.rs
- examples/app/without_winit.rs
- examples/window/custom_cursor_image.rs
- examples/ecs/custom_query_param.rs
- examples/ui/feathers.rs
- examples/ecs/system_param.rs
- examples/3d/irradiance_volumes.rs
- examples/ui/button.rs
- examples/ui/standard_widgets.rs
- examples/ui/standard_widgets_observers.rs
- examples/ecs/one_shot_systems.rs
- examples/scene/scene.rs
- examples/ui/viewport_debug.rs
- examples/audio/audio.rs
- examples/asset/custom_asset_reader.rs
- examples/window/transparent_window.rs
- examples/3d/mixed_lighting.rs
- examples/time/timers.rs
- examples/2d/sprite.rs
- examples/3d/reflection_probes.rs
- examples/asset/asset_decompression.rs
- examples/ecs/removal_detection.rs
- examples/2d/move_sprite.rs
- examples/app/logs.rs
- examples/audio/decodable.rs
- examples/testbed/ui.rs
- examples/app/log_layers_ecs.rs
- examples/ecs/change_detection.rs
- examples/usage/context_menu.rs
- examples/3d/fog.rs
- examples/asset/multi_asset_sync.rs
- examples/2d/mesh2d.rs
- examples/asset/web_asset.rs
- examples/ecs/component_hooks.rs
- examples/2d/sprite_flipping.rs
- examples/window/screenshot.rs
- examples/movement/physics_in_fixed_timestep.rs
- examples/camera/2d_screen_shake.rs
- examples/math/render_primitives.rs
- examples/ecs/generic_system.rs
- examples/stress_tests/many_gizmos.rs
- examples/animation/gltf_skinned_mesh.rs
- examples/ecs/state_scoped.rs
- examples/games/alien_cake_addict.rs
- examples/shader/animate_shader.rs
- examples/async_tasks/async_compute.rs
- examples/3d/query_gltf_primitives.rs
- examples/audio/pitch.rs
- examples/ecs/observer_propagation.rs
- examples/2d/sprite_tile.rs
- examples/3d/lightmaps.rs
- examples/shader/shader_material_2d.rs
- examples/shader/shader_material_wesl.rs
- examples/shader_advanced/render_depth_to_texture.rs
- examples/shader/array_texture.rs
- examples/ecs/fallible_params.rs
- examples/3d/ssr.rs
- examples/2d/custom_gltf_vertex_attribute.rs
- examples/ecs/ecs_guide.rs
- examples/camera/2d_top_down_camera.rs
- examples/2d/pixel_grid_snap.rs
- examples/shader/fallback_image.rs
- examples/shader_advanced/custom_phase_item.rs
- examples/ecs/hotpatching_systems.rs
- examples/3d/motion_blur.rs
- examples/gizmos/2d_gizmos.rs
- examples/3d/3d_viewport_to_world.rs
- examples/dev_tools/fps_overlay.rs
- examples/3d/clustered_decals.rs
- examples/shader/shader_material.rs
- examples/shader/shader_material_glsl.rs
- examples/asset/extra_source.rs
- examples/shader_advanced/texture_binding_array.rs
- examples/ui/window_fallthrough.rs
- examples/ui/scrollbars.rs
- examples/asset/hot_asset_reloading.rs
- examples/ecs/parallel_query.rs
- examples/3d/manual_material.rs
- examples/3d/light_textures.rs
- examples/audio/audio_control.rs
- examples/async_tasks/external_source_external_thread.rs
- examples/games/loading_screen.rs
- examples/2d/transparency_2d.rs
- examples/transforms/3d_rotation.rs
- examples/3d/rotate_environment_map.rs
- examples/transforms/scale.rs
- examples/ecs/entity_disabling.rs
- examples/shader_advanced/custom_vertex_attribute.rs
- examples/animation/morph_targets.rs
- examples/3d/post_processing.rs
- tests/window/minimizing.rs
- tests/window/resizing.rs
- examples/3d/atmospheric_fog.rs
- examples/transforms/translation.rs
- examples/3d/load_gltf_extras.rs
- examples/shader/shader_defs.rs
- examples/ui/font_atlas_debug.rs
- examples/3d/clearcoat.rs
- examples/shader/compute_shader_game_of_life.rs
- examples/3d/3d_scene.rs
- examples/asset/embedded_asset.rs
- examples/window/scale_factor_override.rs
- examples/3d/color_grading.rs
- examples/2d/sprite_sheet.rs
- examples/window/window_drag_move.rs
- examples/3d/tonemapping.rs
- examples/shader_advanced/custom_post_processing.rs
- examples/3d/parenting.rs
- examples/animation/animation_graph.rs
- examples/shader/shader_material_screenspace_texture.rs
- examples/3d/pcss.rs
- examples/3d/depth_of_field.rs
- examples/camera/camera_orbit.rs
- examples/3d/edit_material_on_gltf.rs
- examples/shader/shader_material_bindless.rs
- examples/3d/anisotropy.rs
- examples/remote/server.rs
- examples/animation/animation_masks.rs
- examples/2d/tilemap_chunk.rs
- examples/3d/animated_material.rs
- examples/camera/custom_projection.rs
- examples/3d/load_gltf.rs
- examples/input/text_input.rs
- examples/3d/two_passes.rs
- examples/animation/animated_mesh_events.rs
- examples/3d/lines.rs
- examples/stress_tests/many_materials.rs
- examples/animation/animated_mesh.rs
- examples/diagnostics/log_diagnostics.rs
- examples/stress_tests/many_glyphs.rs
- examples/shader/extended_material_bindless.rs
- examples/3d/skybox.rs
- examples/3d/order_independent_transparency.rs
- examples/stress_tests/text_pipeline.rs
- examples/3d/update_gltf_scene.rs
- examples/shader_advanced/custom_render_phase.rs
- examples/3d/atmosphere.rs
- examples/3d/fog_volumes.rs
- examples/ui/text_background_colors.rs
- examples/shader/storage_buffer.rs
- examples/window/low_power.rs
- examples/2d/mesh2d_vertex_color_texture.rs
- examples/ecs/hierarchy.rs
- examples/ui/virtual_keyboard.rs
- examples/3d/generate_custom_mesh.rs
- examples/2d/wireframe_2d.rs
- examples/3d/mesh_ray_cast.rs
- examples/stress_tests/many_sprites.rs
- examples/audio/soundtrack.rs
- examples/animation/color_animation.rs
- examples/audio/spatial_audio_2d.rs
- examples/picking/simple_picking.rs
- examples/movement/smooth_follow.rs
- examples/ui/relative_cursor_position.rs
- examples/ui/ui_material.rs
- examples/shader/extended_material.rs
- examples/animation/animation_events.rs
- examples/3d/vertex_colors.rs
- examples/shader_advanced/custom_shader_instancing.rs
- tests/window/desktop_request_redraw.rs
- examples/3d/orthographic.rs
- examples/games/contributors.rs
- examples/picking/debug_picking.rs
- examples/testbed/2d.rs
- examples/ui/ui_scaling.rs
- examples/shader_advanced/specialized_mesh_pipeline.rs
- examples/3d/spherical_area_lights.rs
- examples/ecs/observers.rs
- examples/math/bounding_2d.rs
- examples/ui/ui_texture_atlas.rs
- examples/2d/2d_viewport_to_world.rs
- examples/usage/cooldown.rs
- examples/transforms/transform.rs
- examples/window/multiple_windows.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/2d/bloom_2d.rs
- examples/camera/first_person_view_model.rs
- examples/stress_tests/many_text2d.rs
- examples/gizmos/axes.rs
- examples/ecs/relationships.rs
- examples/math/custom_primitives.rs
- examples/3d/occlusion_culling.rs
- examples/3d/ssao.rs
- examples/ui/ghost_nodes.rs
- examples/ui/overflow_debug.rs
- examples/animation/animated_ui.rs
- examples/stress_tests/many_buttons.rs
- examples/asset/alter_sprite.rs
- examples/app/headless_renderer.rs
- examples/stress_tests/many_gradients.rs
- examples/animation/eased_motion.rs
- examples/3d/wireframe.rs
- examples/2d/2d_shapes.rs
- examples/stress_tests/transform_hierarchy.rs
- examples/audio/spatial_audio_3d.rs
- examples/shader/automatic_instancing.rs
- examples/ecs/error_handling.rs
- examples/camera/projection_zoom.rs
- examples/2d/rotation.rs
- examples/ui/ui_texture_slice.rs
- examples/3d/specular_tint.rs
- examples/camera/2d_on_ui.rs
- examples/ui/viewport_node.rs
- examples/3d/visibility_range.rs
- examples/2d/sprite_animation.rs
- examples/math/cubic_splines.rs
- examples/3d/volumetric_fog.rs
- examples/animation/animated_mesh_control.rs
- examples/2d/cpu_draw.rs
- examples/testbed/3d.rs
- tests/3d/test_invalid_skinned_mesh.rs
- examples/stress_tests/many_cameras_lights.rs
- examples/3d/texture.rs
- examples/time/virtual_time.rs
- examples/ui/ui_texture_slice_flip_and_tile.rs
- examples/3d/shadow_caster_receiver.rs
- examples/window/monitor_info.rs
- examples/ui/size_constraints.rs
- examples/3d/anti_aliasing.rs
- examples/3d/bloom_3d.rs
- examples/stress_tests/many_lights.rs
- examples/gizmos/3d_gizmos.rs
- examples/ui/transparency_ui.rs
- examples/transforms/align.rs
- examples/math/random_sampling.rs
- examples/ui/ui_texture_atlas_slice.rs
- examples/picking/sprite_picking.rs
- examples/games/stepping.rs
- examples/3d/scrolling_fog.rs
- examples/3d/decal.rs
- examples/2d/mesh2d_alpha_mode.rs
- examples/2d/mesh2d_arcs.rs
- examples/3d/render_to_texture.rs
- examples/asset/repeated_texture.rs
- examples/ecs/iter_combinations.rs
- examples/ui/text_wrap_debug.rs
- examples/2d/mesh2d_manual.rs
- examples/ui/stacked_gradients.rs
- examples/2d/sprite_slice.rs
- examples/asset/alter_mesh.rs
- examples/3d/transparency_3d.rs
- examples/ui/text.rs
- examples/asset/asset_settings.rs
- examples/shader/gpu_readback.rs
- examples/3d/meshlet.rs
- examples/2d/mesh2d_repeated_texture.rs
- examples/gizmos/light_gizmos.rs
- examples/3d/spotlight.rs
- examples/3d/pbr.rs
- examples/ui/ui_target_camera.rs
- examples/3d/3d_shapes.rs
- examples/3d/auto_exposure.rs
- examples/animation/easing_functions.rs
- examples/asset/asset_loading.rs
- examples/ui/overflow.rs
- examples/ui/overflow_clip_margin.rs
- examples/ui/flex_layout.rs
- examples/shader/shader_prepass.rs
- examples/window/multi_window_text.rs
- examples/stress_tests/bevymark.rs
- examples/3d/solari.rs
- examples/ui/display_and_visibility.rs
- examples/3d/shadow_biases.rs
- examples/ui/drag_to_scroll.rs
- examples/ui/tab_navigation.rs
- examples/3d/split_screen.rs
- examples/ui/scroll.rs
- examples/games/breakout.rs
- examples/picking/mesh_picking.rs
- examples/ui/z_index.rs
- examples/ui/render_ui_to_texture.rs
- examples/stress_tests/many_foxes.rs
- examples/games/desk_toy.rs
- examples/math/sampling_primitives.rs
- examples/3d/parallax_mapping.rs
- examples/2d/texture_atlas.rs
- examples/ui/directional_navigation.rs
- examples/ui/ui_drag_and_drop.rs
- examples/3d/deferred_rendering.rs
- examples/ui/box_shadow.rs
- examples/2d/text2d.rs
- examples/animation/custom_skinned_mesh.rs
- examples/3d/blend_modes.rs
- examples/stress_tests/many_cubes.rs
- examples/animation/animated_transform.rs
- examples/3d/lighting.rs
- examples/3d/camera_sub_view.rs
- examples/ui/text_debug.rs
- examples/ui/borders.rs
- examples/ui/grid.rs
- examples/3d/transmission.rs
- examples/ui/ui_transform.rs
- examples/ui/gradients.rs
- examples/testbed/full_ui.rs
Sourcepub fn entity(&mut self, entity: Entity) -> EntityCommands<'_>
pub fn entity(&mut self, entity: Entity) -> EntityCommands<'_>
Returns the EntityCommands
for the given Entity
.
This method does not guarantee that commands queued by the returned EntityCommands
will be successful, since the entity could be despawned before they are executed.
§Example
#[derive(Resource)]
struct PlayerEntity {
entity: Entity
}
#[derive(Component)]
struct Label(&'static str);
fn example_system(mut commands: Commands, player: Res<PlayerEntity>) {
// Get the entity and add a component.
commands.entity(player.entity).insert(Label("hello world"));
}
§See also
get_entity
for the fallible version.
Examples found in repository?
165fn cleanup_menu(mut commands: Commands, menu_data: Res<MenuData>) {
166 commands.entity(menu_data.button_entity).despawn();
167}
168
169const SPEED: f32 = 100.0;
170fn movement(
171 time: Res<Time>,
172 input: Res<ButtonInput<KeyCode>>,
173 mut query: Query<&mut Transform, With<Sprite>>,
174) {
175 for mut transform in &mut query {
176 let mut direction = Vec3::ZERO;
177 if input.pressed(KeyCode::ArrowLeft) {
178 direction.x -= 1.0;
179 }
180 if input.pressed(KeyCode::ArrowRight) {
181 direction.x += 1.0;
182 }
183 if input.pressed(KeyCode::ArrowUp) {
184 direction.y += 1.0;
185 }
186 if input.pressed(KeyCode::ArrowDown) {
187 direction.y -= 1.0;
188 }
189
190 if direction != Vec3::ZERO {
191 transform.translation += direction.normalize() * SPEED * time.delta_secs();
192 }
193 }
194}
195
196fn change_color(time: Res<Time>, mut query: Query<&mut Sprite>) {
197 for mut sprite in &mut query {
198 let new_color = LinearRgba {
199 blue: ops::sin(time.elapsed_secs() * 0.5) + 2.0,
200 ..LinearRgba::from(sprite.color)
201 };
202
203 sprite.color = new_color.into();
204 }
205}
206
207// We can restart the game by pressing "R".
208// This will trigger an [`AppState::InGame`] -> [`AppState::InGame`]
209// transition, which will run our custom schedules.
210fn trigger_game_restart(
211 input: Res<ButtonInput<KeyCode>>,
212 mut next_state: ResMut<NextState<AppState>>,
213) {
214 if input.just_pressed(KeyCode::KeyR) {
215 // Although we are already in this state setting it again will generate an identity transition.
216 // While default schedules ignore those kinds of transitions, our custom schedules will react to them.
217 next_state.set(AppState::InGame);
218 }
219}
220
221fn setup(mut commands: Commands) {
222 commands.spawn(Camera2d);
223}
224
225fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
226 commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
227 info!("Setup game");
228}
229
230fn teardown_game(mut commands: Commands, player: Single<Entity, With<Sprite>>) {
231 commands.entity(*player).despawn();
232 info!("Teardown game");
233}
More examples
- examples/ecs/generic_system.rs
- examples/usage/context_menu.rs
- examples/3d/light_textures.rs
- examples/games/loading_screen.rs
- examples/ecs/removal_detection.rs
- examples/ui/standard_widgets_observers.rs
- examples/async_tasks/external_source_external_thread.rs
- examples/3d/volumetric_fog.rs
- examples/asset/multi_asset_sync.rs
- examples/input/text_input.rs
- examples/ecs/one_shot_systems.rs
- examples/window/screenshot.rs
- examples/3d/reflection_probes.rs
- examples/3d/depth_of_field.rs
- examples/ui/tab_navigation.rs
- examples/ecs/observer_propagation.rs
- examples/ecs/entity_disabling.rs
- examples/shader_advanced/custom_shader_instancing.rs
- examples/3d/pbr.rs
- examples/asset/asset_decompression.rs
- examples/animation/morph_targets.rs
- examples/window/window_settings.rs
- examples/app/log_layers_ecs.rs
- examples/ecs/error_handling.rs
- examples/testbed/3d.rs
- examples/animation/animated_mesh_control.rs
- examples/games/game_menu.rs
- examples/ui/standard_widgets.rs
- examples/3d/anisotropy.rs
- examples/3d/clearcoat.rs
- examples/3d/clustered_decals.rs
- examples/usage/cooldown.rs
- examples/3d/order_independent_transparency.rs
- examples/3d/tonemapping.rs
- examples/3d/irradiance_volumes.rs
- examples/3d/shadow_caster_receiver.rs
- examples/ecs/fallible_params.rs
- examples/games/stepping.rs
- examples/3d/pcss.rs
- examples/3d/visibility_range.rs
- examples/window/custom_cursor_image.rs
- examples/ecs/hierarchy.rs
- examples/audio/soundtrack.rs
- examples/3d/lightmaps.rs
- tests/window/desktop_request_redraw.rs
- examples/animation/animated_mesh.rs
- examples/math/bounding_2d.rs
- examples/ecs/relationships.rs
- examples/3d/occlusion_culling.rs
- examples/animation/eased_motion.rs
- examples/games/alien_cake_addict.rs
- examples/3d/edit_material_on_gltf.rs
- examples/games/breakout.rs
- examples/3d/ssr.rs
- examples/animation/animated_mesh_events.rs
- examples/async_tasks/async_compute.rs
- examples/animation/animation_graph.rs
- examples/window/monitor_info.rs
- examples/3d/blend_modes.rs
- examples/3d/solari.rs
- examples/math/random_sampling.rs
- examples/stress_tests/transform_hierarchy.rs
- examples/ui/text_wrap_debug.rs
- examples/animation/animation_masks.rs
- examples/testbed/ui.rs
- examples/3d/deferred_rendering.rs
- examples/math/sampling_primitives.rs
- examples/3d/mixed_lighting.rs
- examples/diagnostics/log_diagnostics.rs
- examples/ecs/component_hooks.rs
- examples/3d/ssao.rs
- examples/ui/scroll.rs
- tests/3d/test_invalid_skinned_mesh.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/bloom_3d.rs
- examples/ui/directional_navigation.rs
- examples/2d/bloom_2d.rs
- examples/animation/custom_skinned_mesh.rs
- examples/3d/anti_aliasing.rs
- examples/animation/animated_transform.rs
- examples/3d/transmission.rs
- examples/ui/text_debug.rs
- examples/ui/feathers.rs
Sourcepub fn get_entity(
&mut self,
entity: Entity,
) -> Result<EntityCommands<'_>, EntityDoesNotExistError>
pub fn get_entity( &mut self, entity: Entity, ) -> Result<EntityCommands<'_>, EntityDoesNotExistError>
Returns the EntityCommands
for the requested Entity
if it exists.
This method does not guarantee that commands queued by the returned EntityCommands
will be successful, since the entity could be despawned before they are executed.
§Errors
Returns EntityDoesNotExistError
if the requested entity does not exist.
§Example
#[derive(Resource)]
struct PlayerEntity {
entity: Entity
}
#[derive(Component)]
struct Label(&'static str);
fn example_system(mut commands: Commands, player: Res<PlayerEntity>) -> Result {
// Get the entity if it still exists and store the `EntityCommands`.
// If it doesn't exist, the `?` operator will propagate the returned error
// to the system, and the system will pass it to an error handler.
let mut entity_commands = commands.get_entity(player.entity)?;
// Add a component to the entity.
entity_commands.insert(Label("hello world"));
// Return from the system successfully.
Ok(())
}
§See also
entity
for the infallible version.
Examples found in repository?
140fn explode_mine(explode: On<Explode>, query: Query<&Mine>, mut commands: Commands) {
141 // Explode is an EntityEvent. `explode.entity` is the entity that Explode was triggered for.
142 let Ok(mut entity) = commands.get_entity(explode.entity) else {
143 return;
144 };
145 info!("Boom! {} exploded.", explode.entity);
146 entity.despawn();
147 let mine = query.get(explode.entity).unwrap();
148 // Trigger another explosion cascade.
149 commands.trigger(ExplodeMines {
150 pos: mine.pos,
151 radius: mine.size,
152 });
153}
Sourcepub fn spawn_batch<I>(&mut self, batch: I)where
I: IntoIterator + Send + Sync + 'static,
<I as IntoIterator>::Item: Bundle,
<<I as IntoIterator>::Item as DynamicBundle>::Effect: NoBundleEffect,
pub fn spawn_batch<I>(&mut self, batch: I)where
I: IntoIterator + Send + Sync + 'static,
<I as IntoIterator>::Item: Bundle,
<<I as IntoIterator>::Item as DynamicBundle>::Effect: NoBundleEffect,
Spawns multiple entities with the same combination of components,
based on a batch of Bundles
.
A batch can be any type that implements IntoIterator
and contains bundles,
such as a Vec<Bundle>
or an array [Bundle; N]
.
This method is equivalent to iterating the batch
and calling spawn
for each bundle,
but is faster by pre-allocating memory and having exclusive World
access.
§Example
use bevy_ecs::prelude::*;
#[derive(Component)]
struct Score(u32);
fn example_system(mut commands: Commands) {
commands.spawn_batch([
(Name::new("Alice"), Score(0)),
(Name::new("Bob"), Score(0)),
]);
}
§See also
spawn
to spawn an entity with components.spawn_empty
to spawn an entity without components.
Examples found in repository?
183fn startup_system(mut commands: Commands, mut game_state: ResMut<GameState>) {
184 // Create our game rules resource
185 commands.insert_resource(GameRules {
186 max_rounds: 10,
187 winning_score: 4,
188 max_players: 4,
189 });
190
191 // Add some players to our world. Players start with a score of 0 ... we want our game to be
192 // fair!
193 commands.spawn_batch(vec![
194 (
195 Player {
196 name: "Alice".to_string(),
197 },
198 Score { value: 0 },
199 PlayerStreak::None,
200 ),
201 (
202 Player {
203 name: "Bob".to_string(),
204 },
205 Score { value: 0 },
206 PlayerStreak::None,
207 ),
208 ]);
209
210 // set the total players to "2"
211 game_state.total_players = 2;
212}
More examples
54fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<ColorTint>) {
55 warn!(include_str!("warning_string.txt"));
56
57 let mut rng = rand::rng();
58
59 let tile_size = Vec2::splat(64.0);
60 let map_size = Vec2::splat(320.0);
61
62 let half_x = (map_size.x / 2.0) as i32;
63 let half_y = (map_size.y / 2.0) as i32;
64
65 let sprite_handle = assets.load("branding/icon.png");
66
67 // Spawns the camera
68
69 commands.spawn(Camera2d);
70
71 // Builds and spawns the sprites
72 let mut sprites = vec![];
73 for y in -half_y..half_y {
74 for x in -half_x..half_x {
75 let position = Vec2::new(x as f32, y as f32);
76 let translation = (position * tile_size).extend(rng.random::<f32>());
77 let rotation = Quat::from_rotation_z(rng.random::<f32>());
78 let scale = Vec3::splat(rng.random::<f32>() * 2.0);
79
80 sprites.push((
81 Sprite {
82 image: sprite_handle.clone(),
83 custom_size: Some(tile_size),
84 color: if color_tint.0 {
85 COLORS[rng.random_range(0..3)]
86 } else {
87 Color::WHITE
88 },
89 ..default()
90 },
91 Transform {
92 translation,
93 rotation,
94 scale,
95 },
96 ));
97 }
98 }
99 commands.spawn_batch(sprites);
100}
106fn setup(mut commands: Commands, font: Res<FontHandle>, args: Res<Args>) {
107 warn!(include_str!("warning_string.txt"));
108
109 let mut rng = ChaCha8Rng::seed_from_u64(42);
110
111 let tile_size = Vec2::splat(64.0);
112 let map_size = Vec2::splat(640.0);
113
114 let half_x = (map_size.x / 4.0) as i32;
115 let half_y = (map_size.y / 4.0) as i32;
116
117 // Spawns the camera
118
119 commands.spawn(Camera2d);
120
121 // Builds and spawns the `Text2d`s, distributing them in a way that ensures a
122 // good distribution of on-screen and off-screen entities.
123 let mut text2ds = vec![];
124 for y in -half_y..half_y {
125 for x in -half_x..half_x {
126 let position = Vec2::new(x as f32, y as f32);
127 let translation = (position * tile_size).extend(rng.random::<f32>());
128 let rotation = Quat::from_rotation_z(rng.random::<f32>());
129 let scale = Vec3::splat(rng.random::<f32>() * 2.0);
130 let color = Hsla::hsl(rng.random_range(0.0..360.0), 0.8, 0.8);
131
132 text2ds.push((
133 Text2d(random_text(&mut rng, &args)),
134 random_text_font(&mut rng, &args, font.0.clone()),
135 TextColor(color.into()),
136 TextLayout::new_with_justify(if args.center {
137 Justify::Center
138 } else {
139 Justify::Left
140 }),
141 Transform {
142 translation,
143 rotation,
144 scale,
145 },
146 ));
147 }
148 }
149
150 if args.no_frustum_culling {
151 let bundles = text2ds.into_iter().map(|bundle| (bundle, NoFrustumCulling));
152 commands.spawn_batch(bundles);
153 } else {
154 commands.spawn_batch(text2ds);
155 }
156}
41fn setup(
42 mut commands: Commands,
43 mut meshes: ResMut<Assets<Mesh>>,
44 mut materials: ResMut<Assets<StandardMaterial>>,
45) {
46 warn!(include_str!("warning_string.txt"));
47
48 const LIGHT_RADIUS: f32 = 0.3;
49 const LIGHT_INTENSITY: f32 = 1000.0;
50 const RADIUS: f32 = 50.0;
51 const N_LIGHTS: usize = 100_000;
52
53 commands.spawn((
54 Mesh3d(meshes.add(Sphere::new(RADIUS).mesh().ico(9).unwrap())),
55 MeshMaterial3d(materials.add(Color::WHITE)),
56 Transform::from_scale(Vec3::NEG_ONE),
57 ));
58
59 let mesh = meshes.add(Cuboid::default());
60 let material = materials.add(StandardMaterial {
61 base_color: DEEP_PINK.into(),
62 ..default()
63 });
64
65 // NOTE: This pattern is good for testing performance of culling as it provides roughly
66 // the same number of visible meshes regardless of the viewing angle.
67 // NOTE: f64 is used to avoid precision issues that produce visual artifacts in the distribution
68 let golden_ratio = 0.5f64 * (1.0f64 + 5.0f64.sqrt());
69
70 // Spawn N_LIGHTS many lights
71 commands.spawn_batch((0..N_LIGHTS).map(move |i| {
72 let mut rng = rng();
73
74 let spherical_polar_theta_phi = fibonacci_spiral_on_sphere(golden_ratio, i, N_LIGHTS);
75 let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
76
77 (
78 PointLight {
79 range: LIGHT_RADIUS,
80 intensity: LIGHT_INTENSITY,
81 color: Color::hsl(rng.random_range(0.0..360.0), 1.0, 0.5),
82 ..default()
83 },
84 Transform::from_translation((RADIUS as f64 * unit_sphere_p).as_vec3()),
85 )
86 }));
87
88 // camera
89 match std::env::args().nth(1).as_deref() {
90 Some("orthographic") => commands.spawn((
91 Camera3d::default(),
92 Projection::from(OrthographicProjection {
93 scaling_mode: ScalingMode::FixedHorizontal {
94 viewport_width: 20.0,
95 },
96 ..OrthographicProjection::default_3d()
97 }),
98 )),
99 _ => commands.spawn(Camera3d::default()),
100 };
101
102 // add one cube, the only one with strong handles
103 // also serves as a reference point during rotation
104 commands.spawn((
105 Mesh3d(mesh),
106 MeshMaterial3d(material),
107 Transform {
108 translation: Vec3::new(0.0, RADIUS, 0.0),
109 scale: Vec3::splat(5.0),
110 ..default()
111 },
112 ));
113}
38fn setup(
39 mut commands: Commands,
40 mut meshes: ResMut<Assets<Mesh>>,
41 mut materials: ResMut<Assets<StandardMaterial>>,
42) {
43 // ground plane
44 commands.spawn((
45 Mesh3d(meshes.add(Plane3d::default().mesh().size(100.0, 100.0))),
46 MeshMaterial3d(materials.add(Color::WHITE)),
47 Movable,
48 ));
49
50 // cubes
51
52 // We're seeding the PRNG here to make this example deterministic for testing purposes.
53 // This isn't strictly required in practical use unless you need your app to be deterministic.
54 let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
55 let cube_mesh = meshes.add(Cuboid::new(0.5, 0.5, 0.5));
56 let blue = materials.add(Color::srgb_u8(124, 144, 255));
57
58 commands.spawn_batch(
59 std::iter::repeat_with(move || {
60 let x = rng.random_range(-5.0..5.0);
61 let y = rng.random_range(0.0..3.0);
62 let z = rng.random_range(-5.0..5.0);
63
64 (
65 Mesh3d(cube_mesh.clone()),
66 MeshMaterial3d(blue.clone()),
67 Transform::from_xyz(x, y, z),
68 Movable,
69 )
70 })
71 .take(40),
72 );
73
74 let sphere_mesh = meshes.add(Sphere::new(0.05).mesh().uv(32, 18));
75 let sphere_mesh_direction = meshes.add(Sphere::new(0.1).mesh().uv(32, 18));
76 let red_emissive = materials.add(StandardMaterial {
77 base_color: RED.into(),
78 emissive: LinearRgba::new(1.0, 0.0, 0.0, 0.0),
79 ..default()
80 });
81 let maroon_emissive = materials.add(StandardMaterial {
82 base_color: MAROON.into(),
83 emissive: LinearRgba::new(0.369, 0.0, 0.0, 0.0),
84 ..default()
85 });
86
87 for x in 0..4 {
88 for z in 0..4 {
89 let x = x as f32 - 2.0;
90 let z = z as f32 - 2.0;
91 // red spot_light
92 commands.spawn((
93 SpotLight {
94 intensity: 40_000.0, // lumens
95 color: Color::WHITE,
96 shadows_enabled: true,
97 inner_angle: PI / 4.0 * 0.85,
98 outer_angle: PI / 4.0,
99 ..default()
100 },
101 Transform::from_xyz(1.0 + x, 2.0, z)
102 .looking_at(Vec3::new(1.0 + x, 0.0, z), Vec3::X),
103 children![
104 (
105 Mesh3d(sphere_mesh.clone()),
106 MeshMaterial3d(red_emissive.clone()),
107 ),
108 (
109 Mesh3d(sphere_mesh_direction.clone()),
110 MeshMaterial3d(maroon_emissive.clone()),
111 Transform::from_translation(Vec3::Z * -0.1),
112 NotShadowCaster,
113 )
114 ],
115 ));
116 }
117 }
118
119 // camera
120 commands.spawn((
121 Camera3d::default(),
122 Hdr,
123 Transform::from_xyz(-4.0, 5.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
124 ));
125
126 commands.spawn((
127 Text::new(INSTRUCTIONS),
128 Node {
129 position_type: PositionType::Absolute,
130 top: px(12),
131 left: px(12),
132 ..default()
133 },
134 ));
135}
386fn spawn_birds(
387 commands: &mut Commands,
388 args: &Args,
389 primary_window_resolution: &WindowResolution,
390 counter: &mut BevyCounter,
391 spawn_count: usize,
392 bird_resources: &mut BirdResources,
393 waves_to_simulate: Option<usize>,
394 wave: usize,
395) {
396 let bird_x = (primary_window_resolution.width() / -2.) + HALF_BIRD_SIZE;
397 let bird_y = (primary_window_resolution.height() / 2.) - HALF_BIRD_SIZE;
398
399 let half_extents = 0.5 * primary_window_resolution.size();
400
401 let color = counter.color;
402 let current_count = counter.count;
403
404 match args.mode {
405 Mode::Sprite => {
406 let batch = (0..spawn_count)
407 .map(|count| {
408 let bird_z = if args.ordered_z {
409 (current_count + count) as f32 * 0.00001
410 } else {
411 bird_resources.transform_rng.random::<f32>()
412 };
413
414 let (transform, velocity) = bird_velocity_transform(
415 half_extents,
416 Vec3::new(bird_x, bird_y, bird_z),
417 &mut bird_resources.velocity_rng,
418 waves_to_simulate,
419 FIXED_DELTA_TIME,
420 );
421
422 let color = if args.vary_per_instance {
423 Color::linear_rgb(
424 bird_resources.color_rng.random(),
425 bird_resources.color_rng.random(),
426 bird_resources.color_rng.random(),
427 )
428 } else {
429 color
430 };
431 (
432 Sprite {
433 image: bird_resources
434 .textures
435 .choose(&mut bird_resources.material_rng)
436 .unwrap()
437 .clone(),
438 color,
439 ..default()
440 },
441 transform,
442 Bird { velocity },
443 )
444 })
445 .collect::<Vec<_>>();
446 commands.spawn_batch(batch);
447 }
448 Mode::Mesh2d => {
449 let batch = (0..spawn_count)
450 .map(|count| {
451 let bird_z = if args.ordered_z {
452 (current_count + count) as f32 * 0.00001
453 } else {
454 bird_resources.transform_rng.random::<f32>()
455 };
456
457 let (transform, velocity) = bird_velocity_transform(
458 half_extents,
459 Vec3::new(bird_x, bird_y, bird_z),
460 &mut bird_resources.velocity_rng,
461 waves_to_simulate,
462 FIXED_DELTA_TIME,
463 );
464
465 let material =
466 if args.vary_per_instance || args.material_texture_count > args.waves {
467 bird_resources
468 .materials
469 .choose(&mut bird_resources.material_rng)
470 .unwrap()
471 .clone()
472 } else {
473 bird_resources.materials[wave % bird_resources.materials.len()].clone()
474 };
475 (
476 Mesh2d(bird_resources.quad.clone()),
477 MeshMaterial2d(material),
478 transform,
479 Bird { velocity },
480 )
481 })
482 .collect::<Vec<_>>();
483 commands.spawn_batch(batch);
484 }
485 }
486
487 counter.count += spawn_count;
488 counter.color = Color::linear_rgb(
489 bird_resources.color_rng.random(),
490 bird_resources.color_rng.random(),
491 bird_resources.color_rng.random(),
492 );
493}
Sourcepub fn queue<C, T>(&mut self, command: C)where
C: Command<T> + HandleError<T>,
pub fn queue<C, T>(&mut self, command: C)where
C: Command<T> + HandleError<T>,
Pushes a generic Command
to the command queue.
If the Command
returns a Result
,
it will be handled using the default error handler.
To use a custom error handler, see Commands::queue_handled
.
The command can be:
- A custom struct that implements
Command
. - A closure or function that matches one of the following signatures:
- A built-in command from the
command
module.
§Example
#[derive(Resource, Default)]
struct Counter(u64);
struct AddToCounter(String);
impl Command<Result> for AddToCounter {
fn apply(self, world: &mut World) -> Result {
let mut counter = world.get_resource_or_insert_with(Counter::default);
let amount: u64 = self.0.parse()?;
counter.0 += amount;
Ok(())
}
}
fn add_three_to_counter_system(mut commands: Commands) {
commands.queue(AddToCounter("3".to_string()));
}
fn add_twenty_five_to_counter_system(mut commands: Commands) {
commands.queue(|world: &mut World| {
let mut counter = world.get_resource_or_insert_with(Counter::default);
counter.0 += 25;
});
}
Sourcepub fn queue_handled<C, T>(
&mut self,
command: C,
error_handler: fn(BevyError, ErrorContext),
)where
C: Command<T> + HandleError<T>,
pub fn queue_handled<C, T>(
&mut self,
command: C,
error_handler: fn(BevyError, ErrorContext),
)where
C: Command<T> + HandleError<T>,
Pushes a generic Command
to the command queue.
If the Command
returns a Result
,
the given error_handler
will be used to handle error cases.
To implicitly use the default error handler, see Commands::queue
.
The command can be:
- A custom struct that implements
Command
. - A closure or function that matches one of the following signatures:
- A built-in command from the
command
module.
§Example
use bevy_ecs::error::warn;
#[derive(Resource, Default)]
struct Counter(u64);
struct AddToCounter(String);
impl Command<Result> for AddToCounter {
fn apply(self, world: &mut World) -> Result {
let mut counter = world.get_resource_or_insert_with(Counter::default);
let amount: u64 = self.0.parse()?;
counter.0 += amount;
Ok(())
}
}
fn add_three_to_counter_system(mut commands: Commands) {
commands.queue_handled(AddToCounter("3".to_string()), warn);
}
fn add_twenty_five_to_counter_system(mut commands: Commands) {
commands.queue(|world: &mut World| {
let mut counter = world.get_resource_or_insert_with(Counter::default);
counter.0 += 25;
});
}
Examples found in repository?
161fn failing_commands(mut commands: Commands) {
162 commands
163 // This entity doesn't exist!
164 .entity(Entity::from_raw_u32(12345678).unwrap())
165 // Normally, this failed command would panic,
166 // but since we've set the global error handler to `warn`
167 // it will log a warning instead.
168 .insert(Transform::default());
169
170 // The error handlers for commands can be set individually as well,
171 // by using the queue_handled method.
172 commands.queue_handled(
173 |world: &mut World| -> Result {
174 world
175 .get_resource::<UninitializedResource>()
176 .ok_or("Resource not initialized when accessed in a command")?;
177
178 Ok(())
179 },
180 |error, context| {
181 error!("{error}, {context}");
182 },
183 );
184}
Sourcepub fn queue_silenced<C, T>(&mut self, command: C)where
C: Command<T> + HandleError<T>,
pub fn queue_silenced<C, T>(&mut self, command: C)where
C: Command<T> + HandleError<T>,
Pushes a generic Command
to the queue like Commands::queue_handled
, but instead silently ignores any errors.
Sourcepub fn insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
Adds a series of Bundles
to each Entity
they are paired with,
based on a batch of (Entity, Bundle)
pairs.
A batch can be any type that implements IntoIterator
and contains (Entity, Bundle)
tuples,
such as a Vec<(Entity, Bundle)>
or an array [(Entity, Bundle); N]
.
This will overwrite any pre-existing components shared by the Bundle
type.
Use Commands::insert_batch_if_new
to keep the pre-existing components instead.
This method is equivalent to iterating the batch
and calling insert
for each pair,
but is faster by caching data that is shared between entities.
§Fallible
This command will fail if any of the given entities do not exist.
It will internally return a TryInsertBatchError
,
which will be handled by the default error handler.
Sourcepub fn insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
Adds a series of Bundles
to each Entity
they are paired with,
based on a batch of (Entity, Bundle)
pairs.
A batch can be any type that implements IntoIterator
and contains (Entity, Bundle)
tuples,
such as a Vec<(Entity, Bundle)>
or an array [(Entity, Bundle); N]
.
This will keep any pre-existing components shared by the Bundle
type
and discard the new values.
Use Commands::insert_batch
to overwrite the pre-existing components instead.
This method is equivalent to iterating the batch
and calling insert_if_new
for each pair,
but is faster by caching data that is shared between entities.
§Fallible
This command will fail if any of the given entities do not exist.
It will internally return a TryInsertBatchError
,
which will be handled by the default error handler.
Sourcepub fn try_insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn try_insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
Adds a series of Bundles
to each Entity
they are paired with,
based on a batch of (Entity, Bundle)
pairs.
A batch can be any type that implements IntoIterator
and contains (Entity, Bundle)
tuples,
such as a Vec<(Entity, Bundle)>
or an array [(Entity, Bundle); N]
.
This will overwrite any pre-existing components shared by the Bundle
type.
Use Commands::try_insert_batch_if_new
to keep the pre-existing components instead.
This method is equivalent to iterating the batch
and calling insert
for each pair,
but is faster by caching data that is shared between entities.
§Fallible
This command will fail if any of the given entities do not exist.
It will internally return a TryInsertBatchError
,
which will be handled by logging the error at the warn
level.
Examples found in repository?
330pub fn extract_colored_mesh2d(
331 mut commands: Commands,
332 mut previous_len: Local<usize>,
333 // When extracting, you must use `Extract` to mark the `SystemParam`s
334 // which should be taken from the main world.
335 query: Extract<
336 Query<
337 (
338 Entity,
339 RenderEntity,
340 &ViewVisibility,
341 &GlobalTransform,
342 &Mesh2d,
343 ),
344 With<ColoredMesh2d>,
345 >,
346 >,
347 mut render_mesh_instances: ResMut<RenderColoredMesh2dInstances>,
348) {
349 let mut values = Vec::with_capacity(*previous_len);
350 for (entity, render_entity, view_visibility, transform, handle) in &query {
351 if !view_visibility.get() {
352 continue;
353 }
354
355 let transforms = Mesh2dTransforms {
356 world_from_local: (&transform.affine()).into(),
357 flags: MeshFlags::empty().bits(),
358 };
359
360 values.push((render_entity, ColoredMesh2d));
361 render_mesh_instances.insert(
362 entity.into(),
363 RenderMesh2dInstance {
364 mesh_asset_id: handle.0.id(),
365 transforms,
366 material_bind_group_id: Material2dBindGroupId::default(),
367 automatic_batching: false,
368 tag: 0,
369 },
370 );
371 }
372 *previous_len = values.len();
373 commands.try_insert_batch(values);
374}
Sourcepub fn try_insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn try_insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
Adds a series of Bundles
to each Entity
they are paired with,
based on a batch of (Entity, Bundle)
pairs.
A batch can be any type that implements IntoIterator
and contains (Entity, Bundle)
tuples,
such as a Vec<(Entity, Bundle)>
or an array [(Entity, Bundle); N]
.
This will keep any pre-existing components shared by the Bundle
type
and discard the new values.
Use Commands::try_insert_batch
to overwrite the pre-existing components instead.
This method is equivalent to iterating the batch
and calling insert_if_new
for each pair,
but is faster by caching data that is shared between entities.
§Fallible
This command will fail if any of the given entities do not exist.
It will internally return a TryInsertBatchError
,
which will be handled by logging the error at the warn
level.
Sourcepub fn init_resource<R>(&mut self)
pub fn init_resource<R>(&mut self)
Inserts a Resource
into the World
with an inferred value.
The inferred value is determined by the FromWorld
trait of the resource.
Note that any resource with the Default
trait automatically implements FromWorld
,
and those default values will be used.
If the resource already exists when the command is applied, nothing happens.
§Example
#[derive(Resource, Default)]
struct Scoreboard {
current_score: u32,
high_score: u32,
}
fn initialize_scoreboard(mut commands: Commands) {
commands.init_resource::<Scoreboard>();
}
Examples found in repository?
More examples
58fn setup(
59 mut commands: Commands,
60 mut meshes: ResMut<Assets<Mesh>>,
61 mut materials: ResMut<Assets<StandardMaterial>>,
62) {
63 // circular base
64 commands.spawn((
65 Mesh3d(meshes.add(Circle::new(4.0))),
66 MeshMaterial3d(materials.add(Color::WHITE)),
67 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
68 ));
69 // cube
70 commands.spawn((
71 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
72 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
73 Transform::from_xyz(0.0, 0.5, 0.0),
74 ));
75 // light
76 commands.spawn((
77 PointLight {
78 shadows_enabled: true,
79 ..default()
80 },
81 Transform::from_xyz(4.0, 8.0, 4.0),
82 ));
83 // camera
84 commands.spawn((
85 Camera3d::default(),
86 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
87 ));
88
89 commands.init_resource::<LogDiagnosticsFilters>();
90 commands.init_resource::<LogDiagnosticsStatus>();
91
92 commands.spawn((
93 LogDiagnosticsCommands,
94 Node {
95 top: px(5),
96 left: px(5),
97 flex_direction: FlexDirection::Column,
98 ..default()
99 },
100 ));
101}
Sourcepub fn insert_resource<R>(&mut self, resource: R)where
R: Resource,
pub fn insert_resource<R>(&mut self, resource: R)where
R: Resource,
Inserts a Resource
into the World
with a specific value.
This will overwrite any previous value of the same resource type.
§Example
#[derive(Resource)]
struct Scoreboard {
current_score: u32,
high_score: u32,
}
fn system(mut commands: Commands) {
commands.insert_resource(Scoreboard {
current_score: 0,
high_score: 0,
});
}
Examples found in repository?
More examples
- examples/shader_advanced/specialized_mesh_pipeline.rs
- examples/2d/mesh2d_manual.rs
- examples/async_tasks/async_compute.rs
- examples/asset/processing/asset_processing.rs
- examples/2d/sprite_tile.rs
- examples/shader/array_texture.rs
- examples/window/window_settings.rs
- examples/audio/soundtrack.rs
- examples/games/desk_toy.rs
- examples/async_tasks/external_source_external_thread.rs
- examples/games/loading_screen.rs
- examples/ecs/ecs_guide.rs
- examples/shader/compute_shader_game_of_life.rs
- examples/3d/manual_material.rs
- examples/games/game_menu.rs
- examples/remote/server.rs
- examples/ui/font_atlas_debug.rs
- examples/2d/tilemap_chunk.rs
- examples/asset/multi_asset_sync.rs
- examples/state/custom_transitions.rs
- examples/testbed/3d.rs
- examples/state/states.rs
- examples/3d/skybox.rs
- examples/state/sub_states.rs
- examples/shader/storage_buffer.rs
- examples/movement/smooth_follow.rs
- examples/games/contributors.rs
- examples/gizmos/axes.rs
- examples/3d/motion_blur.rs
- examples/animation/animated_mesh_events.rs
- examples/math/cubic_splines.rs
- examples/animation/animation_graph.rs
- examples/animation/animated_mesh_control.rs
- examples/2d/cpu_draw.rs
- examples/shader_advanced/custom_post_processing.rs
- examples/transforms/align.rs
- examples/math/random_sampling.rs
- examples/3d/solari.rs
- examples/state/computed_states.rs
- examples/animation/animation_masks.rs
- examples/games/alien_cake_addict.rs
- examples/shader/gpu_readback.rs
- examples/3d/auto_exposure.rs
- examples/stress_tests/bevymark.rs
- examples/ui/drag_to_scroll.rs
- examples/games/breakout.rs
- examples/stress_tests/many_foxes.rs
- examples/math/sampling_primitives.rs
- examples/3d/lighting.rs
Sourcepub fn remove_resource<R>(&mut self)where
R: Resource,
pub fn remove_resource<R>(&mut self)where
R: Resource,
Removes a Resource
from the World
.
§Example
#[derive(Resource)]
struct Scoreboard {
current_score: u32,
high_score: u32,
}
fn system(mut commands: Commands) {
commands.remove_resource::<Scoreboard>();
}
Examples found in repository?
More examples
Sourcepub fn run_system(&mut self, id: SystemId)
pub fn run_system(&mut self, id: SystemId)
Runs the system corresponding to the given SystemId
.
Before running a system, it must first be registered via
Commands::register_system
or World::register_system
.
The system is run in an exclusive and single-threaded way. Running slow systems can become a bottleneck.
There is no way to get the output of a system when run as a command, because the
execution of the system happens later. To get the output of a system, use
World::run_system
or World::run_system_with
instead of running the system as a command.
§Fallible
This command will fail if the given SystemId
does not correspond to a System
.
It will internally return a RegisteredSystemError
,
which will be handled by logging the error at the warn
level.
Examples found in repository?
More examples
97fn level_selection(
98 mut commands: Commands,
99 keyboard: Res<ButtonInput<KeyCode>>,
100 level_data: Res<LevelData>,
101 loading_state: Res<LoadingState>,
102) {
103 // Only trigger a load if the current level is fully loaded.
104 if let LoadingState::LevelReady = loading_state.as_ref() {
105 if keyboard.just_pressed(KeyCode::Digit1) {
106 commands.run_system(level_data.unload_level_id);
107 commands.run_system(level_data.level_1_id);
108 } else if keyboard.just_pressed(KeyCode::Digit2) {
109 commands.run_system(level_data.unload_level_id);
110 commands.run_system(level_data.level_2_id);
111 }
112 }
113}
Sourcepub fn run_system_with<I>(
&mut self,
id: SystemId<I>,
input: <I as SystemInput>::Inner<'static>,
)
pub fn run_system_with<I>( &mut self, id: SystemId<I>, input: <I as SystemInput>::Inner<'static>, )
Runs the system corresponding to the given SystemId
with input.
Before running a system, it must first be registered via
Commands::register_system
or World::register_system
.
The system is run in an exclusive and single-threaded way. Running slow systems can become a bottleneck.
There is no way to get the output of a system when run as a command, because the
execution of the system happens later. To get the output of a system, use
World::run_system
or World::run_system_with
instead of running the system as a command.
§Fallible
This command will fail if the given SystemId
does not correspond to a System
.
It will internally return a RegisteredSystemError
,
which will be handled by logging the error at the warn
level.
Sourcepub fn register_system<I, O, M>(
&mut self,
system: impl IntoSystem<I, O, M> + 'static,
) -> SystemId<I, O>
pub fn register_system<I, O, M>( &mut self, system: impl IntoSystem<I, O, M> + 'static, ) -> SystemId<I, O>
Registers a system and returns its SystemId
so it can later be called by
Commands::run_system
or World::run_system
.
This is different from adding systems to a Schedule
,
because the SystemId
that is returned can be used anywhere in the World
to run the associated system.
Using a Schedule
is still preferred for most cases
due to its better performance and ability to run non-conflicting systems simultaneously.
§Note
If the same system is registered more than once,
each registration will be considered a different system,
and they will each be given their own SystemId
.
If you want to avoid registering the same system multiple times,
consider using Commands::run_system_cached
or storing the SystemId
in a Local
.
§Example
#[derive(Resource)]
struct Counter(i32);
fn register_system(
mut commands: Commands,
mut local_system: Local<Option<SystemId>>,
) {
if let Some(system) = *local_system {
commands.run_system(system);
} else {
*local_system = Some(commands.register_system(increment_counter));
}
}
fn increment_counter(mut value: ResMut<Counter>) {
value.0 += 1;
}
Examples found in repository?
More examples
71fn setup(mut commands: Commands) {
72 let level_data = LevelData {
73 unload_level_id: commands.register_system(unload_current_level),
74 level_1_id: commands.register_system(load_level_1),
75 level_2_id: commands.register_system(load_level_2),
76 };
77 commands.insert_resource(level_data);
78
79 // Spawns the UI that will show the user prompts.
80 let text_style = TextFont {
81 font_size: 42.0,
82 ..default()
83 };
84 commands
85 .spawn((
86 Node {
87 justify_self: JustifySelf::Center,
88 align_self: AlignSelf::FlexEnd,
89 ..default()
90 },
91 BackgroundColor(Color::NONE),
92 ))
93 .with_child((Text::new("Press 1 or 2 to load a new scene."), text_style));
94}
Sourcepub fn unregister_system<I, O>(&mut self, system_id: SystemId<I, O>)
pub fn unregister_system<I, O>(&mut self, system_id: SystemId<I, O>)
Removes a system previously registered with Commands::register_system
or World::register_system
.
After removing a system, the SystemId
becomes invalid
and attempting to use it afterwards will result in an error.
Re-adding the removed system will register it with a new SystemId
.
§Fallible
This command will fail if the given SystemId
does not correspond to a System
.
It will internally return a RegisteredSystemError
,
which will be handled by logging the error at the warn
level.
Sourcepub fn unregister_system_cached<I, O, M, S>(&mut self, system: S)where
I: SystemInput + Send + 'static,
O: 'static,
M: 'static,
S: IntoSystem<I, O, M> + Send + 'static,
pub fn unregister_system_cached<I, O, M, S>(&mut self, system: S)where
I: SystemInput + Send + 'static,
O: 'static,
M: 'static,
S: IntoSystem<I, O, M> + Send + 'static,
Removes a system previously registered with one of the following:
§Fallible
This command will fail if the given system
is not currently cached in a CachedSystemId
resource.
It will internally return a RegisteredSystemError
,
which will be handled by logging the error at the warn
level.
Sourcepub fn run_system_cached<M, S>(&mut self, system: S)
pub fn run_system_cached<M, S>(&mut self, system: S)
Runs a cached system, registering it if necessary.
Unlike Commands::run_system
, this method does not require manual registration.
The first time this method is called for a particular system,
it will register the system and store its SystemId
in a
CachedSystemId
resource for later.
If you would rather manage the SystemId
yourself,
or register multiple copies of the same system,
use Commands::register_system
instead.
§Limitations
This method only accepts ZST (zero-sized) systems to guarantee that any two systems of the same type must be equal. This means that closures that capture the environment, and function pointers, are not accepted.
If you want to access values from the environment within a system,
consider passing them in as inputs via Commands::run_system_cached_with
.
If that’s not an option, consider Commands::register_system
instead.
Sourcepub fn run_system_cached_with<I, M, S>(
&mut self,
system: S,
input: <I as SystemInput>::Inner<'static>,
)where
I: SystemInput + Send + 'static,
<I as SystemInput>::Inner<'static>: Send,
M: 'static,
S: IntoSystem<I, (), M> + Send + 'static,
pub fn run_system_cached_with<I, M, S>(
&mut self,
system: S,
input: <I as SystemInput>::Inner<'static>,
)where
I: SystemInput + Send + 'static,
<I as SystemInput>::Inner<'static>: Send,
M: 'static,
S: IntoSystem<I, (), M> + Send + 'static,
Runs a cached system with an input, registering it if necessary.
Unlike Commands::run_system_with
, this method does not require manual registration.
The first time this method is called for a particular system,
it will register the system and store its SystemId
in a
CachedSystemId
resource for later.
If you would rather manage the SystemId
yourself,
or register multiple copies of the same system,
use Commands::register_system
instead.
§Limitations
This method only accepts ZST (zero-sized) systems to guarantee that any two systems of the same type must be equal. This means that closures that capture the environment, and function pointers, are not accepted.
If you want to access values from the environment within a system, consider passing them in as inputs.
If that’s not an option, consider Commands::register_system
instead.
Sourcepub fn trigger<'a>(&mut self, event: impl Event : Default>)
pub fn trigger<'a>(&mut self, event: impl Event : Default>)
Examples found in repository?
60fn setup(mut commands: Commands) {
61 commands.spawn(Camera2d);
62
63 commands.spawn(background_and_button()).observe(
64 // any click bubbling up here should lead to closing any open menu
65 |_: On<Pointer<Press>>, mut commands: Commands| {
66 commands.trigger(CloseContextMenus);
67 },
68 );
69}
70
71fn on_trigger_close_menus(
72 _event: On<CloseContextMenus>,
73 mut commands: Commands,
74 menus: Query<Entity, With<ContextMenu>>,
75) {
76 for e in menus.iter() {
77 commands.entity(e).despawn();
78 }
79}
80
81fn on_trigger_menu(event: On<OpenContextMenu>, mut commands: Commands) {
82 commands.trigger(CloseContextMenus);
83
84 let pos = event.pos;
85
86 debug!("open context menu at: {pos}");
87
88 commands
89 .spawn((
90 Name::new("context menu"),
91 ContextMenu,
92 Node {
93 position_type: PositionType::Absolute,
94 left: px(pos.x),
95 top: px(pos.y),
96 flex_direction: FlexDirection::Column,
97 ..default()
98 },
99 BorderColor::all(Color::BLACK),
100 BorderRadius::all(px(4)),
101 BackgroundColor(Color::linear_rgb(0.1, 0.1, 0.1)),
102 children![
103 context_item("fuchsia", basic::FUCHSIA),
104 context_item("gray", basic::GRAY),
105 context_item("maroon", basic::MAROON),
106 context_item("purple", basic::PURPLE),
107 context_item("teal", basic::TEAL),
108 ],
109 ))
110 .observe(
111 |event: On<Pointer<Press>>,
112 menu_items: Query<&ContextMenuItem>,
113 mut clear_col: ResMut<ClearColor>,
114 mut commands: Commands| {
115 let target = event.original_event_target();
116
117 if let Ok(item) = menu_items.get(target) {
118 clear_col.0 = item.0.into();
119 commands.trigger(CloseContextMenus);
120 }
121 },
122 );
123}
124
125fn context_item(text: &str, col: Srgba) -> impl Bundle {
126 (
127 Name::new(format!("item-{text}")),
128 ContextMenuItem(col),
129 Button,
130 Node {
131 padding: UiRect::all(px(5)),
132 ..default()
133 },
134 children![(
135 Pickable::IGNORE,
136 Text::new(text),
137 TextFont {
138 font_size: 24.0,
139 ..default()
140 },
141 TextColor(Color::WHITE),
142 )],
143 )
144}
145
146fn background_and_button() -> impl Bundle {
147 (
148 Name::new("background"),
149 Node {
150 width: percent(100),
151 height: percent(100),
152 align_items: AlignItems::Center,
153 justify_content: JustifyContent::Center,
154 ..default()
155 },
156 ZIndex(-10),
157 Children::spawn(SpawnWith(|parent: &mut RelatedSpawner<ChildOf>| {
158 parent
159 .spawn((
160 Name::new("button"),
161 Button,
162 Node {
163 width: px(250),
164 height: px(65),
165 border: UiRect::all(px(5)),
166 justify_content: JustifyContent::Center,
167 align_items: AlignItems::Center,
168 ..default()
169 },
170 BorderColor::all(Color::BLACK),
171 BorderRadius::MAX,
172 BackgroundColor(Color::BLACK),
173 children![(
174 Pickable::IGNORE,
175 Text::new("Context Menu"),
176 TextFont {
177 font_size: 28.0,
178 ..default()
179 },
180 TextColor(Color::WHITE),
181 TextShadow::default(),
182 )],
183 ))
184 .observe(|mut event: On<Pointer<Press>>, mut commands: Commands| {
185 // by default this event would bubble up further leading to the `CloseContextMenus`
186 // event being triggered and undoing the opening of one here right away.
187 event.propagate(false);
188
189 debug!("click: {}", event.pointer_location.position);
190
191 commands.trigger(OpenContextMenu {
192 pos: event.pointer_location.position,
193 });
194 });
195 })),
196 )
197}
More examples
25fn send_scroll_events(
26 mut mouse_wheel_reader: MessageReader<MouseWheel>,
27 hover_map: Res<HoverMap>,
28 keyboard_input: Res<ButtonInput<KeyCode>>,
29 mut commands: Commands,
30) {
31 for mouse_wheel in mouse_wheel_reader.read() {
32 let mut delta = -Vec2::new(mouse_wheel.x, mouse_wheel.y);
33
34 if mouse_wheel.unit == MouseScrollUnit::Line {
35 delta *= LINE_HEIGHT;
36 }
37
38 if keyboard_input.any_pressed([KeyCode::ControlLeft, KeyCode::ControlRight]) {
39 std::mem::swap(&mut delta.x, &mut delta.y);
40 }
41
42 for pointer_map in hover_map.values() {
43 for entity in pointer_map.keys().copied() {
44 commands.trigger(Scroll { entity, delta });
45 }
46 }
47 }
48}
373fn interact_with_focused_button(
374 action_state: Res<ActionState>,
375 input_focus: Res<InputFocus>,
376 mut commands: Commands,
377) {
378 if action_state
379 .pressed_actions
380 .contains(&DirectionalNavigationAction::Select)
381 && let Some(focused_entity) = input_focus.0
382 {
383 commands.trigger(Pointer::<Click> {
384 entity: focused_entity,
385 // We're pretending that we're a mouse
386 pointer_id: PointerId::Mouse,
387 // This field isn't used, so we're just setting it to a placeholder value
388 pointer_location: Location {
389 target: NormalizedRenderTarget::None {
390 width: 0,
391 height: 0,
392 },
393 position: Vec2::ZERO,
394 },
395 event: Click {
396 button: PointerButton::Primary,
397 // This field isn't used, so we're just setting it to a placeholder value
398 hit: HitData {
399 camera: Entity::PLACEHOLDER,
400 depth: 0.0,
401 position: None,
402 normal: None,
403 },
404 duration: Duration::from_secs_f32(0.1),
405 },
406 });
407 }
408}
10fn main() {
11 App::new()
12 .add_plugins(DefaultPlugins)
13 .init_resource::<SpatialIndex>()
14 .add_systems(Startup, setup)
15 .add_systems(Update, (draw_shapes, handle_click))
16 // Observers are systems that run when an event is "triggered". This observer runs whenever
17 // `ExplodeMines` is triggered.
18 .add_observer(
19 |explode_mines: On<ExplodeMines>,
20 mines: Query<&Mine>,
21 index: Res<SpatialIndex>,
22 mut commands: Commands| {
23 // Access resources
24 for entity in index.get_nearby(explode_mines.pos) {
25 // Run queries
26 let mine = mines.get(entity).unwrap();
27 if mine.pos.distance(explode_mines.pos) < mine.size + explode_mines.radius {
28 // And queue commands, including triggering additional events
29 // Here we trigger the `Explode` event for entity `e`
30 commands.trigger(Explode { entity });
31 }
32 }
33 },
34 )
35 // This observer runs whenever the `Mine` component is added to an entity, and places it in a simple spatial index.
36 .add_observer(on_add_mine)
37 // This observer runs whenever the `Mine` component is removed from an entity (including despawning it)
38 // and removes it from the spatial index.
39 .add_observer(on_remove_mine)
40 .run();
41}
42
43#[derive(Component)]
44struct Mine {
45 pos: Vec2,
46 size: f32,
47}
48
49impl Mine {
50 fn random(rand: &mut ChaCha8Rng) -> Self {
51 Mine {
52 pos: Vec2::new(
53 (rand.random::<f32>() - 0.5) * 1200.0,
54 (rand.random::<f32>() - 0.5) * 600.0,
55 ),
56 size: 4.0 + rand.random::<f32>() * 16.0,
57 }
58 }
59}
60
61/// This is a normal [`Event`]. Any observer that watches for it will run when it is triggered.
62#[derive(Event)]
63struct ExplodeMines {
64 pos: Vec2,
65 radius: f32,
66}
67
68/// An [`EntityEvent`] is a specialized type of [`Event`] that can target a specific entity. In addition to
69/// running normal "top level" observers when it is triggered (which target _any_ entity that Explodes), it will
70/// also run any observers that target the _specific_ entity for that event.
71#[derive(EntityEvent)]
72struct Explode {
73 entity: Entity,
74}
75
76fn setup(mut commands: Commands) {
77 commands.spawn(Camera2d);
78 commands.spawn((
79 Text::new(
80 "Click on a \"Mine\" to trigger it.\n\
81 When it explodes it will trigger all overlapping mines.",
82 ),
83 Node {
84 position_type: PositionType::Absolute,
85 top: px(12),
86 left: px(12),
87 ..default()
88 },
89 ));
90
91 let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
92
93 commands
94 .spawn(Mine::random(&mut rng))
95 // Observers can watch for events targeting a specific entity.
96 // This will create a new observer that runs whenever the Explode event
97 // is triggered for this spawned entity.
98 .observe(explode_mine);
99
100 // We want to spawn a bunch of mines. We could just call the code above for each of them.
101 // That would create a new observer instance for every Mine entity. Having duplicate observers
102 // generally isn't worth worrying about as the overhead is low. But if you want to be maximally efficient,
103 // you can reuse observers across entities.
104 //
105 // First, observers are actually just entities with the Observer component! The `observe()` functions
106 // you've seen so far in this example are just shorthand for manually spawning an observer.
107 let mut observer = Observer::new(explode_mine);
108
109 // As we spawn entities, we can make this observer watch each of them:
110 for _ in 0..1000 {
111 let entity = commands.spawn(Mine::random(&mut rng)).id();
112 observer.watch_entity(entity);
113 }
114
115 // By spawning the Observer component, it becomes active!
116 commands.spawn(observer);
117}
118
119fn on_add_mine(add: On<Add, Mine>, query: Query<&Mine>, mut index: ResMut<SpatialIndex>) {
120 let mine = query.get(add.entity).unwrap();
121 let tile = (
122 (mine.pos.x / CELL_SIZE).floor() as i32,
123 (mine.pos.y / CELL_SIZE).floor() as i32,
124 );
125 index.map.entry(tile).or_default().insert(add.entity);
126}
127
128// Remove despawned mines from our index
129fn on_remove_mine(remove: On<Remove, Mine>, query: Query<&Mine>, mut index: ResMut<SpatialIndex>) {
130 let mine = query.get(remove.entity).unwrap();
131 let tile = (
132 (mine.pos.x / CELL_SIZE).floor() as i32,
133 (mine.pos.y / CELL_SIZE).floor() as i32,
134 );
135 index.map.entry(tile).and_modify(|set| {
136 set.remove(&remove.entity);
137 });
138}
139
140fn explode_mine(explode: On<Explode>, query: Query<&Mine>, mut commands: Commands) {
141 // Explode is an EntityEvent. `explode.entity` is the entity that Explode was triggered for.
142 let Ok(mut entity) = commands.get_entity(explode.entity) else {
143 return;
144 };
145 info!("Boom! {} exploded.", explode.entity);
146 entity.despawn();
147 let mine = query.get(explode.entity).unwrap();
148 // Trigger another explosion cascade.
149 commands.trigger(ExplodeMines {
150 pos: mine.pos,
151 radius: mine.size,
152 });
153}
154
155// Draw a circle for each mine using `Gizmos`
156fn draw_shapes(mut gizmos: Gizmos, mines: Query<&Mine>) {
157 for mine in &mines {
158 gizmos.circle_2d(
159 mine.pos,
160 mine.size,
161 Color::hsl((mine.size - 4.0) / 16.0 * 360.0, 1.0, 0.8),
162 );
163 }
164}
165
166// Trigger `ExplodeMines` at the position of a given click
167fn handle_click(
168 mouse_button_input: Res<ButtonInput<MouseButton>>,
169 camera: Single<(&Camera, &GlobalTransform)>,
170 windows: Query<&Window>,
171 mut commands: Commands,
172) {
173 let Ok(windows) = windows.single() else {
174 return;
175 };
176
177 let (camera, camera_transform) = *camera;
178 if let Some(pos) = windows
179 .cursor_position()
180 .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
181 .map(|ray| ray.origin.truncate())
182 && mouse_button_input.just_pressed(MouseButton::Left)
183 {
184 commands.trigger(ExplodeMines { pos, radius: 1.0 });
185 }
186}
335fn check_for_collisions(
336 mut commands: Commands,
337 mut score: ResMut<Score>,
338 ball_query: Single<(&mut Velocity, &Transform), With<Ball>>,
339 collider_query: Query<(Entity, &Transform, Option<&Brick>), With<Collider>>,
340) {
341 let (mut ball_velocity, ball_transform) = ball_query.into_inner();
342
343 for (collider_entity, collider_transform, maybe_brick) in &collider_query {
344 let collision = ball_collision(
345 BoundingCircle::new(ball_transform.translation.truncate(), BALL_DIAMETER / 2.),
346 Aabb2d::new(
347 collider_transform.translation.truncate(),
348 collider_transform.scale.truncate() / 2.,
349 ),
350 );
351
352 if let Some(collision) = collision {
353 // Trigger observers of the "BallCollided" event
354 commands.trigger(BallCollided);
355
356 // Bricks should be despawned and increment the scoreboard on collision
357 if maybe_brick.is_some() {
358 commands.entity(collider_entity).despawn();
359 **score += 1;
360 }
361
362 // Reflect the ball's velocity when it collides
363 let mut reflect_x = false;
364 let mut reflect_y = false;
365
366 // Reflect only if the velocity is in the opposite direction of the collision
367 // This prevents the ball from getting stuck inside the bar
368 match collision {
369 Collision::Left => reflect_x = ball_velocity.x > 0.0,
370 Collision::Right => reflect_x = ball_velocity.x < 0.0,
371 Collision::Top => reflect_y = ball_velocity.y < 0.0,
372 Collision::Bottom => reflect_y = ball_velocity.y > 0.0,
373 }
374
375 // Reflect velocity on the x-axis if we hit something on the x-axis
376 if reflect_x {
377 ball_velocity.x = -ball_velocity.x;
378 }
379
380 // Reflect velocity on the y-axis if we hit something on the y-axis
381 if reflect_y {
382 ball_velocity.y = -ball_velocity.y;
383 }
384 }
385 }
386}
Sourcepub fn trigger_targets<'a>(&mut self, event: impl Event : Default>)
👎Deprecated since 0.17.0: Use Commands::trigger
instead.
pub fn trigger_targets<'a>(&mut self, event: impl Event : Default>)
Commands::trigger
instead.A deprecated alias for trigger
to ease migration.
Instead of specifying the trigger target separately, information about the target of the event is embedded in the data held by the event type itself.
Sourcepub fn trigger_with<E>(
&mut self,
event: E,
trigger: <E as Event>::Trigger<'static>,
)
pub fn trigger_with<E>( &mut self, event: E, trigger: <E as Event>::Trigger<'static>, )
Sourcepub fn add_observer<E, B, M>(
&mut self,
observer: impl IntoObserverSystem<E, B, M>,
) -> EntityCommands<'_>
pub fn add_observer<E, B, M>( &mut self, observer: impl IntoObserverSystem<E, B, M>, ) -> EntityCommands<'_>
Spawns an Observer
and returns the EntityCommands
associated
with the entity that stores the observer.
observer
can be any system whose first parameter is On
.
Calling observe
on the returned
EntityCommands
will observe the observer itself, which you very
likely do not want.
§Panics
Panics if the given system is an exclusive system.
Sourcepub fn write_message<M>(&mut self, message: M) -> &mut Commands<'w, 's>where
M: Message,
pub fn write_message<M>(&mut self, message: M) -> &mut Commands<'w, 's>where
M: Message,
Writes an arbitrary Message
.
This is a convenience method for writing messages
without requiring a MessageWriter
.
§Performance
Since this is a command, exclusive world access is used, which means that it will not profit from system-level parallelism on supported platforms.
If these messages are performance-critical or very frequently sent,
consider using a MessageWriter
instead.
Examples found in repository?
More examples
154fn setup(
155 mut commands: Commands,
156 asset_server: Res<AssetServer>,
157 app_status: Res<AppStatus>,
158 render_device: Res<RenderDevice>,
159 render_adapter: Res<RenderAdapter>,
160 mut meshes: ResMut<Assets<Mesh>>,
161 mut materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, CustomDecalExtension>>>,
162) {
163 // Error out if clustered decals aren't supported on the current platform.
164 if !decal::clustered::clustered_decals_are_usable(&render_device, &render_adapter) {
165 error!("Clustered decals aren't usable on this platform.");
166 commands.write_message(AppExit::error());
167 }
168
169 spawn_cube(&mut commands, &mut meshes, &mut materials);
170 spawn_camera(&mut commands);
171 spawn_light(&mut commands);
172 spawn_decals(&mut commands, &asset_server);
173 spawn_buttons(&mut commands);
174 spawn_help_text(&mut commands, &app_status);
175}
143fn setup(
144 mut commands: Commands,
145 asset_server: Res<AssetServer>,
146 app_status: Res<AppStatus>,
147 render_device: Res<RenderDevice>,
148 render_adapter: Res<RenderAdapter>,
149 mut meshes: ResMut<Assets<Mesh>>,
150 mut materials: ResMut<Assets<StandardMaterial>>,
151) {
152 // Error out if clustered decals (and so light textures) aren't supported on the current platform.
153 if !decal::clustered::clustered_decals_are_usable(&render_device, &render_adapter) {
154 error!("Light textures aren't usable on this platform.");
155 commands.write_message(AppExit::error());
156 }
157
158 spawn_cubes(&mut commands, &mut meshes, &mut materials);
159 spawn_camera(&mut commands);
160 spawn_light(&mut commands, &asset_server);
161 spawn_buttons(&mut commands);
162 spawn_help_text(&mut commands, &app_status);
163 spawn_light_textures(&mut commands, &asset_server, &mut meshes, &mut materials);
164}
Sourcepub fn send_event<E>(&mut self, event: E) -> &mut Commands<'w, 's>where
E: Message,
👎Deprecated since 0.17.0: Use Commands::write_message
instead.
pub fn send_event<E>(&mut self, event: E) -> &mut Commands<'w, 's>where
E: Message,
Commands::write_message
instead.Writes an arbitrary Message
.
This is a convenience method for writing events
without requiring a MessageWriter
.
§Performance
Since this is a command, exclusive world access is used, which means that it will not profit from system-level parallelism on supported platforms.
If these events are performance-critical or very frequently sent,
consider using a typed MessageWriter
instead.
Sourcepub fn run_schedule(&mut self, label: impl ScheduleLabel)
pub fn run_schedule(&mut self, label: impl ScheduleLabel)
Runs the schedule corresponding to the given ScheduleLabel
.
Calls World::try_run_schedule
.
§Fallible
This command will fail if the given ScheduleLabel
does not correspond to a Schedule
.
It will internally return a TryRunScheduleError
,
which will be handled by logging the error at the warn
level.
§Example
#[derive(ScheduleLabel, Hash, Debug, PartialEq, Eq, Clone, Copy)]
struct FooSchedule;
commands.run_schedule(FooSchedule);
Trait Implementations§
Source§impl CommandsStatesExt for Commands<'_, '_>
impl CommandsStatesExt for Commands<'_, '_>
Source§fn set_state<S>(&mut self, state: S)where
S: FreelyMutableState,
fn set_state<S>(&mut self, state: S)where
S: FreelyMutableState,
Source§impl SystemParam for Commands<'_, '_>
impl SystemParam for Commands<'_, '_>
Source§type Item<'w, 's> = Commands<'w, 's>
type Item<'w, 's> = Commands<'w, 's>
Self
, instantiated with new lifetimes. Read moreSource§fn init_state(world: &mut World) -> <Commands<'_, '_> as SystemParam>::State
fn init_state(world: &mut World) -> <Commands<'_, '_> as SystemParam>::State
State
.Source§fn init_access(
state: &<Commands<'_, '_> as SystemParam>::State,
system_meta: &mut SystemMeta,
component_access_set: &mut FilteredAccessSet,
world: &mut World,
)
fn init_access( state: &<Commands<'_, '_> as SystemParam>::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World, )
World
access used by this SystemParam
Source§fn apply(
state: &mut <Commands<'_, '_> as SystemParam>::State,
system_meta: &SystemMeta,
world: &mut World,
)
fn apply( state: &mut <Commands<'_, '_> as SystemParam>::State, system_meta: &SystemMeta, world: &mut World, )
SystemParam
’s state.
This is used to apply Commands
during ApplyDeferred
.Source§fn queue(
state: &mut <Commands<'_, '_> as SystemParam>::State,
system_meta: &SystemMeta,
world: DeferredWorld<'_>,
)
fn queue( state: &mut <Commands<'_, '_> as SystemParam>::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )
ApplyDeferred
.Source§unsafe fn validate_param(
state: &mut <Commands<'_, '_> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'_>,
) -> Result<(), SystemParamValidationError>
unsafe fn validate_param( state: &mut <Commands<'_, '_> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'_>, ) -> Result<(), SystemParamValidationError>
Source§unsafe fn get_param<'w, 's>(
state: &'s mut <Commands<'_, '_> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick,
) -> <Commands<'_, '_> as SystemParam>::Item<'w, 's>
unsafe fn get_param<'w, 's>( state: &'s mut <Commands<'_, '_> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> <Commands<'_, '_> as SystemParam>::Item<'w, 's>
SystemParamFunction
. Read moreimpl<'w, 's> ReadOnlySystemParam for Commands<'w, 's>
impl Send for Commands<'_, '_>
impl Sync for Commands<'_, '_>
Auto Trait Implementations§
impl<'w, 's> Freeze for Commands<'w, 's>
impl<'w, 's> RefUnwindSafe for Commands<'w, 's>
impl<'w, 's> Unpin for Commands<'w, 's>
impl<'w, 's> !UnwindSafe for Commands<'w, 's>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.