use crate::{1First, Main, MainSchedulePlugin, PlaceholderPlugin, Plugin, Plugins, PluginsState, SubApp,2SubApps,3};4use alloc::{5boxed::Box,6string::{String, ToString},7vec::Vec,8};9pub use bevy_derive::AppLabel;10use bevy_ecs::{11component::RequiredComponentsError,12error::{DefaultErrorHandler, ErrorHandler},13event::{event_update_system, EventCursor},14intern::Interned,15prelude::*,16schedule::{InternedSystemSet, ScheduleBuildSettings, ScheduleLabel},17system::{IntoObserverSystem, ScheduleSystem, SystemId, SystemInput},18};19use bevy_platform::collections::HashMap;20use core::{fmt::Debug, num::NonZero, panic::AssertUnwindSafe};21use log::debug;2223#[cfg(feature = "trace")]24use tracing::info_span;2526#[cfg(feature = "std")]27use std::{28panic::{catch_unwind, resume_unwind},29process::{ExitCode, Termination},30};3132bevy_ecs::define_label!(33/// A strongly-typed class of labels used to identify an [`App`].34#[diagnostic::on_unimplemented(35note = "consider annotating `{Self}` with `#[derive(AppLabel)]`"36)]37AppLabel,38APP_LABEL_INTERNER39);4041pub use bevy_ecs::label::DynEq;4243/// A shorthand for `Interned<dyn AppLabel>`.44pub type InternedAppLabel = Interned<dyn AppLabel>;4546#[derive(Debug, thiserror::Error)]47pub(crate) enum AppError {48#[error("duplicate plugin {plugin_name:?}")]49DuplicatePlugin { plugin_name: String },50}5152/// [`App`] is the primary API for writing user applications. It automates the setup of a53/// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).54///55/// A single [`App`] can contain multiple [`SubApp`] instances, but [`App`] methods only affect56/// the "main" one. To access a particular [`SubApp`], use [`get_sub_app`](App::get_sub_app)57/// or [`get_sub_app_mut`](App::get_sub_app_mut).58///59///60/// # Examples61///62/// Here is a simple "Hello World" Bevy app:63///64/// ```65/// # use bevy_app::prelude::*;66/// # use bevy_ecs::prelude::*;67/// #68/// fn main() {69/// App::new()70/// .add_systems(Update, hello_world_system)71/// .run();72/// }73///74/// fn hello_world_system() {75/// println!("hello world");76/// }77/// ```78pub struct App {79pub(crate) sub_apps: SubApps,80/// The function that will manage the app's lifecycle.81///82/// Bevy provides the [`WinitPlugin`] and [`ScheduleRunnerPlugin`] for windowed and headless83/// applications, respectively.84///85/// [`WinitPlugin`]: https://docs.rs/bevy/latest/bevy/winit/struct.WinitPlugin.html86/// [`ScheduleRunnerPlugin`]: https://docs.rs/bevy/latest/bevy/app/struct.ScheduleRunnerPlugin.html87pub(crate) runner: RunnerFn,88default_error_handler: Option<ErrorHandler>,89}9091impl Debug for App {92fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {93write!(f, "App {{ sub_apps: ")?;94f.debug_map()95.entries(self.sub_apps.sub_apps.iter())96.finish()?;97write!(f, "}}")98}99}100101impl Default for App {102fn default() -> Self {103let mut app = App::empty();104app.sub_apps.main.update_schedule = Some(Main.intern());105106#[cfg(feature = "bevy_reflect")]107{108#[cfg(not(feature = "reflect_auto_register"))]109app.init_resource::<AppTypeRegistry>();110111#[cfg(feature = "reflect_auto_register")]112app.insert_resource(AppTypeRegistry::new_with_derived_types());113}114115#[cfg(feature = "reflect_functions")]116app.init_resource::<AppFunctionRegistry>();117118app.add_plugins(MainSchedulePlugin);119app.add_systems(120First,121event_update_system122.in_set(bevy_ecs::event::EventUpdateSystems)123.run_if(bevy_ecs::event::event_update_condition),124);125app.add_event::<AppExit>();126127app128}129}130131impl App {132/// Creates a new [`App`] with some default structure to enable core engine features.133/// This is the preferred constructor for most use cases.134pub fn new() -> App {135App::default()136}137138/// Creates a new empty [`App`] with minimal default configuration.139///140/// Use this constructor if you want to customize scheduling, exit handling, cleanup, etc.141pub fn empty() -> App {142Self {143sub_apps: SubApps {144main: SubApp::new(),145sub_apps: HashMap::default(),146},147runner: Box::new(run_once),148default_error_handler: None,149}150}151152/// Runs the default schedules of all sub-apps (starting with the "main" app) once.153pub fn update(&mut self) {154if self.is_building_plugins() {155panic!("App::update() was called while a plugin was building.");156}157158self.sub_apps.update();159}160161/// Runs the [`App`] by calling its [runner](Self::set_runner).162///163/// This will (re)build the [`App`] first. For general usage, see the example on the item164/// level documentation.165///166/// # Caveats167///168/// Calls to [`App::run()`] will never return on iOS and Web.169///170/// Headless apps can generally expect this method to return control to the caller when171/// it completes, but that is not the case for windowed apps. Windowed apps are typically172/// driven by an event loop and some platforms expect the program to terminate when the173/// event loop ends.174///175/// By default, *Bevy* uses the `winit` crate for window creation.176///177/// # Panics178///179/// Panics if not all plugins have been built.180pub fn run(&mut self) -> AppExit {181#[cfg(feature = "trace")]182let _bevy_app_run_span = info_span!("bevy_app").entered();183if self.is_building_plugins() {184panic!("App::run() was called while a plugin was building.");185}186187let runner = core::mem::replace(&mut self.runner, Box::new(run_once));188let app = core::mem::replace(self, App::empty());189(runner)(app)190}191192/// Sets the function that will be called when the app is run.193///194/// The runner function `f` is called only once by [`App::run`]. If the195/// presence of a main loop in the app is desired, it is the responsibility of the runner196/// function to provide it.197///198/// The runner function is usually not set manually, but by Bevy integrated plugins199/// (e.g. `WinitPlugin`).200///201/// # Examples202///203/// ```204/// # use bevy_app::prelude::*;205/// #206/// fn my_runner(mut app: App) -> AppExit {207/// loop {208/// println!("In main loop");209/// app.update();210/// if let Some(exit) = app.should_exit() {211/// return exit;212/// }213/// }214/// }215///216/// App::new()217/// .set_runner(my_runner);218/// ```219pub fn set_runner(&mut self, f: impl FnOnce(App) -> AppExit + 'static) -> &mut Self {220self.runner = Box::new(f);221self222}223224/// Returns the state of all plugins. This is usually called by the event loop, but can be225/// useful for situations where you want to use [`App::update`].226// TODO: &mut self -> &self227#[inline]228pub fn plugins_state(&mut self) -> PluginsState {229let mut overall_plugins_state = match self.main_mut().plugins_state {230PluginsState::Adding => {231let mut state = PluginsState::Ready;232let plugins = core::mem::take(&mut self.main_mut().plugin_registry);233for plugin in &plugins {234// plugins installed to main need to see all sub-apps235if !plugin.ready(self) {236state = PluginsState::Adding;237break;238}239}240self.main_mut().plugin_registry = plugins;241state242}243state => state,244};245246// overall state is the earliest state of any sub-app247self.sub_apps.iter_mut().skip(1).for_each(|s| {248overall_plugins_state = overall_plugins_state.min(s.plugins_state());249});250251overall_plugins_state252}253254/// Runs [`Plugin::finish`] for each plugin. This is usually called by the event loop once all255/// plugins are ready, but can be useful for situations where you want to use [`App::update`].256pub fn finish(&mut self) {257#[cfg(feature = "trace")]258let _finish_span = info_span!("plugin finish").entered();259// plugins installed to main should see all sub-apps260// do hokey pokey with a boxed zst plugin (doesn't allocate)261let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);262for i in 0..self.main().plugin_registry.len() {263core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);264#[cfg(feature = "trace")]265let _plugin_finish_span =266info_span!("plugin finish", plugin = hokeypokey.name()).entered();267hokeypokey.finish(self);268core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);269}270self.main_mut().plugins_state = PluginsState::Finished;271self.sub_apps.iter_mut().skip(1).for_each(SubApp::finish);272}273274/// Runs [`Plugin::cleanup`] for each plugin. This is usually called by the event loop after275/// [`App::finish`], but can be useful for situations where you want to use [`App::update`].276pub fn cleanup(&mut self) {277#[cfg(feature = "trace")]278let _cleanup_span = info_span!("plugin cleanup").entered();279// plugins installed to main should see all sub-apps280// do hokey pokey with a boxed zst plugin (doesn't allocate)281let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);282for i in 0..self.main().plugin_registry.len() {283core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);284#[cfg(feature = "trace")]285let _plugin_cleanup_span =286info_span!("plugin cleanup", plugin = hokeypokey.name()).entered();287hokeypokey.cleanup(self);288core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);289}290self.main_mut().plugins_state = PluginsState::Cleaned;291self.sub_apps.iter_mut().skip(1).for_each(SubApp::cleanup);292}293294/// Returns `true` if any of the sub-apps are building plugins.295pub(crate) fn is_building_plugins(&self) -> bool {296self.sub_apps.iter().any(SubApp::is_building_plugins)297}298299/// Adds one or more systems to the given schedule in this app's [`Schedules`].300///301/// # Examples302///303/// ```304/// # use bevy_app::prelude::*;305/// # use bevy_ecs::prelude::*;306/// #307/// # let mut app = App::new();308/// # fn system_a() {}309/// # fn system_b() {}310/// # fn system_c() {}311/// # fn should_run() -> bool { true }312/// #313/// app.add_systems(Update, (system_a, system_b, system_c));314/// app.add_systems(Update, (system_a, system_b).run_if(should_run));315/// ```316pub fn add_systems<M>(317&mut self,318schedule: impl ScheduleLabel,319systems: impl IntoScheduleConfigs<ScheduleSystem, M>,320) -> &mut Self {321self.main_mut().add_systems(schedule, systems);322self323}324325/// Registers a system and returns a [`SystemId`] so it can later be called by [`World::run_system`].326///327/// It's possible to register the same systems more than once, they'll be stored separately.328///329/// This is different from adding systems to a [`Schedule`] with [`App::add_systems`],330/// because the [`SystemId`] that is returned can be used anywhere in the [`World`] to run the associated system.331/// This allows for running systems in a push-based fashion.332/// Using a [`Schedule`] is still preferred for most cases333/// due to its better performance and ability to run non-conflicting systems simultaneously.334pub fn register_system<I, O, M>(335&mut self,336system: impl IntoSystem<I, O, M> + 'static,337) -> SystemId<I, O>338where339I: SystemInput + 'static,340O: 'static,341{342self.main_mut().register_system(system)343}344345/// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.346#[track_caller]347pub fn configure_sets<M>(348&mut self,349schedule: impl ScheduleLabel,350sets: impl IntoScheduleConfigs<InternedSystemSet, M>,351) -> &mut Self {352self.main_mut().configure_sets(schedule, sets);353self354}355356/// Initializes [`BufferedEvent`] handling for `T` by inserting an event queue resource ([`Events::<T>`])357/// and scheduling an [`event_update_system`] in [`First`].358///359/// See [`Events`] for information on how to define events.360///361/// # Examples362///363/// ```364/// # use bevy_app::prelude::*;365/// # use bevy_ecs::prelude::*;366/// #367/// # #[derive(BufferedEvent)]368/// # struct MyEvent;369/// # let mut app = App::new();370/// #371/// app.add_event::<MyEvent>();372/// ```373pub fn add_event<T>(&mut self) -> &mut Self374where375T: BufferedEvent,376{377self.main_mut().add_event::<T>();378self379}380381/// Inserts the [`Resource`] into the app, overwriting any existing resource of the same type.382///383/// There is also an [`init_resource`](Self::init_resource) for resources that have384/// [`Default`] or [`FromWorld`] implementations.385///386/// # Examples387///388/// ```389/// # use bevy_app::prelude::*;390/// # use bevy_ecs::prelude::*;391/// #392/// #[derive(Resource)]393/// struct MyCounter {394/// counter: usize,395/// }396///397/// App::new()398/// .insert_resource(MyCounter { counter: 0 });399/// ```400pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {401self.main_mut().insert_resource(resource);402self403}404405/// Inserts the [`Resource`], initialized with its default value, into the app,406/// if there is no existing instance of `R`.407///408/// `R` must implement [`FromWorld`].409/// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and410/// initialize the [`Resource`] with [`Default::default`].411///412/// # Examples413///414/// ```415/// # use bevy_app::prelude::*;416/// # use bevy_ecs::prelude::*;417/// #418/// #[derive(Resource)]419/// struct MyCounter {420/// counter: usize,421/// }422///423/// impl Default for MyCounter {424/// fn default() -> MyCounter {425/// MyCounter {426/// counter: 100427/// }428/// }429/// }430///431/// App::new()432/// .init_resource::<MyCounter>();433/// ```434pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {435self.main_mut().init_resource::<R>();436self437}438439/// Inserts the [`!Send`](Send) resource into the app, overwriting any existing resource440/// of the same type.441///442/// There is also an [`init_non_send_resource`](Self::init_non_send_resource) for443/// resources that implement [`Default`]444///445/// # Examples446///447/// ```448/// # use bevy_app::prelude::*;449/// # use bevy_ecs::prelude::*;450/// #451/// struct MyCounter {452/// counter: usize,453/// }454///455/// App::new()456/// .insert_non_send_resource(MyCounter { counter: 0 });457/// ```458pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {459self.world_mut().insert_non_send_resource(resource);460self461}462463/// Inserts the [`!Send`](Send) resource into the app if there is no existing instance of `R`.464///465/// `R` must implement [`FromWorld`].466/// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and467/// initialize the [`Resource`] with [`Default::default`].468pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {469self.world_mut().init_non_send_resource::<R>();470self471}472473pub(crate) fn add_boxed_plugin(474&mut self,475plugin: Box<dyn Plugin>,476) -> Result<&mut Self, AppError> {477debug!("added plugin: {}", plugin.name());478if plugin.is_unique() && self.main_mut().plugin_names.contains(plugin.name()) {479Err(AppError::DuplicatePlugin {480plugin_name: plugin.name().to_string(),481})?;482}483484// Reserve position in the plugin registry. If the plugin adds more plugins,485// they'll all end up in insertion order.486let index = self.main().plugin_registry.len();487self.main_mut()488.plugin_registry489.push(Box::new(PlaceholderPlugin));490491self.main_mut().plugin_build_depth += 1;492493#[cfg(feature = "trace")]494let _plugin_build_span = info_span!("plugin build", plugin = plugin.name()).entered();495496let f = AssertUnwindSafe(|| plugin.build(self));497498#[cfg(feature = "std")]499let result = catch_unwind(f);500501#[cfg(not(feature = "std"))]502f();503504self.main_mut()505.plugin_names506.insert(plugin.name().to_string());507self.main_mut().plugin_build_depth -= 1;508509#[cfg(feature = "std")]510if let Err(payload) = result {511resume_unwind(payload);512}513514self.main_mut().plugin_registry[index] = plugin;515Ok(self)516}517518/// Returns `true` if the [`Plugin`] has already been added.519pub fn is_plugin_added<T>(&self) -> bool520where521T: Plugin,522{523self.main().is_plugin_added::<T>()524}525526/// Returns a vector of references to all plugins of type `T` that have been added.527///528/// This can be used to read the settings of any existing plugins.529/// This vector will be empty if no plugins of that type have been added.530/// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector.531///532/// ```533/// # use bevy_app::prelude::*;534/// # #[derive(Default)]535/// # struct ImagePlugin {536/// # default_sampler: bool,537/// # }538/// # impl Plugin for ImagePlugin {539/// # fn build(&self, app: &mut App) {}540/// # }541/// # let mut app = App::new();542/// # app.add_plugins(ImagePlugin::default());543/// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;544/// ```545pub fn get_added_plugins<T>(&self) -> Vec<&T>546where547T: Plugin,548{549self.main().get_added_plugins::<T>()550}551552/// Installs a [`Plugin`] collection.553///554/// Bevy prioritizes modularity as a core principle. **All** engine features are implemented555/// as plugins, even the complex ones like rendering.556///557/// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].558///559/// There are built-in [`PluginGroup`]s that provide core engine functionality.560/// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`.561///562/// To customize the plugins in the group (reorder, disable a plugin, add a new plugin563/// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group,564/// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder).565///566/// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and567/// [`PluginGroup`]s. See [`Plugins`] for more details.568///569/// ## Examples570/// ```571/// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins};572/// #573/// # // Dummies created to avoid using `bevy_log`,574/// # // which pulls in too many dependencies and breaks rust-analyzer575/// # pub struct LogPlugin;576/// # impl Plugin for LogPlugin {577/// # fn build(&self, app: &mut App) {}578/// # }579/// App::new()580/// .add_plugins(MinimalPlugins);581/// App::new()582/// .add_plugins((MinimalPlugins, LogPlugin));583/// ```584///585/// # Panics586///587/// Panics if one of the plugins had already been added to the application.588///589/// [`PluginGroup`]:super::PluginGroup590#[track_caller]591pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {592if matches!(593self.plugins_state(),594PluginsState::Cleaned | PluginsState::Finished595) {596panic!(597"Plugins cannot be added after App::cleanup() or App::finish() has been called."598);599}600plugins.add_to_app(self);601self602}603604/// Registers the type `T` in the [`AppTypeRegistry`] resource,605/// adding reflect data as specified in the [`Reflect`](bevy_reflect::Reflect) derive:606/// ```ignore (No serde "derive" feature)607/// #[derive(Component, Serialize, Deserialize, Reflect)]608/// #[reflect(Component, Serialize, Deserialize)] // will register ReflectComponent, ReflectSerialize, ReflectDeserialize609/// ```610///611/// See [`bevy_reflect::TypeRegistry::register`] for more information.612#[cfg(feature = "bevy_reflect")]613pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {614self.main_mut().register_type::<T>();615self616}617618/// Associates type data `D` with type `T` in the [`AppTypeRegistry`] resource.619///620/// Most of the time [`register_type`](Self::register_type) can be used instead to register a621/// type you derived [`Reflect`](bevy_reflect::Reflect) for. However, in cases where you want to622/// add a piece of type data that was not included in the list of `#[reflect(...)]` type data in623/// the derive, or where the type is generic and cannot register e.g. `ReflectSerialize`624/// unconditionally without knowing the specific type parameters, this method can be used to625/// insert additional type data.626///627/// # Example628/// ```629/// use bevy_app::App;630/// use bevy_reflect::{ReflectSerialize, ReflectDeserialize};631///632/// App::new()633/// .register_type::<Option<String>>()634/// .register_type_data::<Option<String>, ReflectSerialize>()635/// .register_type_data::<Option<String>, ReflectDeserialize>();636/// ```637///638/// See [`bevy_reflect::TypeRegistry::register_type_data`].639#[cfg(feature = "bevy_reflect")]640pub fn register_type_data<641T: bevy_reflect::Reflect + bevy_reflect::TypePath,642D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,643>(644&mut self,645) -> &mut Self {646self.main_mut().register_type_data::<T, D>();647self648}649650/// Registers the given function into the [`AppFunctionRegistry`] resource.651///652/// The given function will internally be stored as a [`DynamicFunction`]653/// and mapped according to its [name].654///655/// Because the function must have a name,656/// anonymous functions (e.g. `|a: i32, b: i32| { a + b }`) and closures must instead657/// be registered using [`register_function_with_name`] or converted to a [`DynamicFunction`]658/// and named using [`DynamicFunction::with_name`].659/// Failure to do so will result in a panic.660///661/// Only types that implement [`IntoFunction`] may be registered via this method.662///663/// See [`FunctionRegistry::register`] for more information.664///665/// # Panics666///667/// Panics if a function has already been registered with the given name668/// or if the function is missing a name (such as when it is an anonymous function).669///670/// # Examples671///672/// ```673/// use bevy_app::App;674///675/// fn add(a: i32, b: i32) -> i32 {676/// a + b677/// }678///679/// App::new().register_function(add);680/// ```681///682/// Functions cannot be registered more than once.683///684/// ```should_panic685/// use bevy_app::App;686///687/// fn add(a: i32, b: i32) -> i32 {688/// a + b689/// }690///691/// App::new()692/// .register_function(add)693/// // Panic! A function has already been registered with the name "my_function"694/// .register_function(add);695/// ```696///697/// Anonymous functions and closures should be registered using [`register_function_with_name`] or given a name using [`DynamicFunction::with_name`].698///699/// ```should_panic700/// use bevy_app::App;701///702/// // Panic! Anonymous functions cannot be registered using `register_function`703/// App::new().register_function(|a: i32, b: i32| a + b);704/// ```705///706/// [`register_function_with_name`]: Self::register_function_with_name707/// [`DynamicFunction`]: bevy_reflect::func::DynamicFunction708/// [name]: bevy_reflect::func::FunctionInfo::name709/// [`DynamicFunction::with_name`]: bevy_reflect::func::DynamicFunction::with_name710/// [`IntoFunction`]: bevy_reflect::func::IntoFunction711/// [`FunctionRegistry::register`]: bevy_reflect::func::FunctionRegistry::register712#[cfg(feature = "reflect_functions")]713pub fn register_function<F, Marker>(&mut self, function: F) -> &mut Self714where715F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,716{717self.main_mut().register_function(function);718self719}720721/// Registers the given function or closure into the [`AppFunctionRegistry`] resource using the given name.722///723/// To avoid conflicts, it's recommended to use a unique name for the function.724/// This can be achieved by "namespacing" the function with a unique identifier,725/// such as the name of your crate.726///727/// For example, to register a function, `add`, from a crate, `my_crate`,728/// you could use the name, `"my_crate::add"`.729///730/// Another approach could be to use the [type name] of the function,731/// however, it should be noted that anonymous functions do _not_ have unique type names.732///733/// For named functions (e.g. `fn add(a: i32, b: i32) -> i32 { a + b }`) where a custom name is not needed,734/// it's recommended to use [`register_function`] instead as the generated name is guaranteed to be unique.735///736/// Only types that implement [`IntoFunction`] may be registered via this method.737///738/// See [`FunctionRegistry::register_with_name`] for more information.739///740/// # Panics741///742/// Panics if a function has already been registered with the given name.743///744/// # Examples745///746/// ```747/// use bevy_app::App;748///749/// fn mul(a: i32, b: i32) -> i32 {750/// a * b751/// }752///753/// let div = |a: i32, b: i32| a / b;754///755/// App::new()756/// // Registering an anonymous function with a unique name757/// .register_function_with_name("my_crate::add", |a: i32, b: i32| {758/// a + b759/// })760/// // Registering an existing function with its type name761/// .register_function_with_name(std::any::type_name_of_val(&mul), mul)762/// // Registering an existing function with a custom name763/// .register_function_with_name("my_crate::mul", mul)764/// // Be careful not to register anonymous functions with their type name.765/// // This code works but registers the function with a non-unique name like `foo::bar::{{closure}}`766/// .register_function_with_name(std::any::type_name_of_val(&div), div);767/// ```768///769/// Names must be unique.770///771/// ```should_panic772/// use bevy_app::App;773///774/// fn one() {}775/// fn two() {}776///777/// App::new()778/// .register_function_with_name("my_function", one)779/// // Panic! A function has already been registered with the name "my_function"780/// .register_function_with_name("my_function", two);781/// ```782///783/// [type name]: std::any::type_name784/// [`register_function`]: Self::register_function785/// [`IntoFunction`]: bevy_reflect::func::IntoFunction786/// [`FunctionRegistry::register_with_name`]: bevy_reflect::func::FunctionRegistry::register_with_name787#[cfg(feature = "reflect_functions")]788pub fn register_function_with_name<F, Marker>(789&mut self,790name: impl Into<alloc::borrow::Cow<'static, str>>,791function: F,792) -> &mut Self793where794F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,795{796self.main_mut().register_function_with_name(name, function);797self798}799800/// Registers the given component `R` as a [required component] for `T`.801///802/// When `T` is added to an entity, `R` and its own required components will also be added803/// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.804/// If a custom constructor is desired, use [`App::register_required_components_with`] instead.805///806/// For the non-panicking version, see [`App::try_register_required_components`].807///808/// Note that requirements must currently be registered before `T` is inserted into the world809/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.810///811/// [required component]: Component#required-components812///813/// # Panics814///815/// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added816/// on an entity before the registration.817///818/// Indirect requirements through other components are allowed. In those cases, any existing requirements819/// will only be overwritten if the new requirement is more specific.820///821/// # Example822///823/// ```824/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};825/// # use bevy_ecs::prelude::*;826/// #[derive(Component)]827/// struct A;828///829/// #[derive(Component, Default, PartialEq, Eq, Debug)]830/// struct B(usize);831///832/// #[derive(Component, Default, PartialEq, Eq, Debug)]833/// struct C(u32);834///835/// # let mut app = App::new();836/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);837/// // Register B as required by A and C as required by B.838/// app.register_required_components::<A, B>();839/// app.register_required_components::<B, C>();840///841/// fn setup(mut commands: Commands) {842/// // This will implicitly also insert B and C with their Default constructors.843/// commands.spawn(A);844/// }845///846/// fn validate(query: Option<Single<(&A, &B, &C)>>) {847/// let (a, b, c) = query.unwrap().into_inner();848/// assert_eq!(b, &B(0));849/// assert_eq!(c, &C(0));850/// }851/// # app.update();852/// ```853pub fn register_required_components<T: Component, R: Component + Default>(854&mut self,855) -> &mut Self {856self.world_mut().register_required_components::<T, R>();857self858}859860/// Registers the given component `R` as a [required component] for `T`.861///862/// When `T` is added to an entity, `R` and its own required components will also be added863/// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.864/// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.865///866/// For the non-panicking version, see [`App::try_register_required_components_with`].867///868/// Note that requirements must currently be registered before `T` is inserted into the world869/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.870///871/// [required component]: Component#required-components872///873/// # Panics874///875/// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added876/// on an entity before the registration.877///878/// Indirect requirements through other components are allowed. In those cases, any existing requirements879/// will only be overwritten if the new requirement is more specific.880///881/// # Example882///883/// ```884/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};885/// # use bevy_ecs::prelude::*;886/// #[derive(Component)]887/// struct A;888///889/// #[derive(Component, Default, PartialEq, Eq, Debug)]890/// struct B(usize);891///892/// #[derive(Component, Default, PartialEq, Eq, Debug)]893/// struct C(u32);894///895/// # let mut app = App::new();896/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);897/// // Register B and C as required by A and C as required by B.898/// // A requiring C directly will overwrite the indirect requirement through B.899/// app.register_required_components::<A, B>();900/// app.register_required_components_with::<B, C>(|| C(1));901/// app.register_required_components_with::<A, C>(|| C(2));902///903/// fn setup(mut commands: Commands) {904/// // This will implicitly also insert B with its Default constructor and C905/// // with the custom constructor defined by A.906/// commands.spawn(A);907/// }908///909/// fn validate(query: Option<Single<(&A, &B, &C)>>) {910/// let (a, b, c) = query.unwrap().into_inner();911/// assert_eq!(b, &B(0));912/// assert_eq!(c, &C(2));913/// }914/// # app.update();915/// ```916pub fn register_required_components_with<T: Component, R: Component>(917&mut self,918constructor: fn() -> R,919) -> &mut Self {920self.world_mut()921.register_required_components_with::<T, R>(constructor);922self923}924925/// Tries to register the given component `R` as a [required component] for `T`.926///927/// When `T` is added to an entity, `R` and its own required components will also be added928/// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.929/// If a custom constructor is desired, use [`App::register_required_components_with`] instead.930///931/// For the panicking version, see [`App::register_required_components`].932///933/// Note that requirements must currently be registered before `T` is inserted into the world934/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.935///936/// [required component]: Component#required-components937///938/// # Errors939///940/// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added941/// on an entity before the registration.942///943/// Indirect requirements through other components are allowed. In those cases, any existing requirements944/// will only be overwritten if the new requirement is more specific.945///946/// # Example947///948/// ```949/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};950/// # use bevy_ecs::prelude::*;951/// #[derive(Component)]952/// struct A;953///954/// #[derive(Component, Default, PartialEq, Eq, Debug)]955/// struct B(usize);956///957/// #[derive(Component, Default, PartialEq, Eq, Debug)]958/// struct C(u32);959///960/// # let mut app = App::new();961/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);962/// // Register B as required by A and C as required by B.963/// app.register_required_components::<A, B>();964/// app.register_required_components::<B, C>();965///966/// // Duplicate registration! This will fail.967/// assert!(app.try_register_required_components::<A, B>().is_err());968///969/// fn setup(mut commands: Commands) {970/// // This will implicitly also insert B and C with their Default constructors.971/// commands.spawn(A);972/// }973///974/// fn validate(query: Option<Single<(&A, &B, &C)>>) {975/// let (a, b, c) = query.unwrap().into_inner();976/// assert_eq!(b, &B(0));977/// assert_eq!(c, &C(0));978/// }979/// # app.update();980/// ```981pub fn try_register_required_components<T: Component, R: Component + Default>(982&mut self,983) -> Result<(), RequiredComponentsError> {984self.world_mut().try_register_required_components::<T, R>()985}986987/// Tries to register the given component `R` as a [required component] for `T`.988///989/// When `T` is added to an entity, `R` and its own required components will also be added990/// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.991/// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.992///993/// For the panicking version, see [`App::register_required_components_with`].994///995/// Note that requirements must currently be registered before `T` is inserted into the world996/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.997///998/// [required component]: Component#required-components999///1000/// # Errors1001///1002/// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added1003/// on an entity before the registration.1004///1005/// Indirect requirements through other components are allowed. In those cases, any existing requirements1006/// will only be overwritten if the new requirement is more specific.1007///1008/// # Example1009///1010/// ```1011/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};1012/// # use bevy_ecs::prelude::*;1013/// #[derive(Component)]1014/// struct A;1015///1016/// #[derive(Component, Default, PartialEq, Eq, Debug)]1017/// struct B(usize);1018///1019/// #[derive(Component, Default, PartialEq, Eq, Debug)]1020/// struct C(u32);1021///1022/// # let mut app = App::new();1023/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);1024/// // Register B and C as required by A and C as required by B.1025/// // A requiring C directly will overwrite the indirect requirement through B.1026/// app.register_required_components::<A, B>();1027/// app.register_required_components_with::<B, C>(|| C(1));1028/// app.register_required_components_with::<A, C>(|| C(2));1029///1030/// // Duplicate registration! Even if the constructors were different, this would fail.1031/// assert!(app.try_register_required_components_with::<B, C>(|| C(1)).is_err());1032///1033/// fn setup(mut commands: Commands) {1034/// // This will implicitly also insert B with its Default constructor and C1035/// // with the custom constructor defined by A.1036/// commands.spawn(A);1037/// }1038///1039/// fn validate(query: Option<Single<(&A, &B, &C)>>) {1040/// let (a, b, c) = query.unwrap().into_inner();1041/// assert_eq!(b, &B(0));1042/// assert_eq!(c, &C(2));1043/// }1044/// # app.update();1045/// ```1046pub fn try_register_required_components_with<T: Component, R: Component>(1047&mut self,1048constructor: fn() -> R,1049) -> Result<(), RequiredComponentsError> {1050self.world_mut()1051.try_register_required_components_with::<T, R>(constructor)1052}10531054/// Registers a component type as "disabling",1055/// using [default query filters](bevy_ecs::entity_disabling::DefaultQueryFilters) to exclude entities with the component from queries.1056///1057/// # Warning1058///1059/// As discussed in the [module docs](bevy_ecs::entity_disabling), this can have performance implications,1060/// as well as create interoperability issues, and should be used with caution.1061pub fn register_disabling_component<C: Component>(&mut self) {1062self.world_mut().register_disabling_component::<C>();1063}10641065/// Returns a reference to the main [`SubApp`]'s [`World`]. This is the same as calling1066/// [`app.main().world()`].1067///1068/// [`app.main().world()`]: SubApp::world1069pub fn world(&self) -> &World {1070self.main().world()1071}10721073/// Returns a mutable reference to the main [`SubApp`]'s [`World`]. This is the same as calling1074/// [`app.main_mut().world_mut()`].1075///1076/// [`app.main_mut().world_mut()`]: SubApp::world_mut1077pub fn world_mut(&mut self) -> &mut World {1078self.main_mut().world_mut()1079}10801081/// Returns a reference to the main [`SubApp`].1082pub fn main(&self) -> &SubApp {1083&self.sub_apps.main1084}10851086/// Returns a mutable reference to the main [`SubApp`].1087pub fn main_mut(&mut self) -> &mut SubApp {1088&mut self.sub_apps.main1089}10901091/// Returns a reference to the [`SubApps`] collection.1092pub fn sub_apps(&self) -> &SubApps {1093&self.sub_apps1094}10951096/// Returns a mutable reference to the [`SubApps`] collection.1097pub fn sub_apps_mut(&mut self) -> &mut SubApps {1098&mut self.sub_apps1099}11001101/// Returns a reference to the [`SubApp`] with the given label.1102///1103/// # Panics1104///1105/// Panics if the [`SubApp`] doesn't exist.1106pub fn sub_app(&self, label: impl AppLabel) -> &SubApp {1107let str = label.intern();1108self.get_sub_app(label).unwrap_or_else(|| {1109panic!("No sub-app with label '{:?}' exists.", str);1110})1111}11121113/// Returns a reference to the [`SubApp`] with the given label.1114///1115/// # Panics1116///1117/// Panics if the [`SubApp`] doesn't exist.1118pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut SubApp {1119let str = label.intern();1120self.get_sub_app_mut(label).unwrap_or_else(|| {1121panic!("No sub-app with label '{:?}' exists.", str);1122})1123}11241125/// Returns a reference to the [`SubApp`] with the given label, if it exists.1126pub fn get_sub_app(&self, label: impl AppLabel) -> Option<&SubApp> {1127self.sub_apps.sub_apps.get(&label.intern())1128}11291130/// Returns a mutable reference to the [`SubApp`] with the given label, if it exists.1131pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Option<&mut SubApp> {1132self.sub_apps.sub_apps.get_mut(&label.intern())1133}11341135/// Inserts a [`SubApp`] with the given label.1136pub fn insert_sub_app(&mut self, label: impl AppLabel, mut sub_app: SubApp) {1137if let Some(handler) = self.default_error_handler {1138sub_app1139.world_mut()1140.get_resource_or_insert_with(|| DefaultErrorHandler(handler));1141}1142self.sub_apps.sub_apps.insert(label.intern(), sub_app);1143}11441145/// Removes the [`SubApp`] with the given label, if it exists.1146pub fn remove_sub_app(&mut self, label: impl AppLabel) -> Option<SubApp> {1147self.sub_apps.sub_apps.remove(&label.intern())1148}11491150/// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.1151pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {1152self.sub_apps.update_subapp_by_label(label);1153}11541155/// Inserts a new `schedule` under the provided `label`, overwriting any existing1156/// schedule with the same label.1157pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {1158self.main_mut().add_schedule(schedule);1159self1160}11611162/// Initializes an empty `schedule` under the provided `label`, if it does not exist.1163///1164/// See [`add_schedule`](Self::add_schedule) to insert an existing schedule.1165pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {1166self.main_mut().init_schedule(label);1167self1168}11691170/// Returns a reference to the [`Schedule`] with the provided `label` if it exists.1171pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {1172self.main().get_schedule(label)1173}11741175/// Returns a mutable reference to the [`Schedule`] with the provided `label` if it exists.1176pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {1177self.main_mut().get_schedule_mut(label)1178}11791180/// Runs function `f` with the [`Schedule`] associated with `label`.1181///1182/// **Note:** This will create the schedule if it does not already exist.1183pub fn edit_schedule(1184&mut self,1185label: impl ScheduleLabel,1186f: impl FnMut(&mut Schedule),1187) -> &mut Self {1188self.main_mut().edit_schedule(label, f);1189self1190}11911192/// Applies the provided [`ScheduleBuildSettings`] to all schedules.1193pub fn configure_schedules(1194&mut self,1195schedule_build_settings: ScheduleBuildSettings,1196) -> &mut Self {1197self.main_mut().configure_schedules(schedule_build_settings);1198self1199}12001201/// When doing [ambiguity checking](ScheduleBuildSettings) this1202/// ignores systems that are ambiguous on [`Component`] T.1203///1204/// This settings only applies to the main world. To apply this to other worlds call the1205/// [corresponding method](World::allow_ambiguous_component) on World1206///1207/// ## Example1208///1209/// ```1210/// # use bevy_app::prelude::*;1211/// # use bevy_ecs::prelude::*;1212/// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};1213/// # use bevy_utils::default;1214///1215/// #[derive(Component)]1216/// struct A;1217///1218/// // these systems are ambiguous on A1219/// fn system_1(_: Query<&mut A>) {}1220/// fn system_2(_: Query<&A>) {}1221///1222/// let mut app = App::new();1223/// app.configure_schedules(ScheduleBuildSettings {1224/// ambiguity_detection: LogLevel::Error,1225/// ..default()1226/// });1227///1228/// app.add_systems(Update, ( system_1, system_2 ));1229/// app.allow_ambiguous_component::<A>();1230///1231/// // running the app does not error.1232/// app.update();1233/// ```1234pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {1235self.main_mut().allow_ambiguous_component::<T>();1236self1237}12381239/// When doing [ambiguity checking](ScheduleBuildSettings) this1240/// ignores systems that are ambiguous on [`Resource`] T.1241///1242/// This settings only applies to the main world. To apply this to other worlds call the1243/// [corresponding method](World::allow_ambiguous_resource) on World1244///1245/// ## Example1246///1247/// ```1248/// # use bevy_app::prelude::*;1249/// # use bevy_ecs::prelude::*;1250/// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};1251/// # use bevy_utils::default;1252///1253/// #[derive(Resource)]1254/// struct R;1255///1256/// // these systems are ambiguous on R1257/// fn system_1(_: ResMut<R>) {}1258/// fn system_2(_: Res<R>) {}1259///1260/// let mut app = App::new();1261/// app.configure_schedules(ScheduleBuildSettings {1262/// ambiguity_detection: LogLevel::Error,1263/// ..default()1264/// });1265/// app.insert_resource(R);1266///1267/// app.add_systems(Update, ( system_1, system_2 ));1268/// app.allow_ambiguous_resource::<R>();1269///1270/// // running the app does not error.1271/// app.update();1272/// ```1273pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {1274self.main_mut().allow_ambiguous_resource::<T>();1275self1276}12771278/// Suppress warnings and errors that would result from systems in these sets having ambiguities1279/// (conflicting access but indeterminate order) with systems in `set`.1280///1281/// When possible, do this directly in the `.add_systems(Update, a.ambiguous_with(b))` call.1282/// However, sometimes two independent plugins `A` and `B` are reported as ambiguous, which you1283/// can only suppress as the consumer of both.1284#[track_caller]1285pub fn ignore_ambiguity<M1, M2, S1, S2>(1286&mut self,1287schedule: impl ScheduleLabel,1288a: S1,1289b: S2,1290) -> &mut Self1291where1292S1: IntoSystemSet<M1>,1293S2: IntoSystemSet<M2>,1294{1295self.main_mut().ignore_ambiguity(schedule, a, b);1296self1297}12981299/// Attempts to determine if an [`AppExit`] was raised since the last update.1300///1301/// Will attempt to return the first [`Error`](AppExit::Error) it encounters.1302/// This should be called after every [`update()`](App::update) otherwise you risk1303/// dropping possible [`AppExit`] events.1304pub fn should_exit(&self) -> Option<AppExit> {1305let mut reader = EventCursor::default();13061307let events = self.world().get_resource::<Events<AppExit>>()?;1308let mut events = reader.read(events);13091310if events.len() != 0 {1311return Some(1312events1313.find(|exit| exit.is_error())1314.cloned()1315.unwrap_or(AppExit::Success),1316);1317}13181319None1320}13211322/// Spawns an [`Observer`] entity, which will watch for and respond to the given event.1323///1324/// `observer` can be any system whose first parameter is [`On`].1325///1326/// # Examples1327///1328/// ```rust1329/// # use bevy_app::prelude::*;1330/// # use bevy_ecs::prelude::*;1331/// # use bevy_utils::default;1332/// #1333/// # let mut app = App::new();1334/// #1335/// # #[derive(Event)]1336/// # struct Party {1337/// # friends_allowed: bool,1338/// # };1339/// #1340/// # #[derive(EntityEvent)]1341/// # struct Invite;1342/// #1343/// # #[derive(Component)]1344/// # struct Friend;1345/// #1346///1347/// app.add_observer(|event: On<Party>, friends: Query<Entity, With<Friend>>, mut commands: Commands| {1348/// if event.friends_allowed {1349/// for friend in friends.iter() {1350/// commands.trigger_targets(Invite, friend);1351/// }1352/// }1353/// });1354/// ```1355pub fn add_observer<E: Event, B: Bundle, M>(1356&mut self,1357observer: impl IntoObserverSystem<E, B, M>,1358) -> &mut Self {1359self.world_mut().add_observer(observer);1360self1361}13621363/// Gets the error handler to set for new supapps.1364///1365/// Note that the error handler of existing subapps may differ.1366pub fn get_error_handler(&self) -> Option<ErrorHandler> {1367self.default_error_handler1368}13691370/// Set the [default error handler] for the all subapps (including the main one and future ones)1371/// that do not have one.1372///1373/// May only be called once and should be set by the application, not by libraries.1374///1375/// The handler will be called when an error is produced and not otherwise handled.1376///1377/// # Panics1378/// Panics if called multiple times.1379///1380/// # Example1381/// ```1382/// # use bevy_app::*;1383/// # use bevy_ecs::error::warn;1384/// # fn MyPlugins(_: &mut App) {}1385/// App::new()1386/// .set_error_handler(warn)1387/// .add_plugins(MyPlugins)1388/// .run();1389/// ```1390///1391/// [default error handler]: bevy_ecs::error::DefaultErrorHandler1392pub fn set_error_handler(&mut self, handler: ErrorHandler) -> &mut Self {1393assert!(1394self.default_error_handler.is_none(),1395"`set_error_handler` called multiple times on same `App`"1396);1397self.default_error_handler = Some(handler);1398for sub_app in self.sub_apps.iter_mut() {1399sub_app1400.world_mut()1401.get_resource_or_insert_with(|| DefaultErrorHandler(handler));1402}1403self1404}1405}14061407// Used for doing hokey pokey in finish and cleanup1408pub(crate) struct HokeyPokey;1409impl Plugin for HokeyPokey {1410fn build(&self, _: &mut App) {}1411}14121413type RunnerFn = Box<dyn FnOnce(App) -> AppExit>;14141415fn run_once(mut app: App) -> AppExit {1416while app.plugins_state() == PluginsState::Adding {1417#[cfg(not(all(target_arch = "wasm32", feature = "web")))]1418bevy_tasks::tick_global_task_pools_on_main_thread();1419}1420app.finish();1421app.cleanup();14221423app.update();14241425app.should_exit().unwrap_or(AppExit::Success)1426}14271428/// A [`BufferedEvent`] that indicates the [`App`] should exit. If one or more of these are present at the end of an update,1429/// the [runner](App::set_runner) will end and ([maybe](App::run)) return control to the caller.1430///1431/// This event can be used to detect when an exit is requested. Make sure that systems listening1432/// for this event run before the current update ends.1433///1434/// # Portability1435/// 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 concerns1436/// (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#))1437/// we only allow error codes between 1 and [255](u8::MAX).1438#[derive(BufferedEvent, Debug, Clone, Default, PartialEq, Eq)]1439pub enum AppExit {1440/// [`App`] exited without any problems.1441#[default]1442Success,1443/// The [`App`] experienced an unhandleable error.1444/// Holds the exit code we expect our app to return.1445Error(NonZero<u8>),1446}14471448impl AppExit {1449/// Creates a [`AppExit::Error`] with an error code of 1.1450#[must_use]1451pub const fn error() -> Self {1452Self::Error(NonZero::<u8>::MIN)1453}14541455/// Returns `true` if `self` is a [`AppExit::Success`].1456#[must_use]1457pub const fn is_success(&self) -> bool {1458matches!(self, AppExit::Success)1459}14601461/// Returns `true` if `self` is a [`AppExit::Error`].1462#[must_use]1463pub const fn is_error(&self) -> bool {1464matches!(self, AppExit::Error(_))1465}14661467/// Creates a [`AppExit`] from a code.1468///1469/// When `code` is 0 a [`AppExit::Success`] is constructed otherwise a1470/// [`AppExit::Error`] is constructed.1471#[must_use]1472pub const fn from_code(code: u8) -> Self {1473match NonZero::<u8>::new(code) {1474Some(code) => Self::Error(code),1475None => Self::Success,1476}1477}1478}14791480impl From<u8> for AppExit {1481fn from(value: u8) -> Self {1482Self::from_code(value)1483}1484}14851486#[cfg(feature = "std")]1487impl Termination for AppExit {1488fn report(self) -> ExitCode {1489match self {1490AppExit::Success => ExitCode::SUCCESS,1491// We leave logging an error to our users1492AppExit::Error(value) => ExitCode::from(value.get()),1493}1494}1495}14961497#[cfg(test)]1498mod tests {1499use core::marker::PhantomData;1500use std::sync::Mutex;15011502use bevy_ecs::{1503change_detection::{DetectChanges, ResMut},1504component::Component,1505entity::Entity,1506event::{BufferedEvent, EventWriter, Events},1507lifecycle::RemovedComponents,1508query::With,1509resource::Resource,1510schedule::{IntoScheduleConfigs, ScheduleLabel},1511system::{Commands, Query},1512world::{FromWorld, World},1513};15141515use crate::{App, AppExit, Plugin, SubApp, Update};15161517struct PluginA;1518impl Plugin for PluginA {1519fn build(&self, _app: &mut App) {}1520}1521struct PluginB;1522impl Plugin for PluginB {1523fn build(&self, _app: &mut App) {}1524}1525struct PluginC<T>(T);1526impl<T: Send + Sync + 'static> Plugin for PluginC<T> {1527fn build(&self, _app: &mut App) {}1528}1529struct PluginD;1530impl Plugin for PluginD {1531fn build(&self, _app: &mut App) {}1532fn is_unique(&self) -> bool {1533false1534}1535}15361537struct PluginE;15381539impl Plugin for PluginE {1540fn build(&self, _app: &mut App) {}15411542fn finish(&self, app: &mut App) {1543if app.is_plugin_added::<PluginA>() {1544panic!("cannot run if PluginA is already registered");1545}1546}1547}15481549struct PluginF;15501551impl Plugin for PluginF {1552fn build(&self, _app: &mut App) {}15531554fn finish(&self, app: &mut App) {1555// Ensure other plugins are available during finish1556assert_eq!(1557app.is_plugin_added::<PluginA>(),1558!app.get_added_plugins::<PluginA>().is_empty(),1559);1560}15611562fn cleanup(&self, app: &mut App) {1563// Ensure other plugins are available during finish1564assert_eq!(1565app.is_plugin_added::<PluginA>(),1566!app.get_added_plugins::<PluginA>().is_empty(),1567);1568}1569}15701571struct PluginG;15721573impl Plugin for PluginG {1574fn build(&self, _app: &mut App) {}15751576fn finish(&self, app: &mut App) {1577app.add_plugins(PluginB);1578}1579}15801581#[test]1582fn can_add_two_plugins() {1583App::new().add_plugins((PluginA, PluginB));1584}15851586#[test]1587#[should_panic]1588fn cant_add_twice_the_same_plugin() {1589App::new().add_plugins((PluginA, PluginA));1590}15911592#[test]1593fn can_add_twice_the_same_plugin_with_different_type_param() {1594App::new().add_plugins((PluginC(0), PluginC(true)));1595}15961597#[test]1598fn can_add_twice_the_same_plugin_not_unique() {1599App::new().add_plugins((PluginD, PluginD));1600}16011602#[test]1603#[should_panic]1604fn cant_call_app_run_from_plugin_build() {1605struct PluginRun;1606struct InnerPlugin;1607impl Plugin for InnerPlugin {1608fn build(&self, _: &mut App) {}1609}1610impl Plugin for PluginRun {1611fn build(&self, app: &mut App) {1612app.add_plugins(InnerPlugin).run();1613}1614}1615App::new().add_plugins(PluginRun);1616}16171618#[derive(ScheduleLabel, Hash, Clone, PartialEq, Eq, Debug)]1619struct EnterMainMenu;16201621#[derive(Component)]1622struct A;16231624fn bar(mut commands: Commands) {1625commands.spawn(A);1626}16271628fn foo(mut commands: Commands) {1629commands.spawn(A);1630}16311632#[test]1633fn add_systems_should_create_schedule_if_it_does_not_exist() {1634let mut app = App::new();1635app.add_systems(EnterMainMenu, (foo, bar));16361637app.world_mut().run_schedule(EnterMainMenu);1638assert_eq!(app.world_mut().query::<&A>().query(app.world()).count(), 2);1639}16401641#[test]1642#[should_panic]1643fn test_is_plugin_added_works_during_finish() {1644let mut app = App::new();1645app.add_plugins(PluginA);1646app.add_plugins(PluginE);1647app.finish();1648}16491650#[test]1651fn test_get_added_plugins_works_during_finish_and_cleanup() {1652let mut app = App::new();1653app.add_plugins(PluginA);1654app.add_plugins(PluginF);1655app.finish();1656}16571658#[test]1659fn test_adding_plugin_works_during_finish() {1660let mut app = App::new();1661app.add_plugins(PluginA);1662app.add_plugins(PluginG);1663app.finish();1664assert_eq!(1665app.main().plugin_registry[0].name(),1666"bevy_app::main_schedule::MainSchedulePlugin"1667);1668assert_eq!(1669app.main().plugin_registry[1].name(),1670"bevy_app::app::tests::PluginA"1671);1672assert_eq!(1673app.main().plugin_registry[2].name(),1674"bevy_app::app::tests::PluginG"1675);1676// PluginG adds PluginB during finish1677assert_eq!(1678app.main().plugin_registry[3].name(),1679"bevy_app::app::tests::PluginB"1680);1681}16821683#[test]1684fn test_derive_app_label() {1685use super::AppLabel;16861687#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1688struct UnitLabel;16891690#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1691struct TupleLabel(u32, u32);16921693#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1694struct StructLabel {1695a: u32,1696b: u32,1697}16981699#[expect(1700dead_code,1701reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."1702)]1703#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1704struct EmptyTupleLabel();17051706#[expect(1707dead_code,1708reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."1709)]1710#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1711struct EmptyStructLabel {}17121713#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1714enum EnumLabel {1715#[default]1716Unit,1717Tuple(u32, u32),1718Struct {1719a: u32,1720b: u32,1721},1722}17231724#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1725struct GenericLabel<T>(PhantomData<T>);17261727assert_eq!(UnitLabel.intern(), UnitLabel.intern());1728assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());1729assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());1730assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());1731assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());17321733assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());1734assert_eq!(1735EnumLabel::Tuple(0, 0).intern(),1736EnumLabel::Tuple(0, 0).intern()1737);1738assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());1739assert_ne!(1740EnumLabel::Tuple(0, 0).intern(),1741EnumLabel::Tuple(0, 1).intern()1742);1743assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());1744assert_ne!(1745TupleLabel(0, 0).intern(),1746StructLabel { a: 0, b: 0 }.intern()1747);1748assert_ne!(1749EnumLabel::Tuple(0, 0).intern(),1750EnumLabel::Struct { a: 0, b: 0 }.intern()1751);17521753assert_eq!(1754StructLabel { a: 0, b: 0 }.intern(),1755StructLabel { a: 0, b: 0 }.intern()1756);1757assert_eq!(1758EnumLabel::Struct { a: 0, b: 0 }.intern(),1759EnumLabel::Struct { a: 0, b: 0 }.intern()1760);1761assert_ne!(1762StructLabel { a: 0, b: 0 }.intern(),1763StructLabel { a: 0, b: 1 }.intern()1764);1765assert_ne!(1766EnumLabel::Struct { a: 0, b: 0 }.intern(),1767EnumLabel::Struct { a: 0, b: 1 }.intern()1768);1769assert_ne!(1770StructLabel { a: 0, b: 0 }.intern(),1771EnumLabel::Struct { a: 0, b: 0 }.intern()1772);1773assert_ne!(1774StructLabel { a: 0, b: 0 }.intern(),1775EnumLabel::Struct { a: 0, b: 0 }.intern()1776);1777assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);1778assert_ne!(1779EnumLabel::Struct { a: 0, b: 0 }.intern(),1780EnumLabel::Unit.intern()1781);17821783assert_eq!(1784GenericLabel::<u32>(PhantomData).intern(),1785GenericLabel::<u32>(PhantomData).intern()1786);1787assert_ne!(1788GenericLabel::<u32>(PhantomData).intern(),1789GenericLabel::<u64>(PhantomData).intern()1790);1791}17921793#[test]1794fn test_update_clears_trackers_once() {1795#[derive(Component, Copy, Clone)]1796struct Foo;17971798let mut app = App::new();1799app.world_mut().spawn_batch(core::iter::repeat_n(Foo, 5));18001801fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {1802if let Some(e) = foos.iter().next() {1803commands.entity(e).despawn();1804};1805}1806fn check_despawns(mut removed_foos: RemovedComponents<Foo>) {1807let mut despawn_count = 0;1808for _ in removed_foos.read() {1809despawn_count += 1;1810}18111812assert_eq!(despawn_count, 2);1813}18141815app.add_systems(Update, despawn_one_foo);1816app.update(); // Frame 01817app.update(); // Frame 11818app.add_systems(Update, check_despawns.after(despawn_one_foo));1819app.update(); // Should see despawns from frames 1 & 2, but not frame 01820}18211822#[test]1823fn test_extract_sees_changes() {1824use super::AppLabel;18251826#[derive(AppLabel, Clone, Copy, Hash, PartialEq, Eq, Debug)]1827struct MySubApp;18281829#[derive(Resource)]1830struct Foo(usize);18311832let mut app = App::new();1833app.world_mut().insert_resource(Foo(0));1834app.add_systems(Update, |mut foo: ResMut<Foo>| {1835foo.0 += 1;1836});18371838let mut sub_app = SubApp::new();1839sub_app.set_extract(|main_world, _sub_world| {1840assert!(main_world.get_resource_ref::<Foo>().unwrap().is_changed());1841});18421843app.insert_sub_app(MySubApp, sub_app);18441845app.update();1846}18471848#[test]1849fn runner_returns_correct_exit_code() {1850fn raise_exits(mut exits: EventWriter<AppExit>) {1851// Exit codes chosen by a fair dice roll.1852// Unlikely to overlap with default values.1853exits.write(AppExit::Success);1854exits.write(AppExit::from_code(4));1855exits.write(AppExit::from_code(73));1856}18571858let exit = App::new().add_systems(Update, raise_exits).run();18591860assert_eq!(exit, AppExit::from_code(4));1861}18621863/// Custom runners should be in charge of when `app::update` gets called as they may need to1864/// coordinate some state.1865/// bug: <https://github.com/bevyengine/bevy/issues/10385>1866/// fix: <https://github.com/bevyengine/bevy/pull/10389>1867#[test]1868fn regression_test_10385() {1869use super::{Res, Resource};1870use crate::PreUpdate;18711872#[derive(Resource)]1873struct MyState {}18741875fn my_runner(mut app: App) -> AppExit {1876let my_state = MyState {};1877app.world_mut().insert_resource(my_state);18781879for _ in 0..5 {1880app.update();1881}18821883AppExit::Success1884}18851886fn my_system(_: Res<MyState>) {1887// access state during app update1888}18891890// Should not panic due to missing resource1891App::new()1892.set_runner(my_runner)1893.add_systems(PreUpdate, my_system)1894.run();1895}18961897#[test]1898fn app_exit_size() {1899// There wont be many of them so the size isn't an issue but1900// it's nice they're so small let's keep it that way.1901assert_eq!(size_of::<AppExit>(), size_of::<u8>());1902}19031904#[test]1905fn initializing_resources_from_world() {1906#[derive(Resource)]1907struct TestResource;1908impl FromWorld for TestResource {1909fn from_world(_world: &mut World) -> Self {1910TestResource1911}1912}19131914#[derive(Resource)]1915struct NonSendTestResource {1916_marker: PhantomData<Mutex<()>>,1917}1918impl FromWorld for NonSendTestResource {1919fn from_world(_world: &mut World) -> Self {1920NonSendTestResource {1921_marker: PhantomData,1922}1923}1924}19251926App::new()1927.init_non_send_resource::<NonSendTestResource>()1928.init_resource::<TestResource>();1929}19301931#[test]1932/// Plugin should not be considered inserted while it's being built1933///1934/// bug: <https://github.com/bevyengine/bevy/issues/13815>1935fn plugin_should_not_be_added_during_build_time() {1936pub struct Foo;19371938impl Plugin for Foo {1939fn build(&self, app: &mut App) {1940assert!(!app.is_plugin_added::<Self>());1941}1942}19431944App::new().add_plugins(Foo);1945}1946#[test]1947fn events_should_be_updated_once_per_update() {1948#[derive(BufferedEvent, Clone)]1949struct TestEvent;19501951let mut app = App::new();1952app.add_event::<TestEvent>();19531954// Starts empty1955let test_events = app.world().resource::<Events<TestEvent>>();1956assert_eq!(test_events.len(), 0);1957assert_eq!(test_events.iter_current_update_events().count(), 0);1958app.update();19591960// Sending one event1961app.world_mut().write_event(TestEvent);19621963let test_events = app.world().resource::<Events<TestEvent>>();1964assert_eq!(test_events.len(), 1);1965assert_eq!(test_events.iter_current_update_events().count(), 1);1966app.update();19671968// Sending two events on the next frame1969app.world_mut().write_event(TestEvent);1970app.world_mut().write_event(TestEvent);19711972let test_events = app.world().resource::<Events<TestEvent>>();1973assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 31974assert_eq!(test_events.iter_current_update_events().count(), 2);1975app.update();19761977// Sending zero events1978let test_events = app.world().resource::<Events<TestEvent>>();1979assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 21980assert_eq!(test_events.iter_current_update_events().count(), 0);1981}1982}198319841985