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