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