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,14intern::Interned,15message::{message_update_system, MessageCursor},16prelude::*,17schedule::{InternedSystemSet, ScheduleBuildSettings, ScheduleLabel},18system::{IntoObserverSystem, ScheduleSystem, SystemId, SystemInput},19};20use bevy_platform::collections::HashMap;21use core::{fmt::Debug, num::NonZero, panic::AssertUnwindSafe};22use log::debug;2324#[cfg(feature = "trace")]25use tracing::info_span;2627#[cfg(feature = "std")]28use std::{29panic::{catch_unwind, resume_unwind},30process::{ExitCode, Termination},31};3233bevy_ecs::define_label!(34/// A strongly-typed class of labels used to identify an [`App`].35#[diagnostic::on_unimplemented(36note = "consider annotating `{Self}` with `#[derive(AppLabel)]`"37)]38AppLabel,39APP_LABEL_INTERNER40);4142pub use bevy_ecs::label::DynEq;4344/// A shorthand for `Interned<dyn AppLabel>`.45pub type InternedAppLabel = Interned<dyn AppLabel>;4647#[derive(Debug, thiserror::Error)]48pub(crate) enum AppError {49#[error("duplicate plugin {plugin_name:?}")]50DuplicatePlugin { plugin_name: String },51}5253/// [`App`] is the primary API for writing user applications. It automates the setup of a54/// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).55///56/// A single [`App`] can contain multiple [`SubApp`] instances, but [`App`] methods only affect57/// the "main" one. To access a particular [`SubApp`], use [`get_sub_app`](App::get_sub_app)58/// or [`get_sub_app_mut`](App::get_sub_app_mut).59///60///61/// # Examples62///63/// Here is a simple "Hello World" Bevy app:64///65/// ```66/// # use bevy_app::prelude::*;67/// # use bevy_ecs::prelude::*;68/// #69/// fn main() {70/// App::new()71/// .add_systems(Update, hello_world_system)72/// .run();73/// }74///75/// fn hello_world_system() {76/// println!("hello world");77/// }78/// ```79#[must_use]80pub struct App {81pub(crate) sub_apps: SubApps,82/// The function that will manage the app's lifecycle.83///84/// Bevy provides the [`WinitPlugin`] and [`ScheduleRunnerPlugin`] for windowed and headless85/// applications, respectively.86///87/// [`WinitPlugin`]: https://docs.rs/bevy/latest/bevy/winit/struct.WinitPlugin.html88/// [`ScheduleRunnerPlugin`]: https://docs.rs/bevy/latest/bevy/app/struct.ScheduleRunnerPlugin.html89pub(crate) runner: RunnerFn,90default_error_handler: Option<ErrorHandler>,91}9293impl Debug for App {94fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {95write!(f, "App {{ sub_apps: ")?;96f.debug_map()97.entries(self.sub_apps.sub_apps.iter())98.finish()?;99write!(f, "}}")100}101}102103impl Default for App {104fn default() -> Self {105let mut app = App::empty();106app.sub_apps.main.update_schedule = Some(Main.intern());107108#[cfg(feature = "bevy_reflect")]109{110#[cfg(not(feature = "reflect_auto_register"))]111app.init_resource::<AppTypeRegistry>();112113#[cfg(feature = "reflect_auto_register")]114app.insert_resource(AppTypeRegistry::new_with_derived_types());115}116117#[cfg(feature = "reflect_functions")]118app.init_resource::<AppFunctionRegistry>();119120app.add_plugins(MainSchedulePlugin);121app.add_systems(122First,123message_update_system124.in_set(bevy_ecs::message::MessageUpdateSystems)125.run_if(bevy_ecs::message::message_update_condition),126);127app.add_message::<AppExit>();128129app130}131}132133impl App {134/// Creates a new [`App`] with some default structure to enable core engine features.135/// This is the preferred constructor for most use cases.136pub fn new() -> App {137App::default()138}139140/// Creates a new empty [`App`] with minimal default configuration.141///142/// Use this constructor if you want to customize scheduling, exit handling, cleanup, etc.143pub fn empty() -> App {144Self {145sub_apps: SubApps {146main: SubApp::new(),147sub_apps: HashMap::default(),148},149runner: Box::new(run_once),150default_error_handler: None,151}152}153154/// Runs the default schedules of all sub-apps (starting with the "main" app) once.155pub fn update(&mut self) {156if self.is_building_plugins() {157panic!("App::update() was called while a plugin was building.");158}159160self.sub_apps.update();161}162163/// Runs the [`App`] by calling its [runner](Self::set_runner).164///165/// This will (re)build the [`App`] first. For general usage, see the example on the item166/// level documentation.167///168/// # Caveats169///170/// Calls to [`App::run()`] will never return on iOS and Web.171///172/// Headless apps can generally expect this method to return control to the caller when173/// it completes, but that is not the case for windowed apps. Windowed apps are typically174/// driven by an event loop and some platforms expect the program to terminate when the175/// event loop ends.176///177/// By default, *Bevy* uses the `winit` crate for window creation.178///179/// # Panics180///181/// Panics if not all plugins have been built.182pub fn run(&mut self) -> AppExit {183#[cfg(feature = "trace")]184let _bevy_app_run_span = info_span!("bevy_app").entered();185if self.is_building_plugins() {186panic!("App::run() was called while a plugin was building.");187}188189let runner = core::mem::replace(&mut self.runner, Box::new(run_once));190let app = core::mem::replace(self, App::empty());191(runner)(app)192}193194/// Sets the function that will be called when the app is run.195///196/// The runner function `f` is called only once by [`App::run`]. If the197/// presence of a main loop in the app is desired, it is the responsibility of the runner198/// function to provide it.199///200/// The runner function is usually not set manually, but by Bevy integrated plugins201/// (e.g. `WinitPlugin`).202///203/// # Examples204///205/// ```206/// # use bevy_app::prelude::*;207/// #208/// fn my_runner(mut app: App) -> AppExit {209/// loop {210/// println!("In main loop");211/// app.update();212/// if let Some(exit) = app.should_exit() {213/// return exit;214/// }215/// }216/// }217///218/// App::new()219/// .set_runner(my_runner);220/// ```221pub fn set_runner(&mut self, f: impl FnOnce(App) -> AppExit + 'static) -> &mut Self {222self.runner = Box::new(f);223self224}225226/// Returns the state of all plugins. This is usually called by the event loop, but can be227/// useful for situations where you want to use [`App::update`].228// TODO: &mut self -> &self229#[inline]230pub fn plugins_state(&mut self) -> PluginsState {231let mut overall_plugins_state = match self.main_mut().plugins_state {232PluginsState::Adding => {233let mut state = PluginsState::Ready;234let plugins = core::mem::take(&mut self.main_mut().plugin_registry);235for plugin in &plugins {236// plugins installed to main need to see all sub-apps237if !plugin.ready(self) {238state = PluginsState::Adding;239break;240}241}242self.main_mut().plugin_registry = plugins;243state244}245state => state,246};247248// overall state is the earliest state of any sub-app249self.sub_apps.iter_mut().skip(1).for_each(|s| {250overall_plugins_state = overall_plugins_state.min(s.plugins_state());251});252253overall_plugins_state254}255256/// Runs [`Plugin::finish`] for each plugin. This is usually called by the event loop once all257/// plugins are ready, but can be useful for situations where you want to use [`App::update`].258pub fn finish(&mut self) {259#[cfg(feature = "trace")]260let _finish_span = info_span!("plugin finish").entered();261// plugins installed to main should see all sub-apps262// do hokey pokey with a boxed zst plugin (doesn't allocate)263let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);264for i in 0..self.main().plugin_registry.len() {265core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);266#[cfg(feature = "trace")]267let _plugin_finish_span =268info_span!("plugin finish", plugin = hokeypokey.name()).entered();269hokeypokey.finish(self);270core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);271}272self.main_mut().plugins_state = PluginsState::Finished;273self.sub_apps.iter_mut().skip(1).for_each(SubApp::finish);274}275276/// Runs [`Plugin::cleanup`] for each plugin. This is usually called by the event loop after277/// [`App::finish`], but can be useful for situations where you want to use [`App::update`].278pub fn cleanup(&mut self) {279#[cfg(feature = "trace")]280let _cleanup_span = info_span!("plugin cleanup").entered();281// plugins installed to main should see all sub-apps282// do hokey pokey with a boxed zst plugin (doesn't allocate)283let mut hokeypokey: Box<dyn Plugin> = Box::new(HokeyPokey);284for i in 0..self.main().plugin_registry.len() {285core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);286#[cfg(feature = "trace")]287let _plugin_cleanup_span =288info_span!("plugin cleanup", plugin = hokeypokey.name()).entered();289hokeypokey.cleanup(self);290core::mem::swap(&mut self.main_mut().plugin_registry[i], &mut hokeypokey);291}292self.main_mut().plugins_state = PluginsState::Cleaned;293self.sub_apps.iter_mut().skip(1).for_each(SubApp::cleanup);294}295296/// Returns `true` if any of the sub-apps are building plugins.297pub(crate) fn is_building_plugins(&self) -> bool {298self.sub_apps.iter().any(SubApp::is_building_plugins)299}300301/// Adds one or more systems to the given schedule in this app's [`Schedules`].302///303/// # Examples304///305/// ```306/// # use bevy_app::prelude::*;307/// # use bevy_ecs::prelude::*;308/// #309/// # let mut app = App::new();310/// # fn system_a() {}311/// # fn system_b() {}312/// # fn system_c() {}313/// # fn should_run() -> bool { true }314/// #315/// app.add_systems(Update, (system_a, system_b, system_c));316/// app.add_systems(Update, (system_a, system_b).run_if(should_run));317/// ```318pub fn add_systems<M>(319&mut self,320schedule: impl ScheduleLabel,321systems: impl IntoScheduleConfigs<ScheduleSystem, M>,322) -> &mut Self {323self.main_mut().add_systems(schedule, systems);324self325}326327/// Registers a system and returns a [`SystemId`] so it can later be called by [`World::run_system`].328///329/// It's possible to register the same systems more than once, they'll be stored separately.330///331/// This is different from adding systems to a [`Schedule`] with [`App::add_systems`],332/// because the [`SystemId`] that is returned can be used anywhere in the [`World`] to run the associated system.333/// This allows for running systems in a push-based fashion.334/// Using a [`Schedule`] is still preferred for most cases335/// due to its better performance and ability to run non-conflicting systems simultaneously.336pub fn register_system<I, O, M>(337&mut self,338system: impl IntoSystem<I, O, M> + 'static,339) -> SystemId<I, O>340where341I: SystemInput + 'static,342O: 'static,343{344self.main_mut().register_system(system)345}346347/// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.348#[track_caller]349pub fn configure_sets<M>(350&mut self,351schedule: impl ScheduleLabel,352sets: impl IntoScheduleConfigs<InternedSystemSet, M>,353) -> &mut Self {354self.main_mut().configure_sets(schedule, sets);355self356}357358/// Initializes [`Message`] handling for `T` by inserting an event queue resource ([`Messages::<T>`])359/// and scheduling an [`message_update_system`] in [`First`].360///361/// See [`Messages`] for information on how to define events.362///363/// # Examples364///365/// ```366/// # use bevy_app::prelude::*;367/// # use bevy_ecs::prelude::*;368/// #369/// # #[derive(Message)]370/// # struct MyMessage;371/// # let mut app = App::new();372/// #373/// app.add_event::<MyMessage>();374/// ```375#[deprecated(since = "0.17.0", note = "Use `add_message` instead.")]376pub fn add_event<T>(&mut self) -> &mut Self377where378T: Message,379{380self.add_message::<T>()381}382383/// Initializes [`Message`] handling for `T` by inserting a message queue resource ([`Messages::<T>`])384/// and scheduling an [`message_update_system`] in [`First`].385///386/// See [`Messages`] for information on how to define messages.387///388/// # Examples389///390/// ```391/// # use bevy_app::prelude::*;392/// # use bevy_ecs::prelude::*;393/// #394/// # #[derive(Message)]395/// # struct MyMessage;396/// # let mut app = App::new();397/// #398/// app.add_message::<MyMessage>();399/// ```400pub fn add_message<M: Message>(&mut self) -> &mut Self {401self.main_mut().add_message::<M>();402self403}404405/// Inserts the [`Resource`] into the app, overwriting any existing resource of the same type.406///407/// There is also an [`init_resource`](Self::init_resource) for resources that have408/// [`Default`] or [`FromWorld`] implementations.409///410/// # Examples411///412/// ```413/// # use bevy_app::prelude::*;414/// # use bevy_ecs::prelude::*;415/// #416/// #[derive(Resource)]417/// struct MyCounter {418/// counter: usize,419/// }420///421/// App::new()422/// .insert_resource(MyCounter { counter: 0 });423/// ```424pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {425self.main_mut().insert_resource(resource);426self427}428429/// Inserts the [`Resource`], initialized with its default value, into the app,430/// if there is no existing instance of `R`.431///432/// `R` must implement [`FromWorld`].433/// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and434/// initialize the [`Resource`] with [`Default::default`].435///436/// # Examples437///438/// ```439/// # use bevy_app::prelude::*;440/// # use bevy_ecs::prelude::*;441/// #442/// #[derive(Resource)]443/// struct MyCounter {444/// counter: usize,445/// }446///447/// impl Default for MyCounter {448/// fn default() -> MyCounter {449/// MyCounter {450/// counter: 100451/// }452/// }453/// }454///455/// App::new()456/// .init_resource::<MyCounter>();457/// ```458pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {459self.main_mut().init_resource::<R>();460self461}462463/// Inserts the [`!Send`](Send) resource into the app, overwriting any existing resource464/// of the same type.465///466/// There is also an [`init_non_send_resource`](Self::init_non_send_resource) for467/// resources that implement [`Default`]468///469/// # Examples470///471/// ```472/// # use bevy_app::prelude::*;473/// # use bevy_ecs::prelude::*;474/// #475/// struct MyCounter {476/// counter: usize,477/// }478///479/// App::new()480/// .insert_non_send_resource(MyCounter { counter: 0 });481/// ```482pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {483self.world_mut().insert_non_send_resource(resource);484self485}486487/// Inserts the [`!Send`](Send) resource into the app if there is no existing instance of `R`.488///489/// `R` must implement [`FromWorld`].490/// If `R` implements [`Default`], [`FromWorld`] will be automatically implemented and491/// initialize the [`Resource`] with [`Default::default`].492pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {493self.world_mut().init_non_send_resource::<R>();494self495}496497pub(crate) fn add_boxed_plugin(498&mut self,499plugin: Box<dyn Plugin>,500) -> Result<&mut Self, AppError> {501debug!("added plugin: {}", plugin.name());502if plugin.is_unique() && self.main_mut().plugin_names.contains(plugin.name()) {503Err(AppError::DuplicatePlugin {504plugin_name: plugin.name().to_string(),505})?;506}507508// Reserve position in the plugin registry. If the plugin adds more plugins,509// they'll all end up in insertion order.510let index = self.main().plugin_registry.len();511self.main_mut()512.plugin_registry513.push(Box::new(PlaceholderPlugin));514515self.main_mut().plugin_build_depth += 1;516517#[cfg(feature = "trace")]518let _plugin_build_span = info_span!("plugin build", plugin = plugin.name()).entered();519520let f = AssertUnwindSafe(|| plugin.build(self));521522#[cfg(feature = "std")]523let result = catch_unwind(f);524525#[cfg(not(feature = "std"))]526f();527528self.main_mut()529.plugin_names530.insert(plugin.name().to_string());531self.main_mut().plugin_build_depth -= 1;532533#[cfg(feature = "std")]534if let Err(payload) = result {535resume_unwind(payload);536}537538self.main_mut().plugin_registry[index] = plugin;539Ok(self)540}541542/// Returns `true` if the [`Plugin`] has already been added.543pub fn is_plugin_added<T>(&self) -> bool544where545T: Plugin,546{547self.main().is_plugin_added::<T>()548}549550/// Returns a vector of references to all plugins of type `T` that have been added.551///552/// This can be used to read the settings of any existing plugins.553/// This vector will be empty if no plugins of that type have been added.554/// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector.555///556/// ```557/// # use bevy_app::prelude::*;558/// # #[derive(Default)]559/// # struct ImagePlugin {560/// # default_sampler: bool,561/// # }562/// # impl Plugin for ImagePlugin {563/// # fn build(&self, app: &mut App) {}564/// # }565/// # let mut app = App::new();566/// # app.add_plugins(ImagePlugin::default());567/// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;568/// ```569pub fn get_added_plugins<T>(&self) -> Vec<&T>570where571T: Plugin,572{573self.main().get_added_plugins::<T>()574}575576/// Installs a [`Plugin`] collection.577///578/// Bevy prioritizes modularity as a core principle. **All** engine features are implemented579/// as plugins, even the complex ones like rendering.580///581/// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].582///583/// There are built-in [`PluginGroup`]s that provide core engine functionality.584/// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`.585///586/// To customize the plugins in the group (reorder, disable a plugin, add a new plugin587/// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group,588/// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder).589///590/// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and591/// [`PluginGroup`]s. See [`Plugins`] for more details.592///593/// ## Examples594/// ```595/// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins};596/// #597/// # // Dummies created to avoid using `bevy_log`,598/// # // which pulls in too many dependencies and breaks rust-analyzer599/// # pub struct LogPlugin;600/// # impl Plugin for LogPlugin {601/// # fn build(&self, app: &mut App) {}602/// # }603/// App::new()604/// .add_plugins(MinimalPlugins);605/// App::new()606/// .add_plugins((MinimalPlugins, LogPlugin));607/// ```608///609/// # Panics610///611/// Panics if one of the plugins had already been added to the application.612///613/// [`PluginGroup`]:super::PluginGroup614#[track_caller]615pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {616if matches!(617self.plugins_state(),618PluginsState::Cleaned | PluginsState::Finished619) {620panic!(621"Plugins cannot be added after App::cleanup() or App::finish() has been called."622);623}624plugins.add_to_app(self);625self626}627628/// Registers the type `T` in the [`AppTypeRegistry`] resource,629/// adding reflect data as specified in the [`Reflect`](bevy_reflect::Reflect) derive:630/// ```ignore (No serde "derive" feature)631/// #[derive(Component, Serialize, Deserialize, Reflect)]632/// #[reflect(Component, Serialize, Deserialize)] // will register ReflectComponent, ReflectSerialize, ReflectDeserialize633/// ```634///635/// See [`bevy_reflect::TypeRegistry::register`] for more information.636#[cfg(feature = "bevy_reflect")]637pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {638self.main_mut().register_type::<T>();639self640}641642/// Associates type data `D` with type `T` in the [`AppTypeRegistry`] resource.643///644/// Most of the time [`register_type`](Self::register_type) can be used instead to register a645/// type you derived [`Reflect`](bevy_reflect::Reflect) for. However, in cases where you want to646/// add a piece of type data that was not included in the list of `#[reflect(...)]` type data in647/// the derive, or where the type is generic and cannot register e.g. `ReflectSerialize`648/// unconditionally without knowing the specific type parameters, this method can be used to649/// insert additional type data.650///651/// # Example652/// ```653/// use bevy_app::App;654/// use bevy_reflect::{ReflectSerialize, ReflectDeserialize};655///656/// App::new()657/// .register_type::<Option<String>>()658/// .register_type_data::<Option<String>, ReflectSerialize>()659/// .register_type_data::<Option<String>, ReflectDeserialize>();660/// ```661///662/// See [`bevy_reflect::TypeRegistry::register_type_data`].663#[cfg(feature = "bevy_reflect")]664pub fn register_type_data<665T: bevy_reflect::Reflect + bevy_reflect::TypePath,666D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,667>(668&mut self,669) -> &mut Self {670self.main_mut().register_type_data::<T, D>();671self672}673674/// Registers the given function into the [`AppFunctionRegistry`] resource.675///676/// The given function will internally be stored as a [`DynamicFunction`]677/// and mapped according to its [name].678///679/// Because the function must have a name,680/// anonymous functions (e.g. `|a: i32, b: i32| { a + b }`) and closures must instead681/// be registered using [`register_function_with_name`] or converted to a [`DynamicFunction`]682/// and named using [`DynamicFunction::with_name`].683/// Failure to do so will result in a panic.684///685/// Only types that implement [`IntoFunction`] may be registered via this method.686///687/// See [`FunctionRegistry::register`] for more information.688///689/// # Panics690///691/// Panics if a function has already been registered with the given name692/// or if the function is missing a name (such as when it is an anonymous function).693///694/// # Examples695///696/// ```697/// use bevy_app::App;698///699/// fn add(a: i32, b: i32) -> i32 {700/// a + b701/// }702///703/// App::new().register_function(add);704/// ```705///706/// Functions cannot be registered more than once.707///708/// ```should_panic709/// use bevy_app::App;710///711/// fn add(a: i32, b: i32) -> i32 {712/// a + b713/// }714///715/// App::new()716/// .register_function(add)717/// // Panic! A function has already been registered with the name "my_function"718/// .register_function(add);719/// ```720///721/// Anonymous functions and closures should be registered using [`register_function_with_name`] or given a name using [`DynamicFunction::with_name`].722///723/// ```should_panic724/// use bevy_app::App;725///726/// // Panic! Anonymous functions cannot be registered using `register_function`727/// App::new().register_function(|a: i32, b: i32| a + b);728/// ```729///730/// [`register_function_with_name`]: Self::register_function_with_name731/// [`DynamicFunction`]: bevy_reflect::func::DynamicFunction732/// [name]: bevy_reflect::func::FunctionInfo::name733/// [`DynamicFunction::with_name`]: bevy_reflect::func::DynamicFunction::with_name734/// [`IntoFunction`]: bevy_reflect::func::IntoFunction735/// [`FunctionRegistry::register`]: bevy_reflect::func::FunctionRegistry::register736#[cfg(feature = "reflect_functions")]737pub fn register_function<F, Marker>(&mut self, function: F) -> &mut Self738where739F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,740{741self.main_mut().register_function(function);742self743}744745/// Registers the given function or closure into the [`AppFunctionRegistry`] resource using the given name.746///747/// To avoid conflicts, it's recommended to use a unique name for the function.748/// This can be achieved by "namespacing" the function with a unique identifier,749/// such as the name of your crate.750///751/// For example, to register a function, `add`, from a crate, `my_crate`,752/// you could use the name, `"my_crate::add"`.753///754/// Another approach could be to use the [type name] of the function,755/// however, it should be noted that anonymous functions do _not_ have unique type names.756///757/// For named functions (e.g. `fn add(a: i32, b: i32) -> i32 { a + b }`) where a custom name is not needed,758/// it's recommended to use [`register_function`] instead as the generated name is guaranteed to be unique.759///760/// Only types that implement [`IntoFunction`] may be registered via this method.761///762/// See [`FunctionRegistry::register_with_name`] for more information.763///764/// # Panics765///766/// Panics if a function has already been registered with the given name.767///768/// # Examples769///770/// ```771/// use bevy_app::App;772///773/// fn mul(a: i32, b: i32) -> i32 {774/// a * b775/// }776///777/// let div = |a: i32, b: i32| a / b;778///779/// App::new()780/// // Registering an anonymous function with a unique name781/// .register_function_with_name("my_crate::add", |a: i32, b: i32| {782/// a + b783/// })784/// // Registering an existing function with its type name785/// .register_function_with_name(std::any::type_name_of_val(&mul), mul)786/// // Registering an existing function with a custom name787/// .register_function_with_name("my_crate::mul", mul)788/// // Be careful not to register anonymous functions with their type name.789/// // This code works but registers the function with a non-unique name like `foo::bar::{{closure}}`790/// .register_function_with_name(std::any::type_name_of_val(&div), div);791/// ```792///793/// Names must be unique.794///795/// ```should_panic796/// use bevy_app::App;797///798/// fn one() {}799/// fn two() {}800///801/// App::new()802/// .register_function_with_name("my_function", one)803/// // Panic! A function has already been registered with the name "my_function"804/// .register_function_with_name("my_function", two);805/// ```806///807/// [type name]: std::any::type_name808/// [`register_function`]: Self::register_function809/// [`IntoFunction`]: bevy_reflect::func::IntoFunction810/// [`FunctionRegistry::register_with_name`]: bevy_reflect::func::FunctionRegistry::register_with_name811#[cfg(feature = "reflect_functions")]812pub fn register_function_with_name<F, Marker>(813&mut self,814name: impl Into<alloc::borrow::Cow<'static, str>>,815function: F,816) -> &mut Self817where818F: bevy_reflect::func::IntoFunction<'static, Marker> + 'static,819{820self.main_mut().register_function_with_name(name, function);821self822}823824/// Registers the given component `R` as a [required component] for `T`.825///826/// When `T` is added to an entity, `R` and its own required components will also be added827/// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.828/// If a custom constructor is desired, use [`App::register_required_components_with`] instead.829///830/// For the non-panicking version, see [`App::try_register_required_components`].831///832/// Note that requirements must currently be registered before `T` is inserted into the world833/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.834///835/// [required component]: Component#required-components836///837/// # Panics838///839/// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added840/// on an entity before the registration.841///842/// Indirect requirements through other components are allowed. In those cases, any existing requirements843/// will only be overwritten if the new requirement is more specific.844///845/// # Example846///847/// ```848/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};849/// # use bevy_ecs::prelude::*;850/// #[derive(Component)]851/// struct A;852///853/// #[derive(Component, Default, PartialEq, Eq, Debug)]854/// struct B(usize);855///856/// #[derive(Component, Default, PartialEq, Eq, Debug)]857/// struct C(u32);858///859/// # let mut app = App::new();860/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);861/// // Register B as required by A and C as required by B.862/// app.register_required_components::<A, B>();863/// app.register_required_components::<B, C>();864///865/// fn setup(mut commands: Commands) {866/// // This will implicitly also insert B and C with their Default constructors.867/// commands.spawn(A);868/// }869///870/// fn validate(query: Option<Single<(&A, &B, &C)>>) {871/// let (a, b, c) = query.unwrap().into_inner();872/// assert_eq!(b, &B(0));873/// assert_eq!(c, &C(0));874/// }875/// # app.update();876/// ```877pub fn register_required_components<T: Component, R: Component + Default>(878&mut self,879) -> &mut Self {880self.world_mut().register_required_components::<T, R>();881self882}883884/// Registers the given component `R` as a [required component] for `T`.885///886/// When `T` is added to an entity, `R` and its own required components will also be added887/// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.888/// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.889///890/// For the non-panicking version, see [`App::try_register_required_components_with`].891///892/// Note that requirements must currently be registered before `T` is inserted into the world893/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.894///895/// [required component]: Component#required-components896///897/// # Panics898///899/// Panics if `R` is already a directly required component for `T`, or if `T` has ever been added900/// on an entity before the registration.901///902/// Indirect requirements through other components are allowed. In those cases, any existing requirements903/// will only be overwritten if the new requirement is more specific.904///905/// # Example906///907/// ```908/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};909/// # use bevy_ecs::prelude::*;910/// #[derive(Component)]911/// struct A;912///913/// #[derive(Component, Default, PartialEq, Eq, Debug)]914/// struct B(usize);915///916/// #[derive(Component, Default, PartialEq, Eq, Debug)]917/// struct C(u32);918///919/// # let mut app = App::new();920/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);921/// // Register B and C as required by A and C as required by B.922/// // A requiring C directly will overwrite the indirect requirement through B.923/// app.register_required_components::<A, B>();924/// app.register_required_components_with::<B, C>(|| C(1));925/// app.register_required_components_with::<A, C>(|| C(2));926///927/// fn setup(mut commands: Commands) {928/// // This will implicitly also insert B with its Default constructor and C929/// // with the custom constructor defined by A.930/// commands.spawn(A);931/// }932///933/// fn validate(query: Option<Single<(&A, &B, &C)>>) {934/// let (a, b, c) = query.unwrap().into_inner();935/// assert_eq!(b, &B(0));936/// assert_eq!(c, &C(2));937/// }938/// # app.update();939/// ```940pub fn register_required_components_with<T: Component, R: Component>(941&mut self,942constructor: fn() -> R,943) -> &mut Self {944self.world_mut()945.register_required_components_with::<T, R>(constructor);946self947}948949/// Tries to register the given component `R` as a [required component] for `T`.950///951/// When `T` is added to an entity, `R` and its own required components will also be added952/// if `R` was not already provided. The [`Default`] `constructor` will be used for the creation of `R`.953/// If a custom constructor is desired, use [`App::register_required_components_with`] instead.954///955/// For the panicking version, see [`App::register_required_components`].956///957/// Note that requirements must currently be registered before `T` is inserted into the world958/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.959///960/// [required component]: Component#required-components961///962/// # Errors963///964/// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added965/// on an entity before the registration.966///967/// Indirect requirements through other components are allowed. In those cases, any existing requirements968/// will only be overwritten if the new requirement is more specific.969///970/// # Example971///972/// ```973/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};974/// # use bevy_ecs::prelude::*;975/// #[derive(Component)]976/// struct A;977///978/// #[derive(Component, Default, PartialEq, Eq, Debug)]979/// struct B(usize);980///981/// #[derive(Component, Default, PartialEq, Eq, Debug)]982/// struct C(u32);983///984/// # let mut app = App::new();985/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);986/// // Register B as required by A and C as required by B.987/// app.register_required_components::<A, B>();988/// app.register_required_components::<B, C>();989///990/// // Duplicate registration! This will fail.991/// assert!(app.try_register_required_components::<A, B>().is_err());992///993/// fn setup(mut commands: Commands) {994/// // This will implicitly also insert B and C with their Default constructors.995/// commands.spawn(A);996/// }997///998/// fn validate(query: Option<Single<(&A, &B, &C)>>) {999/// let (a, b, c) = query.unwrap().into_inner();1000/// assert_eq!(b, &B(0));1001/// assert_eq!(c, &C(0));1002/// }1003/// # app.update();1004/// ```1005pub fn try_register_required_components<T: Component, R: Component + Default>(1006&mut self,1007) -> Result<(), RequiredComponentsError> {1008self.world_mut().try_register_required_components::<T, R>()1009}10101011/// Tries to register the given component `R` as a [required component] for `T`.1012///1013/// When `T` is added to an entity, `R` and its own required components will also be added1014/// if `R` was not already provided. The given `constructor` will be used for the creation of `R`.1015/// If a [`Default`] constructor is desired, use [`App::register_required_components`] instead.1016///1017/// For the panicking version, see [`App::register_required_components_with`].1018///1019/// Note that requirements must currently be registered before `T` is inserted into the world1020/// for the first time. Commonly, this is done in plugins. This limitation may be fixed in the future.1021///1022/// [required component]: Component#required-components1023///1024/// # Errors1025///1026/// Returns a [`RequiredComponentsError`] if `R` is already a directly required component for `T`, or if `T` has ever been added1027/// on an entity before the registration.1028///1029/// Indirect requirements through other components are allowed. In those cases, any existing requirements1030/// will only be overwritten if the new requirement is more specific.1031///1032/// # Example1033///1034/// ```1035/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, Startup};1036/// # use bevy_ecs::prelude::*;1037/// #[derive(Component)]1038/// struct A;1039///1040/// #[derive(Component, Default, PartialEq, Eq, Debug)]1041/// struct B(usize);1042///1043/// #[derive(Component, Default, PartialEq, Eq, Debug)]1044/// struct C(u32);1045///1046/// # let mut app = App::new();1047/// # app.add_plugins(MinimalPlugins).add_systems(Startup, setup);1048/// // Register B and C as required by A and C as required by B.1049/// // A requiring C directly will overwrite the indirect requirement through B.1050/// app.register_required_components::<A, B>();1051/// app.register_required_components_with::<B, C>(|| C(1));1052/// app.register_required_components_with::<A, C>(|| C(2));1053///1054/// // Duplicate registration! Even if the constructors were different, this would fail.1055/// assert!(app.try_register_required_components_with::<B, C>(|| C(1)).is_err());1056///1057/// fn setup(mut commands: Commands) {1058/// // This will implicitly also insert B with its Default constructor and C1059/// // with the custom constructor defined by A.1060/// commands.spawn(A);1061/// }1062///1063/// fn validate(query: Option<Single<(&A, &B, &C)>>) {1064/// let (a, b, c) = query.unwrap().into_inner();1065/// assert_eq!(b, &B(0));1066/// assert_eq!(c, &C(2));1067/// }1068/// # app.update();1069/// ```1070pub fn try_register_required_components_with<T: Component, R: Component>(1071&mut self,1072constructor: fn() -> R,1073) -> Result<(), RequiredComponentsError> {1074self.world_mut()1075.try_register_required_components_with::<T, R>(constructor)1076}10771078/// Registers a component type as "disabling",1079/// using [default query filters](bevy_ecs::entity_disabling::DefaultQueryFilters) to exclude entities with the component from queries.1080///1081/// # Warning1082///1083/// As discussed in the [module docs](bevy_ecs::entity_disabling), this can have performance implications,1084/// as well as create interoperability issues, and should be used with caution.1085pub fn register_disabling_component<C: Component>(&mut self) {1086self.world_mut().register_disabling_component::<C>();1087}10881089/// Returns a reference to the main [`SubApp`]'s [`World`]. This is the same as calling1090/// [`app.main().world()`].1091///1092/// [`app.main().world()`]: SubApp::world1093pub fn world(&self) -> &World {1094self.main().world()1095}10961097/// Returns a mutable reference to the main [`SubApp`]'s [`World`]. This is the same as calling1098/// [`app.main_mut().world_mut()`].1099///1100/// [`app.main_mut().world_mut()`]: SubApp::world_mut1101pub fn world_mut(&mut self) -> &mut World {1102self.main_mut().world_mut()1103}11041105/// Returns a reference to the main [`SubApp`].1106pub fn main(&self) -> &SubApp {1107&self.sub_apps.main1108}11091110/// Returns a mutable reference to the main [`SubApp`].1111pub fn main_mut(&mut self) -> &mut SubApp {1112&mut self.sub_apps.main1113}11141115/// Returns a reference to the [`SubApps`] collection.1116pub fn sub_apps(&self) -> &SubApps {1117&self.sub_apps1118}11191120/// Returns a mutable reference to the [`SubApps`] collection.1121pub fn sub_apps_mut(&mut self) -> &mut SubApps {1122&mut self.sub_apps1123}11241125/// Returns a reference to the [`SubApp`] with the given label.1126///1127/// # Panics1128///1129/// Panics if the [`SubApp`] doesn't exist.1130pub fn sub_app(&self, label: impl AppLabel) -> &SubApp {1131let str = label.intern();1132self.get_sub_app(label).unwrap_or_else(|| {1133panic!("No sub-app with label '{:?}' exists.", str);1134})1135}11361137/// Returns a reference to the [`SubApp`] with the given label.1138///1139/// # Panics1140///1141/// Panics if the [`SubApp`] doesn't exist.1142pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut SubApp {1143let str = label.intern();1144self.get_sub_app_mut(label).unwrap_or_else(|| {1145panic!("No sub-app with label '{:?}' exists.", str);1146})1147}11481149/// Returns a reference to the [`SubApp`] with the given label, if it exists.1150pub fn get_sub_app(&self, label: impl AppLabel) -> Option<&SubApp> {1151self.sub_apps.sub_apps.get(&label.intern())1152}11531154/// Returns a mutable reference to the [`SubApp`] with the given label, if it exists.1155pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Option<&mut SubApp> {1156self.sub_apps.sub_apps.get_mut(&label.intern())1157}11581159/// Inserts a [`SubApp`] with the given label.1160pub fn insert_sub_app(&mut self, label: impl AppLabel, mut sub_app: SubApp) {1161if let Some(handler) = self.default_error_handler {1162sub_app1163.world_mut()1164.get_resource_or_insert_with(|| DefaultErrorHandler(handler));1165}1166self.sub_apps.sub_apps.insert(label.intern(), sub_app);1167}11681169/// Removes the [`SubApp`] with the given label, if it exists.1170pub fn remove_sub_app(&mut self, label: impl AppLabel) -> Option<SubApp> {1171self.sub_apps.sub_apps.remove(&label.intern())1172}11731174/// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.1175pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {1176self.sub_apps.update_subapp_by_label(label);1177}11781179/// Inserts a new `schedule` under the provided `label`, overwriting any existing1180/// schedule with the same label.1181pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {1182self.main_mut().add_schedule(schedule);1183self1184}11851186/// Initializes an empty `schedule` under the provided `label`, if it does not exist.1187///1188/// See [`add_schedule`](Self::add_schedule) to insert an existing schedule.1189pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {1190self.main_mut().init_schedule(label);1191self1192}11931194/// Returns a reference to the [`Schedule`] with the provided `label` if it exists.1195pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {1196self.main().get_schedule(label)1197}11981199/// Returns a mutable reference to the [`Schedule`] with the provided `label` if it exists.1200pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {1201self.main_mut().get_schedule_mut(label)1202}12031204/// Runs function `f` with the [`Schedule`] associated with `label`.1205///1206/// **Note:** This will create the schedule if it does not already exist.1207pub fn edit_schedule(1208&mut self,1209label: impl ScheduleLabel,1210f: impl FnMut(&mut Schedule),1211) -> &mut Self {1212self.main_mut().edit_schedule(label, f);1213self1214}12151216/// Applies the provided [`ScheduleBuildSettings`] to all schedules.1217pub fn configure_schedules(1218&mut self,1219schedule_build_settings: ScheduleBuildSettings,1220) -> &mut Self {1221self.main_mut().configure_schedules(schedule_build_settings);1222self1223}12241225/// When doing [ambiguity checking](ScheduleBuildSettings) this1226/// ignores systems that are ambiguous on [`Component`] T.1227///1228/// This settings only applies to the main world. To apply this to other worlds call the1229/// [corresponding method](World::allow_ambiguous_component) on World1230///1231/// ## Example1232///1233/// ```1234/// # use bevy_app::prelude::*;1235/// # use bevy_ecs::prelude::*;1236/// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};1237/// # use bevy_utils::default;1238///1239/// #[derive(Component)]1240/// struct A;1241///1242/// // these systems are ambiguous on A1243/// fn system_1(_: Query<&mut A>) {}1244/// fn system_2(_: Query<&A>) {}1245///1246/// let mut app = App::new();1247/// app.configure_schedules(ScheduleBuildSettings {1248/// ambiguity_detection: LogLevel::Error,1249/// ..default()1250/// });1251///1252/// app.add_systems(Update, ( system_1, system_2 ));1253/// app.allow_ambiguous_component::<A>();1254///1255/// // running the app does not error.1256/// app.update();1257/// ```1258pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {1259self.main_mut().allow_ambiguous_component::<T>();1260self1261}12621263/// When doing [ambiguity checking](ScheduleBuildSettings) this1264/// ignores systems that are ambiguous on [`Resource`] T.1265///1266/// This settings only applies to the main world. To apply this to other worlds call the1267/// [corresponding method](World::allow_ambiguous_resource) on World1268///1269/// ## Example1270///1271/// ```1272/// # use bevy_app::prelude::*;1273/// # use bevy_ecs::prelude::*;1274/// # use bevy_ecs::schedule::{LogLevel, ScheduleBuildSettings};1275/// # use bevy_utils::default;1276///1277/// #[derive(Resource)]1278/// struct R;1279///1280/// // these systems are ambiguous on R1281/// fn system_1(_: ResMut<R>) {}1282/// fn system_2(_: Res<R>) {}1283///1284/// let mut app = App::new();1285/// app.configure_schedules(ScheduleBuildSettings {1286/// ambiguity_detection: LogLevel::Error,1287/// ..default()1288/// });1289/// app.insert_resource(R);1290///1291/// app.add_systems(Update, ( system_1, system_2 ));1292/// app.allow_ambiguous_resource::<R>();1293///1294/// // running the app does not error.1295/// app.update();1296/// ```1297pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {1298self.main_mut().allow_ambiguous_resource::<T>();1299self1300}13011302/// Suppress warnings and errors that would result from systems in these sets having ambiguities1303/// (conflicting access but indeterminate order) with systems in `set`.1304///1305/// When possible, do this directly in the `.add_systems(Update, a.ambiguous_with(b))` call.1306/// However, sometimes two independent plugins `A` and `B` are reported as ambiguous, which you1307/// can only suppress as the consumer of both.1308#[track_caller]1309pub fn ignore_ambiguity<M1, M2, S1, S2>(1310&mut self,1311schedule: impl ScheduleLabel,1312a: S1,1313b: S2,1314) -> &mut Self1315where1316S1: IntoSystemSet<M1>,1317S2: IntoSystemSet<M2>,1318{1319self.main_mut().ignore_ambiguity(schedule, a, b);1320self1321}13221323/// Attempts to determine if an [`AppExit`] was raised since the last update.1324///1325/// Will attempt to return the first [`Error`](AppExit::Error) it encounters.1326/// This should be called after every [`update()`](App::update) otherwise you risk1327/// dropping possible [`AppExit`] events.1328pub fn should_exit(&self) -> Option<AppExit> {1329let mut reader = MessageCursor::default();13301331let messages = self.world().get_resource::<Messages<AppExit>>()?;1332let mut messages = reader.read(messages);13331334if messages.len() != 0 {1335return Some(1336messages1337.find(|exit| exit.is_error())1338.cloned()1339.unwrap_or(AppExit::Success),1340);1341}13421343None1344}13451346/// Spawns an [`Observer`] entity, which will watch for and respond to the given event.1347///1348/// `observer` can be any system whose first parameter is [`On`].1349///1350/// # Examples1351///1352/// ```rust1353/// # use bevy_app::prelude::*;1354/// # use bevy_ecs::prelude::*;1355/// # use bevy_utils::default;1356/// #1357/// # let mut app = App::new();1358/// #1359/// # #[derive(Event)]1360/// # struct Party {1361/// # friends_allowed: bool,1362/// # };1363/// #1364/// # #[derive(EntityEvent)]1365/// # struct Invite {1366/// # entity: Entity,1367/// # }1368/// #1369/// # #[derive(Component)]1370/// # struct Friend;1371/// #1372///1373/// app.add_observer(|event: On<Party>, friends: Query<Entity, With<Friend>>, mut commands: Commands| {1374/// if event.friends_allowed {1375/// for entity in friends.iter() {1376/// commands.trigger(Invite { entity } );1377/// }1378/// }1379/// });1380/// ```1381pub fn add_observer<E: Event, B: Bundle, M>(1382&mut self,1383observer: impl IntoObserverSystem<E, B, M>,1384) -> &mut Self {1385self.world_mut().add_observer(observer);1386self1387}13881389/// Gets the error handler to set for new supapps.1390///1391/// Note that the error handler of existing subapps may differ.1392pub fn get_error_handler(&self) -> Option<ErrorHandler> {1393self.default_error_handler1394}13951396/// Set the [default error handler] for the all subapps (including the main one and future ones)1397/// that do not have one.1398///1399/// May only be called once and should be set by the application, not by libraries.1400///1401/// The handler will be called when an error is produced and not otherwise handled.1402///1403/// # Panics1404/// Panics if called multiple times.1405///1406/// # Example1407/// ```1408/// # use bevy_app::*;1409/// # use bevy_ecs::error::warn;1410/// # fn MyPlugins(_: &mut App) {}1411/// App::new()1412/// .set_error_handler(warn)1413/// .add_plugins(MyPlugins)1414/// .run();1415/// ```1416///1417/// [default error handler]: bevy_ecs::error::DefaultErrorHandler1418pub fn set_error_handler(&mut self, handler: ErrorHandler) -> &mut Self {1419assert!(1420self.default_error_handler.is_none(),1421"`set_error_handler` called multiple times on same `App`"1422);1423self.default_error_handler = Some(handler);1424for sub_app in self.sub_apps.iter_mut() {1425sub_app1426.world_mut()1427.get_resource_or_insert_with(|| DefaultErrorHandler(handler));1428}1429self1430}1431}14321433// Used for doing hokey pokey in finish and cleanup1434pub(crate) struct HokeyPokey;1435impl Plugin for HokeyPokey {1436fn build(&self, _: &mut App) {}1437}14381439type RunnerFn = Box<dyn FnOnce(App) -> AppExit>;14401441fn run_once(mut app: App) -> AppExit {1442while app.plugins_state() == PluginsState::Adding {1443#[cfg(not(all(target_arch = "wasm32", feature = "web")))]1444bevy_tasks::tick_global_task_pools_on_main_thread();1445}1446app.finish();1447app.cleanup();14481449app.update();14501451app.should_exit().unwrap_or(AppExit::Success)1452}14531454/// A [`Message`] that indicates the [`App`] should exit. If one or more of these are present at the end of an update,1455/// the [runner](App::set_runner) will end and ([maybe](App::run)) return control to the caller.1456///1457/// This message can be used to detect when an exit is requested. Make sure that systems listening1458/// for this message run before the current update ends.1459///1460/// # Portability1461/// 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 concerns1462/// (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#))1463/// we only allow error codes between 1 and [255](u8::MAX).1464#[derive(Message, Debug, Clone, Default, PartialEq, Eq)]1465pub enum AppExit {1466/// [`App`] exited without any problems.1467#[default]1468Success,1469/// The [`App`] experienced an unhandleable error.1470/// Holds the exit code we expect our app to return.1471Error(NonZero<u8>),1472}14731474impl AppExit {1475/// Creates a [`AppExit::Error`] with an error code of 1.1476#[must_use]1477pub const fn error() -> Self {1478Self::Error(NonZero::<u8>::MIN)1479}14801481/// Returns `true` if `self` is a [`AppExit::Success`].1482#[must_use]1483pub const fn is_success(&self) -> bool {1484matches!(self, AppExit::Success)1485}14861487/// Returns `true` if `self` is a [`AppExit::Error`].1488#[must_use]1489pub const fn is_error(&self) -> bool {1490matches!(self, AppExit::Error(_))1491}14921493/// Creates a [`AppExit`] from a code.1494///1495/// When `code` is 0 a [`AppExit::Success`] is constructed otherwise a1496/// [`AppExit::Error`] is constructed.1497#[must_use]1498pub const fn from_code(code: u8) -> Self {1499match NonZero::<u8>::new(code) {1500Some(code) => Self::Error(code),1501None => Self::Success,1502}1503}1504}15051506impl From<u8> for AppExit {1507fn from(value: u8) -> Self {1508Self::from_code(value)1509}1510}15111512#[cfg(feature = "std")]1513impl Termination for AppExit {1514fn report(self) -> ExitCode {1515match self {1516AppExit::Success => ExitCode::SUCCESS,1517// We leave logging an error to our users1518AppExit::Error(value) => ExitCode::from(value.get()),1519}1520}1521}15221523#[cfg(test)]1524mod tests {1525use core::marker::PhantomData;1526use std::sync::Mutex;15271528use bevy_ecs::{1529change_detection::{DetectChanges, ResMut},1530component::Component,1531entity::Entity,1532lifecycle::RemovedComponents,1533message::{Message, MessageWriter, Messages},1534query::With,1535resource::Resource,1536schedule::{IntoScheduleConfigs, ScheduleLabel},1537system::{Commands, Query},1538world::{FromWorld, World},1539};15401541use crate::{App, AppExit, Plugin, SubApp, Update};15421543struct PluginA;1544impl Plugin for PluginA {1545fn build(&self, _app: &mut App) {}1546}1547struct PluginB;1548impl Plugin for PluginB {1549fn build(&self, _app: &mut App) {}1550}1551struct PluginC<T>(T);1552impl<T: Send + Sync + 'static> Plugin for PluginC<T> {1553fn build(&self, _app: &mut App) {}1554}1555struct PluginD;1556impl Plugin for PluginD {1557fn build(&self, _app: &mut App) {}1558fn is_unique(&self) -> bool {1559false1560}1561}15621563struct PluginE;15641565impl Plugin for PluginE {1566fn build(&self, _app: &mut App) {}15671568fn finish(&self, app: &mut App) {1569if app.is_plugin_added::<PluginA>() {1570panic!("cannot run if PluginA is already registered");1571}1572}1573}15741575struct PluginF;15761577impl Plugin for PluginF {1578fn build(&self, _app: &mut App) {}15791580fn finish(&self, app: &mut App) {1581// Ensure other plugins are available during finish1582assert_eq!(1583app.is_plugin_added::<PluginA>(),1584!app.get_added_plugins::<PluginA>().is_empty(),1585);1586}15871588fn cleanup(&self, app: &mut App) {1589// Ensure other plugins are available during finish1590assert_eq!(1591app.is_plugin_added::<PluginA>(),1592!app.get_added_plugins::<PluginA>().is_empty(),1593);1594}1595}15961597struct PluginG;15981599impl Plugin for PluginG {1600fn build(&self, _app: &mut App) {}16011602fn finish(&self, app: &mut App) {1603app.add_plugins(PluginB);1604}1605}16061607#[test]1608fn can_add_two_plugins() {1609App::new().add_plugins((PluginA, PluginB));1610}16111612#[test]1613#[should_panic]1614fn cant_add_twice_the_same_plugin() {1615App::new().add_plugins((PluginA, PluginA));1616}16171618#[test]1619fn can_add_twice_the_same_plugin_with_different_type_param() {1620App::new().add_plugins((PluginC(0), PluginC(true)));1621}16221623#[test]1624fn can_add_twice_the_same_plugin_not_unique() {1625App::new().add_plugins((PluginD, PluginD));1626}16271628#[test]1629#[should_panic]1630fn cant_call_app_run_from_plugin_build() {1631struct PluginRun;1632struct InnerPlugin;1633impl Plugin for InnerPlugin {1634fn build(&self, _: &mut App) {}1635}1636impl Plugin for PluginRun {1637fn build(&self, app: &mut App) {1638app.add_plugins(InnerPlugin).run();1639}1640}1641App::new().add_plugins(PluginRun);1642}16431644#[derive(ScheduleLabel, Hash, Clone, PartialEq, Eq, Debug)]1645struct EnterMainMenu;16461647#[derive(Component)]1648struct A;16491650fn bar(mut commands: Commands) {1651commands.spawn(A);1652}16531654fn foo(mut commands: Commands) {1655commands.spawn(A);1656}16571658#[test]1659fn add_systems_should_create_schedule_if_it_does_not_exist() {1660let mut app = App::new();1661app.add_systems(EnterMainMenu, (foo, bar));16621663app.world_mut().run_schedule(EnterMainMenu);1664assert_eq!(app.world_mut().query::<&A>().query(app.world()).count(), 2);1665}16661667#[test]1668#[should_panic]1669fn test_is_plugin_added_works_during_finish() {1670let mut app = App::new();1671app.add_plugins(PluginA);1672app.add_plugins(PluginE);1673app.finish();1674}16751676#[test]1677fn test_get_added_plugins_works_during_finish_and_cleanup() {1678let mut app = App::new();1679app.add_plugins(PluginA);1680app.add_plugins(PluginF);1681app.finish();1682}16831684#[test]1685fn test_adding_plugin_works_during_finish() {1686let mut app = App::new();1687app.add_plugins(PluginA);1688app.add_plugins(PluginG);1689app.finish();1690assert_eq!(1691app.main().plugin_registry[0].name(),1692"bevy_app::main_schedule::MainSchedulePlugin"1693);1694assert_eq!(1695app.main().plugin_registry[1].name(),1696"bevy_app::app::tests::PluginA"1697);1698assert_eq!(1699app.main().plugin_registry[2].name(),1700"bevy_app::app::tests::PluginG"1701);1702// PluginG adds PluginB during finish1703assert_eq!(1704app.main().plugin_registry[3].name(),1705"bevy_app::app::tests::PluginB"1706);1707}17081709#[test]1710fn test_derive_app_label() {1711use super::AppLabel;17121713#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1714struct UnitLabel;17151716#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1717struct TupleLabel(u32, u32);17181719#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1720struct StructLabel {1721a: u32,1722b: u32,1723}17241725#[expect(1726dead_code,1727reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."1728)]1729#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1730struct EmptyTupleLabel();17311732#[expect(1733dead_code,1734reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."1735)]1736#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1737struct EmptyStructLabel {}17381739#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1740enum EnumLabel {1741#[default]1742Unit,1743Tuple(u32, u32),1744Struct {1745a: u32,1746b: u32,1747},1748}17491750#[derive(AppLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]1751struct GenericLabel<T>(PhantomData<T>);17521753assert_eq!(UnitLabel.intern(), UnitLabel.intern());1754assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());1755assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());1756assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());1757assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());17581759assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());1760assert_eq!(1761EnumLabel::Tuple(0, 0).intern(),1762EnumLabel::Tuple(0, 0).intern()1763);1764assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());1765assert_ne!(1766EnumLabel::Tuple(0, 0).intern(),1767EnumLabel::Tuple(0, 1).intern()1768);1769assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());1770assert_ne!(1771TupleLabel(0, 0).intern(),1772StructLabel { a: 0, b: 0 }.intern()1773);1774assert_ne!(1775EnumLabel::Tuple(0, 0).intern(),1776EnumLabel::Struct { a: 0, b: 0 }.intern()1777);17781779assert_eq!(1780StructLabel { a: 0, b: 0 }.intern(),1781StructLabel { a: 0, b: 0 }.intern()1782);1783assert_eq!(1784EnumLabel::Struct { a: 0, b: 0 }.intern(),1785EnumLabel::Struct { a: 0, b: 0 }.intern()1786);1787assert_ne!(1788StructLabel { a: 0, b: 0 }.intern(),1789StructLabel { a: 0, b: 1 }.intern()1790);1791assert_ne!(1792EnumLabel::Struct { a: 0, b: 0 }.intern(),1793EnumLabel::Struct { a: 0, b: 1 }.intern()1794);1795assert_ne!(1796StructLabel { a: 0, b: 0 }.intern(),1797EnumLabel::Struct { a: 0, b: 0 }.intern()1798);1799assert_ne!(1800StructLabel { a: 0, b: 0 }.intern(),1801EnumLabel::Struct { a: 0, b: 0 }.intern()1802);1803assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);1804assert_ne!(1805EnumLabel::Struct { a: 0, b: 0 }.intern(),1806EnumLabel::Unit.intern()1807);18081809assert_eq!(1810GenericLabel::<u32>(PhantomData).intern(),1811GenericLabel::<u32>(PhantomData).intern()1812);1813assert_ne!(1814GenericLabel::<u32>(PhantomData).intern(),1815GenericLabel::<u64>(PhantomData).intern()1816);1817}18181819#[test]1820fn test_update_clears_trackers_once() {1821#[derive(Component, Copy, Clone)]1822struct Foo;18231824let mut app = App::new();1825app.world_mut().spawn_batch(core::iter::repeat_n(Foo, 5));18261827fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {1828if let Some(e) = foos.iter().next() {1829commands.entity(e).despawn();1830};1831}1832fn check_despawns(mut removed_foos: RemovedComponents<Foo>) {1833let mut despawn_count = 0;1834for _ in removed_foos.read() {1835despawn_count += 1;1836}18371838assert_eq!(despawn_count, 2);1839}18401841app.add_systems(Update, despawn_one_foo);1842app.update(); // Frame 01843app.update(); // Frame 11844app.add_systems(Update, check_despawns.after(despawn_one_foo));1845app.update(); // Should see despawns from frames 1 & 2, but not frame 01846}18471848#[test]1849fn test_extract_sees_changes() {1850use super::AppLabel;18511852#[derive(AppLabel, Clone, Copy, Hash, PartialEq, Eq, Debug)]1853struct MySubApp;18541855#[derive(Resource)]1856struct Foo(usize);18571858let mut app = App::new();1859app.world_mut().insert_resource(Foo(0));1860app.add_systems(Update, |mut foo: ResMut<Foo>| {1861foo.0 += 1;1862});18631864let mut sub_app = SubApp::new();1865sub_app.set_extract(|main_world, _sub_world| {1866assert!(main_world.get_resource_ref::<Foo>().unwrap().is_changed());1867});18681869app.insert_sub_app(MySubApp, sub_app);18701871app.update();1872}18731874#[test]1875fn runner_returns_correct_exit_code() {1876fn raise_exits(mut exits: MessageWriter<AppExit>) {1877// Exit codes chosen by a fair dice roll.1878// Unlikely to overlap with default values.1879exits.write(AppExit::Success);1880exits.write(AppExit::from_code(4));1881exits.write(AppExit::from_code(73));1882}18831884let exit = App::new().add_systems(Update, raise_exits).run();18851886assert_eq!(exit, AppExit::from_code(4));1887}18881889/// Custom runners should be in charge of when `app::update` gets called as they may need to1890/// coordinate some state.1891/// bug: <https://github.com/bevyengine/bevy/issues/10385>1892/// fix: <https://github.com/bevyengine/bevy/pull/10389>1893#[test]1894fn regression_test_10385() {1895use super::{Res, Resource};1896use crate::PreUpdate;18971898#[derive(Resource)]1899struct MyState {}19001901fn my_runner(mut app: App) -> AppExit {1902let my_state = MyState {};1903app.world_mut().insert_resource(my_state);19041905for _ in 0..5 {1906app.update();1907}19081909AppExit::Success1910}19111912fn my_system(_: Res<MyState>) {1913// access state during app update1914}19151916// Should not panic due to missing resource1917App::new()1918.set_runner(my_runner)1919.add_systems(PreUpdate, my_system)1920.run();1921}19221923#[test]1924fn app_exit_size() {1925// There wont be many of them so the size isn't an issue but1926// it's nice they're so small let's keep it that way.1927assert_eq!(size_of::<AppExit>(), size_of::<u8>());1928}19291930#[test]1931fn initializing_resources_from_world() {1932#[derive(Resource)]1933struct TestResource;1934impl FromWorld for TestResource {1935fn from_world(_world: &mut World) -> Self {1936TestResource1937}1938}19391940#[derive(Resource)]1941struct NonSendTestResource {1942_marker: PhantomData<Mutex<()>>,1943}1944impl FromWorld for NonSendTestResource {1945fn from_world(_world: &mut World) -> Self {1946NonSendTestResource {1947_marker: PhantomData,1948}1949}1950}19511952App::new()1953.init_non_send_resource::<NonSendTestResource>()1954.init_resource::<TestResource>();1955}19561957#[test]1958/// Plugin should not be considered inserted while it's being built1959///1960/// bug: <https://github.com/bevyengine/bevy/issues/13815>1961fn plugin_should_not_be_added_during_build_time() {1962pub struct Foo;19631964impl Plugin for Foo {1965fn build(&self, app: &mut App) {1966assert!(!app.is_plugin_added::<Self>());1967}1968}19691970App::new().add_plugins(Foo);1971}1972#[test]1973fn events_should_be_updated_once_per_update() {1974#[derive(Message, Clone)]1975struct TestMessage;19761977let mut app = App::new();1978app.add_message::<TestMessage>();19791980// Starts empty1981let test_messages = app.world().resource::<Messages<TestMessage>>();1982assert_eq!(test_messages.len(), 0);1983assert_eq!(test_messages.iter_current_update_messages().count(), 0);1984app.update();19851986// Sending one event1987app.world_mut().write_message(TestMessage);19881989let test_events = app.world().resource::<Messages<TestMessage>>();1990assert_eq!(test_events.len(), 1);1991assert_eq!(test_events.iter_current_update_messages().count(), 1);1992app.update();19931994// Sending two events on the next frame1995app.world_mut().write_message(TestMessage);1996app.world_mut().write_message(TestMessage);19971998let test_events = app.world().resource::<Messages<TestMessage>>();1999assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 32000assert_eq!(test_events.iter_current_update_messages().count(), 2);2001app.update();20022003// Sending zero events2004let test_events = app.world().resource::<Messages<TestMessage>>();2005assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 22006assert_eq!(test_events.iter_current_update_messages().count(), 0);2007}2008}200920102011