bevy_app/
app.rs

1use crate::{
2    First, Main, MainSchedulePlugin, PlaceholderPlugin, Plugin, Plugins, PluginsState, SubApp,
3    SubApps,
4};
5pub use bevy_derive::AppLabel;
6use bevy_ecs::{
7    event::{event_update_system, ManualEventReader},
8    intern::Interned,
9    prelude::*,
10    schedule::{ScheduleBuildSettings, ScheduleLabel},
11    system::{IntoObserverSystem, SystemId},
12};
13#[cfg(feature = "trace")]
14use bevy_utils::tracing::info_span;
15use bevy_utils::{tracing::debug, HashMap};
16use std::{
17    fmt::Debug,
18    process::{ExitCode, Termination},
19};
20use std::{
21    num::NonZeroU8,
22    panic::{catch_unwind, resume_unwind, AssertUnwindSafe},
23};
24use thiserror::Error;
25
26bevy_ecs::define_label!(
27    /// A strongly-typed class of labels used to identify an [`App`].
28    AppLabel,
29    APP_LABEL_INTERNER
30);
31
32pub use bevy_ecs::label::DynEq;
33
34/// A shorthand for `Interned<dyn AppLabel>`.
35pub type InternedAppLabel = Interned<dyn AppLabel>;
36
37#[derive(Debug, Error)]
38pub(crate) enum AppError {
39    #[error("duplicate plugin {plugin_name:?}")]
40    DuplicatePlugin { plugin_name: String },
41}
42
43#[allow(clippy::needless_doctest_main)]
44/// [`App`] is the primary API for writing user applications. It automates the setup of a
45/// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).
46///
47/// A single [`App`] can contain multiple [`SubApp`] instances, but [`App`] methods only affect
48/// the "main" one. To access a particular [`SubApp`], use [`get_sub_app`](App::get_sub_app)
49/// or [`get_sub_app_mut`](App::get_sub_app_mut).
50///
51///
52/// # Examples
53///
54/// Here is a simple "Hello World" Bevy app:
55///
56/// ```
57/// # use bevy_app::prelude::*;
58/// # use bevy_ecs::prelude::*;
59/// #
60/// fn main() {
61///    App::new()
62///        .add_systems(Update, hello_world_system)
63///        .run();
64/// }
65///
66/// fn hello_world_system() {
67///    println!("hello world");
68/// }
69/// ```
70pub struct App {
71    pub(crate) sub_apps: SubApps,
72    /// The function that will manage the app's lifecycle.
73    ///
74    /// Bevy provides the [`WinitPlugin`] and [`ScheduleRunnerPlugin`] for windowed and headless
75    /// applications, respectively.
76    ///
77    /// [`WinitPlugin`]: https://docs.rs/bevy/latest/bevy/winit/struct.WinitPlugin.html
78    /// [`ScheduleRunnerPlugin`]: https://docs.rs/bevy/latest/bevy/app/struct.ScheduleRunnerPlugin.html
79    pub(crate) runner: RunnerFn,
80}
81
82impl Debug for App {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        write!(f, "App {{ sub_apps: ")?;
85        f.debug_map()
86            .entries(self.sub_apps.sub_apps.iter())
87            .finish()?;
88        write!(f, "}}")
89    }
90}
91
92impl Default for App {
93    fn default() -> Self {
94        let mut app = App::empty();
95        app.sub_apps.main.update_schedule = Some(Main.intern());
96
97        #[cfg(feature = "bevy_reflect")]
98        app.init_resource::<AppTypeRegistry>();
99        app.add_plugins(MainSchedulePlugin);
100        app.add_systems(
101            First,
102            event_update_system
103                .in_set(bevy_ecs::event::EventUpdates)
104                .run_if(bevy_ecs::event::event_update_condition),
105        );
106        app.add_event::<AppExit>();
107
108        app
109    }
110}
111
112impl App {
113    /// Creates a new [`App`] with some default structure to enable core engine features.
114    /// This is the preferred constructor for most use cases.
115    pub fn new() -> App {
116        App::default()
117    }
118
119    /// Creates a new empty [`App`] with minimal default configuration.
120    ///
121    /// Use this constructor if you want to customize scheduling, exit handling, cleanup, etc.
122    pub fn empty() -> App {
123        Self {
124            sub_apps: SubApps {
125                main: SubApp::new(),
126                sub_apps: HashMap::new(),
127            },
128            runner: Box::new(run_once),
129        }
130    }
131
132    /// Runs the default schedules of all sub-apps (starting with the "main" app) once.
133    pub fn update(&mut self) {
134        if self.is_building_plugins() {
135            panic!("App::update() was called while a plugin was building.");
136        }
137
138        self.sub_apps.update();
139    }
140
141    /// Runs the [`App`] by calling its [runner](Self::set_runner).
142    ///
143    /// This will (re)build the [`App`] first. For general usage, see the example on the item
144    /// level documentation.
145    ///
146    /// # Caveats
147    ///
148    /// Calls to [`App::run()`] will never return on iOS and Web.
149    ///
150    /// Headless apps can generally expect this method to return control to the caller when
151    /// it completes, but that is not the case for windowed apps. Windowed apps are typically
152    /// driven by an event loop and some platforms expect the program to terminate when the
153    /// event loop ends.
154    ///
155    /// By default, *Bevy* uses the `winit` crate for window creation.
156    ///
157    /// # Panics
158    ///
159    /// Panics if not all plugins have been built.
160    pub fn run(&mut self) -> AppExit {
161        #[cfg(feature = "trace")]
162        let _bevy_app_run_span = info_span!("bevy_app").entered();
163        if self.is_building_plugins() {
164            panic!("App::run() was called while a plugin was building.");
165        }
166
167        let runner = std::mem::replace(&mut self.runner, Box::new(run_once));
168        let app = std::mem::replace(self, App::empty());
169        (runner)(app)
170    }
171
172    /// Sets the function that will be called when the app is run.
173    ///
174    /// The runner function `f` is called only once by [`App::run`]. If the
175    /// presence of a main loop in the app is desired, it is the responsibility of the runner
176    /// function to provide it.
177    ///
178    /// The runner function is usually not set manually, but by Bevy integrated plugins
179    /// (e.g. `WinitPlugin`).
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// # use bevy_app::prelude::*;
185    /// #
186    /// fn my_runner(mut app: App) -> AppExit {
187    ///     loop {
188    ///         println!("In main loop");
189    ///         app.update();
190    ///         if let Some(exit) = app.should_exit() {
191    ///             return exit;
192    ///         }
193    ///     }
194    /// }
195    ///
196    /// App::new()
197    ///     .set_runner(my_runner);
198    /// ```
199    pub fn set_runner(&mut self, f: impl FnOnce(App) -> AppExit + 'static) -> &mut Self {
200        self.runner = Box::new(f);
201        self
202    }
203
204    /// Returns the state of all plugins. This is usually called by the event loop, but can be
205    /// useful for situations where you want to use [`App::update`].
206    // TODO: &mut self -> &self
207    #[inline]
208    pub fn plugins_state(&mut self) -> PluginsState {
209        let mut overall_plugins_state = match self.main_mut().plugins_state {
210            PluginsState::Adding => {
211                let mut state = PluginsState::Ready;
212                let plugins = std::mem::take(&mut self.main_mut().plugin_registry);
213                for plugin in &plugins {
214                    // plugins installed to main need to see all sub-apps
215                    if !plugin.ready(self) {
216                        state = PluginsState::Adding;
217                        break;
218                    }
219                }
220                self.main_mut().plugin_registry = plugins;
221                state
222            }
223            state => state,
224        };
225
226        // overall state is the earliest state of any sub-app
227        self.sub_apps.iter_mut().skip(1).for_each(|s| {
228            overall_plugins_state = overall_plugins_state.min(s.plugins_state());
229        });
230
231        overall_plugins_state
232    }
233
234    /// Runs [`Plugin::finish`] for each plugin. This is usually called by the event loop once all
235    /// plugins are ready, but can be useful for situations where you want to use [`App::update`].
236    pub fn finish(&mut self) {
237        // plugins installed to main should see all sub-apps
238        let plugins = std::mem::take(&mut self.main_mut().plugin_registry);
239        for plugin in &plugins {
240            plugin.finish(self);
241        }
242        let main = self.main_mut();
243        main.plugin_registry = plugins;
244        main.plugins_state = PluginsState::Finished;
245        self.sub_apps.iter_mut().skip(1).for_each(|s| s.finish());
246    }
247
248    /// Runs [`Plugin::cleanup`] for each plugin. This is usually called by the event loop after
249    /// [`App::finish`], but can be useful for situations where you want to use [`App::update`].
250    pub fn cleanup(&mut self) {
251        // plugins installed to main should see all sub-apps
252        let plugins = std::mem::take(&mut self.main_mut().plugin_registry);
253        for plugin in &plugins {
254            plugin.cleanup(self);
255        }
256        let main = self.main_mut();
257        main.plugin_registry = plugins;
258        main.plugins_state = PluginsState::Cleaned;
259        self.sub_apps.iter_mut().skip(1).for_each(|s| s.cleanup());
260    }
261
262    /// Returns `true` if any of the sub-apps are building plugins.
263    pub(crate) fn is_building_plugins(&self) -> bool {
264        self.sub_apps.iter().any(|s| s.is_building_plugins())
265    }
266
267    /// Adds one or more systems to the given schedule in this app's [`Schedules`].
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// # use bevy_app::prelude::*;
273    /// # use bevy_ecs::prelude::*;
274    /// #
275    /// # let mut app = App::new();
276    /// # fn system_a() {}
277    /// # fn system_b() {}
278    /// # fn system_c() {}
279    /// # fn should_run() -> bool { true }
280    /// #
281    /// app.add_systems(Update, (system_a, system_b, system_c));
282    /// app.add_systems(Update, (system_a, system_b).run_if(should_run));
283    /// ```
284    pub fn add_systems<M>(
285        &mut self,
286        schedule: impl ScheduleLabel,
287        systems: impl IntoSystemConfigs<M>,
288    ) -> &mut Self {
289        self.main_mut().add_systems(schedule, systems);
290        self
291    }
292
293    /// Registers a system and returns a [`SystemId`] so it can later be called by [`World::run_system`].
294    ///
295    /// It's possible to register the same systems more than once, they'll be stored separately.
296    ///
297    /// This is different from adding systems to a [`Schedule`] with [`App::add_systems`],
298    /// because the [`SystemId`] that is returned can be used anywhere in the [`World`] to run the associated system.
299    /// This allows for running systems in a push-based fashion.
300    /// Using a [`Schedule`] is still preferred for most cases
301    /// due to its better performance and ability to run non-conflicting systems simultaneously.
302    pub fn register_system<I: 'static, O: 'static, M, S: IntoSystem<I, O, M> + 'static>(
303        &mut self,
304        system: S,
305    ) -> SystemId<I, O> {
306        self.main_mut().register_system(system)
307    }
308
309    /// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.
310    #[track_caller]
311    pub fn configure_sets(
312        &mut self,
313        schedule: impl ScheduleLabel,
314        sets: impl IntoSystemSetConfigs,
315    ) -> &mut Self {
316        self.main_mut().configure_sets(schedule, sets);
317        self
318    }
319
320    /// Initializes `T` event handling by inserting an event queue resource ([`Events::<T>`])
321    /// and scheduling an [`event_update_system`] in [`First`](crate::First).
322    ///
323    /// See [`Events`] for information on how to define events.
324    ///
325    /// # Examples
326    ///
327    /// ```
328    /// # use bevy_app::prelude::*;
329    /// # use bevy_ecs::prelude::*;
330    /// #
331    /// # #[derive(Event)]
332    /// # struct MyEvent;
333    /// # let mut app = App::new();
334    /// #
335    /// app.add_event::<MyEvent>();
336    /// ```
337    pub fn add_event<T>(&mut self) -> &mut Self
338    where
339        T: Event,
340    {
341        self.main_mut().add_event::<T>();
342        self
343    }
344
345    /// Inserts the [`Resource`] into the app, overwriting any existing resource of the same type.
346    ///
347    /// There is also an [`init_resource`](Self::init_resource) for resources that have
348    /// [`Default`] or [`FromWorld`] implementations.
349    ///
350    /// # Examples
351    ///
352    /// ```
353    /// # use bevy_app::prelude::*;
354    /// # use bevy_ecs::prelude::*;
355    /// #
356    /// #[derive(Resource)]
357    /// struct MyCounter {
358    ///     counter: usize,
359    /// }
360    ///
361    /// App::new()
362    ///    .insert_resource(MyCounter { counter: 0 });
363    /// ```
364    pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
365        self.main_mut().insert_resource(resource);
366        self
367    }
368
369    /// Inserts the [`Resource`], initialized with its default value, into the app,
370    /// if there is no existing instance of `R`.
371    ///
372    /// `R` must implement [`FromWorld`].
373    /// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and
374    /// initialize the [`Resource`] with [`Default::default`].
375    ///
376    /// # Examples
377    ///
378    /// ```
379    /// # use bevy_app::prelude::*;
380    /// # use bevy_ecs::prelude::*;
381    /// #
382    /// #[derive(Resource)]
383    /// struct MyCounter {
384    ///     counter: usize,
385    /// }
386    ///
387    /// impl Default for MyCounter {
388    ///     fn default() -> MyCounter {
389    ///         MyCounter {
390    ///             counter: 100
391    ///         }
392    ///     }
393    /// }
394    ///
395    /// App::new()
396    ///     .init_resource::<MyCounter>();
397    /// ```
398    pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
399        self.main_mut().init_resource::<R>();
400        self
401    }
402
403    /// Inserts the [`!Send`](Send) resource into the app, overwriting any existing resource
404    /// of the same type.
405    ///
406    /// There is also an [`init_non_send_resource`](Self::init_non_send_resource) for
407    /// resources that implement [`Default`]
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// # use bevy_app::prelude::*;
413    /// # use bevy_ecs::prelude::*;
414    /// #
415    /// struct MyCounter {
416    ///     counter: usize,
417    /// }
418    ///
419    /// App::new()
420    ///     .insert_non_send_resource(MyCounter { counter: 0 });
421    /// ```
422    pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {
423        self.world_mut().insert_non_send_resource(resource);
424        self
425    }
426
427    /// Inserts the [`!Send`](Send) resource into the app if there is no existing instance of `R`.
428    ///
429    /// `R` must implement [`FromWorld`].
430    /// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and
431    /// initialize the [`Resource`] with [`Default::default`].
432    pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {
433        self.world_mut().init_non_send_resource::<R>();
434        self
435    }
436
437    pub(crate) fn add_boxed_plugin(
438        &mut self,
439        plugin: Box<dyn Plugin>,
440    ) -> Result<&mut Self, AppError> {
441        debug!("added plugin: {}", plugin.name());
442        if plugin.is_unique() && self.main_mut().plugin_names.contains(plugin.name()) {
443            Err(AppError::DuplicatePlugin {
444                plugin_name: plugin.name().to_string(),
445            })?;
446        }
447
448        // Reserve position in the plugin registry. If the plugin adds more plugins,
449        // they'll all end up in insertion order.
450        let index = self.main().plugin_registry.len();
451        self.main_mut()
452            .plugin_registry
453            .push(Box::new(PlaceholderPlugin));
454
455        self.main_mut().plugin_build_depth += 1;
456        let result = catch_unwind(AssertUnwindSafe(|| plugin.build(self)));
457        self.main_mut()
458            .plugin_names
459            .insert(plugin.name().to_string());
460        self.main_mut().plugin_build_depth -= 1;
461
462        if let Err(payload) = result {
463            resume_unwind(payload);
464        }
465
466        self.main_mut().plugin_registry[index] = plugin;
467        Ok(self)
468    }
469
470    /// Returns `true` if the [`Plugin`] has already been added.
471    pub fn is_plugin_added<T>(&self) -> bool
472    where
473        T: Plugin,
474    {
475        self.main().is_plugin_added::<T>()
476    }
477
478    /// Returns a vector of references to all plugins of type `T` that have been added.
479    ///
480    /// This can be used to read the settings of any existing plugins.
481    /// This vector will be empty if no plugins of that type have been added.
482    /// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector.
483    ///
484    /// ```
485    /// # use bevy_app::prelude::*;
486    /// # #[derive(Default)]
487    /// # struct ImagePlugin {
488    /// #    default_sampler: bool,
489    /// # }
490    /// # impl Plugin for ImagePlugin {
491    /// #    fn build(&self, app: &mut App) {}
492    /// # }
493    /// # let mut app = App::new();
494    /// # app.add_plugins(ImagePlugin::default());
495    /// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;
496    /// ```
497    pub fn get_added_plugins<T>(&self) -> Vec<&T>
498    where
499        T: Plugin,
500    {
501        self.main().get_added_plugins::<T>()
502    }
503
504    /// Installs a [`Plugin`] collection.
505    ///
506    /// Bevy prioritizes modularity as a core principle. **All** engine features are implemented
507    /// as plugins, even the complex ones like rendering.
508    ///
509    /// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].
510    ///
511    /// There are built-in [`PluginGroup`]s that provide core engine functionality.
512    /// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`.
513    ///
514    /// To customize the plugins in the group (reorder, disable a plugin, add a new plugin
515    /// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group,
516    /// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder).
517    ///
518    /// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and
519    /// [`PluginGroup`]s. See [`Plugins`] for more details.
520    ///
521    /// ## Examples
522    /// ```
523    /// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins};
524    /// #
525    /// # // Dummies created to avoid using `bevy_log`,
526    /// # // which pulls in too many dependencies and breaks rust-analyzer
527    /// # pub struct LogPlugin;
528    /// # impl Plugin for LogPlugin {
529    /// #     fn build(&self, app: &mut App) {}
530    /// # }
531    /// App::new()
532    ///     .add_plugins(MinimalPlugins);
533    /// App::new()
534    ///     .add_plugins((MinimalPlugins, LogPlugin));
535    /// ```
536    ///
537    /// # Panics
538    ///
539    /// Panics if one of the plugins had already been added to the application.
540    ///
541    /// [`PluginGroup`]:super::PluginGroup
542    #[track_caller]
543    pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {
544        if matches!(
545            self.plugins_state(),
546            PluginsState::Cleaned | PluginsState::Finished
547        ) {
548            panic!(
549                "Plugins cannot be added after App::cleanup() or App::finish() has been called."
550            );
551        }
552        plugins.add_to_app(self);
553        self
554    }
555
556    /// Registers the type `T` in the [`TypeRegistry`](bevy_reflect::TypeRegistry) resource,
557    /// adding reflect data as specified in the [`Reflect`](bevy_reflect::Reflect) derive:
558    /// ```ignore (No serde "derive" feature)
559    /// #[derive(Component, Serialize, Deserialize, Reflect)]
560    /// #[reflect(Component, Serialize, Deserialize)] // will register ReflectComponent, ReflectSerialize, ReflectDeserialize
561    /// ```
562    ///
563    /// See [`bevy_reflect::TypeRegistry::register`] for more information.
564    #[cfg(feature = "bevy_reflect")]
565    pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
566        self.main_mut().register_type::<T>();
567        self
568    }
569
570    /// Associates type data `D` with type `T` in the [`TypeRegistry`](bevy_reflect::TypeRegistry) resource.
571    ///
572    /// Most of the time [`register_type`](Self::register_type) can be used instead to register a
573    /// type you derived [`Reflect`](bevy_reflect::Reflect) for. However, in cases where you want to
574    /// add a piece of type data that was not included in the list of `#[reflect(...)]` type data in
575    /// the derive, or where the type is generic and cannot register e.g. `ReflectSerialize`
576    /// unconditionally without knowing the specific type parameters, this method can be used to
577    /// insert additional type data.
578    ///
579    /// # Example
580    /// ```
581    /// use bevy_app::App;
582    /// use bevy_reflect::{ReflectSerialize, ReflectDeserialize};
583    ///
584    /// App::new()
585    ///     .register_type::<Option<String>>()
586    ///     .register_type_data::<Option<String>, ReflectSerialize>()
587    ///     .register_type_data::<Option<String>, ReflectDeserialize>();
588    /// ```
589    ///
590    /// See [`bevy_reflect::TypeRegistry::register_type_data`].
591    #[cfg(feature = "bevy_reflect")]
592    pub fn register_type_data<
593        T: bevy_reflect::Reflect + bevy_reflect::TypePath,
594        D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,
595    >(
596        &mut self,
597    ) -> &mut Self {
598        self.main_mut().register_type_data::<T, D>();
599        self
600    }
601
602    /// Returns a reference to the [`World`].
603    pub fn world(&self) -> &World {
604        self.main().world()
605    }
606
607    /// Returns a mutable reference to the [`World`].
608    pub fn world_mut(&mut self) -> &mut World {
609        self.main_mut().world_mut()
610    }
611
612    /// Returns a reference to the main [`SubApp`].
613    pub fn main(&self) -> &SubApp {
614        &self.sub_apps.main
615    }
616
617    /// Returns a mutable reference to the main [`SubApp`].
618    pub fn main_mut(&mut self) -> &mut SubApp {
619        &mut self.sub_apps.main
620    }
621
622    /// Returns a reference to the [`SubApp`] with the given label.
623    ///
624    /// # Panics
625    ///
626    /// Panics if the [`SubApp`] doesn't exist.
627    pub fn sub_app(&self, label: impl AppLabel) -> &SubApp {
628        let str = label.intern();
629        self.get_sub_app(label).unwrap_or_else(|| {
630            panic!("No sub-app with label '{:?}' exists.", str);
631        })
632    }
633
634    /// Returns a reference to the [`SubApp`] with the given label.
635    ///
636    /// # Panics
637    ///
638    /// Panics if the [`SubApp`] doesn't exist.
639    pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut SubApp {
640        let str = label.intern();
641        self.get_sub_app_mut(label).unwrap_or_else(|| {
642            panic!("No sub-app with label '{:?}' exists.", str);
643        })
644    }
645
646    /// Returns a reference to the [`SubApp`] with the given label, if it exists.
647    pub fn get_sub_app(&self, label: impl AppLabel) -> Option<&SubApp> {
648        self.sub_apps.sub_apps.get(&label.intern())
649    }
650
651    /// Returns a mutable reference to the [`SubApp`] with the given label, if it exists.
652    pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Option<&mut SubApp> {
653        self.sub_apps.sub_apps.get_mut(&label.intern())
654    }
655
656    /// Inserts a [`SubApp`] with the given label.
657    pub fn insert_sub_app(&mut self, label: impl AppLabel, sub_app: SubApp) {
658        self.sub_apps.sub_apps.insert(label.intern(), sub_app);
659    }
660
661    /// Removes the [`SubApp`] with the given label, if it exists.
662    pub fn remove_sub_app(&mut self, label: impl AppLabel) -> Option<SubApp> {
663        self.sub_apps.sub_apps.remove(&label.intern())
664    }
665
666    /// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.
667    pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {
668        self.sub_apps.update_subapp_by_label(label);
669    }
670
671    /// Inserts a new `schedule` under the provided `label`, overwriting any existing
672    /// schedule with the same label.
673    pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {
674        self.main_mut().add_schedule(schedule);
675        self
676    }
677
678    /// Initializes an empty `schedule` under the provided `label`, if it does not exist.
679    ///
680    /// See [`add_schedule`](Self::add_schedule) to insert an existing schedule.
681    pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {
682        self.main_mut().init_schedule(label);
683        self
684    }
685
686    /// Returns a reference to the [`Schedule`] with the provided `label` if it exists.
687    pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {
688        self.main().get_schedule(label)
689    }
690
691    /// Returns a mutable reference to the [`Schedule`] with the provided `label` if it exists.
692    pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {
693        self.main_mut().get_schedule_mut(label)
694    }
695
696    /// Runs function `f` with the [`Schedule`] associated with `label`.
697    ///
698    /// **Note:** This will create the schedule if it does not already exist.
699    pub fn edit_schedule(
700        &mut self,
701        label: impl ScheduleLabel,
702        f: impl FnMut(&mut Schedule),
703    ) -> &mut Self {
704        self.main_mut().edit_schedule(label, f);
705        self
706    }
707
708    /// Applies the provided [`ScheduleBuildSettings`] to all schedules.
709    pub fn configure_schedules(
710        &mut self,
711        schedule_build_settings: ScheduleBuildSettings,
712    ) -> &mut Self {
713        self.main_mut().configure_schedules(schedule_build_settings);
714        self
715    }
716
717    /// When doing [ambiguity checking](ScheduleBuildSettings) this
718    /// ignores systems that are ambiguous on [`Component`] T.
719    ///
720    /// This settings only applies to the main world. To apply this to other worlds call the
721    /// [corresponding method](World::allow_ambiguous_component) on World
722    ///
723    /// ## Example
724    ///
725    /// ```
726    /// # use bevy_app::prelude::*;
727    /// # use bevy_ecs::prelude::*;
728    /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
729    /// # use bevy_utils::default;
730    ///
731    /// #[derive(Component)]
732    /// struct A;
733    ///
734    /// // these systems are ambiguous on A
735    /// fn system_1(_: Query<&mut A>) {}
736    /// fn system_2(_: Query<&A>) {}
737    ///
738    /// let mut app = App::new();
739    /// app.configure_schedules(ScheduleBuildSettings {
740    ///   ambiguity_detection: LogLevel::Error,
741    ///   ..default()
742    /// });
743    ///
744    /// app.add_systems(Update, ( system_1, system_2 ));
745    /// app.allow_ambiguous_component::<A>();
746    ///
747    /// // running the app does not error.
748    /// app.update();
749    /// ```
750    pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {
751        self.main_mut().allow_ambiguous_component::<T>();
752        self
753    }
754
755    /// When doing [ambiguity checking](ScheduleBuildSettings) this
756    /// ignores systems that are ambiguous on [`Resource`] T.
757    ///
758    /// This settings only applies to the main world. To apply this to other worlds call the
759    /// [corresponding method](World::allow_ambiguous_resource) on World
760    ///
761    /// ## Example
762    ///
763    /// ```
764    /// # use bevy_app::prelude::*;
765    /// # use bevy_ecs::prelude::*;
766    /// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};
767    /// # use bevy_utils::default;
768    ///
769    /// #[derive(Resource)]
770    /// struct R;
771    ///
772    /// // these systems are ambiguous on R
773    /// fn system_1(_: ResMut<R>) {}
774    /// fn system_2(_: Res<R>) {}
775    ///
776    /// let mut app = App::new();
777    /// app.configure_schedules(ScheduleBuildSettings {
778    ///   ambiguity_detection: LogLevel::Error,
779    ///   ..default()
780    /// });
781    /// app.insert_resource(R);
782    ///
783    /// app.add_systems(Update, ( system_1, system_2 ));
784    /// app.allow_ambiguous_resource::<R>();
785    ///
786    /// // running the app does not error.
787    /// app.update();
788    /// ```
789    pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {
790        self.main_mut().allow_ambiguous_resource::<T>();
791        self
792    }
793
794    /// Suppress warnings and errors that would result from systems in these sets having ambiguities
795    /// (conflicting access but indeterminate order) with systems in `set`.
796    ///
797    /// When possible, do this directly in the `.add_systems(Update, a.ambiguous_with(b))` call.
798    /// However, sometimes two independent plugins `A` and `B` are reported as ambiguous, which you
799    /// can only suppress as the consumer of both.
800    #[track_caller]
801    pub fn ignore_ambiguity<M1, M2, S1, S2>(
802        &mut self,
803        schedule: impl ScheduleLabel,
804        a: S1,
805        b: S2,
806    ) -> &mut Self
807    where
808        S1: IntoSystemSet<M1>,
809        S2: IntoSystemSet<M2>,
810    {
811        self.main_mut().ignore_ambiguity(schedule, a, b);
812        self
813    }
814
815    /// Attempts to determine if an [`AppExit`] was raised since the last update.
816    ///
817    /// Will attempt to return the first [`Error`](AppExit::Error) it encounters.
818    /// This should be called after every [`update()`](App::update) otherwise you risk
819    /// dropping possible [`AppExit`] events.
820    pub fn should_exit(&self) -> Option<AppExit> {
821        let mut reader = ManualEventReader::default();
822
823        let events = self.world().get_resource::<Events<AppExit>>()?;
824        let mut events = reader.read(events);
825
826        if events.len() != 0 {
827            return Some(
828                events
829                    .find(|exit| exit.is_error())
830                    .cloned()
831                    .unwrap_or(AppExit::Success),
832            );
833        }
834
835        None
836    }
837
838    /// Spawns an [`Observer`] entity, which will watch for and respond to the given event.
839    pub fn observe<E: Event, B: Bundle, M>(
840        &mut self,
841        observer: impl IntoObserverSystem<E, B, M>,
842    ) -> &mut Self {
843        self.world_mut().observe(observer);
844        self
845    }
846}
847
848type RunnerFn = Box<dyn FnOnce(App) -> AppExit>;
849
850fn run_once(mut app: App) -> AppExit {
851    while app.plugins_state() == PluginsState::Adding {
852        #[cfg(not(target_arch = "wasm32"))]
853        bevy_tasks::tick_global_task_pools_on_main_thread();
854    }
855    app.finish();
856    app.cleanup();
857
858    app.update();
859
860    app.should_exit().unwrap_or(AppExit::Success)
861}
862
863/// An event that indicates the [`App`] should exit. If one or more of these are present at the end of an update,
864/// the [runner](App::set_runner) will end and ([maybe](App::run)) return control to the caller.
865///
866/// This event can be used to detect when an exit is requested. Make sure that systems listening
867/// for this event run before the current update ends.
868///
869/// # Portability
870/// 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
871/// (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#))
872/// we only allow error codes between 1 and [255](u8::MAX).
873#[derive(Event, Debug, Clone, Default, PartialEq, Eq)]
874pub enum AppExit {
875    /// [`App`] exited without any problems.
876    #[default]
877    Success,
878    /// The [`App`] experienced an unhandleable error.
879    /// Holds the exit code we expect our app to return.
880    Error(NonZeroU8),
881}
882
883impl AppExit {
884    /// Creates a [`AppExit::Error`] with a error code of 1.
885    #[must_use]
886    pub const fn error() -> Self {
887        Self::Error(NonZeroU8::MIN)
888    }
889
890    /// Returns `true` if `self` is a [`AppExit::Success`].
891    #[must_use]
892    pub const fn is_success(&self) -> bool {
893        matches!(self, AppExit::Success)
894    }
895
896    /// Returns `true` if `self` is a [`AppExit::Error`].
897    #[must_use]
898    pub const fn is_error(&self) -> bool {
899        matches!(self, AppExit::Error(_))
900    }
901
902    /// Creates a [`AppExit`] from a code.
903    ///
904    /// When `code` is 0 a [`AppExit::Success`] is constructed otherwise a
905    /// [`AppExit::Error`] is constructed.
906    #[must_use]
907    pub const fn from_code(code: u8) -> Self {
908        match NonZeroU8::new(code) {
909            Some(code) => Self::Error(code),
910            None => Self::Success,
911        }
912    }
913}
914
915impl From<u8> for AppExit {
916    #[must_use]
917    fn from(value: u8) -> Self {
918        Self::from_code(value)
919    }
920}
921
922impl Termination for AppExit {
923    fn report(self) -> std::process::ExitCode {
924        match self {
925            AppExit::Success => ExitCode::SUCCESS,
926            // We leave logging an error to our users
927            AppExit::Error(value) => ExitCode::from(value.get()),
928        }
929    }
930}
931
932#[cfg(test)]
933mod tests {
934    use std::{iter, marker::PhantomData, mem, sync::Mutex};
935
936    use bevy_ecs::{
937        change_detection::{DetectChanges, ResMut},
938        component::Component,
939        entity::Entity,
940        event::{Event, EventWriter, Events},
941        query::With,
942        removal_detection::RemovedComponents,
943        schedule::{IntoSystemConfigs, ScheduleLabel},
944        system::{Commands, Query, Resource},
945        world::{FromWorld, World},
946    };
947
948    use crate::{App, AppExit, Plugin, SubApp, Update};
949
950    struct PluginA;
951    impl Plugin for PluginA {
952        fn build(&self, _app: &mut App) {}
953    }
954    struct PluginB;
955    impl Plugin for PluginB {
956        fn build(&self, _app: &mut App) {}
957    }
958    struct PluginC<T>(T);
959    impl<T: Send + Sync + 'static> Plugin for PluginC<T> {
960        fn build(&self, _app: &mut App) {}
961    }
962    struct PluginD;
963    impl Plugin for PluginD {
964        fn build(&self, _app: &mut App) {}
965        fn is_unique(&self) -> bool {
966            false
967        }
968    }
969
970    struct PluginE;
971
972    impl Plugin for PluginE {
973        fn build(&self, _app: &mut App) {}
974
975        fn finish(&self, app: &mut App) {
976            if app.is_plugin_added::<PluginA>() {
977                panic!("cannot run if PluginA is already registered");
978            }
979        }
980    }
981
982    #[test]
983    fn can_add_two_plugins() {
984        App::new().add_plugins((PluginA, PluginB));
985    }
986
987    #[test]
988    #[should_panic]
989    fn cant_add_twice_the_same_plugin() {
990        App::new().add_plugins((PluginA, PluginA));
991    }
992
993    #[test]
994    fn can_add_twice_the_same_plugin_with_different_type_param() {
995        App::new().add_plugins((PluginC(0), PluginC(true)));
996    }
997
998    #[test]
999    fn can_add_twice_the_same_plugin_not_unique() {
1000        App::new().add_plugins((PluginD, PluginD));
1001    }
1002
1003    #[test]
1004    #[should_panic]
1005    fn cant_call_app_run_from_plugin_build() {
1006        struct PluginRun;
1007        struct InnerPlugin;
1008        impl Plugin for InnerPlugin {
1009            fn build(&self, _: &mut App) {}
1010        }
1011        impl Plugin for PluginRun {
1012            fn build(&self, app: &mut App) {
1013                app.add_plugins(InnerPlugin).run();
1014            }
1015        }
1016        App::new().add_plugins(PluginRun);
1017    }
1018
1019    #[derive(ScheduleLabel, Hash, Clone, PartialEq, Eq, Debug)]
1020    struct EnterMainMenu;
1021
1022    fn bar(mut commands: Commands) {
1023        commands.spawn_empty();
1024    }
1025
1026    fn foo(mut commands: Commands) {
1027        commands.spawn_empty();
1028    }
1029
1030    #[test]
1031    fn add_systems_should_create_schedule_if_it_does_not_exist() {
1032        let mut app = App::new();
1033        app.add_systems(EnterMainMenu, (foo, bar));
1034
1035        app.world_mut().run_schedule(EnterMainMenu);
1036        assert_eq!(app.world().entities().len(), 2);
1037    }
1038
1039    #[test]
1040    #[should_panic]
1041    fn test_is_plugin_added_works_during_finish() {
1042        let mut app = App::new();
1043        app.add_plugins(PluginA);
1044        app.add_plugins(PluginE);
1045        app.finish();
1046    }
1047
1048    #[test]
1049    fn test_derive_app_label() {
1050        use super::AppLabel;
1051        use crate::{self as bevy_app};
1052
1053        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1054        struct UnitLabel;
1055
1056        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1057        struct TupleLabel(u32, u32);
1058
1059        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1060        struct StructLabel {
1061            a: u32,
1062            b: u32,
1063        }
1064
1065        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1066        struct EmptyTupleLabel();
1067
1068        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1069        struct EmptyStructLabel {}
1070
1071        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1072        enum EnumLabel {
1073            #[default]
1074            Unit,
1075            Tuple(u32, u32),
1076            Struct {
1077                a: u32,
1078                b: u32,
1079            },
1080        }
1081
1082        #[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
1083        struct GenericLabel<T>(PhantomData<T>);
1084
1085        assert_eq!(UnitLabel.intern(), UnitLabel.intern());
1086        assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());
1087        assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());
1088        assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());
1089        assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());
1090
1091        assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());
1092        assert_eq!(
1093            EnumLabel::Tuple(0, 0).intern(),
1094            EnumLabel::Tuple(0, 0).intern()
1095        );
1096        assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());
1097        assert_ne!(
1098            EnumLabel::Tuple(0, 0).intern(),
1099            EnumLabel::Tuple(0, 1).intern()
1100        );
1101        assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());
1102        assert_ne!(
1103            TupleLabel(0, 0).intern(),
1104            StructLabel { a: 0, b: 0 }.intern()
1105        );
1106        assert_ne!(
1107            EnumLabel::Tuple(0, 0).intern(),
1108            EnumLabel::Struct { a: 0, b: 0 }.intern()
1109        );
1110
1111        assert_eq!(
1112            StructLabel { a: 0, b: 0 }.intern(),
1113            StructLabel { a: 0, b: 0 }.intern()
1114        );
1115        assert_eq!(
1116            EnumLabel::Struct { a: 0, b: 0 }.intern(),
1117            EnumLabel::Struct { a: 0, b: 0 }.intern()
1118        );
1119        assert_ne!(
1120            StructLabel { a: 0, b: 0 }.intern(),
1121            StructLabel { a: 0, b: 1 }.intern()
1122        );
1123        assert_ne!(
1124            EnumLabel::Struct { a: 0, b: 0 }.intern(),
1125            EnumLabel::Struct { a: 0, b: 1 }.intern()
1126        );
1127        assert_ne!(
1128            StructLabel { a: 0, b: 0 }.intern(),
1129            EnumLabel::Struct { a: 0, b: 0 }.intern()
1130        );
1131        assert_ne!(
1132            StructLabel { a: 0, b: 0 }.intern(),
1133            EnumLabel::Struct { a: 0, b: 0 }.intern()
1134        );
1135        assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);
1136        assert_ne!(
1137            EnumLabel::Struct { a: 0, b: 0 }.intern(),
1138            EnumLabel::Unit.intern()
1139        );
1140
1141        assert_eq!(
1142            GenericLabel::<u32>(PhantomData).intern(),
1143            GenericLabel::<u32>(PhantomData).intern()
1144        );
1145        assert_ne!(
1146            GenericLabel::<u32>(PhantomData).intern(),
1147            GenericLabel::<u64>(PhantomData).intern()
1148        );
1149    }
1150
1151    #[test]
1152    fn test_update_clears_trackers_once() {
1153        #[derive(Component, Copy, Clone)]
1154        struct Foo;
1155
1156        let mut app = App::new();
1157        app.world_mut().spawn_batch(iter::repeat(Foo).take(5));
1158
1159        fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {
1160            if let Some(e) = foos.iter().next() {
1161                commands.entity(e).despawn();
1162            };
1163        }
1164        fn check_despawns(mut removed_foos: RemovedComponents<Foo>) {
1165            let mut despawn_count = 0;
1166            for _ in removed_foos.read() {
1167                despawn_count += 1;
1168            }
1169
1170            assert_eq!(despawn_count, 2);
1171        }
1172
1173        app.add_systems(Update, despawn_one_foo);
1174        app.update(); // Frame 0
1175        app.update(); // Frame 1
1176        app.add_systems(Update, check_despawns.after(despawn_one_foo));
1177        app.update(); // Should see despawns from frames 1 & 2, but not frame 0
1178    }
1179
1180    #[test]
1181    fn test_extract_sees_changes() {
1182        use super::AppLabel;
1183        use crate::{self as bevy_app};
1184
1185        #[derive(AppLabel, Clone, Copy, Hash, PartialEq, Eq, Debug)]
1186        struct MySubApp;
1187
1188        #[derive(Resource)]
1189        struct Foo(usize);
1190
1191        let mut app = App::new();
1192        app.world_mut().insert_resource(Foo(0));
1193        app.add_systems(Update, |mut foo: ResMut<Foo>| {
1194            foo.0 += 1;
1195        });
1196
1197        let mut sub_app = SubApp::new();
1198        sub_app.set_extract(|main_world, _sub_world| {
1199            assert!(main_world.get_resource_ref::<Foo>().unwrap().is_changed());
1200        });
1201
1202        app.insert_sub_app(MySubApp, sub_app);
1203
1204        app.update();
1205    }
1206
1207    #[test]
1208    fn runner_returns_correct_exit_code() {
1209        fn raise_exits(mut exits: EventWriter<AppExit>) {
1210            // Exit codes chosen by a fair dice roll.
1211            // Unlikely to overlap with default values.
1212            exits.send(AppExit::Success);
1213            exits.send(AppExit::from_code(4));
1214            exits.send(AppExit::from_code(73));
1215        }
1216
1217        let exit = App::new().add_systems(Update, raise_exits).run();
1218
1219        assert_eq!(exit, AppExit::from_code(4));
1220    }
1221
1222    /// Custom runners should be in charge of when `app::update` gets called as they may need to
1223    /// coordinate some state.
1224    /// bug: <https://github.com/bevyengine/bevy/issues/10385>
1225    /// fix: <https://github.com/bevyengine/bevy/pull/10389>
1226    #[test]
1227    fn regression_test_10385() {
1228        use super::{Res, Resource};
1229        use crate::PreUpdate;
1230
1231        #[derive(Resource)]
1232        struct MyState {}
1233
1234        fn my_runner(mut app: App) -> AppExit {
1235            let my_state = MyState {};
1236            app.world_mut().insert_resource(my_state);
1237
1238            for _ in 0..5 {
1239                app.update();
1240            }
1241
1242            AppExit::Success
1243        }
1244
1245        fn my_system(_: Res<MyState>) {
1246            // access state during app update
1247        }
1248
1249        // Should not panic due to missing resource
1250        App::new()
1251            .set_runner(my_runner)
1252            .add_systems(PreUpdate, my_system)
1253            .run();
1254    }
1255
1256    #[test]
1257    fn app_exit_size() {
1258        // There wont be many of them so the size isn't a issue but
1259        // it's nice they're so small let's keep it that way.
1260        assert_eq!(mem::size_of::<AppExit>(), mem::size_of::<u8>());
1261    }
1262
1263    #[test]
1264    fn initializing_resources_from_world() {
1265        #[derive(Resource)]
1266        struct TestResource;
1267        impl FromWorld for TestResource {
1268            fn from_world(_world: &mut World) -> Self {
1269                TestResource
1270            }
1271        }
1272
1273        #[derive(Resource)]
1274        struct NonSendTestResource {
1275            _marker: PhantomData<Mutex<()>>,
1276        }
1277        impl FromWorld for NonSendTestResource {
1278            fn from_world(_world: &mut World) -> Self {
1279                NonSendTestResource {
1280                    _marker: PhantomData,
1281                }
1282            }
1283        }
1284
1285        App::new()
1286            .init_non_send_resource::<NonSendTestResource>()
1287            .init_resource::<TestResource>();
1288    }
1289
1290    #[test]
1291    /// Plugin should not be considered inserted while it's being built
1292    ///
1293    /// bug: <https://github.com/bevyengine/bevy/issues/13815>
1294    fn plugin_should_not_be_added_during_build_time() {
1295        pub struct Foo;
1296
1297        impl Plugin for Foo {
1298            fn build(&self, app: &mut App) {
1299                assert!(!app.is_plugin_added::<Self>());
1300            }
1301        }
1302
1303        App::new().add_plugins(Foo);
1304    }
1305    #[test]
1306    fn events_should_be_updated_once_per_update() {
1307        #[derive(Event, Clone)]
1308        struct TestEvent;
1309
1310        let mut app = App::new();
1311        app.add_event::<TestEvent>();
1312
1313        // Starts empty
1314        let test_events = app.world().resource::<Events<TestEvent>>();
1315        assert_eq!(test_events.len(), 0);
1316        assert_eq!(test_events.iter_current_update_events().count(), 0);
1317        app.update();
1318
1319        // Sending one event
1320        app.world_mut().send_event(TestEvent);
1321
1322        let test_events = app.world().resource::<Events<TestEvent>>();
1323        assert_eq!(test_events.len(), 1);
1324        assert_eq!(test_events.iter_current_update_events().count(), 1);
1325        app.update();
1326
1327        // Sending two events on the next frame
1328        app.world_mut().send_event(TestEvent);
1329        app.world_mut().send_event(TestEvent);
1330
1331        let test_events = app.world().resource::<Events<TestEvent>>();
1332        assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3
1333        assert_eq!(test_events.iter_current_update_events().count(), 2);
1334        app.update();
1335
1336        // Sending zero events
1337        let test_events = app.world().resource::<Events<TestEvent>>();
1338        assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2
1339        assert_eq!(test_events.iter_current_update_events().count(), 0);
1340    }
1341}