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