bevy_app/app.rs
1use crate::{
2 First, Main, MainSchedulePlugin, PlaceholderPlugin, Plugin, Plugins, PluginsState, SubApp,
3 SubApps,
4};
5use alloc::{
6 boxed::Box,
7 string::{String, ToString},
8 vec::Vec,
9};
10pub use bevy_derive::AppLabel;
11use bevy_ecs::{
12 component::RequiredComponentsError,
13 error::{DefaultErrorHandler, ErrorHandler},
14 event::Event,
15 intern::Interned,
16 message::{message_update_system, MessageCursor},
17 prelude::*,
18 schedule::{InternedSystemSet, ScheduleBuildSettings, ScheduleLabel},
19 system::{IntoObserverSystem, ScheduleSystem, SystemId, SystemInput},
20};
21use bevy_platform::collections::HashMap;
22use core::{fmt::Debug, num::NonZero, panic::AssertUnwindSafe};
23use log::debug;
24
25#[cfg(feature = "trace")]
26use tracing::info_span;
27
28#[cfg(feature = "std")]
29use std::{
30 panic::{catch_unwind, resume_unwind},
31 process::{ExitCode, Termination},
32};
33
34bevy_ecs::define_label!(
35 /// A strongly-typed class of labels used to identify an [`App`].
36 #[diagnostic::on_unimplemented(
37 note = "consider annotating `{Self}` with `#[derive(AppLabel)]`"
38 )]
39 AppLabel,
40 APP_LABEL_INTERNER
41);
42
43pub use bevy_ecs::label::DynEq;
44
45/// A shorthand for `Interned<dyn AppLabel>`.
46pub type InternedAppLabel = Interned<dyn AppLabel>;
47
48#[derive(Debug, thiserror::Error)]
49pub(crate) enum AppError {
50 #[error("duplicate plugin {plugin_name:?}")]
51 DuplicatePlugin { plugin_name: String },
52}
53
54/// [`App`] is the primary API for writing user applications. It automates the setup of a
55/// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).
56///
57/// A single [`App`] can contain multiple [`SubApp`] instances, but [`App`] methods only affect
58/// the "main" one. To access a particular [`SubApp`], use [`get_sub_app`](App::get_sub_app)
59/// or [`get_sub_app_mut`](App::get_sub_app_mut).
60///
61///
62/// # Examples
63///
64/// Here is a simple "Hello World" Bevy app:
65///
66/// ```
67/// # use bevy_app::prelude::*;
68/// # use bevy_ecs::prelude::*;
69/// #
70/// fn main() {
71/// App::new()
72/// .add_systems(Update, hello_world_system)
73/// .run();
74/// }
75///
76/// fn hello_world_system() {
77/// println!("hello world");
78/// }
79/// ```
80pub struct App {
81 pub(crate) sub_apps: SubApps,
82 /// The function that will manage the app's lifecycle.
83 ///
84 /// Bevy provides the [`WinitPlugin`] and [`ScheduleRunnerPlugin`] for windowed and headless
85 /// applications, respectively.
86 ///
87 /// [`WinitPlugin`]: https://docs.rs/bevy/latest/bevy/winit/struct.WinitPlugin.html
88 /// [`ScheduleRunnerPlugin`]: https://docs.rs/bevy/latest/bevy/app/struct.ScheduleRunnerPlugin.html
89 pub(crate) runner: RunnerFn,
90 default_error_handler: Option<ErrorHandler>,
91}
92
93impl Debug for App {
94 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95 write!(f, "App {{ sub_apps: ")?;
96 f.debug_map()
97 .entries(self.sub_apps.sub_apps.iter())
98 .finish()?;
99 write!(f, "}}")
100 }
101}
102
103impl Default for App {
104 fn default() -> Self {
105 let mut app = App::empty();
106 app.sub_apps.main.update_schedule = Some(Main.intern());
107
108 #[cfg(feature = "bevy_reflect")]
109 {
110 #[cfg(not(feature = "reflect_auto_register"))]
111 app.init_resource::<AppTypeRegistry>();
112
113 #[cfg(feature = "reflect_auto_register")]
114 app.insert_resource(AppTypeRegistry::new_with_derived_types());
115 }
116
117 #[cfg(feature = "reflect_functions")]
118 app.init_resource::<AppFunctionRegistry>();
119
120 app.add_plugins(MainSchedulePlugin);
121 app.add_systems(
122 First,
123 message_update_system
124 .in_set(bevy_ecs::message::MessageUpdateSystems)
125 .run_if(bevy_ecs::message::message_update_condition),
126 );
127 app.add_message::<AppExit>();
128
129 app
130 }
131}
132
133impl App {
134 /// Creates a new [`App`] with some default structure to enable core engine features.
135 /// This is the preferred constructor for most use cases.
136 pub fn new() -> App {
137 App::default()
138 }
139
140 /// Creates a new empty [`App`] with minimal default configuration.
141 ///
142 /// Use this constructor if you want to customize scheduling, exit handling, cleanup, etc.
143 pub fn empty() -> App {
144 Self {
145 sub_apps: SubApps {
146 main: SubApp::new(),
147 sub_apps: HashMap::default(),
148 },
149 runner: Box::new(run_once),
150 default_error_handler: None,
151 }
152 }
153
154 /// Runs the default schedules of all sub-apps (starting with the "main" app) once.
155 pub fn update(&mut self) {
156 if self.is_building_plugins() {
157 panic!("App::update() was called while a plugin was building.");
158 }
159
160 self.sub_apps.update();
161 }
162
163 /// Runs the [`App`] by calling its [runner](Self::set_runner).
164 ///
165 /// This will (re)build the [`App`] first. For general usage, see the example on the item
166 /// level documentation.
167 ///
168 /// # Caveats
169 ///
170 /// Calls to [`App::run()`] will never return on iOS and Web.
171 ///
172 /// Headless apps can generally expect this method to return control to the caller when
173 /// it completes, but that is not the case for windowed apps. Windowed apps are typically
174 /// driven by an event loop and some platforms expect the program to terminate when the
175 /// event loop ends.
176 ///
177 /// By default, *Bevy* uses the `winit` crate for window creation.
178 ///
179 /// # Panics
180 ///
181 /// Panics if not all plugins have been built.
182 pub fn run(&mut self) -> AppExit {
183 #[cfg(feature = "trace")]
184 let _bevy_app_run_span = info_span!("bevy_app").entered();
185 if self.is_building_plugins() {
186 panic!("App::run() was called while a plugin was building.");
187 }
188
189 let runner = core::mem::replace(&mut self.runner, Box::new(run_once));
190 let app = core::mem::replace(self, App::empty());
191 (runner)(app)
192 }
193
194 /// Sets the function that will be called when the app is run.
195 ///
196 /// The runner function `f` is called only once by [`App::run`]. If the
197 /// presence of a main loop in the app is desired, it is the responsibility of the runner
198 /// function to provide it.
199 ///
200 /// The runner function is usually not set manually, but by Bevy integrated plugins
201 /// (e.g. `WinitPlugin`).
202 ///
203 /// # Examples
204 ///
205 /// ```
206 /// # use bevy_app::prelude::*;
207 /// #
208 /// fn my_runner(mut app: App) -> AppExit {
209 /// loop {
210 /// println!("In main loop");
211 /// app.update();
212 /// if let Some(exit) = app.should_exit() {
213 /// return exit;
214 /// }
215 /// }
216 /// }
217 ///
218 /// App::new()
219 /// .set_runner(my_runner);
220 /// ```
221 pub fn set_runner(&mut self, f: impl FnOnce(App) -> AppExit + 'static) -> &mut Self {
222 self.runner = Box::new(f);
223 self
224 }
225
226 /// Returns the state of all plugins. This is usually called by the event loop, but can be
227 /// useful for situations where you want to use [`App::update`].
228 // TODO: &mut self -> &self
229 #[inline]
230 pub fn plugins_state(&mut self) -> PluginsState {
231 let mut overall_plugins_state = match self.main_mut().plugins_state {
232 PluginsState::Adding => {
233 let mut state = PluginsState::Ready;
234 let plugins = core::mem::take(&mut self.main_mut().plugin_registry);
235 for plugin in &plugins {
236 // plugins installed to main need to see all sub-apps
237 if !plugin.ready(self) {
238 state = PluginsState::Adding;
239 break;
240 }
241 }
242 self.main_mut().plugin_registry = plugins;
243 state
244 }
245 state => state,
246 };
247
248 // overall state is the earliest state of any sub-app
249 self.sub_apps.iter_mut().skip(1).for_each(|s| {
250 overall_plugins_state = overall_plugins_state.min(s.plugins_state());
251 });
252
253 overall_plugins_state
254 }
255
256 /// Runs [`Plugin::finish`] for each plugin. This is usually called by the event loop once all
257 /// plugins are ready, but can be useful for situations where you want to use [`App::update`].
258 pub fn finish(&mut self) {
259 #[cfg(feature = "trace")]
260 let _finish_span = info_span!("plugin finish").entered();
261 // plugins installed to main should see all sub-apps
262 // do hokey pokey with a boxed zst plugin (doesn't allocate)
263 let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);
264 for i in 0..self.main().plugin_registry.len() {
265 core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);
266 #[cfg(feature = "trace")]
267 let _plugin_finish_span =
268 info_span!("plugin finish", plugin = hokeypokey.name()).entered();
269 hokeypokey.finish(self);
270 core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);
271 }
272 self.main_mut().plugins_state = PluginsState::Finished;
273 self.sub_apps.iter_mut().skip(1).for_each(SubApp::finish);
274 }
275
276 /// Runs [`Plugin::cleanup`] for each plugin. This is usually called by the event loop after
277 /// [`App::finish`], but can be useful for situations where you want to use [`App::update`].
278 pub fn cleanup(&mut self) {
279 #[cfg(feature = "trace")]
280 let _cleanup_span = info_span!("plugin cleanup").entered();
281 // plugins installed to main should see all sub-apps
282 // do hokey pokey with a boxed zst plugin (doesn't allocate)
283 let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);
284 for i in 0..self.main().plugin_registry.len() {
285 core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);
286 #[cfg(feature = "trace")]
287 let _plugin_cleanup_span =
288 info_span!("plugin cleanup", plugin = hokeypokey.name()).entered();
289 hokeypokey.cleanup(self);
290 core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);
291 }
292 self.main_mut().plugins_state = PluginsState::Cleaned;
293 self.sub_apps.iter_mut().skip(1).for_each(SubApp::cleanup);
294 }
295
296 /// Returns `true` if any of the sub-apps are building plugins.
297 pub(crate) fn is_building_plugins(&self) -> bool {
298 self.sub_apps.iter().any(SubApp::is_building_plugins)
299 }
300
301 /// Adds one or more systems to the given schedule in this app's [`Schedules`].
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// # use bevy_app::prelude::*;
307 /// # use bevy_ecs::prelude::*;
308 /// #
309 /// # let mut app = App::new();
310 /// # fn system_a() {}
311 /// # fn system_b() {}
312 /// # fn system_c() {}
313 /// # fn should_run() -> bool { true }
314 /// #
315 /// app.add_systems(Update, (system_a, system_b, system_c));
316 /// app.add_systems(Update, (system_a, system_b).run_if(should_run));
317 /// ```
318 pub fn add_systems<M>(
319 &mut self,
320 schedule: impl ScheduleLabel,
321 systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
322 ) -> &mut Self {
323 self.main_mut().add_systems(schedule, systems);
324 self
325 }
326
327 /// Registers a system and returns a [`SystemId`] so it can later be called by [`World::run_system`].
328 ///
329 /// It's possible to register the same systems more than once, they'll be stored separately.
330 ///
331 /// This is different from adding systems to a [`Schedule`] with [`App::add_systems`],
332 /// because the [`SystemId`] that is returned can be used anywhere in the [`World`] to run the associated system.
333 /// This allows for running systems in a push-based fashion.
334 /// Using a [`Schedule`] is still preferred for most cases
335 /// due to its better performance and ability to run non-conflicting systems simultaneously.
336 pub fn register_system<I, O, M>(
337 &mut self,
338 system: impl IntoSystem<I, O, M> + 'static,
339 ) -> SystemId<I, O>
340 where
341 I: SystemInput + 'static,
342 O: 'static,
343 {
344 self.main_mut().register_system(system)
345 }
346
347 /// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.
348 #[track_caller]
349 pub fn configure_sets<M>(
350 &mut self,
351 schedule: impl ScheduleLabel,
352 sets: impl IntoScheduleConfigs<InternedSystemSet, M>,
353 ) -> &mut Self {
354 self.main_mut().configure_sets(schedule, sets);
355 self
356 }
357
358 /// Initializes [`Message`] handling for `T` by inserting an event queue resource ([`Messages::<T>`])
359 /// and scheduling an [`message_update_system`] in [`First`].
360 ///
361 /// See [`Messages`] for information on how to define events.
362 ///
363 /// # Examples
364 ///
365 /// ```
366 /// # use bevy_app::prelude::*;
367 /// # use bevy_ecs::prelude::*;
368 /// #
369 /// # #[derive(Message)]
370 /// # struct MyMessage;
371 /// # let mut app = App::new();
372 /// #
373 /// app.add_event::<MyMessage>();
374 /// ```
375 #[deprecated(since = "0.17.0", note = "Use `add_message` instead.")]
376 pub fn add_event<T>(&mut self) -> &mut Self
377 where
378 T: Message,
379 {
380 self.add_message::<T>()
381 }
382
383 /// Initializes [`Message`] handling for `T` by inserting a message queue resource ([`Messages::<T>`])
384 /// and scheduling an [`message_update_system`] in [`First`].
385 ///
386 /// See [`Messages`] for information on how to define messages.
387 ///
388 /// # Examples
389 ///
390 /// ```
391 /// # use bevy_app::prelude::*;
392 /// # use bevy_ecs::prelude::*;
393 /// #
394 /// # #[derive(Message)]
395 /// # struct MyMessage;
396 /// # let mut app = App::new();
397 /// #
398 /// app.add_message::<MyMessage>();
399 /// ```
400 pub fn add_message<M: Message>(&mut self) -> &mut Self {
401 self.main_mut().add_message::<M>();
402 self
403 }
404
405 /// Inserts the [`Resource`] into the app, overwriting any existing resource of the same type.
406 ///
407 /// There is also an [`init_resource`](Self::init_resource) for resources that have
408 /// [`Default`] or [`FromWorld`] implementations.
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// # use bevy_app::prelude::*;
414 /// # use bevy_ecs::prelude::*;
415 /// #
416 /// #[derive(Resource)]
417 /// struct MyCounter {
418 /// counter: usize,
419 /// }
420 ///
421 /// App::new()
422 /// .insert_resource(MyCounter { counter: 0 });
423 /// ```
424 pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
425 self.main_mut().insert_resource(resource);
426 self
427 }
428
429 /// Inserts the [`Resource`], initialized with its default value, into the app,
430 /// if there is no existing instance of `R`.
431 ///
432 /// `R` must implement [`FromWorld`].
433 /// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and
434 /// initialize the [`Resource`] with [`Default::default`].
435 ///
436 /// # Examples
437 ///
438 /// ```
439 /// # use bevy_app::prelude::*;
440 /// # use bevy_ecs::prelude::*;
441 /// #
442 /// #[derive(Resource)]
443 /// struct MyCounter {
444 /// counter: usize,
445 /// }
446 ///
447 /// impl Default for MyCounter {
448 /// fn default() -> MyCounter {
449 /// MyCounter {
450 /// counter: 100
451 /// }
452 /// }
453 /// }
454 ///
455 /// App::new()
456 /// .init_resource::<MyCounter>();
457 /// ```
458 pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
459 self.main_mut().init_resource::<R>();
460 self
461 }
462
463 /// Inserts the [`!Send`](Send) resource into the app, overwriting any existing resource
464 /// of the same type.
465 ///
466 /// There is also an [`init_non_send_resource`](Self::init_non_send_resource) for
467 /// resources that implement [`Default`]
468 ///
469 /// # Examples
470 ///
471 /// ```
472 /// # use bevy_app::prelude::*;
473 /// # use bevy_ecs::prelude::*;
474 /// #
475 /// struct MyCounter {
476 /// counter: usize,
477 /// }
478 ///
479 /// App::new()
480 /// .insert_non_send_resource(MyCounter { counter: 0 });
481 /// ```
482 pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {
483 self.world_mut().insert_non_send_resource(resource);
484 self
485 }
486
487 /// Inserts the [`!Send`](Send) resource into the app if there is no existing instance of `R`.
488 ///
489 /// `R` must implement [`FromWorld`].
490 /// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and
491 /// initialize the [`Resource`] with [`Default::default`].
492 pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {
493 self.world_mut().init_non_send_resource::<R>();
494 self
495 }
496
497 pub(crate) fn add_boxed_plugin(
498 &mut self,
499 plugin: Box<dyn Plugin>,
500 ) -> Result<&mut Self, AppError> {
501 debug!("added plugin: {}", plugin.name());
502 if plugin.is_unique() && self.main_mut().plugin_names.contains(plugin.name()) {
503 Err(AppError::DuplicatePlugin {
504 plugin_name: plugin.name().to_string(),
505 })?;
506 }
507
508 // Reserve position in the plugin registry. If the plugin adds more plugins,
509 // they'll all end up in insertion order.
510 let index = self.main().plugin_registry.len();
511 self.main_mut()
512 .plugin_registry
513 .push(Box::new(PlaceholderPlugin));
514
515 self.main_mut().plugin_build_depth += 1;
516
517 #[cfg(feature = "trace")]
518 let _plugin_build_span = info_span!("plugin build", plugin = plugin.name()).entered();
519
520 let f = AssertUnwindSafe(|| plugin.build(self));
521
522 #[cfg(feature = "std")]
523 let result = catch_unwind(f);
524
525 #[cfg(not(feature = "std"))]
526 f();
527
528 self.main_mut()
529 .plugin_names
530 .insert(plugin.name().to_string());
531 self.main_mut().plugin_build_depth -= 1;
532
533 #[cfg(feature = "std")]
534 if let Err(payload) = result {
535 resume_unwind(payload);
536 }
537
538 self.main_mut().plugin_registry[index] = plugin;
539 Ok(self)
540 }
541
542 /// Returns `true` if the [`Plugin`] has already been added.
543 pub fn is_plugin_added<T>(&self) -> bool
544 where
545 T: Plugin,
546 {
547 self.main().is_plugin_added::<T>()
548 }
549
550 /// Returns a vector of references to all plugins of type `T` that have been added.
551 ///
552 /// This can be used to read the settings of any existing plugins.
553 /// This vector will be empty if no plugins of that type have been added.
554 /// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector.
555 ///
556 /// ```
557 /// # use bevy_app::prelude::*;
558 /// # #[derive(Default)]
559 /// # struct ImagePlugin {
560 /// # default_sampler: bool,
561 /// # }
562 /// # impl Plugin for ImagePlugin {
563 /// # fn build(&self, app: &mut App) {}
564 /// # }
565 /// # let mut app = App::new();
566 /// # app.add_plugins(ImagePlugin::default());
567 /// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;
568 /// ```
569 pub fn get_added_plugins<T>(&self) -> Vec<&T>
570 where
571 T: Plugin,
572 {
573 self.main().get_added_plugins::<T>()
574 }
575
576 /// Installs a [`Plugin`] collection.
577 ///
578 /// Bevy prioritizes modularity as a core principle. **All** engine features are implemented
579 /// as plugins, even the complex ones like rendering.
580 ///
581 /// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].
582 ///
583 /// There are built-in [`PluginGroup`]s that provide core engine functionality.
584 /// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`.
585 ///
586 /// To customize the plugins in the group (reorder, disable a plugin, add a new plugin
587 /// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group,
588 /// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder).
589 ///
590 /// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and
591 /// [`PluginGroup`]s. See [`Plugins`] for more details.
592 ///
593 /// ## Examples
594 /// ```
595 /// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins};
596 /// #
597 /// # // Dummies created to avoid using `bevy_log`,
598 /// # // which pulls in too many dependencies and breaks rust-analyzer
599 /// # pub struct LogPlugin;
600 /// # impl Plugin for LogPlugin {
601 /// # fn build(&self, app: &mut App) {}
602 /// # }
603 /// App::new()
604 /// .add_plugins(MinimalPlugins);
605 /// App::new()
606 /// .add_plugins((MinimalPlugins, LogPlugin));
607 /// ```
608 ///
609 /// # Panics
610 ///
611 /// Panics if one of the plugins had already been added to the application.
612 ///
613 /// [`PluginGroup`]:super::PluginGroup
614 #[track_caller]
615 pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {
616 if matches!(
617 self.plugins_state(),
618 PluginsState::Cleaned | PluginsState::Finished
619 ) {
620 panic!(
621 "Plugins cannot be added after App::cleanup() or App::finish() has been called."
622 );
623 }
624 plugins.add_to_app(self);
625 self
626 }
627
628 /// Registers the type `T` in the [`AppTypeRegistry`] resource,
629 /// adding reflect data as specified in the [`Reflect`](bevy_reflect::Reflect) derive:
630 /// ```ignore (No serde "derive" feature)
631 /// #[derive(Component, Serialize, Deserialize, Reflect)]
632 /// #[reflect(Component, Serialize, Deserialize)] // will register ReflectComponent, ReflectSerialize, ReflectDeserialize
633 /// ```
634 ///
635 /// See [`bevy_reflect::TypeRegistry::register`] for more information.
636 #[cfg(feature = "bevy_reflect")]
637 pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
638 self.main_mut().register_type::<T>();
639 self
640 }
641
642 /// Associates type data `D` with type `T` in the [`AppTypeRegistry`] resource.
643 ///
644 /// Most of the time [`register_type`](Self::register_type) can be used instead to register a
645 /// type you derived [`Reflect`](bevy_reflect::Reflect) for. However, in cases where you want to
646 /// add a piece of type data that was not included in the list of `#[reflect(...)]` type data in
647 /// the derive, or where the type is generic and cannot register e.g. `ReflectSerialize`
648 /// unconditionally without knowing the specific type parameters, this method can be used to
649 /// insert additional type data.
650 ///
651 /// # Example
652 /// ```
653 /// use bevy_app::App;
654 /// use bevy_reflect::{ReflectSerialize, ReflectDeserialize};
655 ///
656 /// App::new()
657 /// .register_type::<Option<String>>()
658 /// .register_type_data::<Option<String>, ReflectSerialize>()
659 /// .register_type_data::<Option<String>, ReflectDeserialize>();
660 /// ```
661 ///
662 /// See [`bevy_reflect::TypeRegistry::register_type_data`].
663 #[cfg(feature = "bevy_reflect")]
664 pub fn register_type_data<
665 T: bevy_reflect::Reflect + bevy_reflect::TypePath,
666 D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,
667 >(
668 &mut self,
669 ) -> &mut Self {
670 self.main_mut().register_type_data::<T, D>();
671 self
672 }
673
674 /// Registers the given function into the [`AppFunctionRegistry`] resource.
675 ///
676 /// The given function will internally be stored as a [`DynamicFunction`]
677 /// and mapped according to its [name].
678 ///
679 /// Because the function must have a name,
680 /// anonymous functions (e.g. `|a: i32, b: i32| { a + b }`) and closures must instead
681 /// be registered using [`register_function_with_name`] or converted to a [`DynamicFunction`]
682 /// and named using [`DynamicFunction::with_name`].
683 /// Failure to do so will result in a panic.
684 ///
685 /// Only types that implement [`IntoFunction`] may be registered via this method.
686 ///
687 /// See [`FunctionRegistry::register`] for more information.
688 ///
689 /// # Panics
690 ///
691 /// Panics if a function has already been registered with the given name
692 /// or if the function is missing a name (such as when it is an anonymous function).
693 ///
694 /// # Examples
695 ///
696 /// ```
697 /// use bevy_app::App;
698 ///
699 /// fn add(a: i32, b: i32) -> i32 {
700 /// a + b
701 /// }
702 ///
703 /// App::new().register_function(add);
704 /// ```
705 ///
706 /// Functions cannot be registered more than once.
707 ///
708 /// ```should_panic
709 /// use bevy_app::App;
710 ///
711 /// fn add(a: i32, b: i32) -> i32 {
712 /// a + b
713 /// }
714 ///
715 /// App::new()
716 /// .register_function(add)
717 /// // Panic! A function has already been registered with the name "my_function"
718 /// .register_function(add);
719 /// ```
720 ///
721 /// Anonymous functions and closures should be registered using [`register_function_with_name`] or given a name using [`DynamicFunction::with_name`].
722 ///
723 /// ```should_panic
724 /// use bevy_app::App;
725 ///
726 /// // Panic! Anonymous functions cannot be registered using `register_function`
727 /// App::new().register_function(|a: i32, b: i32| a + b);
728 /// ```
729 ///
730 /// [`register_function_with_name`]: Self::register_function_with_name
731 /// [`DynamicFunction`]: bevy_reflect::func::DynamicFunction
732 /// [name]: bevy_reflect::func::FunctionInfo::name
733 /// [`DynamicFunction::with_name`]: bevy_reflect::func::DynamicFunction::with_name
734 /// [`IntoFunction`]: bevy_reflect::func::IntoFunction
735 /// [`FunctionRegistry::register`]: bevy_reflect::func::FunctionRegistry::register
736 #[cfg(feature = "reflect_functions")]
737 pub fn register_function<F, Marker>(&mut self, function: F) -> &mut Self
738 where
739 F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,
740 {
741 self.main_mut().register_function(function);
742 self
743 }
744
745 /// Registers the given function or closure into the [`AppFunctionRegistry`] resource using the given name.
746 ///
747 /// To avoid conflicts, it's recommended to use a unique name for the function.
748 /// This can be achieved by "namespacing" the function with a unique identifier,
749 /// such as the name of your crate.
750 ///
751 /// For example, to register a function, `add`, from a crate, `my_crate`,
752 /// you could use the name, `"my_crate::add"`.
753 ///
754 /// Another approach could be to use the [type name] of the function,
755 /// however, it should be noted that anonymous functions do _not_ have unique type names.
756 ///
757 /// For named functions (e.g. `fn add(a: i32, b: i32) -> i32 { a + b }`) where a custom name is not needed,
758 /// it's recommended to use [`register_function`] instead as the generated name is guaranteed to be unique.
759 ///
760 /// Only types that implement [`IntoFunction`] may be registered via this method.
761 ///
762 /// See [`FunctionRegistry::register_with_name`] for more information.
763 ///
764 /// # Panics
765 ///
766 /// Panics if a function has already been registered with the given name.
767 ///
768 /// # Examples
769 ///
770 /// ```
771 /// use bevy_app::App;
772 ///
773 /// fn mul(a: i32, b: i32) -> i32 {
774 /// a * b
775 /// }
776 ///
777 /// let div = |a: i32, b: i32| a / b;
778 ///
779 /// App::new()
780 /// // Registering an anonymous function with a unique name
781 /// .register_function_with_name("my_crate::add", |a: i32, b: i32| {
782 /// a + b
783 /// })
784 /// // Registering an existing function with its type name
785 /// .register_function_with_name(std::any::type_name_of_val(&mul), mul)
786 /// // Registering an existing function with a custom name
787 /// .register_function_with_name("my_crate::mul", mul)
788 /// // Be careful not to register anonymous functions with their type name.
789 /// // This code works but registers the function with a non-unique name like `foo::bar::{{closure}}`
790 /// .register_function_with_name(std::any::type_name_of_val(&div), div);
791 /// ```
792 ///
793 /// Names must be unique.
794 ///
795 /// ```should_panic
796 /// use bevy_app::App;
797 ///
798 /// fn one() {}
799 /// fn two() {}
800 ///
801 /// App::new()
802 /// .register_function_with_name("my_function", one)
803 /// // Panic! A function has already been registered with the name "my_function"
804 /// .register_function_with_name("my_function", two);
805 /// ```
806 ///
807 /// [type name]: std::any::type_name
808 /// [`register_function`]: Self::register_function
809 /// [`IntoFunction`]: bevy_reflect::func::IntoFunction
810 /// [`FunctionRegistry::register_with_name`]: bevy_reflect::func::FunctionRegistry::register_with_name
811 #[cfg(feature = "reflect_functions")]
812 pub fn register_function_with_name<F, Marker>(
813 &mut self,
814 name: impl Into<alloc::borrow::Cow<'static, str>>,
815 function: F,
816 ) -> &mut Self
817 where
818 F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,
819 {
820 self.main_mut().register_function_with_name(name, function);
821 self
822 }
823
824 /// Registers the given component `R` as a [required component] for `T`.
825 ///
826 /// When `T` is added to an entity, `R` and its own required components will also be added
827 /// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.
828 /// If a custom constructor is desired, use [`App::register_required_components_with`] instead.
829 ///
830 /// For the non-panicking version, see [`App::try_register_required_components`].
831 ///
832 /// Note that requirements must currently be registered before `T` is inserted into the world
833 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
834 ///
835 /// [required component]: Component#required-components
836 ///
837 /// # Panics
838 ///
839 /// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added
840 /// on an entity before the registration.
841 ///
842 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
843 /// will only be overwritten if the new requirement is more specific.
844 ///
845 /// # Example
846 ///
847 /// ```
848 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
849 /// # use bevy_ecs::prelude::*;
850 /// #[derive(Component)]
851 /// struct A;
852 ///
853 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
854 /// struct B(usize);
855 ///
856 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
857 /// struct C(u32);
858 ///
859 /// # let mut app = App::new();
860 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
861 /// // Register B as required by A and C as required by B.
862 /// app.register_required_components::<A, B>();
863 /// app.register_required_components::<B, C>();
864 ///
865 /// fn setup(mut commands: Commands) {
866 /// // This will implicitly also insert B and C with their Default constructors.
867 /// commands.spawn(A);
868 /// }
869 ///
870 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
871 /// let (a, b, c) = query.unwrap().into_inner();
872 /// assert_eq!(b, &B(0));
873 /// assert_eq!(c, &C(0));
874 /// }
875 /// # app.update();
876 /// ```
877 pub fn register_required_components<T: Component, R: Component + Default>(
878 &mut self,
879 ) -> &mut Self {
880 self.world_mut().register_required_components::<T, R>();
881 self
882 }
883
884 /// Registers the given component `R` as a [required component] for `T`.
885 ///
886 /// When `T` is added to an entity, `R` and its own required components will also be added
887 /// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.
888 /// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.
889 ///
890 /// For the non-panicking version, see [`App::try_register_required_components_with`].
891 ///
892 /// Note that requirements must currently be registered before `T` is inserted into the world
893 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
894 ///
895 /// [required component]: Component#required-components
896 ///
897 /// # Panics
898 ///
899 /// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added
900 /// on an entity before the registration.
901 ///
902 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
903 /// will only be overwritten if the new requirement is more specific.
904 ///
905 /// # Example
906 ///
907 /// ```
908 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
909 /// # use bevy_ecs::prelude::*;
910 /// #[derive(Component)]
911 /// struct A;
912 ///
913 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
914 /// struct B(usize);
915 ///
916 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
917 /// struct C(u32);
918 ///
919 /// # let mut app = App::new();
920 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
921 /// // Register B and C as required by A and C as required by B.
922 /// // A requiring C directly will overwrite the indirect requirement through B.
923 /// app.register_required_components::<A, B>();
924 /// app.register_required_components_with::<B, C>(|| C(1));
925 /// app.register_required_components_with::<A, C>(|| C(2));
926 ///
927 /// fn setup(mut commands: Commands) {
928 /// // This will implicitly also insert B with its Default constructor and C
929 /// // with the custom constructor defined by A.
930 /// commands.spawn(A);
931 /// }
932 ///
933 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
934 /// let (a, b, c) = query.unwrap().into_inner();
935 /// assert_eq!(b, &B(0));
936 /// assert_eq!(c, &C(2));
937 /// }
938 /// # app.update();
939 /// ```
940 pub fn register_required_components_with<T: Component, R: Component>(
941 &mut self,
942 constructor: fn() -> R,
943 ) -> &mut Self {
944 self.world_mut()
945 .register_required_components_with::<T, R>(constructor);
946 self
947 }
948
949 /// Tries to register the given component `R` as a [required component] for `T`.
950 ///
951 /// When `T` is added to an entity, `R` and its own required components will also be added
952 /// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.
953 /// If a custom constructor is desired, use [`App::register_required_components_with`] instead.
954 ///
955 /// For the panicking version, see [`App::register_required_components`].
956 ///
957 /// Note that requirements must currently be registered before `T` is inserted into the world
958 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
959 ///
960 /// [required component]: Component#required-components
961 ///
962 /// # Errors
963 ///
964 /// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added
965 /// on an entity before the registration.
966 ///
967 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
968 /// will only be overwritten if the new requirement is more specific.
969 ///
970 /// # Example
971 ///
972 /// ```
973 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
974 /// # use bevy_ecs::prelude::*;
975 /// #[derive(Component)]
976 /// struct A;
977 ///
978 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
979 /// struct B(usize);
980 ///
981 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
982 /// struct C(u32);
983 ///
984 /// # let mut app = App::new();
985 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
986 /// // Register B as required by A and C as required by B.
987 /// app.register_required_components::<A, B>();
988 /// app.register_required_components::<B, C>();
989 ///
990 /// // Duplicate registration! This will fail.
991 /// assert!(app.try_register_required_components::<A, B>().is_err());
992 ///
993 /// fn setup(mut commands: Commands) {
994 /// // This will implicitly also insert B and C with their Default constructors.
995 /// commands.spawn(A);
996 /// }
997 ///
998 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
999 /// let (a, b, c) = query.unwrap().into_inner();
1000 /// assert_eq!(b, &B(0));
1001 /// assert_eq!(c, &C(0));
1002 /// }
1003 /// # app.update();
1004 /// ```
1005 pub fn try_register_required_components<T: Component, R: Component + Default>(
1006 &mut self,
1007 ) -> Result<(), RequiredComponentsError> {
1008 self.world_mut().try_register_required_components::<T, R>()
1009 }
1010
1011 /// Tries to register the given component `R` as a [required component] for `T`.
1012 ///
1013 /// When `T` is added to an entity, `R` and its own required components will also be added
1014 /// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.
1015 /// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.
1016 ///
1017 /// For the panicking version, see [`App::register_required_components_with`].
1018 ///
1019 /// Note that requirements must currently be registered before `T` is inserted into the world
1020 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
1021 ///
1022 /// [required component]: Component#required-components
1023 ///
1024 /// # Errors
1025 ///
1026 /// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added
1027 /// on an entity before the registration.
1028 ///
1029 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
1030 /// will only be overwritten if the new requirement is more specific.
1031 ///
1032 /// # Example
1033 ///
1034 /// ```
1035 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
1036 /// # use bevy_ecs::prelude::*;
1037 /// #[derive(Component)]
1038 /// struct A;
1039 ///
1040 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1041 /// struct B(usize);
1042 ///
1043 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1044 /// struct C(u32);
1045 ///
1046 /// # let mut app = App::new();
1047 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
1048 /// // Register B and C as required by A and C as required by B.
1049 /// // A requiring C directly will overwrite the indirect requirement through B.
1050 /// app.register_required_components::<A, B>();
1051 /// app.register_required_components_with::<B, C>(|| C(1));
1052 /// app.register_required_components_with::<A, C>(|| C(2));
1053 ///
1054 /// // Duplicate registration! Even if the constructors were different, this would fail.
1055 /// assert!(app.try_register_required_components_with::<B, C>(|| C(1)).is_err());
1056 ///
1057 /// fn setup(mut commands: Commands) {
1058 /// // This will implicitly also insert B with its Default constructor and C
1059 /// // with the custom constructor defined by A.
1060 /// commands.spawn(A);
1061 /// }
1062 ///
1063 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
1064 /// let (a, b, c) = query.unwrap().into_inner();
1065 /// assert_eq!(b, &B(0));
1066 /// assert_eq!(c, &C(2));
1067 /// }
1068 /// # app.update();
1069 /// ```
1070 pub fn try_register_required_components_with<T: Component, R: Component>(
1071 &mut self,
1072 constructor: fn() -> R,
1073 ) -> Result<(), RequiredComponentsError> {
1074 self.world_mut()
1075 .try_register_required_components_with::<T, R>(constructor)
1076 }
1077
1078 /// Registers a component type as "disabling",
1079 /// using [default query filters](bevy_ecs::entity_disabling::DefaultQueryFilters) to exclude entities with the component from queries.
1080 ///
1081 /// # Warning
1082 ///
1083 /// As discussed in the [module docs](bevy_ecs::entity_disabling), this can have performance implications,
1084 /// as well as create interoperability issues, and should be used with caution.
1085 pub fn register_disabling_component<C: Component>(&mut self) {
1086 self.world_mut().register_disabling_component::<C>();
1087 }
1088
1089 /// Returns a reference to the main [`SubApp`]'s [`World`]. This is the same as calling
1090 /// [`app.main().world()`].
1091 ///
1092 /// [`app.main().world()`]: SubApp::world
1093 pub fn world(&self) -> &World {
1094 self.main().world()
1095 }
1096
1097 /// Returns a mutable reference to the main [`SubApp`]'s [`World`]. This is the same as calling
1098 /// [`app.main_mut().world_mut()`].
1099 ///
1100 /// [`app.main_mut().world_mut()`]: SubApp::world_mut
1101 pub fn world_mut(&mut self) -> &mut World {
1102 self.main_mut().world_mut()
1103 }
1104
1105 /// Returns a reference to the main [`SubApp`].
1106 pub fn main(&self) -> &SubApp {
1107 &self.sub_apps.main
1108 }
1109
1110 /// Returns a mutable reference to the main [`SubApp`].
1111 pub fn main_mut(&mut self) -> &mut SubApp {
1112 &mut self.sub_apps.main
1113 }
1114
1115 /// Returns a reference to the [`SubApps`] collection.
1116 pub fn sub_apps(&self) -> &SubApps {
1117 &self.sub_apps
1118 }
1119
1120 /// Returns a mutable reference to the [`SubApps`] collection.
1121 pub fn sub_apps_mut(&mut self) -> &mut SubApps {
1122 &mut self.sub_apps
1123 }
1124
1125 /// Returns a reference to the [`SubApp`] with the given label.
1126 ///
1127 /// # Panics
1128 ///
1129 /// Panics if the [`SubApp`] doesn't exist.
1130 pub fn sub_app(&self, label: impl AppLabel) -> &SubApp {
1131 let str = label.intern();
1132 self.get_sub_app(label).unwrap_or_else(|| {
1133 panic!("No sub-app with label '{:?}' exists.", str);
1134 })
1135 }
1136
1137 /// Returns a reference to the [`SubApp`] with the given label.
1138 ///
1139 /// # Panics
1140 ///
1141 /// Panics if the [`SubApp`] doesn't exist.
1142 pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut SubApp {
1143 let str = label.intern();
1144 self.get_sub_app_mut(label).unwrap_or_else(|| {
1145 panic!("No sub-app with label '{:?}' exists.", str);
1146 })
1147 }
1148
1149 /// Returns a reference to the [`SubApp`] with the given label, if it exists.
1150 pub fn get_sub_app(&self, label: impl AppLabel) -> Option<&SubApp> {
1151 self.sub_apps.sub_apps.get(&label.intern())
1152 }
1153
1154 /// Returns a mutable reference to the [`SubApp`] with the given label, if it exists.
1155 pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Option<&mut SubApp> {
1156 self.sub_apps.sub_apps.get_mut(&label.intern())
1157 }
1158
1159 /// Inserts a [`SubApp`] with the given label.
1160 pub fn insert_sub_app(&mut self, label: impl AppLabel, mut sub_app: SubApp) {
1161 if let Some(handler) = self.default_error_handler {
1162 sub_app
1163 .world_mut()
1164 .get_resource_or_insert_with(|| DefaultErrorHandler(handler));
1165 }
1166 self.sub_apps.sub_apps.insert(label.intern(), sub_app);
1167 }
1168
1169 /// Removes the [`SubApp`] with the given label, if it exists.
1170 pub fn remove_sub_app(&mut self, label: impl AppLabel) -> Option<SubApp> {
1171 self.sub_apps.sub_apps.remove(&label.intern())
1172 }
1173
1174 /// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.
1175 pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {
1176 self.sub_apps.update_subapp_by_label(label);
1177 }
1178
1179 /// Inserts a new `schedule` under the provided `label`, overwriting any existing
1180 /// schedule with the same label.
1181 pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {
1182 self.main_mut().add_schedule(schedule);
1183 self
1184 }
1185
1186 /// Initializes an empty `schedule` under the provided `label`, if it does not exist.
1187 ///
1188 /// See [`add_schedule`](Self::add_schedule) to insert an existing schedule.
1189 pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {
1190 self.main_mut().init_schedule(label);
1191 self
1192 }
1193
1194 /// Returns a reference to the [`Schedule`] with the provided `label` if it exists.
1195 pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {
1196 self.main().get_schedule(label)
1197 }
1198
1199 /// Returns a mutable reference to the [`Schedule`] with the provided `label` if it exists.
1200 pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {
1201 self.main_mut().get_schedule_mut(label)
1202 }
1203
1204 /// Runs function `f` with the [`Schedule`] associated with `label`.
1205 ///
1206 /// **Note:** This will create the schedule if it does not already exist.
1207 pub fn edit_schedule(
1208 &mut self,
1209 label: impl ScheduleLabel,
1210 f: impl FnMut(&mut Schedule),
1211 ) -> &mut Self {
1212 self.main_mut().edit_schedule(label, f);
1213 self
1214 }
1215
1216 /// Applies the provided [`ScheduleBuildSettings`] to all schedules.
1217 pub fn configure_schedules(
1218 &mut self,
1219 schedule_build_settings: ScheduleBuildSettings,
1220 ) -> &mut Self {
1221 self.main_mut().configure_schedules(schedule_build_settings);
1222 self
1223 }
1224
1225 /// When doing [ambiguity checking](ScheduleBuildSettings) this
1226 /// ignores systems that are ambiguous on [`Component`] T.
1227 ///
1228 /// This settings only applies to the main world. To apply this to other worlds call the
1229 /// [corresponding method](World::allow_ambiguous_component) on World
1230 ///
1231 /// ## Example
1232 ///
1233 /// ```
1234 /// # use bevy_app::prelude::*;
1235 /// # use bevy_ecs::prelude::*;
1236 /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
1237 /// # use bevy_utils::default;
1238 ///
1239 /// #[derive(Component)]
1240 /// struct A;
1241 ///
1242 /// // these systems are ambiguous on A
1243 /// fn system_1(_: Query<&mut A>) {}
1244 /// fn system_2(_: Query<&A>) {}
1245 ///
1246 /// let mut app = App::new();
1247 /// app.configure_schedules(ScheduleBuildSettings {
1248 /// ambiguity_detection: LogLevel::Error,
1249 /// ..default()
1250 /// });
1251 ///
1252 /// app.add_systems(Update, ( system_1, system_2 ));
1253 /// app.allow_ambiguous_component::<A>();
1254 ///
1255 /// // running the app does not error.
1256 /// app.update();
1257 /// ```
1258 pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {
1259 self.main_mut().allow_ambiguous_component::<T>();
1260 self
1261 }
1262
1263 /// When doing [ambiguity checking](ScheduleBuildSettings) this
1264 /// ignores systems that are ambiguous on [`Resource`] T.
1265 ///
1266 /// This settings only applies to the main world. To apply this to other worlds call the
1267 /// [corresponding method](World::allow_ambiguous_resource) on World
1268 ///
1269 /// ## Example
1270 ///
1271 /// ```
1272 /// # use bevy_app::prelude::*;
1273 /// # use bevy_ecs::prelude::*;
1274 /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
1275 /// # use bevy_utils::default;
1276 ///
1277 /// #[derive(Resource)]
1278 /// struct R;
1279 ///
1280 /// // these systems are ambiguous on R
1281 /// fn system_1(_: ResMut<R>) {}
1282 /// fn system_2(_: Res<R>) {}
1283 ///
1284 /// let mut app = App::new();
1285 /// app.configure_schedules(ScheduleBuildSettings {
1286 /// ambiguity_detection: LogLevel::Error,
1287 /// ..default()
1288 /// });
1289 /// app.insert_resource(R);
1290 ///
1291 /// app.add_systems(Update, ( system_1, system_2 ));
1292 /// app.allow_ambiguous_resource::<R>();
1293 ///
1294 /// // running the app does not error.
1295 /// app.update();
1296 /// ```
1297 pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {
1298 self.main_mut().allow_ambiguous_resource::<T>();
1299 self
1300 }
1301
1302 /// Suppress warnings and errors that would result from systems in these sets having ambiguities
1303 /// (conflicting access but indeterminate order) with systems in `set`.
1304 ///
1305 /// When possible, do this directly in the `.add_systems(Update, a.ambiguous_with(b))` call.
1306 /// However, sometimes two independent plugins `A` and `B` are reported as ambiguous, which you
1307 /// can only suppress as the consumer of both.
1308 #[track_caller]
1309 pub fn ignore_ambiguity<M1, M2, S1, S2>(
1310 &mut self,
1311 schedule: impl ScheduleLabel,
1312 a: S1,
1313 b: S2,
1314 ) -> &mut Self
1315 where
1316 S1: IntoSystemSet<M1>,
1317 S2: IntoSystemSet<M2>,
1318 {
1319 self.main_mut().ignore_ambiguity(schedule, a, b);
1320 self
1321 }
1322
1323 /// Attempts to determine if an [`AppExit`] was raised since the last update.
1324 ///
1325 /// Will attempt to return the first [`Error`](AppExit::Error) it encounters.
1326 /// This should be called after every [`update()`](App::update) otherwise you risk
1327 /// dropping possible [`AppExit`] events.
1328 pub fn should_exit(&self) -> Option<AppExit> {
1329 let mut reader = MessageCursor::default();
1330
1331 let messages = self.world().get_resource::<Messages<AppExit>>()?;
1332 let mut messages = reader.read(messages);
1333
1334 if messages.len() != 0 {
1335 return Some(
1336 messages
1337 .find(|exit| exit.is_error())
1338 .cloned()
1339 .unwrap_or(AppExit::Success),
1340 );
1341 }
1342
1343 None
1344 }
1345
1346 /// Spawns an [`Observer`] entity, which will watch for and respond to the given event.
1347 ///
1348 /// `observer` can be any system whose first parameter is [`On`].
1349 ///
1350 /// # Examples
1351 ///
1352 /// ```rust
1353 /// # use bevy_app::prelude::*;
1354 /// # use bevy_ecs::prelude::*;
1355 /// # use bevy_utils::default;
1356 /// #
1357 /// # let mut app = App::new();
1358 /// #
1359 /// # #[derive(Event)]
1360 /// # struct Party {
1361 /// # friends_allowed: bool,
1362 /// # };
1363 /// #
1364 /// # #[derive(EntityEvent)]
1365 /// # struct Invite {
1366 /// # entity: Entity,
1367 /// # }
1368 /// #
1369 /// # #[derive(Component)]
1370 /// # struct Friend;
1371 /// #
1372 ///
1373 /// app.add_observer(|event: On<Party>, friends: Query<Entity, With<Friend>>, mut commands: Commands| {
1374 /// if event.friends_allowed {
1375 /// for entity in friends.iter() {
1376 /// commands.trigger(Invite { entity } );
1377 /// }
1378 /// }
1379 /// });
1380 /// ```
1381 pub fn add_observer<E: Event, B: Bundle, M>(
1382 &mut self,
1383 observer: impl IntoObserverSystem<E, B, M>,
1384 ) -> &mut Self {
1385 self.world_mut().add_observer(observer);
1386 self
1387 }
1388
1389 /// Gets the error handler to set for new supapps.
1390 ///
1391 /// Note that the error handler of existing subapps may differ.
1392 pub fn get_error_handler(&self) -> Option<ErrorHandler> {
1393 self.default_error_handler
1394 }
1395
1396 /// Set the [default error handler] for the all subapps (including the main one and future ones)
1397 /// that do not have one.
1398 ///
1399 /// May only be called once and should be set by the application, not by libraries.
1400 ///
1401 /// The handler will be called when an error is produced and not otherwise handled.
1402 ///
1403 /// # Panics
1404 /// Panics if called multiple times.
1405 ///
1406 /// # Example
1407 /// ```
1408 /// # use bevy_app::*;
1409 /// # use bevy_ecs::error::warn;
1410 /// # fn MyPlugins(_: &mut App) {}
1411 /// App::new()
1412 /// .set_error_handler(warn)
1413 /// .add_plugins(MyPlugins)
1414 /// .run();
1415 /// ```
1416 ///
1417 /// [default error handler]: bevy_ecs::error::DefaultErrorHandler
1418 pub fn set_error_handler(&mut self, handler: ErrorHandler) -> &mut Self {
1419 assert!(
1420 self.default_error_handler.is_none(),
1421 "`set_error_handler` called multiple times on same `App`"
1422 );
1423 self.default_error_handler = Some(handler);
1424 for sub_app in self.sub_apps.iter_mut() {
1425 sub_app
1426 .world_mut()
1427 .get_resource_or_insert_with(|| DefaultErrorHandler(handler));
1428 }
1429 self
1430 }
1431}
1432
1433// Used for doing hokey pokey in finish and cleanup
1434pub(crate) struct HokeyPokey;
1435impl Plugin for HokeyPokey {
1436 fn build(&self, _: &mut App) {}
1437}
1438
1439type RunnerFn = Box<dyn FnOnce(App) -> AppExit>;
1440
1441fn run_once(mut app: App) -> AppExit {
1442 while app.plugins_state() == PluginsState::Adding {
1443 #[cfg(not(all(target_arch = "wasm32", feature = "web")))]
1444 bevy_tasks::tick_global_task_pools_on_main_thread();
1445 }
1446 app.finish();
1447 app.cleanup();
1448
1449 app.update();
1450
1451 app.should_exit().unwrap_or(AppExit::Success)
1452}
1453
1454/// A [`Message`] that indicates the [`App`] should exit. If one or more of these are present at the end of an update,
1455/// the [runner](App::set_runner) will end and ([maybe](App::run)) return control to the caller.
1456///
1457/// This message can be used to detect when an exit is requested. Make sure that systems listening
1458/// for this message run before the current update ends.
1459///
1460/// # Portability
1461/// This type is roughly meant to map to a standard definition of a process exit code (0 means success, not 0 means error). Due to portability concerns
1462/// (see [`ExitCode`](https://doc.rust-lang.org/std/process/struct.ExitCode.html) and [`process::exit`](https://doc.rust-lang.org/std/process/fn.exit.html#))
1463/// we only allow error codes between 1 and [255](u8::MAX).
1464#[derive(Message, Debug, Clone, Default, PartialEq, Eq)]
1465pub enum AppExit {
1466 /// [`App`] exited without any problems.
1467 #[default]
1468 Success,
1469 /// The [`App`] experienced an unhandleable error.
1470 /// Holds the exit code we expect our app to return.
1471 Error(NonZero<u8>),
1472}
1473
1474impl AppExit {
1475 /// Creates a [`AppExit::Error`] with an error code of 1.
1476 #[must_use]
1477 pub const fn error() -> Self {
1478 Self::Error(NonZero::<u8>::MIN)
1479 }
1480
1481 /// Returns `true` if `self` is a [`AppExit::Success`].
1482 #[must_use]
1483 pub const fn is_success(&self) -> bool {
1484 matches!(self, AppExit::Success)
1485 }
1486
1487 /// Returns `true` if `self` is a [`AppExit::Error`].
1488 #[must_use]
1489 pub const fn is_error(&self) -> bool {
1490 matches!(self, AppExit::Error(_))
1491 }
1492
1493 /// Creates a [`AppExit`] from a code.
1494 ///
1495 /// When `code` is 0 a [`AppExit::Success`] is constructed otherwise a
1496 /// [`AppExit::Error`] is constructed.
1497 #[must_use]
1498 pub const fn from_code(code: u8) -> Self {
1499 match NonZero::<u8>::new(code) {
1500 Some(code) => Self::Error(code),
1501 None => Self::Success,
1502 }
1503 }
1504}
1505
1506impl From<u8> for AppExit {
1507 fn from(value: u8) -> Self {
1508 Self::from_code(value)
1509 }
1510}
1511
1512#[cfg(feature = "std")]
1513impl Termination for AppExit {
1514 fn report(self) -> ExitCode {
1515 match self {
1516 AppExit::Success => ExitCode::SUCCESS,
1517 // We leave logging an error to our users
1518 AppExit::Error(value) => ExitCode::from(value.get()),
1519 }
1520 }
1521}
1522
1523#[cfg(test)]
1524mod tests {
1525 use core::marker::PhantomData;
1526 use std::sync::Mutex;
1527
1528 use bevy_ecs::{
1529 change_detection::{DetectChanges, ResMut},
1530 component::Component,
1531 entity::Entity,
1532 lifecycle::RemovedComponents,
1533 message::{Message, MessageWriter, Messages},
1534 query::With,
1535 resource::Resource,
1536 schedule::{IntoScheduleConfigs, ScheduleLabel},
1537 system::{Commands, Query},
1538 world::{FromWorld, World},
1539 };
1540
1541 use crate::{App, AppExit, Plugin, SubApp, Update};
1542
1543 struct PluginA;
1544 impl Plugin for PluginA {
1545 fn build(&self, _app: &mut App) {}
1546 }
1547 struct PluginB;
1548 impl Plugin for PluginB {
1549 fn build(&self, _app: &mut App) {}
1550 }
1551 struct PluginC<T>(T);
1552 impl<T: Send + Sync + 'static> Plugin for PluginC<T> {
1553 fn build(&self, _app: &mut App) {}
1554 }
1555 struct PluginD;
1556 impl Plugin for PluginD {
1557 fn build(&self, _app: &mut App) {}
1558 fn is_unique(&self) -> bool {
1559 false
1560 }
1561 }
1562
1563 struct PluginE;
1564
1565 impl Plugin for PluginE {
1566 fn build(&self, _app: &mut App) {}
1567
1568 fn finish(&self, app: &mut App) {
1569 if app.is_plugin_added::<PluginA>() {
1570 panic!("cannot run if PluginA is already registered");
1571 }
1572 }
1573 }
1574
1575 struct PluginF;
1576
1577 impl Plugin for PluginF {
1578 fn build(&self, _app: &mut App) {}
1579
1580 fn finish(&self, app: &mut App) {
1581 // Ensure other plugins are available during finish
1582 assert_eq!(
1583 app.is_plugin_added::<PluginA>(),
1584 !app.get_added_plugins::<PluginA>().is_empty(),
1585 );
1586 }
1587
1588 fn cleanup(&self, app: &mut App) {
1589 // Ensure other plugins are available during finish
1590 assert_eq!(
1591 app.is_plugin_added::<PluginA>(),
1592 !app.get_added_plugins::<PluginA>().is_empty(),
1593 );
1594 }
1595 }
1596
1597 struct PluginG;
1598
1599 impl Plugin for PluginG {
1600 fn build(&self, _app: &mut App) {}
1601
1602 fn finish(&self, app: &mut App) {
1603 app.add_plugins(PluginB);
1604 }
1605 }
1606
1607 #[test]
1608 fn can_add_two_plugins() {
1609 App::new().add_plugins((PluginA, PluginB));
1610 }
1611
1612 #[test]
1613 #[should_panic]
1614 fn cant_add_twice_the_same_plugin() {
1615 App::new().add_plugins((PluginA, PluginA));
1616 }
1617
1618 #[test]
1619 fn can_add_twice_the_same_plugin_with_different_type_param() {
1620 App::new().add_plugins((PluginC(0), PluginC(true)));
1621 }
1622
1623 #[test]
1624 fn can_add_twice_the_same_plugin_not_unique() {
1625 App::new().add_plugins((PluginD, PluginD));
1626 }
1627
1628 #[test]
1629 #[should_panic]
1630 fn cant_call_app_run_from_plugin_build() {
1631 struct PluginRun;
1632 struct InnerPlugin;
1633 impl Plugin for InnerPlugin {
1634 fn build(&self, _: &mut App) {}
1635 }
1636 impl Plugin for PluginRun {
1637 fn build(&self, app: &mut App) {
1638 app.add_plugins(InnerPlugin).run();
1639 }
1640 }
1641 App::new().add_plugins(PluginRun);
1642 }
1643
1644 #[derive(ScheduleLabel, Hash, Clone, PartialEq, Eq, Debug)]
1645 struct EnterMainMenu;
1646
1647 #[derive(Component)]
1648 struct A;
1649
1650 fn bar(mut commands: Commands) {
1651 commands.spawn(A);
1652 }
1653
1654 fn foo(mut commands: Commands) {
1655 commands.spawn(A);
1656 }
1657
1658 #[test]
1659 fn add_systems_should_create_schedule_if_it_does_not_exist() {
1660 let mut app = App::new();
1661 app.add_systems(EnterMainMenu, (foo, bar));
1662
1663 app.world_mut().run_schedule(EnterMainMenu);
1664 assert_eq!(app.world_mut().query::<&A>().query(app.world()).count(), 2);
1665 }
1666
1667 #[test]
1668 #[should_panic]
1669 fn test_is_plugin_added_works_during_finish() {
1670 let mut app = App::new();
1671 app.add_plugins(PluginA);
1672 app.add_plugins(PluginE);
1673 app.finish();
1674 }
1675
1676 #[test]
1677 fn test_get_added_plugins_works_during_finish_and_cleanup() {
1678 let mut app = App::new();
1679 app.add_plugins(PluginA);
1680 app.add_plugins(PluginF);
1681 app.finish();
1682 }
1683
1684 #[test]
1685 fn test_adding_plugin_works_during_finish() {
1686 let mut app = App::new();
1687 app.add_plugins(PluginA);
1688 app.add_plugins(PluginG);
1689 app.finish();
1690 assert_eq!(
1691 app.main().plugin_registry[0].name(),
1692 "bevy_app::main_schedule::MainSchedulePlugin"
1693 );
1694 assert_eq!(
1695 app.main().plugin_registry[1].name(),
1696 "bevy_app::app::tests::PluginA"
1697 );
1698 assert_eq!(
1699 app.main().plugin_registry[2].name(),
1700 "bevy_app::app::tests::PluginG"
1701 );
1702 // PluginG adds PluginB during finish
1703 assert_eq!(
1704 app.main().plugin_registry[3].name(),
1705 "bevy_app::app::tests::PluginB"
1706 );
1707 }
1708
1709 #[test]
1710 fn test_derive_app_label() {
1711 use super::AppLabel;
1712
1713 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1714 struct UnitLabel;
1715
1716 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1717 struct TupleLabel(u32, u32);
1718
1719 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1720 struct StructLabel {
1721 a: u32,
1722 b: u32,
1723 }
1724
1725 #[expect(
1726 dead_code,
1727 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1728 )]
1729 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1730 struct EmptyTupleLabel();
1731
1732 #[expect(
1733 dead_code,
1734 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1735 )]
1736 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1737 struct EmptyStructLabel {}
1738
1739 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1740 enum EnumLabel {
1741 #[default]
1742 Unit,
1743 Tuple(u32, u32),
1744 Struct {
1745 a: u32,
1746 b: u32,
1747 },
1748 }
1749
1750 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1751 struct GenericLabel<T>(PhantomData<T>);
1752
1753 assert_eq!(UnitLabel.intern(), UnitLabel.intern());
1754 assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());
1755 assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());
1756 assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());
1757 assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());
1758
1759 assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());
1760 assert_eq!(
1761 EnumLabel::Tuple(0, 0).intern(),
1762 EnumLabel::Tuple(0, 0).intern()
1763 );
1764 assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());
1765 assert_ne!(
1766 EnumLabel::Tuple(0, 0).intern(),
1767 EnumLabel::Tuple(0, 1).intern()
1768 );
1769 assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());
1770 assert_ne!(
1771 TupleLabel(0, 0).intern(),
1772 StructLabel { a: 0, b: 0 }.intern()
1773 );
1774 assert_ne!(
1775 EnumLabel::Tuple(0, 0).intern(),
1776 EnumLabel::Struct { a: 0, b: 0 }.intern()
1777 );
1778
1779 assert_eq!(
1780 StructLabel { a: 0, b: 0 }.intern(),
1781 StructLabel { a: 0, b: 0 }.intern()
1782 );
1783 assert_eq!(
1784 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1785 EnumLabel::Struct { a: 0, b: 0 }.intern()
1786 );
1787 assert_ne!(
1788 StructLabel { a: 0, b: 0 }.intern(),
1789 StructLabel { a: 0, b: 1 }.intern()
1790 );
1791 assert_ne!(
1792 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1793 EnumLabel::Struct { a: 0, b: 1 }.intern()
1794 );
1795 assert_ne!(
1796 StructLabel { a: 0, b: 0 }.intern(),
1797 EnumLabel::Struct { a: 0, b: 0 }.intern()
1798 );
1799 assert_ne!(
1800 StructLabel { a: 0, b: 0 }.intern(),
1801 EnumLabel::Struct { a: 0, b: 0 }.intern()
1802 );
1803 assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);
1804 assert_ne!(
1805 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1806 EnumLabel::Unit.intern()
1807 );
1808
1809 assert_eq!(
1810 GenericLabel::<u32>(PhantomData).intern(),
1811 GenericLabel::<u32>(PhantomData).intern()
1812 );
1813 assert_ne!(
1814 GenericLabel::<u32>(PhantomData).intern(),
1815 GenericLabel::<u64>(PhantomData).intern()
1816 );
1817 }
1818
1819 #[test]
1820 fn test_update_clears_trackers_once() {
1821 #[derive(Component, Copy, Clone)]
1822 struct Foo;
1823
1824 let mut app = App::new();
1825 app.world_mut().spawn_batch(core::iter::repeat_n(Foo, 5));
1826
1827 fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {
1828 if let Some(e) = foos.iter().next() {
1829 commands.entity(e).despawn();
1830 };
1831 }
1832 fn check_despawns(mut removed_foos: RemovedComponents<Foo>) {
1833 let mut despawn_count = 0;
1834 for _ in removed_foos.read() {
1835 despawn_count += 1;
1836 }
1837
1838 assert_eq!(despawn_count, 2);
1839 }
1840
1841 app.add_systems(Update, despawn_one_foo);
1842 app.update(); // Frame 0
1843 app.update(); // Frame 1
1844 app.add_systems(Update, check_despawns.after(despawn_one_foo));
1845 app.update(); // Should see despawns from frames 1 & 2, but not frame 0
1846 }
1847
1848 #[test]
1849 fn test_extract_sees_changes() {
1850 use super::AppLabel;
1851
1852 #[derive(AppLabel, Clone, Copy, Hash, PartialEq, Eq, Debug)]
1853 struct MySubApp;
1854
1855 #[derive(Resource)]
1856 struct Foo(usize);
1857
1858 let mut app = App::new();
1859 app.world_mut().insert_resource(Foo(0));
1860 app.add_systems(Update, |mut foo: ResMut<Foo>| {
1861 foo.0 += 1;
1862 });
1863
1864 let mut sub_app = SubApp::new();
1865 sub_app.set_extract(|main_world, _sub_world| {
1866 assert!(main_world.get_resource_ref::<Foo>().unwrap().is_changed());
1867 });
1868
1869 app.insert_sub_app(MySubApp, sub_app);
1870
1871 app.update();
1872 }
1873
1874 #[test]
1875 fn runner_returns_correct_exit_code() {
1876 fn raise_exits(mut exits: MessageWriter<AppExit>) {
1877 // Exit codes chosen by a fair dice roll.
1878 // Unlikely to overlap with default values.
1879 exits.write(AppExit::Success);
1880 exits.write(AppExit::from_code(4));
1881 exits.write(AppExit::from_code(73));
1882 }
1883
1884 let exit = App::new().add_systems(Update, raise_exits).run();
1885
1886 assert_eq!(exit, AppExit::from_code(4));
1887 }
1888
1889 /// Custom runners should be in charge of when `app::update` gets called as they may need to
1890 /// coordinate some state.
1891 /// bug: <https://github.com/bevyengine/bevy/issues/10385>
1892 /// fix: <https://github.com/bevyengine/bevy/pull/10389>
1893 #[test]
1894 fn regression_test_10385() {
1895 use super::{Res, Resource};
1896 use crate::PreUpdate;
1897
1898 #[derive(Resource)]
1899 struct MyState {}
1900
1901 fn my_runner(mut app: App) -> AppExit {
1902 let my_state = MyState {};
1903 app.world_mut().insert_resource(my_state);
1904
1905 for _ in 0..5 {
1906 app.update();
1907 }
1908
1909 AppExit::Success
1910 }
1911
1912 fn my_system(_: Res<MyState>) {
1913 // access state during app update
1914 }
1915
1916 // Should not panic due to missing resource
1917 App::new()
1918 .set_runner(my_runner)
1919 .add_systems(PreUpdate, my_system)
1920 .run();
1921 }
1922
1923 #[test]
1924 fn app_exit_size() {
1925 // There wont be many of them so the size isn't an issue but
1926 // it's nice they're so small let's keep it that way.
1927 assert_eq!(size_of::<AppExit>(), size_of::<u8>());
1928 }
1929
1930 #[test]
1931 fn initializing_resources_from_world() {
1932 #[derive(Resource)]
1933 struct TestResource;
1934 impl FromWorld for TestResource {
1935 fn from_world(_world: &mut World) -> Self {
1936 TestResource
1937 }
1938 }
1939
1940 #[derive(Resource)]
1941 struct NonSendTestResource {
1942 _marker: PhantomData<Mutex<()>>,
1943 }
1944 impl FromWorld for NonSendTestResource {
1945 fn from_world(_world: &mut World) -> Self {
1946 NonSendTestResource {
1947 _marker: PhantomData,
1948 }
1949 }
1950 }
1951
1952 App::new()
1953 .init_non_send_resource::<NonSendTestResource>()
1954 .init_resource::<TestResource>();
1955 }
1956
1957 #[test]
1958 /// Plugin should not be considered inserted while it's being built
1959 ///
1960 /// bug: <https://github.com/bevyengine/bevy/issues/13815>
1961 fn plugin_should_not_be_added_during_build_time() {
1962 pub struct Foo;
1963
1964 impl Plugin for Foo {
1965 fn build(&self, app: &mut App) {
1966 assert!(!app.is_plugin_added::<Self>());
1967 }
1968 }
1969
1970 App::new().add_plugins(Foo);
1971 }
1972 #[test]
1973 fn events_should_be_updated_once_per_update() {
1974 #[derive(Message, Clone)]
1975 struct TestMessage;
1976
1977 let mut app = App::new();
1978 app.add_message::<TestMessage>();
1979
1980 // Starts empty
1981 let test_messages = app.world().resource::<Messages<TestMessage>>();
1982 assert_eq!(test_messages.len(), 0);
1983 assert_eq!(test_messages.iter_current_update_messages().count(), 0);
1984 app.update();
1985
1986 // Sending one event
1987 app.world_mut().write_message(TestMessage);
1988
1989 let test_events = app.world().resource::<Messages<TestMessage>>();
1990 assert_eq!(test_events.len(), 1);
1991 assert_eq!(test_events.iter_current_update_messages().count(), 1);
1992 app.update();
1993
1994 // Sending two events on the next frame
1995 app.world_mut().write_message(TestMessage);
1996 app.world_mut().write_message(TestMessage);
1997
1998 let test_events = app.world().resource::<Messages<TestMessage>>();
1999 assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3
2000 assert_eq!(test_events.iter_current_update_messages().count(), 2);
2001 app.update();
2002
2003 // Sending zero events
2004 let test_events = app.world().resource::<Messages<TestMessage>>();
2005 assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2
2006 assert_eq!(test_events.iter_current_update_messages().count(), 0);
2007 }
2008}