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