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::{FromType, Reflect, TypeData, 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 identify an [`App`].
40 #[diagnostic::on_unimplemented(
41 note = "consider annotating `{Self}` with `#[derive(AppLabel)]`"
42 )]
43 AppLabel,
44 APP_LABEL_INTERNER
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) resource into the app, overwriting any existing data
491 /// of the same type.
492 #[deprecated(since = "0.19.0", note = "use App::insert_non_send")]
493 pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {
494 self.insert_non_send(resource)
495 }
496
497 /// Inserts the [`!Send`](Send) data into the app, overwriting any existing data
498 /// of the same type.
499 ///
500 /// There is also an [`init_non_send`](Self::init_non_send) for [`!Send`](Send) data
501 /// that implement [`Default`]
502 ///
503 /// # Examples
504 ///
505 /// ```
506 /// # use bevy_app::prelude::*;
507 /// # use bevy_ecs::prelude::*;
508 /// #
509 /// struct MyCounter {
510 /// counter: usize,
511 /// }
512 ///
513 /// App::new()
514 /// .insert_non_send(MyCounter { counter: 0 });
515 /// ```
516 pub fn insert_non_send<R: 'static>(&mut self, resource: R) -> &mut Self {
517 self.world_mut().insert_non_send(resource);
518 self
519 }
520
521 /// Inserts the [`!Send`](Send) resource into the app if there is no existing instance of `R`.
522 #[deprecated(since = "0.19.0", note = "use App::init_non_send")]
523 pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {
524 self.init_non_send::<R>()
525 }
526
527 /// Inserts the [`!Send`](Send) data into the app if there is no existing instance of `R`.
528 ///
529 /// `R` must implement [`FromWorld`].
530 /// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and
531 /// initialize the [`Resource`] with [`Default::default`].
532 pub fn init_non_send<R: 'static + FromWorld>(&mut self) -> &mut Self {
533 self.world_mut().init_non_send::<R>();
534 self
535 }
536
537 pub(crate) fn add_boxed_plugin(
538 &mut self,
539 plugin: Box<dyn Plugin>,
540 ) -> Result<&mut Self, AppError> {
541 debug!("added plugin: {}", plugin.name());
542 if plugin.is_unique() && self.main_mut().plugin_names.contains(plugin.name()) {
543 Err(AppError::DuplicatePlugin {
544 plugin_name: plugin.name().to_string(),
545 })?;
546 }
547
548 // Reserve position in the plugin registry. If the plugin adds more plugins,
549 // they'll all end up in insertion order.
550 let index = self.main().plugin_registry.len();
551 self.main_mut()
552 .plugin_registry
553 .push(Box::new(PlaceholderPlugin));
554
555 self.main_mut().plugin_build_depth += 1;
556
557 #[cfg(feature = "trace")]
558 let _plugin_build_span = info_span!("plugin build", plugin = plugin.name()).entered();
559
560 let f = AssertUnwindSafe(|| plugin.build(self));
561
562 #[cfg(feature = "std")]
563 let result = catch_unwind(f);
564
565 #[cfg(not(feature = "std"))]
566 f();
567
568 self.main_mut()
569 .plugin_names
570 .insert(plugin.name().to_string());
571 self.main_mut().plugin_build_depth -= 1;
572
573 #[cfg(feature = "std")]
574 if let Err(payload) = result {
575 resume_unwind(payload);
576 }
577
578 self.main_mut().plugin_registry[index] = plugin;
579 Ok(self)
580 }
581
582 /// Returns `true` if the [`Plugin`] has already been added.
583 pub fn is_plugin_added<T>(&self) -> bool
584 where
585 T: Plugin,
586 {
587 self.main().is_plugin_added::<T>()
588 }
589
590 /// Returns a vector of references to all plugins of type `T` that have been added.
591 ///
592 /// This can be used to read the settings of any existing plugins.
593 /// This vector will be empty if no plugins of that type have been added.
594 /// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector.
595 ///
596 /// ```
597 /// # use bevy_app::prelude::*;
598 /// # #[derive(Default)]
599 /// # struct ImagePlugin {
600 /// # default_sampler: bool,
601 /// # }
602 /// # impl Plugin for ImagePlugin {
603 /// # fn build(&self, app: &mut App) {}
604 /// # }
605 /// # let mut app = App::new();
606 /// # app.add_plugins(ImagePlugin::default());
607 /// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;
608 /// ```
609 pub fn get_added_plugins<T>(&self) -> Vec<&T>
610 where
611 T: Plugin,
612 {
613 self.main().get_added_plugins::<T>()
614 }
615
616 /// Installs a [`Plugin`] collection.
617 ///
618 /// Bevy prioritizes modularity as a core principle. **All** engine features are implemented
619 /// as plugins, even the complex ones like rendering.
620 ///
621 /// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].
622 ///
623 /// There are built-in [`PluginGroup`]s that provide core engine functionality.
624 /// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`.
625 ///
626 /// To customize the plugins in the group (reorder, disable a plugin, add a new plugin
627 /// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group,
628 /// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder).
629 ///
630 /// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and
631 /// [`PluginGroup`]s. See [`Plugins`] for more details.
632 ///
633 /// ## Examples
634 /// ```
635 /// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins};
636 /// #
637 /// # // Dummies created to avoid using `bevy_log`,
638 /// # // which pulls in too many dependencies and breaks rust-analyzer
639 /// # pub struct LogPlugin;
640 /// # impl Plugin for LogPlugin {
641 /// # fn build(&self, app: &mut App) {}
642 /// # }
643 /// App::new()
644 /// .add_plugins(MinimalPlugins);
645 /// App::new()
646 /// .add_plugins((MinimalPlugins, LogPlugin));
647 /// ```
648 ///
649 /// # Panics
650 ///
651 /// Panics if one of the plugins had already been added to the application.
652 ///
653 /// [`PluginGroup`]:super::PluginGroup
654 #[track_caller]
655 pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {
656 if matches!(
657 self.plugins_state(),
658 PluginsState::Cleaned | PluginsState::Finished
659 ) {
660 panic!(
661 "Plugins cannot be added after App::cleanup() or App::finish() has been called."
662 );
663 }
664 plugins.add_to_app(self);
665 self
666 }
667
668 /// Registers the type `T` in the [`AppTypeRegistry`] resource,
669 /// adding reflect data as specified in the [`Reflect`] derive:
670 /// ```ignore (No serde "derive" feature)
671 /// #[derive(Component, Serialize, Deserialize, Reflect)]
672 /// #[reflect(Component, Serialize, Deserialize)] // will register ReflectComponent, ReflectSerialize, ReflectDeserialize
673 /// ```
674 ///
675 /// See [`bevy_reflect::TypeRegistry::register`] for more information.
676 #[cfg(feature = "bevy_reflect")]
677 pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
678 self.main_mut().register_type::<T>();
679 self
680 }
681
682 /// Associates type data `D` with type `T` in the [`AppTypeRegistry`] resource.
683 ///
684 /// Most of the time [`register_type`](Self::register_type) can be used instead to register a
685 /// type you derived [`Reflect`] for. However, in cases where you want to
686 /// add a piece of type data that was not included in the list of `#[reflect(...)]` type data in
687 /// the derive, or where the type is generic and cannot register e.g. `ReflectSerialize`
688 /// unconditionally without knowing the specific type parameters, this method can be used to
689 /// insert additional type data.
690 ///
691 /// # Example
692 /// ```
693 /// use bevy_app::App;
694 /// use bevy_reflect::{ReflectSerialize, ReflectDeserialize};
695 ///
696 /// App::new()
697 /// .register_type::<Option<String>>()
698 /// .register_type_data::<Option<String>, ReflectSerialize>()
699 /// .register_type_data::<Option<String>, ReflectDeserialize>();
700 /// ```
701 ///
702 /// See [`bevy_reflect::TypeRegistry::register_type_data`].
703 #[cfg(feature = "bevy_reflect")]
704 pub fn register_type_data<T: Reflect + TypePath, D: TypeData + FromType<T>>(
705 &mut self,
706 ) -> &mut Self {
707 self.main_mut().register_type_data::<T, D>();
708 self
709 }
710
711 /// Registers a fallible conversion from type T to U with the reflection
712 /// system.
713 ///
714 /// The supplied closure is expected to produce a value of type U, given an
715 /// instance of type T. If the conversion fails, the closure should return
716 /// the input value, wrapped in an `Err` variant.
717 ///
718 /// # Example
719 /// ```
720 /// use bevy_app::App;
721 ///
722 /// App::new()
723 /// .register_type::<i32>()
724 /// .register_type::<String>()
725 /// .register_type_conversion::<i32, String, _>(|n| Ok(n.to_string()));
726 /// ```
727 ///
728 /// See [`bevy_reflect::TypeRegistry::register_type_conversion`].
729 #[cfg(feature = "bevy_reflect")]
730 pub fn register_type_conversion<T, U, F>(&mut self, function: F) -> &mut Self
731 where
732 T: Reflect + TypePath,
733 U: Reflect + TypePath,
734 F: Fn(T) -> Result<U, T> + Clone + Send + Sync + 'static,
735 {
736 self.main_mut().register_type_conversion(function);
737 self
738 }
739
740 /// Given types T and U, where `U: From<T>`, registers that conversion with
741 /// the reflection system.
742 ///
743 /// # Example
744 /// ```
745 /// use bevy_app::App;
746 ///
747 /// App::new()
748 /// .register_type::<u8>()
749 /// .register_type::<u32>()
750 /// .register_into_type_conversion::<u8, u32>();
751 /// ```
752 ///
753 /// See [`bevy_reflect::TypeRegistry::register_into_type_conversion`].
754 #[cfg(feature = "bevy_reflect")]
755 pub fn register_into_type_conversion<T, U>(&mut self) -> &mut Self
756 where
757 T: Reflect + TypePath,
758 U: Reflect + TypePath + From<T>,
759 {
760 self.main_mut().register_into_type_conversion::<T, U>();
761 self
762 }
763
764 /// Registers the given function into the [`AppFunctionRegistry`] resource.
765 ///
766 /// The given function will internally be stored as a [`DynamicFunction`]
767 /// and mapped according to its [name].
768 ///
769 /// Because the function must have a name,
770 /// anonymous functions (e.g. `|a: i32, b: i32| { a + b }`) and closures must instead
771 /// be registered using [`register_function_with_name`] or converted to a [`DynamicFunction`]
772 /// and named using [`DynamicFunction::with_name`].
773 /// Failure to do so will result in a panic.
774 ///
775 /// Only types that implement [`IntoFunction`] may be registered via this method.
776 ///
777 /// See [`FunctionRegistry::register`] for more information.
778 ///
779 /// # Panics
780 ///
781 /// Panics if a function has already been registered with the given name
782 /// or if the function is missing a name (such as when it is an anonymous function).
783 ///
784 /// # Examples
785 ///
786 /// ```
787 /// use bevy_app::App;
788 ///
789 /// fn add(a: i32, b: i32) -> i32 {
790 /// a + b
791 /// }
792 ///
793 /// App::new().register_function(add);
794 /// ```
795 ///
796 /// Functions cannot be registered more than once.
797 ///
798 /// ```should_panic
799 /// use bevy_app::App;
800 ///
801 /// fn add(a: i32, b: i32) -> i32 {
802 /// a + b
803 /// }
804 ///
805 /// App::new()
806 /// .register_function(add)
807 /// // Panic! A function has already been registered with the name "my_function"
808 /// .register_function(add);
809 /// ```
810 ///
811 /// Anonymous functions and closures should be registered using [`register_function_with_name`] or given a name using [`DynamicFunction::with_name`].
812 ///
813 /// ```should_panic
814 /// use bevy_app::App;
815 ///
816 /// // Panic! Anonymous functions cannot be registered using `register_function`
817 /// App::new().register_function(|a: i32, b: i32| a + b);
818 /// ```
819 ///
820 /// [`register_function_with_name`]: Self::register_function_with_name
821 /// [`DynamicFunction`]: bevy_reflect::func::DynamicFunction
822 /// [name]: bevy_reflect::func::FunctionInfo::name
823 /// [`DynamicFunction::with_name`]: bevy_reflect::func::DynamicFunction::with_name
824 /// [`IntoFunction`]: bevy_reflect::func::IntoFunction
825 /// [`FunctionRegistry::register`]: bevy_reflect::func::FunctionRegistry::register
826 #[cfg(feature = "reflect_functions")]
827 pub fn register_function<F, Marker>(&mut self, function: F) -> &mut Self
828 where
829 F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,
830 {
831 self.main_mut().register_function(function);
832 self
833 }
834
835 /// Registers the given function or closure into the [`AppFunctionRegistry`] resource using the given name.
836 ///
837 /// To avoid conflicts, it's recommended to use a unique name for the function.
838 /// This can be achieved by "namespacing" the function with a unique identifier,
839 /// such as the name of your crate.
840 ///
841 /// For example, to register a function, `add`, from a crate, `my_crate`,
842 /// you could use the name, `"my_crate::add"`.
843 ///
844 /// Another approach could be to use the [type name] of the function,
845 /// however, it should be noted that anonymous functions do _not_ have unique type names.
846 ///
847 /// For named functions (e.g. `fn add(a: i32, b: i32) -> i32 { a + b }`) where a custom name is not needed,
848 /// it's recommended to use [`register_function`] instead as the generated name is guaranteed to be unique.
849 ///
850 /// Only types that implement [`IntoFunction`] may be registered via this method.
851 ///
852 /// See [`FunctionRegistry::register_with_name`] for more information.
853 ///
854 /// # Panics
855 ///
856 /// Panics if a function has already been registered with the given name.
857 ///
858 /// # Examples
859 ///
860 /// ```
861 /// use bevy_app::App;
862 ///
863 /// fn mul(a: i32, b: i32) -> i32 {
864 /// a * b
865 /// }
866 ///
867 /// let div = |a: i32, b: i32| a / b;
868 ///
869 /// App::new()
870 /// // Registering an anonymous function with a unique name
871 /// .register_function_with_name("my_crate::add", |a: i32, b: i32| {
872 /// a + b
873 /// })
874 /// // Registering an existing function with its type name
875 /// .register_function_with_name(std::any::type_name_of_val(&mul), mul)
876 /// // Registering an existing function with a custom name
877 /// .register_function_with_name("my_crate::mul", mul)
878 /// // Be careful not to register anonymous functions with their type name.
879 /// // This code works but registers the function with a non-unique name like `foo::bar::{{closure}}`
880 /// .register_function_with_name(std::any::type_name_of_val(&div), div);
881 /// ```
882 ///
883 /// Names must be unique.
884 ///
885 /// ```should_panic
886 /// use bevy_app::App;
887 ///
888 /// fn one() {}
889 /// fn two() {}
890 ///
891 /// App::new()
892 /// .register_function_with_name("my_function", one)
893 /// // Panic! A function has already been registered with the name "my_function"
894 /// .register_function_with_name("my_function", two);
895 /// ```
896 ///
897 /// [type name]: std::any::type_name
898 /// [`register_function`]: Self::register_function
899 /// [`IntoFunction`]: bevy_reflect::func::IntoFunction
900 /// [`FunctionRegistry::register_with_name`]: bevy_reflect::func::FunctionRegistry::register_with_name
901 #[cfg(feature = "reflect_functions")]
902 pub fn register_function_with_name<F, Marker>(
903 &mut self,
904 name: impl Into<alloc::borrow::Cow<'static, str>>,
905 function: F,
906 ) -> &mut Self
907 where
908 F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,
909 {
910 self.main_mut().register_function_with_name(name, function);
911 self
912 }
913
914 /// Registers the given component `R` as a [required component] for `T`.
915 ///
916 /// When `T` is added to an entity, `R` and its own required components will also be added
917 /// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.
918 /// If a custom constructor is desired, use [`App::register_required_components_with`] instead.
919 ///
920 /// For the non-panicking version, see [`App::try_register_required_components`].
921 ///
922 /// Note that requirements must currently be registered before `T` is inserted into the world
923 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
924 ///
925 /// [required component]: Component#required-components
926 ///
927 /// # Panics
928 ///
929 /// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added
930 /// on an entity before the registration.
931 ///
932 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
933 /// will only be overwritten if the new requirement is more specific.
934 ///
935 /// # Example
936 ///
937 /// ```
938 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
939 /// # use bevy_ecs::prelude::*;
940 /// #[derive(Component)]
941 /// struct A;
942 ///
943 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
944 /// struct B(usize);
945 ///
946 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
947 /// struct C(u32);
948 ///
949 /// # let mut app = App::new();
950 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
951 /// // Register B as required by A and C as required by B.
952 /// app.register_required_components::<A, B>();
953 /// app.register_required_components::<B, C>();
954 ///
955 /// fn setup(mut commands: Commands) {
956 /// // This will implicitly also insert B and C with their Default constructors.
957 /// commands.spawn(A);
958 /// }
959 ///
960 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
961 /// let (a, b, c) = query.unwrap().into_inner();
962 /// assert_eq!(b, &B(0));
963 /// assert_eq!(c, &C(0));
964 /// }
965 /// # app.update();
966 /// ```
967 pub fn register_required_components<T: Component, R: Component + Default>(
968 &mut self,
969 ) -> &mut Self {
970 self.world_mut().register_required_components::<T, R>();
971 self
972 }
973
974 /// Registers the given component `R` as a [required component] for `T`.
975 ///
976 /// When `T` is added to an entity, `R` and its own required components will also be added
977 /// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.
978 /// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.
979 ///
980 /// For the non-panicking version, see [`App::try_register_required_components_with`].
981 ///
982 /// Note that requirements must currently be registered before `T` is inserted into the world
983 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
984 ///
985 /// [required component]: Component#required-components
986 ///
987 /// # Panics
988 ///
989 /// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added
990 /// on an entity before the registration.
991 ///
992 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
993 /// will only be overwritten if the new requirement is more specific.
994 ///
995 /// # Example
996 ///
997 /// ```
998 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
999 /// # use bevy_ecs::prelude::*;
1000 /// #[derive(Component)]
1001 /// struct A;
1002 ///
1003 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1004 /// struct B(usize);
1005 ///
1006 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1007 /// struct C(u32);
1008 ///
1009 /// # let mut app = App::new();
1010 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
1011 /// // Register B and C as required by A and C as required by B.
1012 /// // A requiring C directly will overwrite the indirect requirement through B.
1013 /// app.register_required_components::<A, B>();
1014 /// app.register_required_components_with::<B, C>(|| C(1));
1015 /// app.register_required_components_with::<A, C>(|| C(2));
1016 ///
1017 /// fn setup(mut commands: Commands) {
1018 /// // This will implicitly also insert B with its Default constructor and C
1019 /// // with the custom constructor defined by A.
1020 /// commands.spawn(A);
1021 /// }
1022 ///
1023 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
1024 /// let (a, b, c) = query.unwrap().into_inner();
1025 /// assert_eq!(b, &B(0));
1026 /// assert_eq!(c, &C(2));
1027 /// }
1028 /// # app.update();
1029 /// ```
1030 pub fn register_required_components_with<T: Component, R: Component>(
1031 &mut self,
1032 constructor: fn() -> R,
1033 ) -> &mut Self {
1034 self.world_mut()
1035 .register_required_components_with::<T, R>(constructor);
1036 self
1037 }
1038
1039 /// Tries to register the given component `R` as a [required component] for `T`.
1040 ///
1041 /// When `T` is added to an entity, `R` and its own required components will also be added
1042 /// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.
1043 /// If a custom constructor is desired, use [`App::register_required_components_with`] instead.
1044 ///
1045 /// For the panicking version, see [`App::register_required_components`].
1046 ///
1047 /// Note that requirements must currently be registered before `T` is inserted into the world
1048 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
1049 ///
1050 /// [required component]: Component#required-components
1051 ///
1052 /// # Errors
1053 ///
1054 /// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added
1055 /// on an entity before the registration.
1056 ///
1057 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
1058 /// will only be overwritten if the new requirement is more specific.
1059 ///
1060 /// # Example
1061 ///
1062 /// ```
1063 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
1064 /// # use bevy_ecs::prelude::*;
1065 /// #[derive(Component)]
1066 /// struct A;
1067 ///
1068 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1069 /// struct B(usize);
1070 ///
1071 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1072 /// struct C(u32);
1073 ///
1074 /// # let mut app = App::new();
1075 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
1076 /// // Register B as required by A and C as required by B.
1077 /// app.register_required_components::<A, B>();
1078 /// app.register_required_components::<B, C>();
1079 ///
1080 /// // Duplicate registration! This will fail.
1081 /// assert!(app.try_register_required_components::<A, B>().is_err());
1082 ///
1083 /// fn setup(mut commands: Commands) {
1084 /// // This will implicitly also insert B and C with their Default constructors.
1085 /// commands.spawn(A);
1086 /// }
1087 ///
1088 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
1089 /// let (a, b, c) = query.unwrap().into_inner();
1090 /// assert_eq!(b, &B(0));
1091 /// assert_eq!(c, &C(0));
1092 /// }
1093 /// # app.update();
1094 /// ```
1095 pub fn try_register_required_components<T: Component, R: Component + Default>(
1096 &mut self,
1097 ) -> Result<(), RequiredComponentsError> {
1098 self.world_mut().try_register_required_components::<T, R>()
1099 }
1100
1101 /// Tries to register the given component `R` as a [required component] for `T`.
1102 ///
1103 /// When `T` is added to an entity, `R` and its own required components will also be added
1104 /// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.
1105 /// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.
1106 ///
1107 /// For the panicking version, see [`App::register_required_components_with`].
1108 ///
1109 /// Note that requirements must currently be registered before `T` is inserted into the world
1110 /// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.
1111 ///
1112 /// [required component]: Component#required-components
1113 ///
1114 /// # Errors
1115 ///
1116 /// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added
1117 /// on an entity before the registration.
1118 ///
1119 /// Indirect requirements through other components are allowed. In those cases, any existing requirements
1120 /// will only be overwritten if the new requirement is more specific.
1121 ///
1122 /// # Example
1123 ///
1124 /// ```
1125 /// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};
1126 /// # use bevy_ecs::prelude::*;
1127 /// #[derive(Component)]
1128 /// struct A;
1129 ///
1130 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1131 /// struct B(usize);
1132 ///
1133 /// #[derive(Component, Default, PartialEq, Eq, Debug)]
1134 /// struct C(u32);
1135 ///
1136 /// # let mut app = App::new();
1137 /// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);
1138 /// // Register B and C as required by A and C as required by B.
1139 /// // A requiring C directly will overwrite the indirect requirement through B.
1140 /// app.register_required_components::<A, B>();
1141 /// app.register_required_components_with::<B, C>(|| C(1));
1142 /// app.register_required_components_with::<A, C>(|| C(2));
1143 ///
1144 /// // Duplicate registration! Even if the constructors were different, this would fail.
1145 /// assert!(app.try_register_required_components_with::<B, C>(|| C(1)).is_err());
1146 ///
1147 /// fn setup(mut commands: Commands) {
1148 /// // This will implicitly also insert B with its Default constructor and C
1149 /// // with the custom constructor defined by A.
1150 /// commands.spawn(A);
1151 /// }
1152 ///
1153 /// fn validate(query: Option<Single<(&A, &B, &C)>>) {
1154 /// let (a, b, c) = query.unwrap().into_inner();
1155 /// assert_eq!(b, &B(0));
1156 /// assert_eq!(c, &C(2));
1157 /// }
1158 /// # app.update();
1159 /// ```
1160 pub fn try_register_required_components_with<T: Component, R: Component>(
1161 &mut self,
1162 constructor: fn() -> R,
1163 ) -> Result<(), RequiredComponentsError> {
1164 self.world_mut()
1165 .try_register_required_components_with::<T, R>(constructor)
1166 }
1167
1168 /// Registers a component type as "disabling",
1169 /// using [default query filters](bevy_ecs::entity_disabling::DefaultQueryFilters) to exclude entities with the component from queries.
1170 ///
1171 /// # Warning
1172 ///
1173 /// As discussed in the [module docs](bevy_ecs::entity_disabling), this can have performance implications,
1174 /// as well as create interoperability issues, and should be used with caution.
1175 pub fn register_disabling_component<C: Component>(&mut self) {
1176 self.world_mut().register_disabling_component::<C>();
1177 }
1178
1179 /// Returns a reference to the main [`SubApp`]'s [`World`]. This is the same as calling
1180 /// [`app.main().world()`].
1181 ///
1182 /// [`app.main().world()`]: SubApp::world
1183 pub fn world(&self) -> &World {
1184 self.main().world()
1185 }
1186
1187 /// Returns a mutable reference to the main [`SubApp`]'s [`World`]. This is the same as calling
1188 /// [`app.main_mut().world_mut()`].
1189 ///
1190 /// [`app.main_mut().world_mut()`]: SubApp::world_mut
1191 pub fn world_mut(&mut self) -> &mut World {
1192 self.main_mut().world_mut()
1193 }
1194
1195 /// Returns a reference to the main [`SubApp`].
1196 pub fn main(&self) -> &SubApp {
1197 &self.sub_apps.main
1198 }
1199
1200 /// Returns a mutable reference to the main [`SubApp`].
1201 pub fn main_mut(&mut self) -> &mut SubApp {
1202 &mut self.sub_apps.main
1203 }
1204
1205 /// Returns a reference to the [`SubApps`] collection.
1206 pub fn sub_apps(&self) -> &SubApps {
1207 &self.sub_apps
1208 }
1209
1210 /// Returns a mutable reference to the [`SubApps`] collection.
1211 pub fn sub_apps_mut(&mut self) -> &mut SubApps {
1212 &mut self.sub_apps
1213 }
1214
1215 /// Returns a reference to the [`SubApp`] with the given label.
1216 ///
1217 /// # Panics
1218 ///
1219 /// Panics if the [`SubApp`] doesn't exist.
1220 pub fn sub_app(&self, label: impl AppLabel) -> &SubApp {
1221 let str = label.intern();
1222 self.get_sub_app(label).unwrap_or_else(|| {
1223 panic!("No sub-app with label '{:?}' exists.", str);
1224 })
1225 }
1226
1227 /// Returns a reference to the [`SubApp`] with the given label.
1228 ///
1229 /// # Panics
1230 ///
1231 /// Panics if the [`SubApp`] doesn't exist.
1232 pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut SubApp {
1233 let str = label.intern();
1234 self.get_sub_app_mut(label).unwrap_or_else(|| {
1235 panic!("No sub-app with label '{:?}' exists.", str);
1236 })
1237 }
1238
1239 /// Returns a reference to the [`SubApp`] with the given label, if it exists.
1240 pub fn get_sub_app(&self, label: impl AppLabel) -> Option<&SubApp> {
1241 self.sub_apps.sub_apps.get(&label.intern())
1242 }
1243
1244 /// Returns a mutable reference to the [`SubApp`] with the given label, if it exists.
1245 pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Option<&mut SubApp> {
1246 self.sub_apps.sub_apps.get_mut(&label.intern())
1247 }
1248
1249 /// Inserts a [`SubApp`] with the given label.
1250 pub fn insert_sub_app(&mut self, label: impl AppLabel, mut sub_app: SubApp) {
1251 if let Some(handler) = self.fallback_error_handler {
1252 sub_app
1253 .world_mut()
1254 .get_resource_or_insert_with(|| FallbackErrorHandler(handler));
1255 }
1256 self.sub_apps.sub_apps.insert(label.intern(), sub_app);
1257 }
1258
1259 /// Removes the [`SubApp`] with the given label, if it exists.
1260 pub fn remove_sub_app(&mut self, label: impl AppLabel) -> Option<SubApp> {
1261 self.sub_apps.sub_apps.remove(&label.intern())
1262 }
1263
1264 /// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.
1265 pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {
1266 self.sub_apps.update_subapp_by_label(label);
1267 }
1268
1269 /// Inserts a new `schedule` under the provided `label`, overwriting any existing
1270 /// schedule with the same label.
1271 pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {
1272 self.main_mut().add_schedule(schedule);
1273 self
1274 }
1275
1276 /// Initializes an empty `schedule` under the provided `label`, if it does not exist.
1277 ///
1278 /// See [`add_schedule`](Self::add_schedule) to insert an existing schedule.
1279 pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {
1280 self.main_mut().init_schedule(label);
1281 self
1282 }
1283
1284 /// Returns a reference to the [`Schedule`] with the provided `label` if it exists.
1285 pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {
1286 self.main().get_schedule(label)
1287 }
1288
1289 /// Returns a mutable reference to the [`Schedule`] with the provided `label` if it exists.
1290 pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {
1291 self.main_mut().get_schedule_mut(label)
1292 }
1293
1294 /// Runs function `f` with the [`Schedule`] associated with `label`.
1295 ///
1296 /// **Note:** This will create the schedule if it does not already exist.
1297 pub fn edit_schedule(
1298 &mut self,
1299 label: impl ScheduleLabel,
1300 f: impl FnMut(&mut Schedule),
1301 ) -> &mut Self {
1302 self.main_mut().edit_schedule(label, f);
1303 self
1304 }
1305
1306 /// Applies the provided [`ScheduleBuildSettings`] to all schedules.
1307 ///
1308 /// This mutates all currently present schedules, but does not apply to any custom schedules
1309 /// that might be added in the future.
1310 pub fn configure_schedules(
1311 &mut self,
1312 schedule_build_settings: ScheduleBuildSettings,
1313 ) -> &mut Self {
1314 self.main_mut().configure_schedules(schedule_build_settings);
1315 self
1316 }
1317
1318 /// When doing [ambiguity checking](ScheduleBuildSettings) this
1319 /// ignores systems that are ambiguous on [`Component`] T.
1320 ///
1321 /// This settings only applies to the main world. To apply this to other worlds call the
1322 /// [corresponding method](World::allow_ambiguous_component) on World
1323 ///
1324 /// ## Example
1325 ///
1326 /// ```
1327 /// # use bevy_app::prelude::*;
1328 /// # use bevy_ecs::prelude::*;
1329 /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
1330 /// # use bevy_utils::default;
1331 ///
1332 /// #[derive(Component)]
1333 /// struct A;
1334 ///
1335 /// // these systems are ambiguous on A
1336 /// fn system_1(_: Query<&mut A>) {}
1337 /// fn system_2(_: Query<&A>) {}
1338 ///
1339 /// let mut app = App::new();
1340 /// app.configure_schedules(ScheduleBuildSettings {
1341 /// ambiguity_detection: LogLevel::Error,
1342 /// ..default()
1343 /// });
1344 ///
1345 /// app.add_systems(Update, ( system_1, system_2 ));
1346 /// app.allow_ambiguous_component::<A>();
1347 ///
1348 /// // running the app does not error.
1349 /// app.update();
1350 /// ```
1351 pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {
1352 self.main_mut().allow_ambiguous_component::<T>();
1353 self
1354 }
1355
1356 /// When doing [ambiguity checking](ScheduleBuildSettings) this
1357 /// ignores systems that are ambiguous on [`Resource`] T.
1358 ///
1359 /// This settings only applies to the main world. To apply this to other worlds call the
1360 /// [corresponding method](World::allow_ambiguous_resource) on World
1361 ///
1362 /// ## Example
1363 ///
1364 /// ```
1365 /// # use bevy_app::prelude::*;
1366 /// # use bevy_ecs::prelude::*;
1367 /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
1368 /// # use bevy_utils::default;
1369 ///
1370 /// #[derive(Resource)]
1371 /// struct R;
1372 ///
1373 /// // these systems are ambiguous on R
1374 /// fn system_1(_: ResMut<R>) {}
1375 /// fn system_2(_: Res<R>) {}
1376 ///
1377 /// let mut app = App::new();
1378 /// app.configure_schedules(ScheduleBuildSettings {
1379 /// ambiguity_detection: LogLevel::Error,
1380 /// ..default()
1381 /// });
1382 /// app.insert_resource(R);
1383 ///
1384 /// app.add_systems(Update, ( system_1, system_2 ));
1385 /// app.allow_ambiguous_resource::<R>();
1386 ///
1387 /// // running the app does not error.
1388 /// app.update();
1389 /// ```
1390 pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {
1391 self.main_mut().allow_ambiguous_resource::<T>();
1392 self
1393 }
1394
1395 /// Suppress warnings and errors that would result from systems in these sets having ambiguities
1396 /// (conflicting access but indeterminate order) with systems in `set`.
1397 ///
1398 /// When possible, do this directly in the `.add_systems(Update, a.ambiguous_with(b))` call.
1399 /// However, sometimes two independent plugins `A` and `B` are reported as ambiguous, which you
1400 /// can only suppress as the consumer of both.
1401 #[track_caller]
1402 pub fn ignore_ambiguity<M1, M2, S1, S2>(
1403 &mut self,
1404 schedule: impl ScheduleLabel,
1405 a: S1,
1406 b: S2,
1407 ) -> &mut Self
1408 where
1409 S1: IntoSystemSet<M1>,
1410 S2: IntoSystemSet<M2>,
1411 {
1412 self.main_mut().ignore_ambiguity(schedule, a, b);
1413 self
1414 }
1415
1416 /// Attempts to determine if an [`AppExit`] was raised since the last update.
1417 ///
1418 /// Will attempt to return the first [`Error`](AppExit::Error) it encounters.
1419 /// This should be called after every [`update()`](App::update) otherwise you risk
1420 /// dropping possible [`AppExit`] events.
1421 pub fn should_exit(&self) -> Option<AppExit> {
1422 let mut reader = MessageCursor::default();
1423
1424 let messages = self.world().get_resource::<Messages<AppExit>>()?;
1425 let mut messages = reader.read(messages);
1426
1427 if messages.len() != 0 {
1428 return Some(
1429 messages
1430 .find(|exit| exit.is_error())
1431 .cloned()
1432 .unwrap_or(AppExit::Success),
1433 );
1434 }
1435
1436 None
1437 }
1438
1439 /// Spawns an [`Observer`] entity, which will watch for and respond to the given event.
1440 ///
1441 /// `observer` can be any system whose first parameter is [`On`].
1442 ///
1443 /// # Examples
1444 ///
1445 /// ```rust
1446 /// # use bevy_app::prelude::*;
1447 /// # use bevy_ecs::prelude::*;
1448 /// # use bevy_utils::default;
1449 /// #
1450 /// # let mut app = App::new();
1451 /// #
1452 /// # #[derive(Event)]
1453 /// # struct Party {
1454 /// # friends_allowed: bool,
1455 /// # };
1456 /// #
1457 /// # #[derive(EntityEvent)]
1458 /// # struct Invite {
1459 /// # entity: Entity,
1460 /// # }
1461 /// #
1462 /// # #[derive(Component)]
1463 /// # struct Friend;
1464 /// #
1465 ///
1466 /// app.add_observer(|event: On<Party>, friends: Query<Entity, With<Friend>>, mut commands: Commands| {
1467 /// if event.friends_allowed {
1468 /// for entity in friends.iter() {
1469 /// commands.trigger(Invite { entity } );
1470 /// }
1471 /// }
1472 /// });
1473 /// ```
1474 pub fn add_observer<M>(&mut self, observer: impl IntoObserver<M>) -> &mut Self {
1475 self.world_mut().add_observer(observer);
1476 self
1477 }
1478
1479 /// Gets the error handler to set for new supapps.
1480 ///
1481 /// Note that the error handler of existing subapps may differ.
1482 pub fn get_error_handler(&self) -> Option<ErrorHandler> {
1483 self.fallback_error_handler
1484 }
1485
1486 /// Set the [fallback error handler] for the all subapps (including the main one and future ones)
1487 /// that do not have one.
1488 ///
1489 /// May only be called once and should be set by the application, not by libraries.
1490 ///
1491 /// The handler will be called when an error is produced and not otherwise handled.
1492 ///
1493 /// # Panics
1494 /// Panics if called multiple times.
1495 ///
1496 /// # Example
1497 /// ```
1498 /// # use bevy_app::*;
1499 /// # use bevy_ecs::error::warn;
1500 /// # fn MyPlugins(_: &mut App) {}
1501 /// App::new()
1502 /// .set_error_handler(warn)
1503 /// .add_plugins(MyPlugins)
1504 /// .run();
1505 /// ```
1506 ///
1507 /// [fallback error handler]: bevy_ecs::error::FallbackErrorHandler
1508 pub fn set_error_handler(&mut self, handler: ErrorHandler) -> &mut Self {
1509 assert!(
1510 self.fallback_error_handler.is_none(),
1511 "`set_error_handler` called multiple times on same `App`"
1512 );
1513 self.fallback_error_handler = Some(handler);
1514 for sub_app in self.sub_apps.iter_mut() {
1515 sub_app
1516 .world_mut()
1517 .get_resource_or_insert_with(|| FallbackErrorHandler(handler));
1518 }
1519 self
1520 }
1521}
1522
1523// Used for doing hokey pokey in finish and cleanup
1524pub(crate) struct HokeyPokey;
1525impl Plugin for HokeyPokey {
1526 fn build(&self, _: &mut App) {}
1527}
1528
1529type RunnerFn = Box<dyn FnOnce(App) -> AppExit>;
1530
1531fn run_once(mut app: App) -> AppExit {
1532 while app.plugins_state() == PluginsState::Adding {
1533 #[cfg(not(all(target_arch = "wasm32", feature = "web")))]
1534 bevy_tasks::tick_global_task_pools_on_main_thread();
1535 }
1536 app.finish();
1537 app.cleanup();
1538
1539 app.update();
1540
1541 app.should_exit().unwrap_or(AppExit::Success)
1542}
1543
1544/// A [`Message`] that indicates the [`App`] should exit. If one or more of these are present at the end of an update,
1545/// the [runner](App::set_runner) will end and ([maybe](App::run)) return control to the caller.
1546///
1547/// This message can be used to detect when an exit is requested. Make sure that systems listening
1548/// for this message run before the current update ends.
1549///
1550/// # Portability
1551/// 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
1552/// (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#))
1553/// we only allow error codes between 1 and [255](u8::MAX).
1554#[derive(Message, Debug, Clone, Default, PartialEq, Eq)]
1555#[cfg_attr(
1556 feature = "bevy_reflect",
1557 derive(Reflect),
1558 reflect(Debug, PartialEq, Clone, Message)
1559)]
1560pub enum AppExit {
1561 /// [`App`] exited without any problems.
1562 #[default]
1563 Success,
1564 /// The [`App`] experienced an unhandleable error.
1565 /// Holds the exit code we expect our app to return.
1566 Error(NonZero<u8>),
1567}
1568
1569impl AppExit {
1570 /// Creates a [`AppExit::Error`] with an error code of 1.
1571 #[must_use]
1572 pub const fn error() -> Self {
1573 Self::Error(NonZero::<u8>::MIN)
1574 }
1575
1576 /// Returns `true` if `self` is a [`AppExit::Success`].
1577 #[must_use]
1578 pub const fn is_success(&self) -> bool {
1579 matches!(self, AppExit::Success)
1580 }
1581
1582 /// Returns `true` if `self` is a [`AppExit::Error`].
1583 #[must_use]
1584 pub const fn is_error(&self) -> bool {
1585 matches!(self, AppExit::Error(_))
1586 }
1587
1588 /// Creates a [`AppExit`] from a code.
1589 ///
1590 /// When `code` is 0 a [`AppExit::Success`] is constructed otherwise a
1591 /// [`AppExit::Error`] is constructed.
1592 #[must_use]
1593 pub const fn from_code(code: u8) -> Self {
1594 match NonZero::<u8>::new(code) {
1595 Some(code) => Self::Error(code),
1596 None => Self::Success,
1597 }
1598 }
1599}
1600
1601impl From<u8> for AppExit {
1602 fn from(value: u8) -> Self {
1603 Self::from_code(value)
1604 }
1605}
1606
1607#[cfg(feature = "std")]
1608impl Termination for AppExit {
1609 fn report(self) -> ExitCode {
1610 match self {
1611 AppExit::Success => ExitCode::SUCCESS,
1612 // We leave logging an error to our users
1613 AppExit::Error(value) => ExitCode::from(value.get()),
1614 }
1615 }
1616}
1617
1618#[cfg(test)]
1619mod tests {
1620 use core::marker::PhantomData;
1621 use std::sync::Mutex;
1622
1623 use bevy_ecs::{
1624 change_detection::{DetectChanges, ResMut},
1625 component::Component,
1626 entity::Entity,
1627 lifecycle::RemovedComponents,
1628 message::{Message, MessageWriter, Messages},
1629 query::With,
1630 resource::Resource,
1631 schedule::{IntoScheduleConfigs, ScheduleLabel},
1632 system::{Commands, Query},
1633 world::{FromWorld, World},
1634 };
1635
1636 use crate::{App, AppExit, Plugin, SubApp, Update};
1637
1638 struct PluginA;
1639 impl Plugin for PluginA {
1640 fn build(&self, _app: &mut App) {}
1641 }
1642 struct PluginB;
1643 impl Plugin for PluginB {
1644 fn build(&self, _app: &mut App) {}
1645 }
1646 struct PluginC<T>(T);
1647 impl<T: Send + Sync + 'static> Plugin for PluginC<T> {
1648 fn build(&self, _app: &mut App) {}
1649 }
1650 struct PluginD;
1651 impl Plugin for PluginD {
1652 fn build(&self, _app: &mut App) {}
1653 fn is_unique(&self) -> bool {
1654 false
1655 }
1656 }
1657
1658 struct PluginE;
1659
1660 impl Plugin for PluginE {
1661 fn build(&self, _app: &mut App) {}
1662
1663 fn finish(&self, app: &mut App) {
1664 if app.is_plugin_added::<PluginA>() {
1665 panic!("cannot run if PluginA is already registered");
1666 }
1667 }
1668 }
1669
1670 struct PluginF;
1671
1672 impl Plugin for PluginF {
1673 fn build(&self, _app: &mut App) {}
1674
1675 fn finish(&self, app: &mut App) {
1676 // Ensure other plugins are available during finish
1677 assert_eq!(
1678 app.is_plugin_added::<PluginA>(),
1679 !app.get_added_plugins::<PluginA>().is_empty(),
1680 );
1681 }
1682
1683 fn cleanup(&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
1692 struct PluginG;
1693
1694 impl Plugin for PluginG {
1695 fn build(&self, _app: &mut App) {}
1696
1697 fn finish(&self, app: &mut App) {
1698 app.add_plugins(PluginB);
1699 }
1700 }
1701
1702 #[test]
1703 fn can_add_two_plugins() {
1704 App::new().add_plugins((PluginA, PluginB));
1705 }
1706
1707 #[test]
1708 #[should_panic]
1709 fn cant_add_twice_the_same_plugin() {
1710 App::new().add_plugins((PluginA, PluginA));
1711 }
1712
1713 #[test]
1714 fn can_add_twice_the_same_plugin_with_different_type_param() {
1715 App::new().add_plugins((PluginC(0), PluginC(true)));
1716 }
1717
1718 #[test]
1719 fn can_add_twice_the_same_plugin_not_unique() {
1720 App::new().add_plugins((PluginD, PluginD));
1721 }
1722
1723 #[test]
1724 #[should_panic]
1725 fn cant_call_app_run_from_plugin_build() {
1726 struct PluginRun;
1727 struct InnerPlugin;
1728 impl Plugin for InnerPlugin {
1729 fn build(&self, _: &mut App) {}
1730 }
1731 impl Plugin for PluginRun {
1732 fn build(&self, app: &mut App) {
1733 app.add_plugins(InnerPlugin).run();
1734 }
1735 }
1736 App::new().add_plugins(PluginRun);
1737 }
1738
1739 #[derive(ScheduleLabel, Hash, Clone, PartialEq, Eq, Debug)]
1740 struct EnterMainMenu;
1741
1742 #[derive(Component)]
1743 struct A;
1744
1745 fn bar(mut commands: Commands) {
1746 commands.spawn(A);
1747 }
1748
1749 fn foo(mut commands: Commands) {
1750 commands.spawn(A);
1751 }
1752
1753 #[test]
1754 fn add_systems_should_create_schedule_if_it_does_not_exist() {
1755 let mut app = App::new();
1756 app.add_systems(EnterMainMenu, (foo, bar));
1757
1758 app.world_mut().run_schedule(EnterMainMenu);
1759 assert_eq!(app.world_mut().query::<&A>().query(app.world()).count(), 2);
1760 }
1761
1762 #[test]
1763 #[should_panic]
1764 fn test_is_plugin_added_works_during_finish() {
1765 let mut app = App::new();
1766 app.add_plugins(PluginA);
1767 app.add_plugins(PluginE);
1768 app.finish();
1769 }
1770
1771 #[test]
1772 fn test_get_added_plugins_works_during_finish_and_cleanup() {
1773 let mut app = App::new();
1774 app.add_plugins(PluginA);
1775 app.add_plugins(PluginF);
1776 app.finish();
1777 }
1778
1779 #[test]
1780 fn test_adding_plugin_works_during_finish() {
1781 let mut app = App::new();
1782 app.add_plugins(PluginA);
1783 app.add_plugins(PluginG);
1784 app.finish();
1785 assert_eq!(
1786 app.main().plugin_registry[0].name(),
1787 "bevy_app::main_schedule::MainSchedulePlugin"
1788 );
1789 assert_eq!(
1790 app.main().plugin_registry[1].name(),
1791 "bevy_app::app::tests::PluginA"
1792 );
1793 assert_eq!(
1794 app.main().plugin_registry[2].name(),
1795 "bevy_app::app::tests::PluginG"
1796 );
1797 // PluginG adds PluginB during finish
1798 assert_eq!(
1799 app.main().plugin_registry[3].name(),
1800 "bevy_app::app::tests::PluginB"
1801 );
1802 }
1803
1804 #[test]
1805 fn test_derive_app_label() {
1806 use super::AppLabel;
1807
1808 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1809 struct UnitLabel;
1810
1811 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1812 struct TupleLabel(u32, u32);
1813
1814 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1815 struct StructLabel {
1816 a: u32,
1817 b: u32,
1818 }
1819
1820 #[expect(
1821 dead_code,
1822 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1823 )]
1824 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1825 struct EmptyTupleLabel();
1826
1827 #[expect(
1828 dead_code,
1829 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1830 )]
1831 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1832 struct EmptyStructLabel {}
1833
1834 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1835 enum EnumLabel {
1836 #[default]
1837 Unit,
1838 Tuple(u32, u32),
1839 Struct {
1840 a: u32,
1841 b: u32,
1842 },
1843 }
1844
1845 #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1846 struct GenericLabel<T>(PhantomData<T>);
1847
1848 assert_eq!(UnitLabel.intern(), UnitLabel.intern());
1849 assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());
1850 assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());
1851 assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());
1852 assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());
1853
1854 assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());
1855 assert_eq!(
1856 EnumLabel::Tuple(0, 0).intern(),
1857 EnumLabel::Tuple(0, 0).intern()
1858 );
1859 assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());
1860 assert_ne!(
1861 EnumLabel::Tuple(0, 0).intern(),
1862 EnumLabel::Tuple(0, 1).intern()
1863 );
1864 assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());
1865 assert_ne!(
1866 TupleLabel(0, 0).intern(),
1867 StructLabel { a: 0, b: 0 }.intern()
1868 );
1869 assert_ne!(
1870 EnumLabel::Tuple(0, 0).intern(),
1871 EnumLabel::Struct { a: 0, b: 0 }.intern()
1872 );
1873
1874 assert_eq!(
1875 StructLabel { a: 0, b: 0 }.intern(),
1876 StructLabel { a: 0, b: 0 }.intern()
1877 );
1878 assert_eq!(
1879 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1880 EnumLabel::Struct { a: 0, b: 0 }.intern()
1881 );
1882 assert_ne!(
1883 StructLabel { a: 0, b: 0 }.intern(),
1884 StructLabel { a: 0, b: 1 }.intern()
1885 );
1886 assert_ne!(
1887 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1888 EnumLabel::Struct { a: 0, b: 1 }.intern()
1889 );
1890 assert_ne!(
1891 StructLabel { a: 0, b: 0 }.intern(),
1892 EnumLabel::Struct { a: 0, b: 0 }.intern()
1893 );
1894 assert_ne!(
1895 StructLabel { a: 0, b: 0 }.intern(),
1896 EnumLabel::Struct { a: 0, b: 0 }.intern()
1897 );
1898 assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);
1899 assert_ne!(
1900 EnumLabel::Struct { a: 0, b: 0 }.intern(),
1901 EnumLabel::Unit.intern()
1902 );
1903
1904 assert_eq!(
1905 GenericLabel::<u32>(PhantomData).intern(),
1906 GenericLabel::<u32>(PhantomData).intern()
1907 );
1908 assert_ne!(
1909 GenericLabel::<u32>(PhantomData).intern(),
1910 GenericLabel::<u64>(PhantomData).intern()
1911 );
1912 }
1913
1914 #[test]
1915 fn test_update_clears_trackers_once() {
1916 #[derive(Component, Copy, Clone)]
1917 struct Foo;
1918
1919 let mut app = App::new();
1920 app.world_mut().spawn_batch(core::iter::repeat_n(Foo, 5));
1921
1922 fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {
1923 if let Some(e) = foos.iter().next() {
1924 commands.entity(e).despawn();
1925 };
1926 }
1927 fn check_despawns(mut removed_foos: RemovedComponents<Foo>) {
1928 let mut despawn_count = 0;
1929 for _ in removed_foos.read() {
1930 despawn_count += 1;
1931 }
1932
1933 assert_eq!(despawn_count, 2);
1934 }
1935
1936 app.add_systems(Update, despawn_one_foo);
1937 app.update(); // Frame 0
1938 app.update(); // Frame 1
1939 app.add_systems(Update, check_despawns.after(despawn_one_foo));
1940 app.update(); // Should see despawns from frames 1 & 2, but not frame 0
1941 }
1942
1943 #[test]
1944 fn test_extract_sees_changes() {
1945 use super::AppLabel;
1946
1947 #[derive(AppLabel, Clone, Copy, Hash, PartialEq, Eq, Debug)]
1948 struct MySubApp;
1949
1950 #[derive(Resource)]
1951 struct Foo(usize);
1952
1953 let mut app = App::new();
1954 app.world_mut().insert_resource(Foo(0));
1955 app.add_systems(Update, |mut foo: ResMut<Foo>| {
1956 foo.0 += 1;
1957 });
1958
1959 let mut sub_app = SubApp::new();
1960 sub_app.set_extract(|main_world, _sub_world| {
1961 assert!(main_world.get_resource_ref::<Foo>().unwrap().is_changed());
1962 });
1963
1964 app.insert_sub_app(MySubApp, sub_app);
1965
1966 app.update();
1967 }
1968
1969 #[test]
1970 fn runner_returns_correct_exit_code() {
1971 fn raise_exits(mut exits: MessageWriter<AppExit>) {
1972 // Exit codes chosen by a fair dice roll.
1973 // Unlikely to overlap with default values.
1974 exits.write(AppExit::Success);
1975 exits.write(AppExit::from_code(4));
1976 exits.write(AppExit::from_code(73));
1977 }
1978
1979 let exit = App::new().add_systems(Update, raise_exits).run();
1980
1981 assert_eq!(exit, AppExit::from_code(4));
1982 }
1983
1984 /// Custom runners should be in charge of when `app::update` gets called as they may need to
1985 /// coordinate some state.
1986 /// bug: <https://github.com/bevyengine/bevy/issues/10385>
1987 /// fix: <https://github.com/bevyengine/bevy/pull/10389>
1988 #[test]
1989 fn regression_test_10385() {
1990 use super::{Res, Resource};
1991 use crate::PreUpdate;
1992
1993 #[derive(Resource)]
1994 struct MyState {}
1995
1996 fn my_runner(mut app: App) -> AppExit {
1997 let my_state = MyState {};
1998 app.world_mut().insert_resource(my_state);
1999
2000 for _ in 0..5 {
2001 app.update();
2002 }
2003
2004 AppExit::Success
2005 }
2006
2007 fn my_system(_: Res<MyState>) {
2008 // access state during app update
2009 }
2010
2011 // Should not panic due to missing resource
2012 App::new()
2013 .set_runner(my_runner)
2014 .add_systems(PreUpdate, my_system)
2015 .run();
2016 }
2017
2018 #[test]
2019 fn app_exit_size() {
2020 // There wont be many of them so the size isn't an issue but
2021 // it's nice they're so small let's keep it that way.
2022 assert_eq!(size_of::<AppExit>(), size_of::<u8>());
2023 }
2024
2025 #[test]
2026 fn initializing_resources_from_world() {
2027 #[derive(Resource)]
2028 struct TestResource;
2029 impl FromWorld for TestResource {
2030 fn from_world(_world: &mut World) -> Self {
2031 TestResource
2032 }
2033 }
2034
2035 #[derive(Resource)]
2036 struct NonSendTestResource {
2037 _marker: PhantomData<Mutex<()>>,
2038 }
2039 impl FromWorld for NonSendTestResource {
2040 fn from_world(_world: &mut World) -> Self {
2041 NonSendTestResource {
2042 _marker: PhantomData,
2043 }
2044 }
2045 }
2046
2047 App::new()
2048 .init_non_send::<NonSendTestResource>()
2049 .init_resource::<TestResource>();
2050 }
2051
2052 #[test]
2053 /// Plugin should not be considered inserted while it's being built
2054 ///
2055 /// bug: <https://github.com/bevyengine/bevy/issues/13815>
2056 fn plugin_should_not_be_added_during_build_time() {
2057 pub struct Foo;
2058
2059 impl Plugin for Foo {
2060 fn build(&self, app: &mut App) {
2061 assert!(!app.is_plugin_added::<Self>());
2062 }
2063 }
2064
2065 App::new().add_plugins(Foo);
2066 }
2067 #[test]
2068 fn events_should_be_updated_once_per_update() {
2069 #[derive(Message, Clone)]
2070 struct TestMessage;
2071
2072 let mut app = App::new();
2073 app.add_message::<TestMessage>();
2074
2075 // Starts empty
2076 let test_messages = app.world().resource::<Messages<TestMessage>>();
2077 assert_eq!(test_messages.len(), 0);
2078 assert_eq!(test_messages.iter_current_update_messages().count(), 0);
2079 app.update();
2080
2081 // Sending one event
2082 app.world_mut().write_message(TestMessage);
2083
2084 let test_events = app.world().resource::<Messages<TestMessage>>();
2085 assert_eq!(test_events.len(), 1);
2086 assert_eq!(test_events.iter_current_update_messages().count(), 1);
2087 app.update();
2088
2089 // Sending two events on the next frame
2090 app.world_mut().write_message(TestMessage);
2091 app.world_mut().write_message(TestMessage);
2092
2093 let test_events = app.world().resource::<Messages<TestMessage>>();
2094 assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3
2095 assert_eq!(test_events.iter_current_update_messages().count(), 2);
2096 app.update();
2097
2098 // Sending zero events
2099 let test_events = app.world().resource::<Messages<TestMessage>>();
2100 assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2
2101 assert_eq!(test_events.iter_current_update_messages().count(), 0);
2102 }
2103
2104 #[test]
2105 fn auto_despawn_unused_registered_systems() {
2106 let mut app = App::new();
2107
2108 fn my_system() {}
2109
2110 let handle = app.register_tracked_system(my_system);
2111 let entity = handle.entity();
2112
2113 app.update();
2114 assert!(app.world().get_entity(entity).is_ok());
2115
2116 drop(handle);
2117 app.update();
2118 assert!(app.world().get_entity(entity).is_err());
2119 }
2120}