mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Refactor App
and SubApp
internals for better separation (#9202)
# Objective This is a necessary precursor to #9122 (this was split from that PR to reduce the amount of code to review all at once). Moving `!Send` resource ownership to `App` will make it unambiguously `!Send`. `SubApp` must be `Send`, so it can't wrap `App`. ## Solution Refactor `App` and `SubApp` to not have a recursive relationship. Since `SubApp` no longer wraps `App`, once `!Send` resources are moved out of `World` and into `App`, `SubApp` will become unambiguously `Send`. There could be less code duplication between `App` and `SubApp`, but that would break `App` method chaining. ## Changelog - `SubApp` no longer wraps `App`. - `App` fields are no longer publicly accessible. - `App` can no longer be converted into a `SubApp`. - Various methods now return references to a `SubApp` instead of an `App`. ## Migration Guide - To construct a sub-app, use `SubApp::new()`. `App` can no longer convert into `SubApp`. - If you implemented a trait for `App`, you may want to implement it for `SubApp` as well. - If you're accessing `app.world` directly, you now have to use `app.world()` and `app.world_mut()`. - `App::sub_app` now returns `&SubApp`. - `App::sub_app_mut` now returns `&mut SubApp`. - `App::get_sub_app` now returns `Option<&SubApp>.` - `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
This commit is contained in:
parent
ec7755dcce
commit
01649f13e2
86 changed files with 1361 additions and 940 deletions
|
@ -127,19 +127,19 @@ pub fn empty_schedule_run(criterion: &mut Criterion) {
|
|||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded);
|
||||
group.bench_function("SingleThreaded", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
bencher.iter(|| schedule.run(app.world_mut()));
|
||||
});
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::MultiThreaded);
|
||||
group.bench_function("MultiThreaded", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
bencher.iter(|| schedule.run(app.world_mut()));
|
||||
});
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::Simple);
|
||||
group.bench_function("Simple", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
bencher.iter(|| schedule.run(app.world_mut()));
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,6 +13,7 @@ mod panic_handler;
|
|||
mod plugin;
|
||||
mod plugin_group;
|
||||
mod schedule_runner;
|
||||
mod sub_app;
|
||||
|
||||
pub use app::*;
|
||||
pub use bevy_derive::DynamicPlugin;
|
||||
|
@ -21,6 +22,7 @@ pub use panic_handler::*;
|
|||
pub use plugin::*;
|
||||
pub use plugin_group::*;
|
||||
pub use schedule_runner::*;
|
||||
pub use sub_app::*;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub mod prelude {
|
||||
|
@ -32,6 +34,7 @@ pub mod prelude {
|
|||
PostStartup, PostUpdate, PreStartup, PreUpdate, SpawnScene, Startup, StateTransition,
|
||||
Update,
|
||||
},
|
||||
sub_app::SubApp,
|
||||
DynamicPlugin, Plugin, PluginGroup,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,13 +27,14 @@ use bevy_ecs::{
|
|||
/// # Rendering
|
||||
///
|
||||
/// Note rendering is not executed in the main schedule by default.
|
||||
/// Instead, rendering is performed in a separate [`SubApp`](crate::app::SubApp)
|
||||
/// Instead, rendering is performed in a separate [`SubApp`]
|
||||
/// which exchanges data with the main app in between the main schedule runs.
|
||||
///
|
||||
/// See [`RenderPlugin`] and [`PipelinedRenderingPlugin`] for more details.
|
||||
///
|
||||
/// [`RenderPlugin`]: https://docs.rs/bevy/latest/bevy/render/struct.RenderPlugin.html
|
||||
/// [`PipelinedRenderingPlugin`]: https://docs.rs/bevy/latest/bevy/render/pipelined_rendering/struct.PipelinedRenderingPlugin.html
|
||||
/// [`SubApp`]: crate::SubApp
|
||||
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Main;
|
||||
|
||||
|
|
|
@ -100,6 +100,26 @@ impl<T: Fn(&mut App) + Send + Sync + 'static> Plugin for T {
|
|||
}
|
||||
}
|
||||
|
||||
/// Plugins state in the application
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy, PartialOrd, Ord)]
|
||||
pub enum PluginsState {
|
||||
/// Plugins are being added.
|
||||
Adding,
|
||||
/// All plugins already added are ready.
|
||||
Ready,
|
||||
/// Finish has been executed for all plugins added.
|
||||
Finished,
|
||||
/// Cleanup has been executed for all plugins added.
|
||||
Cleaned,
|
||||
}
|
||||
|
||||
/// A dummy plugin that's to temporarily occupy an entry in an app's plugin registry.
|
||||
pub(crate) struct PlaceholderPlugin;
|
||||
|
||||
impl Plugin for PlaceholderPlugin {
|
||||
fn build(&self, _app: &mut App) {}
|
||||
}
|
||||
|
||||
/// A type representing an unsafe function that returns a mutable pointer to a [`Plugin`].
|
||||
/// It is used for dynamically loading plugins.
|
||||
///
|
||||
|
|
|
@ -94,7 +94,7 @@ impl Plugin for ScheduleRunnerPlugin {
|
|||
app.update();
|
||||
|
||||
if let Some(app_exit_events) =
|
||||
app.world.get_resource_mut::<Events<AppExit>>()
|
||||
app.world_mut().get_resource_mut::<Events<AppExit>>()
|
||||
{
|
||||
if let Some(exit) = app_exit_event_reader.read(&app_exit_events).last()
|
||||
{
|
||||
|
|
517
crates/bevy_app/src/sub_app.rs
Normal file
517
crates/bevy_app/src/sub_app.rs
Normal file
|
@ -0,0 +1,517 @@
|
|||
use crate::{App, First, InternedAppLabel, Plugin, Plugins, PluginsState, StateTransition};
|
||||
use bevy_ecs::{
|
||||
prelude::*,
|
||||
schedule::{
|
||||
common_conditions::run_once as run_once_condition, run_enter_schedule,
|
||||
InternedScheduleLabel, ScheduleBuildSettings, ScheduleLabel,
|
||||
},
|
||||
system::SystemId,
|
||||
};
|
||||
#[cfg(feature = "trace")]
|
||||
use bevy_utils::tracing::info_span;
|
||||
use bevy_utils::{default, HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
|
||||
type ExtractFn = Box<dyn Fn(&mut World, &mut World) + Send>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct PluginStore {
|
||||
pub(crate) registry: Vec<Box<dyn Plugin>>,
|
||||
pub(crate) names: HashSet<String>,
|
||||
}
|
||||
|
||||
/// A secondary application with its own [`World`]. These can run independently of each other.
|
||||
///
|
||||
/// These are useful for situations where certain processes (e.g. a render thread) need to be kept
|
||||
/// separate from the main application.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_app::{App, AppLabel, SubApp, Main};
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # use bevy_ecs::schedule::ScheduleLabel;
|
||||
///
|
||||
/// #[derive(Resource, Default)]
|
||||
/// struct Val(pub i32);
|
||||
///
|
||||
/// #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, AppLabel)]
|
||||
/// struct ExampleApp;
|
||||
///
|
||||
/// // Create an app with a certain resource.
|
||||
/// let mut app = App::new();
|
||||
/// app.insert_resource(Val(10));
|
||||
///
|
||||
/// // Create a sub-app with the same resource and a single schedule.
|
||||
/// let mut sub_app = SubApp::new();
|
||||
/// sub_app.insert_resource(Val(100));
|
||||
///
|
||||
/// // Setup an extract function to copy the resource's value in the main world.
|
||||
/// sub_app.set_extract(|main_world, sub_world| {
|
||||
/// sub_world.resource_mut::<Val>().0 = main_world.resource::<Val>().0;
|
||||
/// });
|
||||
///
|
||||
/// // Schedule a system that will verify extraction is working.
|
||||
/// sub_app.add_systems(Main, |counter: Res<Val>| {
|
||||
/// // The value will be copied during extraction, so we should see 10 instead of 100.
|
||||
/// assert_eq!(counter.0, 10);
|
||||
/// });
|
||||
///
|
||||
/// // Add the sub-app to the main app.
|
||||
/// app.insert_sub_app(ExampleApp, sub_app);
|
||||
///
|
||||
/// // Update the application once (using the default runner).
|
||||
/// app.run();
|
||||
/// ```
|
||||
pub struct SubApp {
|
||||
/// The data of this application.
|
||||
world: World,
|
||||
/// Metadata for installed plugins.
|
||||
pub(crate) plugins: PluginStore,
|
||||
/// Panics if an update is attempted while plugins are building.
|
||||
pub(crate) plugin_build_depth: usize,
|
||||
pub(crate) plugins_state: PluginsState,
|
||||
/// The schedule that will be run by [`update`](Self::update).
|
||||
pub update_schedule: Option<InternedScheduleLabel>,
|
||||
/// A function that gives mutable access to two app worlds. This is primarily
|
||||
/// intended for copying data from the main world to secondary worlds.
|
||||
extract: Option<ExtractFn>,
|
||||
}
|
||||
|
||||
impl Debug for SubApp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SubApp")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SubApp {
|
||||
fn default() -> Self {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<Schedules>();
|
||||
Self {
|
||||
world,
|
||||
plugins: default(),
|
||||
plugin_build_depth: 0,
|
||||
plugins_state: PluginsState::Adding,
|
||||
update_schedule: None,
|
||||
extract: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubApp {
|
||||
/// Returns a default, empty [`SubApp`].
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// This method is a workaround. Each [`SubApp`] can have its own plugins, but [`Plugin`]
|
||||
/// works on an [`App`] as a whole.
|
||||
fn run_as_app<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut App),
|
||||
{
|
||||
let mut app = App::empty();
|
||||
std::mem::swap(self, &mut app.sub_apps.main);
|
||||
f(&mut app);
|
||||
std::mem::swap(self, &mut app.sub_apps.main);
|
||||
}
|
||||
|
||||
/// Returns a reference to the [`World`].
|
||||
pub fn world(&self) -> &World {
|
||||
&self.world
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the [`World`].
|
||||
pub fn world_mut(&mut self) -> &mut World {
|
||||
&mut self.world
|
||||
}
|
||||
|
||||
/// Runs the default schedule.
|
||||
pub fn update(&mut self) {
|
||||
if self.is_building_plugins() {
|
||||
panic!("SubApp::update() was called while a plugin was building.");
|
||||
}
|
||||
|
||||
if let Some(label) = self.update_schedule {
|
||||
self.world.run_schedule(label);
|
||||
}
|
||||
self.world.clear_trackers();
|
||||
}
|
||||
|
||||
/// Extracts data from `world` into the app's world using the registered extract method.
|
||||
///
|
||||
/// **Note:** There is no default extract method. Calling `extract` does nothing if
|
||||
/// [`set_extract`](Self::set_extract) has not been called.
|
||||
pub fn extract(&mut self, world: &mut World) {
|
||||
if let Some(f) = self.extract.as_mut() {
|
||||
f(world, &mut self.world);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the method that will be called by [`extract`](Self::extract).
|
||||
///
|
||||
/// The first argument is the `World` to extract data from, the second argument is the app `World`.
|
||||
pub fn set_extract<F>(&mut self, extract: F) -> &mut Self
|
||||
where
|
||||
F: Fn(&mut World, &mut World) + Send + 'static,
|
||||
{
|
||||
self.extract = Some(Box::new(extract));
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::insert_resource`].
|
||||
pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
|
||||
self.world.insert_resource(resource);
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::init_resource`].
|
||||
pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
|
||||
self.world.init_resource::<R>();
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::add_systems`].
|
||||
pub fn add_systems<M>(
|
||||
&mut self,
|
||||
schedule: impl ScheduleLabel,
|
||||
systems: impl IntoSystemConfigs<M>,
|
||||
) -> &mut Self {
|
||||
let label = schedule.intern();
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
if let Some(schedule) = schedules.get_mut(label) {
|
||||
schedule.add_systems(systems);
|
||||
} else {
|
||||
let mut new_schedule = Schedule::new(label);
|
||||
new_schedule.add_systems(systems);
|
||||
schedules.insert(new_schedule);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::register_system`].
|
||||
pub fn register_system<I: 'static, O: 'static, M, S: IntoSystem<I, O, M> + 'static>(
|
||||
&mut self,
|
||||
system: S,
|
||||
) -> SystemId<I, O> {
|
||||
self.world.register_system(system)
|
||||
}
|
||||
|
||||
/// See [`App::configure_sets`].
|
||||
#[track_caller]
|
||||
pub fn configure_sets(
|
||||
&mut self,
|
||||
schedule: impl ScheduleLabel,
|
||||
sets: impl IntoSystemSetConfigs,
|
||||
) -> &mut Self {
|
||||
let label = schedule.intern();
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
if let Some(schedule) = schedules.get_mut(label) {
|
||||
schedule.configure_sets(sets);
|
||||
} else {
|
||||
let mut new_schedule = Schedule::new(label);
|
||||
new_schedule.configure_sets(sets);
|
||||
schedules.insert(new_schedule);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::add_schedule`].
|
||||
pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
schedules.insert(schedule);
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::init_schedule`].
|
||||
pub fn init_schedule(&mut self, label: impl ScheduleLabel) -> &mut Self {
|
||||
let label = label.intern();
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
if !schedules.contains(label) {
|
||||
schedules.insert(Schedule::new(label));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::get_schedule`].
|
||||
pub fn get_schedule(&self, label: impl ScheduleLabel) -> Option<&Schedule> {
|
||||
let schedules = self.world.get_resource::<Schedules>()?;
|
||||
schedules.get(label)
|
||||
}
|
||||
|
||||
/// See [`App::get_schedule_mut`].
|
||||
pub fn get_schedule_mut(&mut self, label: impl ScheduleLabel) -> Option<&mut Schedule> {
|
||||
let schedules = self.world.get_resource_mut::<Schedules>()?;
|
||||
// We must call `.into_inner` here because the borrow checker only understands reborrows
|
||||
// using ordinary references, not our `Mut` smart pointers.
|
||||
schedules.into_inner().get_mut(label)
|
||||
}
|
||||
|
||||
/// See [`App::edit_schedule`].
|
||||
pub fn edit_schedule(
|
||||
&mut self,
|
||||
label: impl ScheduleLabel,
|
||||
mut f: impl FnMut(&mut Schedule),
|
||||
) -> &mut Self {
|
||||
let label = label.intern();
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
if !schedules.contains(label) {
|
||||
schedules.insert(Schedule::new(label));
|
||||
}
|
||||
|
||||
let schedule = schedules.get_mut(label).unwrap();
|
||||
f(schedule);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::configure_schedules`].
|
||||
pub fn configure_schedules(
|
||||
&mut self,
|
||||
schedule_build_settings: ScheduleBuildSettings,
|
||||
) -> &mut Self {
|
||||
self.world_mut()
|
||||
.resource_mut::<Schedules>()
|
||||
.configure_schedules(schedule_build_settings);
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::allow_ambiguous_component`].
|
||||
pub fn allow_ambiguous_component<T: Component>(&mut self) -> &mut Self {
|
||||
self.world_mut().allow_ambiguous_component::<T>();
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::allow_ambiguous_resource`].
|
||||
pub fn allow_ambiguous_resource<T: Resource>(&mut self) -> &mut Self {
|
||||
self.world_mut().allow_ambiguous_resource::<T>();
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::ignore_ambiguity`].
|
||||
#[track_caller]
|
||||
pub fn ignore_ambiguity<M1, M2, S1, S2>(
|
||||
&mut self,
|
||||
schedule: impl ScheduleLabel,
|
||||
a: S1,
|
||||
b: S2,
|
||||
) -> &mut Self
|
||||
where
|
||||
S1: IntoSystemSet<M1>,
|
||||
S2: IntoSystemSet<M2>,
|
||||
{
|
||||
let schedule = schedule.intern();
|
||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
||||
|
||||
if let Some(schedule) = schedules.get_mut(schedule) {
|
||||
let schedule: &mut Schedule = schedule;
|
||||
schedule.ignore_ambiguity(a, b);
|
||||
} else {
|
||||
let mut new_schedule = Schedule::new(schedule);
|
||||
new_schedule.ignore_ambiguity(a, b);
|
||||
schedules.insert(new_schedule);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::init_state`].
|
||||
pub fn init_state<S: States + FromWorld>(&mut self) -> &mut Self {
|
||||
if !self.world.contains_resource::<State<S>>() {
|
||||
self.init_resource::<State<S>>()
|
||||
.init_resource::<NextState<S>>()
|
||||
.add_event::<StateTransitionEvent<S>>()
|
||||
.add_systems(
|
||||
StateTransition,
|
||||
(
|
||||
run_enter_schedule::<S>.run_if(run_once_condition()),
|
||||
apply_state_transition::<S>,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
}
|
||||
|
||||
// The OnEnter, OnExit, and OnTransition schedules are lazily initialized
|
||||
// (i.e. when the first system is added to them), so World::try_run_schedule
|
||||
// is used to fail gracefully if they aren't present.
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::insert_state`].
|
||||
pub fn insert_state<S: States>(&mut self, state: S) -> &mut Self {
|
||||
self.insert_resource(State::new(state))
|
||||
.init_resource::<NextState<S>>()
|
||||
.add_event::<StateTransitionEvent<S>>()
|
||||
.add_systems(
|
||||
StateTransition,
|
||||
(
|
||||
run_enter_schedule::<S>.run_if(run_once_condition()),
|
||||
apply_state_transition::<S>,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::add_event`].
|
||||
pub fn add_event<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Event,
|
||||
{
|
||||
if !self.world.contains_resource::<Events<T>>() {
|
||||
self.init_resource::<Events<T>>().add_systems(
|
||||
First,
|
||||
bevy_ecs::event::event_update_system::<T>
|
||||
.in_set(bevy_ecs::event::EventUpdates)
|
||||
.run_if(bevy_ecs::event::event_update_condition::<T>),
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::add_plugins`].
|
||||
pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {
|
||||
self.run_as_app(|app| plugins.add_to_app(app));
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::is_plugin_added`].
|
||||
pub fn is_plugin_added<T>(&self) -> bool
|
||||
where
|
||||
T: Plugin,
|
||||
{
|
||||
self.plugins
|
||||
.registry
|
||||
.iter()
|
||||
.any(|p| p.downcast_ref::<T>().is_some())
|
||||
}
|
||||
|
||||
/// See [`App::get_added_plugins`].
|
||||
pub fn get_added_plugins<T>(&self) -> Vec<&T>
|
||||
where
|
||||
T: Plugin,
|
||||
{
|
||||
self.plugins
|
||||
.registry
|
||||
.iter()
|
||||
.filter_map(|p| p.downcast_ref())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns `true` if there is no plugin in the middle of being built.
|
||||
pub(crate) fn is_building_plugins(&self) -> bool {
|
||||
self.plugin_build_depth > 0
|
||||
}
|
||||
|
||||
/// Return the state of plugins.
|
||||
#[inline]
|
||||
pub fn plugins_state(&mut self) -> PluginsState {
|
||||
match self.plugins_state {
|
||||
PluginsState::Adding => {
|
||||
let mut state = PluginsState::Ready;
|
||||
let plugins = std::mem::take(&mut self.plugins);
|
||||
self.run_as_app(|app| {
|
||||
for plugin in &plugins.registry {
|
||||
if !plugin.ready(app) {
|
||||
state = PluginsState::Adding;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
self.plugins = plugins;
|
||||
state
|
||||
}
|
||||
state => state,
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs [`Plugin::finish`] for each plugin.
|
||||
pub fn finish(&mut self) {
|
||||
let plugins = std::mem::take(&mut self.plugins);
|
||||
self.run_as_app(|app| {
|
||||
for plugin in &plugins.registry {
|
||||
plugin.finish(app);
|
||||
}
|
||||
});
|
||||
self.plugins = plugins;
|
||||
self.plugins_state = PluginsState::Finished;
|
||||
}
|
||||
|
||||
/// Runs [`Plugin::cleanup`] for each plugin.
|
||||
pub fn cleanup(&mut self) {
|
||||
let plugins = std::mem::take(&mut self.plugins);
|
||||
self.run_as_app(|app| {
|
||||
for plugin in &plugins.registry {
|
||||
plugin.cleanup(app);
|
||||
}
|
||||
});
|
||||
self.plugins = plugins;
|
||||
self.plugins_state = PluginsState::Cleaned;
|
||||
}
|
||||
|
||||
/// See [`App::register_type`].
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
|
||||
let registry = self.world.resource_mut::<AppTypeRegistry>();
|
||||
registry.write().register::<T>();
|
||||
self
|
||||
}
|
||||
|
||||
/// See [`App::register_type_data`].
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
pub fn register_type_data<
|
||||
T: bevy_reflect::Reflect + bevy_reflect::TypePath,
|
||||
D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,
|
||||
>(
|
||||
&mut self,
|
||||
) -> &mut Self {
|
||||
let registry = self.world.resource_mut::<AppTypeRegistry>();
|
||||
registry.write().register_type_data::<T, D>();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The collection of sub-apps that belong to an [`App`].
|
||||
#[derive(Default)]
|
||||
pub struct SubApps {
|
||||
/// The primary sub-app that contains the "main" world.
|
||||
pub main: SubApp,
|
||||
/// Other, labeled sub-apps.
|
||||
pub sub_apps: HashMap<InternedAppLabel, SubApp>,
|
||||
}
|
||||
|
||||
impl SubApps {
|
||||
/// Calls [`update`](SubApp::update) for the main sub-app, and then calls
|
||||
/// [`extract`](SubApp::extract) and [`update`](SubApp::update) for the rest.
|
||||
pub fn update(&mut self) {
|
||||
#[cfg(feature = "trace")]
|
||||
let _bevy_update_span = info_span!("update").entered();
|
||||
{
|
||||
#[cfg(feature = "trace")]
|
||||
let _bevy_frame_update_span = info_span!("main app").entered();
|
||||
self.main.update();
|
||||
}
|
||||
for (_label, sub_app) in self.sub_apps.iter_mut() {
|
||||
#[cfg(feature = "trace")]
|
||||
let _sub_app_span = info_span!("sub app", name = ?_label).entered();
|
||||
sub_app.extract(&mut self.main.world);
|
||||
sub_app.update();
|
||||
}
|
||||
|
||||
self.main.world.clear_trackers();
|
||||
}
|
||||
|
||||
/// Returns an iterator over the sub-apps (starting with the main one).
|
||||
pub fn iter(&self) -> impl Iterator<Item = &SubApp> + '_ {
|
||||
std::iter::once(&self.main).chain(self.sub_apps.values())
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the sub-apps (starting with the main one).
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut SubApp> + '_ {
|
||||
std::iter::once(&mut self.main).chain(self.sub_apps.values_mut())
|
||||
}
|
||||
}
|
|
@ -224,7 +224,7 @@ macro_rules! embedded_asset {
|
|||
|
||||
($app: ident, $source_path: expr, $path: expr) => {{
|
||||
let mut embedded = $app
|
||||
.world
|
||||
.world_mut()
|
||||
.resource_mut::<$crate::io::embedded::EmbeddedAssetRegistry>();
|
||||
let path = $crate::embedded_path!($source_path, $path);
|
||||
let watched_path = $crate::io::embedded::watched_path(file!(), $path);
|
||||
|
@ -253,7 +253,7 @@ pub fn watched_path(_source_file_path: &'static str, _asset_path: &'static str)
|
|||
#[macro_export]
|
||||
macro_rules! load_internal_asset {
|
||||
($app: ident, $handle: expr, $path_str: expr, $loader: expr) => {{
|
||||
let mut assets = $app.world.resource_mut::<$crate::Assets<_>>();
|
||||
let mut assets = $app.world_mut().resource_mut::<$crate::Assets<_>>();
|
||||
assets.insert($handle.id(), ($loader)(
|
||||
include_str!($path_str),
|
||||
std::path::Path::new(file!())
|
||||
|
@ -265,7 +265,7 @@ macro_rules! load_internal_asset {
|
|||
}};
|
||||
// we can't support params without variadic arguments, so internal assets with additional params can't be hot-reloaded
|
||||
($app: ident, $handle: ident, $path_str: expr, $loader: expr $(, $param:expr)+) => {{
|
||||
let mut assets = $app.world.resource_mut::<$crate::Assets<_>>();
|
||||
let mut assets = $app.world_mut().resource_mut::<$crate::Assets<_>>();
|
||||
assets.insert($handle.id(), ($loader)(
|
||||
include_str!($path_str),
|
||||
std::path::Path::new(file!())
|
||||
|
@ -282,7 +282,7 @@ macro_rules! load_internal_asset {
|
|||
#[macro_export]
|
||||
macro_rules! load_internal_binary_asset {
|
||||
($app: ident, $handle: expr, $path_str: expr, $loader: expr) => {{
|
||||
let mut assets = $app.world.resource_mut::<$crate::Assets<_>>();
|
||||
let mut assets = $app.world_mut().resource_mut::<$crate::Assets<_>>();
|
||||
assets.insert(
|
||||
$handle.id(),
|
||||
($loader)(
|
||||
|
|
|
@ -153,7 +153,7 @@ impl Plugin for AssetPlugin {
|
|||
let embedded = EmbeddedAssetRegistry::default();
|
||||
{
|
||||
let mut sources = app
|
||||
.world
|
||||
.world_mut()
|
||||
.get_resource_or_insert_with::<AssetSourceBuilders>(Default::default);
|
||||
sources.init_default_source(
|
||||
&self.file_path,
|
||||
|
@ -169,10 +169,10 @@ impl Plugin for AssetPlugin {
|
|||
}
|
||||
match self.mode {
|
||||
AssetMode::Unprocessed => {
|
||||
let mut builders = app.world.resource_mut::<AssetSourceBuilders>();
|
||||
let mut builders = app.world_mut().resource_mut::<AssetSourceBuilders>();
|
||||
let sources = builders.build_sources(watch, false);
|
||||
let meta_check = app
|
||||
.world
|
||||
.world()
|
||||
.get_resource::<AssetMetaCheck>()
|
||||
.cloned()
|
||||
.unwrap_or_else(AssetMetaCheck::default);
|
||||
|
@ -187,7 +187,7 @@ impl Plugin for AssetPlugin {
|
|||
AssetMode::Processed => {
|
||||
#[cfg(feature = "asset_processor")]
|
||||
{
|
||||
let mut builders = app.world.resource_mut::<AssetSourceBuilders>();
|
||||
let mut builders = app.world_mut().resource_mut::<AssetSourceBuilders>();
|
||||
let processor = AssetProcessor::new(&mut builders);
|
||||
let mut sources = builders.build_sources(false, watch);
|
||||
sources.gate_on_processor(processor.data.clone());
|
||||
|
@ -204,7 +204,7 @@ impl Plugin for AssetPlugin {
|
|||
}
|
||||
#[cfg(not(feature = "asset_processor"))]
|
||||
{
|
||||
let mut builders = app.world.resource_mut::<AssetSourceBuilders>();
|
||||
let mut builders = app.world_mut().resource_mut::<AssetSourceBuilders>();
|
||||
let sources = builders.build_sources(false, watch);
|
||||
app.insert_resource(AssetServer::new_with_meta_check(
|
||||
sources,
|
||||
|
@ -318,12 +318,14 @@ pub trait AssetApp {
|
|||
|
||||
impl AssetApp for App {
|
||||
fn register_asset_loader<L: AssetLoader>(&mut self, loader: L) -> &mut Self {
|
||||
self.world.resource::<AssetServer>().register_loader(loader);
|
||||
self.world()
|
||||
.resource::<AssetServer>()
|
||||
.register_loader(loader);
|
||||
self
|
||||
}
|
||||
|
||||
fn register_asset_processor<P: Process>(&mut self, processor: P) -> &mut Self {
|
||||
if let Some(asset_processor) = self.world.get_resource::<AssetProcessor>() {
|
||||
if let Some(asset_processor) = self.world().get_resource::<AssetProcessor>() {
|
||||
asset_processor.register_processor(processor);
|
||||
}
|
||||
self
|
||||
|
@ -335,13 +337,13 @@ impl AssetApp for App {
|
|||
source: AssetSourceBuilder,
|
||||
) -> &mut Self {
|
||||
let id = id.into();
|
||||
if self.world.get_resource::<AssetServer>().is_some() {
|
||||
if self.world().get_resource::<AssetServer>().is_some() {
|
||||
error!("{} must be registered before `AssetPlugin` (typically added as part of `DefaultPlugins`)", id);
|
||||
}
|
||||
|
||||
{
|
||||
let mut sources = self
|
||||
.world
|
||||
.world_mut()
|
||||
.get_resource_or_insert_with(AssetSourceBuilders::default);
|
||||
sources.insert(id, source);
|
||||
}
|
||||
|
@ -350,22 +352,24 @@ impl AssetApp for App {
|
|||
}
|
||||
|
||||
fn set_default_asset_processor<P: Process>(&mut self, extension: &str) -> &mut Self {
|
||||
if let Some(asset_processor) = self.world.get_resource::<AssetProcessor>() {
|
||||
if let Some(asset_processor) = self.world().get_resource::<AssetProcessor>() {
|
||||
asset_processor.set_default_processor::<P>(extension);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn init_asset_loader<L: AssetLoader + FromWorld>(&mut self) -> &mut Self {
|
||||
let loader = L::from_world(&mut self.world);
|
||||
let loader = L::from_world(self.world_mut());
|
||||
self.register_asset_loader(loader)
|
||||
}
|
||||
|
||||
fn init_asset<A: Asset>(&mut self) -> &mut Self {
|
||||
let assets = Assets::<A>::default();
|
||||
self.world.resource::<AssetServer>().register_asset(&assets);
|
||||
if self.world.contains_resource::<AssetProcessor>() {
|
||||
let processor = self.world.resource::<AssetProcessor>();
|
||||
self.world()
|
||||
.resource::<AssetServer>()
|
||||
.register_asset(&assets);
|
||||
if self.world().contains_resource::<AssetProcessor>() {
|
||||
let processor = self.world().resource::<AssetProcessor>();
|
||||
// The processor should have its own handle provider separate from the Asset storage
|
||||
// to ensure the id spaces are entirely separate. Not _strictly_ necessary, but
|
||||
// desirable.
|
||||
|
@ -394,7 +398,7 @@ impl AssetApp for App {
|
|||
where
|
||||
A: Asset + Reflect + FromReflect + GetTypeRegistration,
|
||||
{
|
||||
let type_registry = self.world.resource::<AppTypeRegistry>();
|
||||
let type_registry = self.world().resource::<AppTypeRegistry>();
|
||||
{
|
||||
let mut type_registry = type_registry.write();
|
||||
|
||||
|
@ -408,7 +412,7 @@ impl AssetApp for App {
|
|||
}
|
||||
|
||||
fn preregister_asset_loader<L: AssetLoader>(&mut self, extensions: &[&str]) -> &mut Self {
|
||||
self.world
|
||||
self.world_mut()
|
||||
.resource_mut::<AssetServer>()
|
||||
.preregister_loader::<L>(extensions);
|
||||
self
|
||||
|
@ -628,7 +632,7 @@ mod tests {
|
|||
pub fn run_app_until(app: &mut App, mut predicate: impl FnMut(&mut World) -> Option<()>) {
|
||||
for _ in 0..LARGE_ITERATION_COUNT {
|
||||
app.update();
|
||||
if predicate(&mut app.world).is_some() {
|
||||
if predicate(app.world_mut()).is_some() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -718,13 +722,13 @@ mod tests {
|
|||
.init_resource::<StoredEvents>()
|
||||
.register_asset_loader(CoolTextLoader)
|
||||
.add_systems(Update, store_asset_events);
|
||||
let asset_server = app.world.resource::<AssetServer>().clone();
|
||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||
let handle: Handle<CoolText> = asset_server.load(a_path);
|
||||
let a_id = handle.id();
|
||||
let entity = app.world.spawn(handle).id();
|
||||
let entity = app.world_mut().spawn(handle).id();
|
||||
app.update();
|
||||
{
|
||||
let a_text = get::<CoolText>(&app.world, a_id);
|
||||
let a_text = get::<CoolText>(app.world(), a_id);
|
||||
let (a_load, a_deps, a_rec_deps) = asset_server.get_load_states(a_id).unwrap();
|
||||
assert!(a_text.is_none(), "a's asset should not exist yet");
|
||||
assert_eq!(a_load, LoadState::Loading, "a should still be loading");
|
||||
|
@ -906,27 +910,27 @@ mod tests {
|
|||
});
|
||||
|
||||
{
|
||||
let mut texts = app.world.resource_mut::<Assets<CoolText>>();
|
||||
let mut texts = app.world_mut().resource_mut::<Assets<CoolText>>();
|
||||
let a = texts.get_mut(a_id).unwrap();
|
||||
a.text = "Changed".to_string();
|
||||
}
|
||||
|
||||
app.world.despawn(entity);
|
||||
app.world_mut().despawn(entity);
|
||||
app.update();
|
||||
assert_eq!(
|
||||
app.world.resource::<Assets<CoolText>>().len(),
|
||||
app.world().resource::<Assets<CoolText>>().len(),
|
||||
0,
|
||||
"CoolText asset entities should be despawned when no more handles exist"
|
||||
);
|
||||
app.update();
|
||||
// this requires a second update because the parent asset was freed in the previous app.update()
|
||||
assert_eq!(
|
||||
app.world.resource::<Assets<SubText>>().len(),
|
||||
app.world().resource::<Assets<SubText>>().len(),
|
||||
0,
|
||||
"SubText asset entities should be despawned when no more handles exist"
|
||||
);
|
||||
let events = app.world.remove_resource::<StoredEvents>().unwrap();
|
||||
let id_results = app.world.remove_resource::<IdResults>().unwrap();
|
||||
let events = app.world_mut().remove_resource::<StoredEvents>().unwrap();
|
||||
let id_results = app.world_mut().remove_resource::<IdResults>().unwrap();
|
||||
let expected_events = vec![
|
||||
AssetEvent::Added { id: a_id },
|
||||
AssetEvent::LoadedWithDependencies {
|
||||
|
@ -1030,7 +1034,7 @@ mod tests {
|
|||
let (mut app, gate_opener) = test_app(dir);
|
||||
app.init_asset::<CoolText>()
|
||||
.register_asset_loader(CoolTextLoader);
|
||||
let asset_server = app.world.resource::<AssetServer>().clone();
|
||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||
let handle: Handle<CoolText> = asset_server.load(a_path);
|
||||
let a_id = handle.id();
|
||||
{
|
||||
|
@ -1046,7 +1050,7 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
app.world.spawn(handle);
|
||||
app.world_mut().spawn(handle);
|
||||
gate_opener.open(a_path);
|
||||
gate_opener.open(b_path);
|
||||
gate_opener.open(c_path);
|
||||
|
@ -1117,7 +1121,7 @@ mod tests {
|
|||
|
||||
let id = {
|
||||
let handle = {
|
||||
let mut texts = app.world.resource_mut::<Assets<CoolText>>();
|
||||
let mut texts = app.world_mut().resource_mut::<Assets<CoolText>>();
|
||||
let handle = texts.add(CoolText::default());
|
||||
texts.get_strong_handle(handle.id()).unwrap()
|
||||
};
|
||||
|
@ -1125,7 +1129,7 @@ mod tests {
|
|||
app.update();
|
||||
|
||||
{
|
||||
let text = app.world.resource::<Assets<CoolText>>().get(&handle);
|
||||
let text = app.world().resource::<Assets<CoolText>>().get(&handle);
|
||||
assert!(text.is_some());
|
||||
}
|
||||
handle.id()
|
||||
|
@ -1133,7 +1137,7 @@ mod tests {
|
|||
// handle is dropped
|
||||
app.update();
|
||||
assert!(
|
||||
app.world.resource::<Assets<CoolText>>().get(id).is_none(),
|
||||
app.world().resource::<Assets<CoolText>>().get(id).is_none(),
|
||||
"asset has no handles, so it should have been dropped last update"
|
||||
);
|
||||
}
|
||||
|
@ -1161,7 +1165,7 @@ mod tests {
|
|||
|
||||
let id = {
|
||||
let handle = {
|
||||
let mut texts = app.world.resource_mut::<Assets<CoolText>>();
|
||||
let mut texts = app.world_mut().resource_mut::<Assets<CoolText>>();
|
||||
texts.add(CoolText {
|
||||
text: hello.clone(),
|
||||
embedded: empty.clone(),
|
||||
|
@ -1174,7 +1178,7 @@ mod tests {
|
|||
|
||||
{
|
||||
let text = app
|
||||
.world
|
||||
.world()
|
||||
.resource::<Assets<CoolText>>()
|
||||
.get(&handle)
|
||||
.unwrap();
|
||||
|
@ -1185,12 +1189,12 @@ mod tests {
|
|||
// handle is dropped
|
||||
app.update();
|
||||
assert!(
|
||||
app.world.resource::<Assets<CoolText>>().get(id).is_none(),
|
||||
app.world().resource::<Assets<CoolText>>().get(id).is_none(),
|
||||
"asset has no handles, so it should have been dropped last update"
|
||||
);
|
||||
// remove event is emitted
|
||||
app.update();
|
||||
let events = std::mem::take(&mut app.world.resource_mut::<StoredEvents>().0);
|
||||
let events = std::mem::take(&mut app.world_mut().resource_mut::<StoredEvents>().0);
|
||||
let expected_events = vec![
|
||||
AssetEvent::Added { id },
|
||||
AssetEvent::Unused { id },
|
||||
|
@ -1198,7 +1202,7 @@ mod tests {
|
|||
];
|
||||
assert_eq!(events, expected_events);
|
||||
|
||||
let dep_handle = app.world.resource::<AssetServer>().load(dep_path);
|
||||
let dep_handle = app.world().resource::<AssetServer>().load(dep_path);
|
||||
let a = CoolText {
|
||||
text: "a".to_string(),
|
||||
embedded: empty,
|
||||
|
@ -1206,19 +1210,19 @@ mod tests {
|
|||
dependencies: vec![dep_handle.clone()],
|
||||
sub_texts: Vec::new(),
|
||||
};
|
||||
let a_handle = app.world.resource::<AssetServer>().load_asset(a);
|
||||
let a_handle = app.world().resource::<AssetServer>().load_asset(a);
|
||||
app.update();
|
||||
// TODO: ideally it doesn't take two updates for the added event to emit
|
||||
app.update();
|
||||
|
||||
let events = std::mem::take(&mut app.world.resource_mut::<StoredEvents>().0);
|
||||
let events = std::mem::take(&mut app.world_mut().resource_mut::<StoredEvents>().0);
|
||||
let expected_events = vec![AssetEvent::Added { id: a_handle.id() }];
|
||||
assert_eq!(events, expected_events);
|
||||
|
||||
gate_opener.open(dep_path);
|
||||
loop {
|
||||
app.update();
|
||||
let events = std::mem::take(&mut app.world.resource_mut::<StoredEvents>().0);
|
||||
let events = std::mem::take(&mut app.world_mut().resource_mut::<StoredEvents>().0);
|
||||
if events.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
@ -1232,7 +1236,7 @@ mod tests {
|
|||
break;
|
||||
}
|
||||
app.update();
|
||||
let events = std::mem::take(&mut app.world.resource_mut::<StoredEvents>().0);
|
||||
let events = std::mem::take(&mut app.world_mut().resource_mut::<StoredEvents>().0);
|
||||
let expected_events = vec![AssetEvent::Added {
|
||||
id: dep_handle.id(),
|
||||
}];
|
||||
|
@ -1283,7 +1287,7 @@ mod tests {
|
|||
app.init_asset::<CoolText>()
|
||||
.init_asset::<SubText>()
|
||||
.register_asset_loader(CoolTextLoader);
|
||||
let asset_server = app.world.resource::<AssetServer>().clone();
|
||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||
let handle: Handle<LoadedFolder> = asset_server.load_folder("text");
|
||||
gate_opener.open(a_path);
|
||||
gate_opener.open(b_path);
|
||||
|
@ -1438,12 +1442,12 @@ mod tests {
|
|||
(asset_event_handler, asset_load_error_event_handler).chain(),
|
||||
);
|
||||
|
||||
let asset_server = app.world.resource::<AssetServer>().clone();
|
||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||
let a_path = format!("unstable://{a_path}");
|
||||
let a_handle: Handle<CoolText> = asset_server.load(a_path);
|
||||
let a_id = a_handle.id();
|
||||
|
||||
app.world.spawn(a_handle);
|
||||
app.world_mut().spawn(a_handle);
|
||||
|
||||
run_app_until(&mut app, |world| {
|
||||
let tracker = world.resource::<ErrorTracker>();
|
||||
|
@ -1476,7 +1480,7 @@ mod tests {
|
|||
});
|
||||
|
||||
// running schedule does not error on ambiguity between the 2 uses_assets systems
|
||||
app.world.run_schedule(Update);
|
||||
app.world_mut().run_schedule(Update);
|
||||
}
|
||||
|
||||
// validate the Asset derive macro for various asset types
|
||||
|
|
|
@ -257,7 +257,7 @@ mod tests {
|
|||
.register_asset_reflect::<AssetType>();
|
||||
|
||||
let reflect_asset = {
|
||||
let type_registry = app.world.resource::<AppTypeRegistry>();
|
||||
let type_registry = app.world().resource::<AppTypeRegistry>();
|
||||
let type_registry = type_registry.read();
|
||||
|
||||
type_registry
|
||||
|
@ -270,9 +270,9 @@ mod tests {
|
|||
field: "test".into(),
|
||||
};
|
||||
|
||||
let handle = reflect_asset.add(&mut app.world, &value);
|
||||
let handle = reflect_asset.add(app.world_mut(), &value);
|
||||
let ReflectMut::Struct(strukt) = reflect_asset
|
||||
.get_mut(&mut app.world, handle)
|
||||
.get_mut(app.world_mut(), handle)
|
||||
.unwrap()
|
||||
.reflect_mut()
|
||||
else {
|
||||
|
@ -283,19 +283,19 @@ mod tests {
|
|||
.unwrap()
|
||||
.apply(&String::from("edited"));
|
||||
|
||||
assert_eq!(reflect_asset.len(&app.world), 1);
|
||||
let ids: Vec<_> = reflect_asset.ids(&app.world).collect();
|
||||
assert_eq!(reflect_asset.len(app.world()), 1);
|
||||
let ids: Vec<_> = reflect_asset.ids(app.world()).collect();
|
||||
assert_eq!(ids.len(), 1);
|
||||
|
||||
let fetched_handle = UntypedHandle::Weak(ids[0]);
|
||||
let asset = reflect_asset
|
||||
.get(&app.world, fetched_handle.clone_weak())
|
||||
.get(app.world(), fetched_handle.clone_weak())
|
||||
.unwrap();
|
||||
assert_eq!(asset.downcast_ref::<AssetType>().unwrap().field, "edited");
|
||||
|
||||
reflect_asset
|
||||
.remove(&mut app.world, fetched_handle)
|
||||
.remove(app.world_mut(), fetched_handle)
|
||||
.unwrap();
|
||||
assert_eq!(reflect_asset.len(&app.world), 0);
|
||||
assert_eq!(reflect_asset.len(app.world()), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ mod tests {
|
|||
));
|
||||
app.update();
|
||||
|
||||
let frame_count = app.world.resource::<FrameCount>();
|
||||
let frame_count = app.world().resource::<FrameCount>();
|
||||
assert_eq!(1, frame_count.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,16 +21,15 @@ impl Plugin for BlitPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
load_internal_asset!(app, BLIT_SHADER_HANDLE, "blit.wgsl", Shader::from_wgsl);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.allow_ambiguous_resource::<SpecializedRenderPipelines<BlitPipeline>>();
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<BlitPipeline>()
|
||||
.init_resource::<SpecializedRenderPipelines<BlitPipeline>>();
|
||||
|
|
|
@ -56,10 +56,9 @@ impl Plugin for BloomPlugin {
|
|||
UniformComponentPlugin::<BloomUniforms>::default(),
|
||||
));
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<SpecializedRenderPipelines<BloomDownsamplingPipeline>>()
|
||||
.init_resource::<SpecializedRenderPipelines<BloomUpsamplingPipeline>>()
|
||||
|
@ -87,10 +86,9 @@ impl Plugin for BloomPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<BloomDownsamplingPipeline>()
|
||||
.init_resource::<BloomUpsamplingPipeline>();
|
||||
|
|
|
@ -116,7 +116,7 @@ impl Plugin for CASPlugin {
|
|||
UniformComponentPlugin::<CASUniform>::default(),
|
||||
));
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app
|
||||
|
@ -160,7 +160,7 @@ impl Plugin for CASPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app.init_resource::<CASPipeline>();
|
||||
|
|
|
@ -56,10 +56,9 @@ impl Plugin for Core2dPlugin {
|
|||
app.register_type::<Camera2d>()
|
||||
.add_plugins(ExtractComponentPlugin::<Camera2d>::default());
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<DrawFunctions<Transparent2d>>()
|
||||
.add_systems(ExtractSchedule, extract_core_2d_camera_phases)
|
||||
|
|
|
@ -99,10 +99,9 @@ impl Plugin for Core3dPlugin {
|
|||
.add_plugins((SkyboxPlugin, ExtractComponentPlugin::<Camera3d>::default()))
|
||||
.add_systems(PostUpdate, check_msaa);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<DrawFunctions<Opaque3d>>()
|
||||
.init_resource::<DrawFunctions<AlphaMask3d>>()
|
||||
|
|
|
@ -35,7 +35,7 @@ impl Plugin for CopyDeferredLightingIdPlugin {
|
|||
"copy_deferred_lighting_id.wgsl",
|
||||
Shader::from_wgsl
|
||||
);
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app.add_systems(
|
||||
|
@ -45,7 +45,7 @@ impl Plugin for CopyDeferredLightingIdPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ impl Plugin for FxaaPlugin {
|
|||
app.register_type::<Fxaa>();
|
||||
app.add_plugins(ExtractComponentPlugin::<Fxaa>::default());
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app
|
||||
|
@ -116,7 +116,7 @@ impl Plugin for FxaaPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app.init_resource::<FxaaPipeline>();
|
||||
|
|
|
@ -21,10 +21,9 @@ pub struct MsaaWritebackPlugin;
|
|||
|
||||
impl Plugin for MsaaWritebackPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app.add_systems(
|
||||
Render,
|
||||
prepare_msaa_writeback_pipelines.in_set(RenderSet::Prepare),
|
||||
|
|
|
@ -38,10 +38,9 @@ impl Plugin for SkyboxPlugin {
|
|||
UniformComponentPlugin::<SkyboxUniforms>::default(),
|
||||
));
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<SpecializedRenderPipelines<SkyboxPipeline>>()
|
||||
.add_systems(
|
||||
|
@ -54,12 +53,10 @@ impl Plugin for SkyboxPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let render_device = render_app.world.resource::<RenderDevice>().clone();
|
||||
|
||||
let render_device = render_app.world().resource::<RenderDevice>().clone();
|
||||
render_app.insert_resource(SkyboxPipeline::new(&render_device));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,10 +49,9 @@ impl Plugin for TemporalAntiAliasPlugin {
|
|||
app.insert_resource(Msaa::Off)
|
||||
.register_type::<TemporalAntiAliasSettings>();
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<SpecializedRenderPipelines<TaaPipeline>>()
|
||||
.add_systems(ExtractSchedule, extract_taa_settings)
|
||||
|
@ -77,7 +76,7 @@ impl Plugin for TemporalAntiAliasPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ impl Plugin for TonemappingPlugin {
|
|||
Shader::from_wgsl
|
||||
);
|
||||
|
||||
if !app.world.is_resource_added::<TonemappingLuts>() {
|
||||
let mut images = app.world.resource_mut::<Assets<Image>>();
|
||||
if !app.world().is_resource_added::<TonemappingLuts>() {
|
||||
let mut images = app.world_mut().resource_mut::<Assets<Image>>();
|
||||
|
||||
#[cfg(feature = "tonemapping_luts")]
|
||||
let tonemapping_luts = {
|
||||
|
@ -96,20 +96,22 @@ impl Plugin for TonemappingPlugin {
|
|||
ExtractComponentPlugin::<DebandDither>::default(),
|
||||
));
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<SpecializedRenderPipelines<TonemappingPipeline>>()
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare_view_tonemapping_pipelines.in_set(RenderSet::Prepare),
|
||||
);
|
||||
}
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app
|
||||
.init_resource::<SpecializedRenderPipelines<TonemappingPipeline>>()
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare_view_tonemapping_pipelines.in_set(RenderSet::Prepare),
|
||||
);
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<TonemappingPipeline>();
|
||||
}
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
render_app.init_resource::<TonemappingPipeline>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ pub struct UpscalingPlugin;
|
|||
|
||||
impl Plugin for UpscalingPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.add_systems(
|
||||
Render,
|
||||
prepare_view_upscaling_pipelines.in_set(RenderSet::Prepare),
|
||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn setup_app(app: &mut App) -> &mut App {
|
|||
};
|
||||
|
||||
if let Some(frame_time) = config.frame_time {
|
||||
app.world
|
||||
app.world_mut()
|
||||
.insert_resource(TimeUpdateStrategy::ManualDuration(Duration::from_secs_f32(
|
||||
frame_time,
|
||||
)));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::{borrow::Cow, collections::VecDeque};
|
||||
|
||||
use bevy_app::App;
|
||||
use bevy_app::{App, SubApp};
|
||||
use bevy_ecs::system::{Deferred, Res, Resource, SystemBuffer, SystemParam};
|
||||
use bevy_utils::{hashbrown::HashMap, Duration, Instant, PassHash};
|
||||
use const_fnv1a_hash::fnv1a_hash_str_64;
|
||||
|
@ -383,10 +383,6 @@ impl SystemBuffer for DiagnosticsBuffer {
|
|||
|
||||
/// Extend [`App`] with new `register_diagnostic` function.
|
||||
pub trait RegisterDiagnostic {
|
||||
fn register_diagnostic(&mut self, diagnostic: Diagnostic) -> &mut Self;
|
||||
}
|
||||
|
||||
impl RegisterDiagnostic for App {
|
||||
/// Register a new [`Diagnostic`] with an [`App`].
|
||||
///
|
||||
/// Will initialize a [`DiagnosticsStore`] if it doesn't exist.
|
||||
|
@ -402,11 +398,22 @@ impl RegisterDiagnostic for App {
|
|||
/// .add_plugins(DiagnosticsPlugin)
|
||||
/// .run();
|
||||
/// ```
|
||||
fn register_diagnostic(&mut self, diagnostic: Diagnostic) -> &mut Self;
|
||||
}
|
||||
|
||||
impl RegisterDiagnostic for SubApp {
|
||||
fn register_diagnostic(&mut self, diagnostic: Diagnostic) -> &mut Self {
|
||||
self.init_resource::<DiagnosticsStore>();
|
||||
let mut diagnostics = self.world.resource_mut::<DiagnosticsStore>();
|
||||
let mut diagnostics = self.world_mut().resource_mut::<DiagnosticsStore>();
|
||||
diagnostics.add(diagnostic);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RegisterDiagnostic for App {
|
||||
fn register_diagnostic(&mut self, diagnostic: Diagnostic) -> &mut Self {
|
||||
SubApp::register_diagnostic(self.main_mut(), diagnostic);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ impl Plugin for GizmoPlugin {
|
|||
.add_plugins(AabbGizmoPlugin)
|
||||
.add_plugins(LightGizmoPlugin);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -162,11 +162,11 @@ impl Plugin for GizmoPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut bevy_app::App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let render_device = render_app.world.resource::<RenderDevice>();
|
||||
let render_device = render_app.world().resource::<RenderDevice>();
|
||||
let line_layout = render_device.create_bind_group_layout(
|
||||
"LineGizmoUniform layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
|
@ -200,12 +200,12 @@ pub trait AppGizmoBuilder {
|
|||
|
||||
impl AppGizmoBuilder for App {
|
||||
fn init_gizmo_group<T: GizmoConfigGroup + Default>(&mut self) -> &mut Self {
|
||||
if self.world.contains_resource::<GizmoStorage<T>>() {
|
||||
if self.world().contains_resource::<GizmoStorage<T>>() {
|
||||
return self;
|
||||
}
|
||||
|
||||
let mut handles = self
|
||||
.world
|
||||
.world_mut()
|
||||
.get_resource_or_insert_with::<LineGizmoHandles>(Default::default);
|
||||
handles.list.insert(TypeId::of::<T>(), None);
|
||||
handles.strip.insert(TypeId::of::<T>(), None);
|
||||
|
@ -213,7 +213,7 @@ impl AppGizmoBuilder for App {
|
|||
self.init_resource::<GizmoStorage<T>>()
|
||||
.add_systems(Last, update_gizmo_meshes::<T>);
|
||||
|
||||
self.world
|
||||
self.world_mut()
|
||||
.get_resource_or_insert_with::<GizmoConfigStore>(Default::default)
|
||||
.register::<T>();
|
||||
|
||||
|
@ -225,16 +225,16 @@ impl AppGizmoBuilder for App {
|
|||
group: T,
|
||||
config: GizmoConfig,
|
||||
) -> &mut Self {
|
||||
self.world
|
||||
self.world_mut()
|
||||
.get_resource_or_insert_with::<GizmoConfigStore>(Default::default)
|
||||
.insert(config, group);
|
||||
|
||||
if self.world.contains_resource::<GizmoStorage<T>>() {
|
||||
if self.world().contains_resource::<GizmoStorage<T>>() {
|
||||
return self;
|
||||
}
|
||||
|
||||
let mut handles = self
|
||||
.world
|
||||
.world_mut()
|
||||
.get_resource_or_insert_with::<LineGizmoHandles>(Default::default);
|
||||
handles.list.insert(TypeId::of::<T>(), None);
|
||||
handles.strip.insert(TypeId::of::<T>(), None);
|
||||
|
|
|
@ -30,7 +30,7 @@ pub struct LineGizmo2dPlugin;
|
|||
|
||||
impl Plugin for LineGizmo2dPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,7 @@ impl Plugin for LineGizmo2dPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use bevy_utils::tracing::error;
|
|||
pub struct LineGizmo3dPlugin;
|
||||
impl Plugin for LineGizmo3dPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ impl Plugin for LineGizmo3dPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,9 +63,8 @@ impl Plugin for GltfPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let supported_compressed_formats = match app.world.get_resource::<RenderDevice>() {
|
||||
let supported_compressed_formats = match app.world().get_resource::<RenderDevice>() {
|
||||
Some(render_device) => CompressedImageFormats::from_features(render_device.features()),
|
||||
|
||||
None => CompressedImageFormats::NONE,
|
||||
};
|
||||
app.register_asset_loader(GltfLoader {
|
||||
|
|
|
@ -177,7 +177,7 @@ impl Plugin for LogPlugin {
|
|||
}
|
||||
}))
|
||||
.build();
|
||||
app.world.insert_non_send_resource(guard);
|
||||
app.insert_non_send_resource(guard);
|
||||
chrome_layer
|
||||
};
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ impl Plugin for DeferredPbrLightingPlugin {
|
|||
Shader::from_wgsl
|
||||
);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -130,7 +130,7 @@ impl Plugin for DeferredPbrLightingPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -352,16 +352,18 @@ impl Plugin for PbrPlugin {
|
|||
app.add_plugins(DeferredPbrLightingPlugin);
|
||||
}
|
||||
|
||||
app.world.resource_mut::<Assets<StandardMaterial>>().insert(
|
||||
&Handle::<StandardMaterial>::default(),
|
||||
StandardMaterial {
|
||||
base_color: Color::srgb(1.0, 0.0, 0.5),
|
||||
unlit: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<StandardMaterial>>()
|
||||
.insert(
|
||||
&Handle::<StandardMaterial>::default(),
|
||||
StandardMaterial {
|
||||
base_color: Color::srgb(1.0, 0.0, 0.5),
|
||||
unlit: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -379,8 +381,8 @@ impl Plugin for PbrPlugin {
|
|||
)
|
||||
.init_resource::<LightMeta>();
|
||||
|
||||
let shadow_pass_node = ShadowPassNode::new(&mut render_app.world);
|
||||
let mut graph = render_app.world.resource_mut::<RenderGraph>();
|
||||
let shadow_pass_node = ShadowPassNode::new(render_app.world_mut());
|
||||
let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||
let draw_3d_graph = graph.get_sub_graph_mut(Core3d).unwrap();
|
||||
draw_3d_graph.add_node(NodePbr::ShadowPass, shadow_pass_node);
|
||||
draw_3d_graph.add_node_edge(NodePbr::ShadowPass, Node3d::StartMainPass);
|
||||
|
@ -396,7 +398,7 @@ impl Plugin for PbrPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ impl Plugin for LightProbePlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ impl Plugin for LightmapPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ where
|
|||
app.init_asset::<M>()
|
||||
.add_plugins(ExtractInstancesPlugin::<AssetId<M>>::extract_visible());
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<DrawFunctions<Shadow>>()
|
||||
.add_render_command::<Shadow, DrawPrepass<M>>()
|
||||
|
@ -310,7 +310,7 @@ where
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<MaterialPipeline<M>>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ impl Plugin for MeshletPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ where
|
|||
Shader::from_wgsl
|
||||
);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ where
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -130,7 +130,10 @@ where
|
|||
M::Data: PartialEq + Eq + Hash + Clone,
|
||||
{
|
||||
fn build(&self, app: &mut App) {
|
||||
let no_prepass_plugin_loaded = app.world.get_resource::<AnyPrepassPluginLoaded>().is_none();
|
||||
let no_prepass_plugin_loaded = app
|
||||
.world()
|
||||
.get_resource::<AnyPrepassPluginLoaded>()
|
||||
.is_none();
|
||||
|
||||
if no_prepass_plugin_loaded {
|
||||
app.insert_resource(AnyPrepassPluginLoaded)
|
||||
|
@ -145,7 +148,7 @@ where
|
|||
);
|
||||
}
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ impl Plugin for FogPlugin {
|
|||
app.register_type::<FogSettings>();
|
||||
app.add_plugins(ExtractComponentPlugin::<FogSettings>::default());
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<FogMeta>()
|
||||
.add_systems(Render, prepare_fog.in_set(RenderSet::PrepareResources));
|
||||
|
|
|
@ -109,7 +109,7 @@ impl Plugin for MeshRenderPlugin {
|
|||
(no_automatic_skin_batching, no_automatic_morph_batching),
|
||||
);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<RenderMeshInstances>()
|
||||
.init_resource::<MeshBindGroups>()
|
||||
|
@ -160,9 +160,9 @@ impl Plugin for MeshRenderPlugin {
|
|||
fn finish(&self, app: &mut App) {
|
||||
let mut mesh_bindings_shader_defs = Vec::with_capacity(1);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(per_object_buffer_batch_size) = GpuArrayBuffer::<MeshUniform>::batch_size(
|
||||
render_app.world.resource::<RenderDevice>(),
|
||||
render_app.world().resource::<RenderDevice>(),
|
||||
) {
|
||||
mesh_bindings_shader_defs.push(ShaderDefVal::UInt(
|
||||
"PER_OBJECT_BUFFER_BATCH_SIZE".into(),
|
||||
|
@ -172,7 +172,7 @@ impl Plugin for MeshRenderPlugin {
|
|||
|
||||
render_app
|
||||
.insert_resource(GpuArrayBuffer::<MeshUniform>::new(
|
||||
render_app.world.resource::<RenderDevice>(),
|
||||
render_app.world().resource::<RenderDevice>(),
|
||||
))
|
||||
.init_resource::<MeshPipeline>();
|
||||
}
|
||||
|
|
|
@ -72,12 +72,12 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !render_app
|
||||
.world
|
||||
.world()
|
||||
.resource::<RenderAdapter>()
|
||||
.get_texture_format_features(TextureFormat::R16Float)
|
||||
.allowed_usages
|
||||
|
@ -88,7 +88,7 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
|
|||
}
|
||||
|
||||
if render_app
|
||||
.world
|
||||
.world()
|
||||
.resource::<RenderDevice>()
|
||||
.limits()
|
||||
.max_storage_textures_per_shader_stage
|
||||
|
|
|
@ -41,13 +41,13 @@ impl Plugin for CameraPlugin {
|
|||
ExtractComponentPlugin::<CameraMainTextureUsages>::default(),
|
||||
));
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<SortedCameras>()
|
||||
.add_systems(ExtractSchedule, extract_cameras)
|
||||
.add_systems(Render, sort_cameras.in_set(RenderSet::ManageViews));
|
||||
let camera_driver_node = CameraDriverNode::new(&mut render_app.world);
|
||||
let mut render_graph = render_app.world.resource_mut::<RenderGraph>();
|
||||
let camera_driver_node = CameraDriverNode::new(render_app.world_mut());
|
||||
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||
render_graph.add_node(crate::graph::CameraDriverLabel, camera_driver_node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,18 +52,18 @@ impl Plugin for RenderDiagnosticsPlugin {
|
|||
app.insert_resource(render_diagnostics_mutex.clone())
|
||||
.add_systems(PreUpdate, sync_diagnostics);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.insert_resource(render_diagnostics_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let device = render_app.world.resource::<RenderDevice>();
|
||||
let queue = render_app.world.resource::<RenderQueue>();
|
||||
let device = render_app.world().resource::<RenderDevice>();
|
||||
let queue = render_app.world().resource::<RenderQueue>();
|
||||
render_app.insert_resource(DiagnosticsRecorder::new(device, queue));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ impl<C> Default for UniformComponentPlugin<C> {
|
|||
|
||||
impl<C: Component + ShaderType + WriteInto + Clone> Plugin for UniformComponentPlugin<C> {
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.insert_resource(ComponentUniforms::<C>::default())
|
||||
.add_systems(
|
||||
|
@ -184,7 +184,7 @@ impl<C, F> ExtractComponentPlugin<C, F> {
|
|||
|
||||
impl<C: ExtractComponent> Plugin for ExtractComponentPlugin<C> {
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if self.only_extract_visible {
|
||||
render_app.add_systems(ExtractSchedule, extract_visible_components::<C>);
|
||||
} else {
|
||||
|
|
|
@ -94,7 +94,7 @@ where
|
|||
EI: ExtractInstance,
|
||||
{
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<ExtractedInstances<EI>>();
|
||||
if self.only_extract_visible {
|
||||
render_app.add_systems(ExtractSchedule, extract_visible::<EI>);
|
||||
|
|
|
@ -31,7 +31,7 @@ impl<R: ExtractResource> Default for ExtractResourcePlugin<R> {
|
|||
|
||||
impl<R: ExtractResource> Plugin for ExtractResourcePlugin<R> {
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.add_systems(ExtractSchedule, extract_resource::<R>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ impl Plugin for GlobalsPlugin {
|
|||
load_internal_asset!(app, GLOBALS_TYPE_HANDLE, "globals.wgsl", Shader::from_wgsl);
|
||||
app.register_type::<GlobalsUniform>();
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<GlobalsBuffer>()
|
||||
.init_resource::<Time>()
|
||||
|
|
|
@ -17,7 +17,7 @@ pub struct GpuComponentArrayBufferPlugin<C: Component + GpuArrayBufferable>(Phan
|
|||
|
||||
impl<C: Component + GpuArrayBufferable> Plugin for GpuComponentArrayBufferPlugin<C> {
|
||||
fn build(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.add_systems(
|
||||
Render,
|
||||
prepare_gpu_component_array_buffers::<C>.in_set(RenderSet::PrepareResources),
|
||||
|
@ -26,9 +26,9 @@ impl<C: Component + GpuArrayBufferable> Plugin for GpuComponentArrayBufferPlugin
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.insert_resource(GpuArrayBuffer::<C>::new(
|
||||
render_app.world.resource::<RenderDevice>(),
|
||||
render_app.world().resource::<RenderDevice>(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ pub struct RenderPlugin {
|
|||
pub synchronous_pipeline_compilation: bool,
|
||||
}
|
||||
|
||||
/// The labels of the default App rendering sets.
|
||||
/// The systems sets of the default [`App`] rendering schedule.
|
||||
///
|
||||
/// that runs immediately after the matching system set.
|
||||
/// These can be useful for ordering, but you almost never want to add your systems to these sets.
|
||||
|
@ -227,7 +227,7 @@ struct FutureRendererResources(
|
|||
>,
|
||||
);
|
||||
|
||||
/// A Label for the rendering sub-app.
|
||||
/// A label for the rendering sub-app.
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, AppLabel)]
|
||||
pub struct RenderApp;
|
||||
|
||||
|
@ -267,8 +267,8 @@ impl Plugin for RenderPlugin {
|
|||
|
||||
let mut system_state: SystemState<
|
||||
Query<&RawHandleWrapper, With<PrimaryWindow>>,
|
||||
> = SystemState::new(&mut app.world);
|
||||
let primary_window = system_state.get(&app.world).get_single().ok().cloned();
|
||||
> = SystemState::new(app.world_mut());
|
||||
let primary_window = system_state.get(app.world()).get_single().ok().cloned();
|
||||
|
||||
let settings = render_creation.clone();
|
||||
let async_renderer = async move {
|
||||
|
@ -347,7 +347,7 @@ impl Plugin for RenderPlugin {
|
|||
}
|
||||
|
||||
fn ready(&self, app: &App) -> bool {
|
||||
app.world
|
||||
app.world()
|
||||
.get_resource::<FutureRendererResources>()
|
||||
.and_then(|frr| frr.0.try_lock().map(|locked| locked.is_some()).ok())
|
||||
.unwrap_or(true)
|
||||
|
@ -356,7 +356,7 @@ impl Plugin for RenderPlugin {
|
|||
fn finish(&self, app: &mut App) {
|
||||
load_internal_asset!(app, MATHS_SHADER_HANDLE, "maths.wgsl", Shader::from_wgsl);
|
||||
if let Some(future_renderer_resources) =
|
||||
app.world.remove_resource::<FutureRendererResources>()
|
||||
app.world_mut().remove_resource::<FutureRendererResources>()
|
||||
{
|
||||
let (device, queue, adapter_info, render_adapter, instance) =
|
||||
future_renderer_resources.0.lock().unwrap().take().unwrap();
|
||||
|
@ -390,16 +390,15 @@ struct ScratchMainWorld(World);
|
|||
|
||||
/// Executes the [`ExtractSchedule`] step of the renderer.
|
||||
/// This updates the render world with the extracted ECS data of the current frame.
|
||||
fn extract(main_world: &mut World, render_app: &mut App) {
|
||||
fn extract(main_world: &mut World, render_world: &mut World) {
|
||||
// temporarily add the app world to the render world as a resource
|
||||
let scratch_world = main_world.remove_resource::<ScratchMainWorld>().unwrap();
|
||||
let inserted_world = std::mem::replace(main_world, scratch_world.0);
|
||||
render_app.world.insert_resource(MainWorld(inserted_world));
|
||||
|
||||
render_app.world.run_schedule(ExtractSchedule);
|
||||
render_world.insert_resource(MainWorld(inserted_world));
|
||||
render_world.run_schedule(ExtractSchedule);
|
||||
|
||||
// move the app world back, as if nothing happened.
|
||||
let inserted_world = render_app.world.remove_resource::<MainWorld>().unwrap();
|
||||
let inserted_world = render_world.remove_resource::<MainWorld>().unwrap();
|
||||
let scratch_world = std::mem::replace(main_world, inserted_world.0);
|
||||
main_world.insert_resource(ScratchMainWorld(scratch_world));
|
||||
}
|
||||
|
@ -408,8 +407,8 @@ fn extract(main_world: &mut World, render_app: &mut App) {
|
|||
unsafe fn initialize_render_app(app: &mut App) {
|
||||
app.init_resource::<ScratchMainWorld>();
|
||||
|
||||
let mut render_app = App::empty();
|
||||
render_app.main_schedule_label = Render.intern();
|
||||
let mut render_app = SubApp::new();
|
||||
render_app.update_schedule = Some(Render.intern());
|
||||
|
||||
let mut extract_schedule = Schedule::new(ExtractSchedule);
|
||||
// We skip applying any commands during the ExtractSchedule
|
||||
|
@ -424,7 +423,7 @@ unsafe fn initialize_render_app(app: &mut App) {
|
|||
.add_schedule(extract_schedule)
|
||||
.add_schedule(Render::base_schedule())
|
||||
.init_resource::<render_graph::RenderGraph>()
|
||||
.insert_resource(app.world.resource::<AssetServer>().clone())
|
||||
.insert_resource(app.world().resource::<AssetServer>().clone())
|
||||
.add_systems(ExtractSchedule, PipelineCache::extract_shaders)
|
||||
.add_systems(
|
||||
Render,
|
||||
|
@ -441,11 +440,7 @@ unsafe fn initialize_render_app(app: &mut App) {
|
|||
),
|
||||
);
|
||||
|
||||
let (sender, receiver) = bevy_time::create_time_channels();
|
||||
app.insert_resource(receiver);
|
||||
render_app.insert_resource(sender);
|
||||
|
||||
app.insert_sub_app(RenderApp, SubApp::new(render_app, move |main_world, render_app| {
|
||||
render_app.set_extract(|main_world, render_world| {
|
||||
#[cfg(feature = "trace")]
|
||||
let _render_span = bevy_utils::tracing::info_span!("extract main app to render subapp").entered();
|
||||
{
|
||||
|
@ -459,23 +454,27 @@ unsafe fn initialize_render_app(app: &mut App) {
|
|||
let total_count = main_world.entities().total_count();
|
||||
|
||||
assert_eq!(
|
||||
render_app.world.entities().len(),
|
||||
render_world.entities().len(),
|
||||
0,
|
||||
"An entity was spawned after the entity list was cleared last frame and before the extract schedule began. This is not supported",
|
||||
);
|
||||
|
||||
// SAFETY: This is safe given the clear_entities call in the past frame and the assert above
|
||||
unsafe {
|
||||
render_app
|
||||
.world
|
||||
render_world
|
||||
.entities_mut()
|
||||
.flush_and_reserve_invalid_assuming_no_entities(total_count);
|
||||
}
|
||||
}
|
||||
|
||||
// run extract schedule
|
||||
extract(main_world, render_app);
|
||||
}));
|
||||
extract(main_world, render_world);
|
||||
});
|
||||
|
||||
let (sender, receiver) = bevy_time::create_time_channels();
|
||||
render_app.insert_resource(sender);
|
||||
app.insert_resource(receiver);
|
||||
app.insert_sub_app(RenderApp, render_app);
|
||||
}
|
||||
|
||||
/// Applies the commands from the extract schedule. This happens during
|
||||
|
|
|
@ -29,7 +29,7 @@ impl Plugin for MeshPlugin {
|
|||
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
|
||||
.add_plugins(RenderAssetPlugin::<Mesh, Image>::default());
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use async_channel::{Receiver, Sender};
|
||||
|
||||
use bevy_app::{App, AppExit, AppLabel, Main, Plugin, SubApp};
|
||||
use bevy_app::{App, AppExit, AppLabel, Plugin, SubApp};
|
||||
use bevy_ecs::{
|
||||
schedule::MainThreadExecutor,
|
||||
system::Resource,
|
||||
|
@ -106,20 +106,20 @@ pub struct PipelinedRenderingPlugin;
|
|||
impl Plugin for PipelinedRenderingPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
// Don't add RenderExtractApp if RenderApp isn't initialized.
|
||||
if app.get_sub_app(RenderApp).is_err() {
|
||||
if app.get_sub_app(RenderApp).is_none() {
|
||||
return;
|
||||
}
|
||||
app.insert_resource(MainThreadExecutor::new());
|
||||
|
||||
let mut sub_app = App::empty();
|
||||
sub_app.init_schedule(Main);
|
||||
app.insert_sub_app(RenderExtractApp, SubApp::new(sub_app, update_rendering));
|
||||
let mut sub_app = SubApp::new();
|
||||
sub_app.set_extract(renderer_extract);
|
||||
app.insert_sub_app(RenderExtractApp, sub_app);
|
||||
}
|
||||
|
||||
// Sets up the render thread and inserts resources into the main app used for controlling the render thread.
|
||||
fn cleanup(&self, app: &mut App) {
|
||||
// skip setting up when headless
|
||||
if app.get_sub_app(RenderExtractApp).is_err() {
|
||||
if app.get_sub_app(RenderExtractApp).is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,8 @@ impl Plugin for PipelinedRenderingPlugin {
|
|||
.expect("Unable to get RenderApp. Another plugin may have removed the RenderApp before PipelinedRenderingPlugin");
|
||||
|
||||
// clone main thread executor to render world
|
||||
let executor = app.world.get_resource::<MainThreadExecutor>().unwrap();
|
||||
render_app.app.world.insert_resource(executor.clone());
|
||||
let executor = app.world().get_resource::<MainThreadExecutor>().unwrap();
|
||||
render_app.world_mut().insert_resource(executor.clone());
|
||||
|
||||
render_to_app_sender.send_blocking(render_app).unwrap();
|
||||
|
||||
|
@ -161,7 +161,7 @@ impl Plugin for PipelinedRenderingPlugin {
|
|||
#[cfg(feature = "trace")]
|
||||
let _sub_app_span =
|
||||
bevy_utils::tracing::info_span!("sub app", name = ?RenderApp).entered();
|
||||
render_app.run();
|
||||
render_app.update();
|
||||
}
|
||||
|
||||
if render_to_app_sender.send_blocking(render_app).is_err() {
|
||||
|
@ -176,7 +176,7 @@ impl Plugin for PipelinedRenderingPlugin {
|
|||
|
||||
// This function waits for the rendering world to be received,
|
||||
// runs extract, and then sends the rendering world back to the render thread.
|
||||
fn update_rendering(app_world: &mut World, _sub_app: &mut App) {
|
||||
fn renderer_extract(app_world: &mut World, _world: &mut World) {
|
||||
app_world.resource_scope(|world, main_thread_executor: Mut<MainThreadExecutor>| {
|
||||
world.resource_scope(|world, mut render_channels: Mut<RenderAppChannels>| {
|
||||
// we use a scope here to run any main thread tasks that the render world still needs to run
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{ExtractSchedule, MainWorld, Render, RenderApp, RenderSet};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_app::{App, Plugin, SubApp};
|
||||
use bevy_asset::{Asset, AssetEvent, AssetId, Assets};
|
||||
use bevy_ecs::{
|
||||
prelude::{Commands, EventReader, IntoSystemConfigs, ResMut, Resource},
|
||||
|
@ -122,7 +122,7 @@ impl<A: RenderAsset, AFTER: RenderAssetDependency + 'static> Plugin
|
|||
{
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<CachedExtractRenderAssetSystemState<A>>();
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<ExtractedAssets<A>>()
|
||||
.init_resource::<RenderAssets<A>>()
|
||||
|
@ -138,17 +138,17 @@ impl<A: RenderAsset, AFTER: RenderAssetDependency + 'static> Plugin
|
|||
|
||||
// helper to allow specifying dependencies between render assets
|
||||
pub trait RenderAssetDependency {
|
||||
fn register_system(render_app: &mut App, system: SystemConfigs);
|
||||
fn register_system(render_app: &mut SubApp, system: SystemConfigs);
|
||||
}
|
||||
|
||||
impl RenderAssetDependency for () {
|
||||
fn register_system(render_app: &mut App, system: SystemConfigs) {
|
||||
fn register_system(render_app: &mut SubApp, system: SystemConfigs) {
|
||||
render_app.add_systems(Render, system);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: RenderAsset> RenderAssetDependency for A {
|
||||
fn register_system(render_app: &mut App, system: SystemConfigs) {
|
||||
fn register_system(render_app: &mut SubApp, system: SystemConfigs) {
|
||||
render_app.add_systems(Render, system.after(prepare_assets::<A>));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use bevy_app::App;
|
||||
use bevy_app::{App, SubApp};
|
||||
use bevy_ecs::world::FromWorld;
|
||||
use bevy_utils::tracing::warn;
|
||||
|
||||
use super::{IntoRenderNodeArray, Node, RenderGraph, RenderLabel, RenderSubGraph};
|
||||
|
||||
/// Adds common [`RenderGraph`] operations to [`App`].
|
||||
/// Adds common [`RenderGraph`] operations to [`SubApp`] (and [`App`]).
|
||||
pub trait RenderGraphApp {
|
||||
// Add a sub graph to the [`RenderGraph`]
|
||||
fn add_render_sub_graph(&mut self, sub_graph: impl RenderSubGraph) -> &mut Self;
|
||||
|
@ -32,23 +32,15 @@ pub trait RenderGraphApp {
|
|||
) -> &mut Self;
|
||||
}
|
||||
|
||||
impl RenderGraphApp for App {
|
||||
fn add_render_sub_graph(&mut self, sub_graph: impl RenderSubGraph) -> &mut Self {
|
||||
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
|
||||
"RenderGraph not found. Make sure you are using add_render_sub_graph on the RenderApp",
|
||||
);
|
||||
render_graph.add_sub_graph(sub_graph, RenderGraph::default());
|
||||
self
|
||||
}
|
||||
|
||||
impl RenderGraphApp for SubApp {
|
||||
fn add_render_graph_node<T: Node + FromWorld>(
|
||||
&mut self,
|
||||
sub_graph: impl RenderSubGraph,
|
||||
node_label: impl RenderLabel,
|
||||
) -> &mut Self {
|
||||
let sub_graph = sub_graph.intern();
|
||||
let node = T::from_world(&mut self.world);
|
||||
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
|
||||
let node = T::from_world(self.world_mut());
|
||||
let mut render_graph = self.world_mut().get_resource_mut::<RenderGraph>().expect(
|
||||
"RenderGraph not found. Make sure you are using add_render_graph_node on the RenderApp",
|
||||
);
|
||||
if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph) {
|
||||
|
@ -67,7 +59,7 @@ impl RenderGraphApp for App {
|
|||
edges: impl IntoRenderNodeArray<N>,
|
||||
) -> &mut Self {
|
||||
let sub_graph = sub_graph.intern();
|
||||
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
|
||||
let mut render_graph = self.world_mut().get_resource_mut::<RenderGraph>().expect(
|
||||
"RenderGraph not found. Make sure you are using add_render_graph_edges on the RenderApp",
|
||||
);
|
||||
if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph) {
|
||||
|
@ -87,7 +79,7 @@ impl RenderGraphApp for App {
|
|||
input_node: impl RenderLabel,
|
||||
) -> &mut Self {
|
||||
let sub_graph = sub_graph.intern();
|
||||
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
|
||||
let mut render_graph = self.world_mut().get_resource_mut::<RenderGraph>().expect(
|
||||
"RenderGraph not found. Make sure you are using add_render_graph_edge on the RenderApp",
|
||||
);
|
||||
if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph) {
|
||||
|
@ -99,4 +91,47 @@ impl RenderGraphApp for App {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn add_render_sub_graph(&mut self, sub_graph: impl RenderSubGraph) -> &mut Self {
|
||||
let mut render_graph = self.world_mut().get_resource_mut::<RenderGraph>().expect(
|
||||
"RenderGraph not found. Make sure you are using add_render_sub_graph on the RenderApp",
|
||||
);
|
||||
render_graph.add_sub_graph(sub_graph, RenderGraph::default());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderGraphApp for App {
|
||||
fn add_render_graph_node<T: Node + FromWorld>(
|
||||
&mut self,
|
||||
sub_graph: impl RenderSubGraph,
|
||||
node_label: impl RenderLabel,
|
||||
) -> &mut Self {
|
||||
SubApp::add_render_graph_node::<T>(self.main_mut(), sub_graph, node_label);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_render_graph_edge(
|
||||
&mut self,
|
||||
sub_graph: impl RenderSubGraph,
|
||||
output_node: impl RenderLabel,
|
||||
input_node: impl RenderLabel,
|
||||
) -> &mut Self {
|
||||
SubApp::add_render_graph_edge(self.main_mut(), sub_graph, output_node, input_node);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_render_graph_edges<const N: usize>(
|
||||
&mut self,
|
||||
sub_graph: impl RenderSubGraph,
|
||||
edges: impl IntoRenderNodeArray<N>,
|
||||
) -> &mut Self {
|
||||
SubApp::add_render_graph_edges(self.main_mut(), sub_graph, edges);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_render_sub_graph(&mut self, sub_graph: impl RenderSubGraph) -> &mut Self {
|
||||
SubApp::add_render_sub_graph(self.main_mut(), sub_graph);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::render_phase::{PhaseItem, TrackedRenderPass};
|
||||
use bevy_app::App;
|
||||
use bevy_app::{App, SubApp};
|
||||
use bevy_ecs::{
|
||||
entity::Entity,
|
||||
query::{QueryState, ROQueryItem, ReadOnlyQueryData},
|
||||
|
@ -310,16 +310,16 @@ pub trait AddRenderCommand {
|
|||
C::Param: ReadOnlySystemParam;
|
||||
}
|
||||
|
||||
impl AddRenderCommand for App {
|
||||
impl AddRenderCommand for SubApp {
|
||||
fn add_render_command<P: PhaseItem, C: RenderCommand<P> + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
) -> &mut Self
|
||||
where
|
||||
C::Param: ReadOnlySystemParam,
|
||||
{
|
||||
let draw_function = RenderCommandState::<P, C>::new(&mut self.world);
|
||||
let draw_function = RenderCommandState::<P, C>::new(self.world_mut());
|
||||
let draw_functions = self
|
||||
.world
|
||||
.world()
|
||||
.get_resource::<DrawFunctions<P>>()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
@ -332,3 +332,15 @@ impl AddRenderCommand for App {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AddRenderCommand for App {
|
||||
fn add_render_command<P: PhaseItem, C: RenderCommand<P> + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
) -> &mut Self
|
||||
where
|
||||
C::Param: ReadOnlySystemParam,
|
||||
{
|
||||
SubApp::add_render_command::<P, C>(self.main_mut());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,12 +88,13 @@ impl Plugin for ImagePlugin {
|
|||
.register_type::<Image>()
|
||||
.init_asset::<Image>()
|
||||
.register_asset_reflect::<Image>();
|
||||
app.world
|
||||
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<Image>>()
|
||||
.insert(&Handle::default(), Image::default());
|
||||
#[cfg(feature = "basis-universal")]
|
||||
if let Some(processor) = app
|
||||
.world
|
||||
.world()
|
||||
.get_resource::<bevy_asset::processor::AssetProcessor>()
|
||||
{
|
||||
processor.register_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>(
|
||||
|
@ -103,7 +104,7 @@ impl Plugin for ImagePlugin {
|
|||
.set_default_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>("png");
|
||||
}
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<TextureCache>().add_systems(
|
||||
Render,
|
||||
update_texture_cache_system.in_set(RenderSet::Cleanup),
|
||||
|
@ -140,9 +141,9 @@ impl Plugin for ImagePlugin {
|
|||
app.init_asset_loader::<ImageLoader>();
|
||||
}
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
let default_sampler = {
|
||||
let device = render_app.world.resource::<RenderDevice>();
|
||||
let device = render_app.world().resource::<RenderDevice>();
|
||||
device.create_sampler(&self.default_sampler.as_wgpu())
|
||||
};
|
||||
render_app
|
||||
|
|
|
@ -55,7 +55,7 @@ impl Plugin for ViewPlugin {
|
|||
// NOTE: windows.is_changed() handles cases where a window was resized
|
||||
.add_plugins((ExtractResourcePlugin::<Msaa>::default(), VisibilityPlugin));
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<ViewUniforms>().add_systems(
|
||||
Render,
|
||||
(
|
||||
|
|
|
@ -475,42 +475,51 @@ mod test {
|
|||
let mut app = App::new();
|
||||
app.add_systems(Update, visibility_propagate_system);
|
||||
|
||||
let root1 = app.world.spawn(visibility_bundle(Visibility::Hidden)).id();
|
||||
let root1_child1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root1_child2 = app.world.spawn(visibility_bundle(Visibility::Hidden)).id();
|
||||
let root1_child1_grandchild1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root1_child2_grandchild1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root1 = app
|
||||
.world_mut()
|
||||
.spawn(visibility_bundle(Visibility::Hidden))
|
||||
.id();
|
||||
let root1_child1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
let root1_child2 = app
|
||||
.world_mut()
|
||||
.spawn(visibility_bundle(Visibility::Hidden))
|
||||
.id();
|
||||
let root1_child1_grandchild1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
let root1_child2_grandchild1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1)
|
||||
.push_children(&[root1_child1, root1_child2]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1_child1)
|
||||
.push_children(&[root1_child1_grandchild1]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1_child2)
|
||||
.push_children(&[root1_child2_grandchild1]);
|
||||
|
||||
let root2 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root2_child1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root2_child2 = app.world.spawn(visibility_bundle(Visibility::Hidden)).id();
|
||||
let root2_child1_grandchild1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root2_child2_grandchild1 = app.world.spawn(VisibilityBundle::default()).id();
|
||||
let root2 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
let root2_child1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
let root2_child2 = app
|
||||
.world_mut()
|
||||
.spawn(visibility_bundle(Visibility::Hidden))
|
||||
.id();
|
||||
let root2_child1_grandchild1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
let root2_child2_grandchild1 = app.world_mut().spawn(VisibilityBundle::default()).id();
|
||||
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root2)
|
||||
.push_children(&[root2_child1, root2_child2]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root2_child1)
|
||||
.push_children(&[root2_child1_grandchild1]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root2_child2)
|
||||
.push_children(&[root2_child2_grandchild1]);
|
||||
|
||||
app.update();
|
||||
|
||||
let is_visible = |e: Entity| {
|
||||
app.world
|
||||
app.world()
|
||||
.entity(e)
|
||||
.get::<InheritedVisibility>()
|
||||
.unwrap()
|
||||
|
@ -566,29 +575,29 @@ mod test {
|
|||
let mut app = App::new();
|
||||
app.add_systems(Update, visibility_propagate_system);
|
||||
|
||||
let root1 = app.world.spawn(visibility_bundle(Visible)).id();
|
||||
let root1_child1 = app.world.spawn(visibility_bundle(Inherited)).id();
|
||||
let root1_child2 = app.world.spawn(visibility_bundle(Hidden)).id();
|
||||
let root1_child1_grandchild1 = app.world.spawn(visibility_bundle(Visible)).id();
|
||||
let root1_child2_grandchild1 = app.world.spawn(visibility_bundle(Visible)).id();
|
||||
let root1 = app.world_mut().spawn(visibility_bundle(Visible)).id();
|
||||
let root1_child1 = app.world_mut().spawn(visibility_bundle(Inherited)).id();
|
||||
let root1_child2 = app.world_mut().spawn(visibility_bundle(Hidden)).id();
|
||||
let root1_child1_grandchild1 = app.world_mut().spawn(visibility_bundle(Visible)).id();
|
||||
let root1_child2_grandchild1 = app.world_mut().spawn(visibility_bundle(Visible)).id();
|
||||
|
||||
let root2 = app.world.spawn(visibility_bundle(Inherited)).id();
|
||||
let root3 = app.world.spawn(visibility_bundle(Hidden)).id();
|
||||
let root2 = app.world_mut().spawn(visibility_bundle(Inherited)).id();
|
||||
let root3 = app.world_mut().spawn(visibility_bundle(Hidden)).id();
|
||||
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1)
|
||||
.push_children(&[root1_child1, root1_child2]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1_child1)
|
||||
.push_children(&[root1_child1_grandchild1]);
|
||||
app.world
|
||||
app.world_mut()
|
||||
.entity_mut(root1_child2)
|
||||
.push_children(&[root1_child2_grandchild1]);
|
||||
|
||||
app.update();
|
||||
|
||||
let is_visible = |e: Entity| {
|
||||
app.world
|
||||
app.world()
|
||||
.entity(e)
|
||||
.get::<InheritedVisibility>()
|
||||
.unwrap()
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Plugin for WindowRenderPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(ScreenshotPlugin);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<ExtractedWindows>()
|
||||
.init_resource::<WindowSurfaces>()
|
||||
|
@ -53,7 +53,7 @@ impl Plugin for WindowRenderPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<ScreenshotToScreenPipeline>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ impl Plugin for ScreenshotPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut bevy_app::App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<SpecializedRenderPipelines<ScreenshotToScreenPipeline>>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,15 +132,18 @@ mod tests {
|
|||
let mut scene_world = World::new();
|
||||
|
||||
// create a new DynamicScene manually
|
||||
let type_registry = app.world.resource::<AppTypeRegistry>().clone();
|
||||
let type_registry = app.world().resource::<AppTypeRegistry>().clone();
|
||||
scene_world.insert_resource(type_registry);
|
||||
scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
|
||||
let scene = DynamicScene::from_world(&scene_world);
|
||||
let scene_handle = app.world.resource_mut::<Assets<DynamicScene>>().add(scene);
|
||||
let scene_handle = app
|
||||
.world_mut()
|
||||
.resource_mut::<Assets<DynamicScene>>()
|
||||
.add(scene);
|
||||
|
||||
// spawn the scene as a child of `entity` using the `DynamicSceneBundle`
|
||||
let entity = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn(DynamicSceneBundle {
|
||||
scene: scene_handle.clone(),
|
||||
..default()
|
||||
|
@ -152,24 +155,27 @@ mod tests {
|
|||
|
||||
// make sure that the scene was added as a child of the root entity
|
||||
let (scene_entity, scene_component_a) = app
|
||||
.world
|
||||
.world_mut()
|
||||
.query::<(Entity, &ComponentA)>()
|
||||
.single(&app.world);
|
||||
.single(app.world());
|
||||
assert_eq!(scene_component_a.x, 3.0);
|
||||
assert_eq!(scene_component_a.y, 4.0);
|
||||
assert_eq!(app.world.entity(entity).get::<Children>().unwrap().len(), 1);
|
||||
assert_eq!(
|
||||
app.world().entity(entity).get::<Children>().unwrap().len(),
|
||||
1
|
||||
);
|
||||
|
||||
// let's try to delete the scene
|
||||
let mut scene_spawner = app.world.resource_mut::<SceneSpawner>();
|
||||
let mut scene_spawner = app.world_mut().resource_mut::<SceneSpawner>();
|
||||
scene_spawner.despawn(&scene_handle);
|
||||
|
||||
// run the scene spawner system to despawn the scene
|
||||
app.update();
|
||||
|
||||
// the scene entity does not exist anymore
|
||||
assert!(app.world.get_entity(scene_entity).is_none());
|
||||
assert!(app.world().get_entity(scene_entity).is_none());
|
||||
|
||||
// the root entity does not have any children anymore
|
||||
assert!(app.world.entity(entity).get::<Children>().is_none());
|
||||
assert!(app.world().entity(entity).get::<Children>().is_none());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Plugin for ScenePlugin {
|
|||
.add_systems(SpawnScene, (scene_spawner, scene_spawner_system).chain());
|
||||
|
||||
// Register component hooks for DynamicScene
|
||||
app.world
|
||||
app.world_mut()
|
||||
.register_component_hooks::<Handle<DynamicScene>>()
|
||||
.on_remove(|mut world, entity, _| {
|
||||
let Some(handle) = world.get::<Handle<DynamicScene>>(entity) else {
|
||||
|
@ -80,7 +80,7 @@ impl Plugin for ScenePlugin {
|
|||
});
|
||||
|
||||
// Register component hooks for Scene
|
||||
app.world
|
||||
app.world_mut()
|
||||
.register_component_hooks::<Handle<Scene>>()
|
||||
.on_remove(|mut world, entity, _| {
|
||||
if let Some(&SceneInstance(scene_instance)) = world.get::<SceneInstance>(entity) {
|
||||
|
|
|
@ -512,18 +512,18 @@ mod tests {
|
|||
app.add_plugins((AssetPlugin::default(), ScenePlugin));
|
||||
|
||||
app.register_type::<ComponentA>();
|
||||
app.world.spawn(ComponentA);
|
||||
app.world.spawn(ComponentA);
|
||||
app.world_mut().spawn(ComponentA);
|
||||
app.world_mut().spawn(ComponentA);
|
||||
|
||||
// Build scene.
|
||||
let scene =
|
||||
app.world
|
||||
app.world_mut()
|
||||
.run_system_once(|world: &World, asset_server: Res<'_, AssetServer>| {
|
||||
asset_server.add(DynamicScene::from_world(world))
|
||||
});
|
||||
|
||||
// Spawn scene.
|
||||
let scene_entity = app.world.run_system_once(
|
||||
let scene_entity = app.world_mut().run_system_once(
|
||||
move |mut commands: Commands<'_, '_>, mut scene_spawner: ResMut<'_, SceneSpawner>| {
|
||||
let scene_entity = commands.spawn_empty().id();
|
||||
scene_spawner.spawn_dynamic_as_child(scene.clone(), scene_entity);
|
||||
|
@ -533,7 +533,7 @@ mod tests {
|
|||
|
||||
// Check for event arrival.
|
||||
app.update();
|
||||
app.world.run_system_once(
|
||||
app.world_mut().run_system_once(
|
||||
move |mut ev_scene: EventReader<'_, '_, SceneInstanceReady>| {
|
||||
let mut events = ev_scene.read();
|
||||
|
||||
|
@ -555,7 +555,7 @@ mod tests {
|
|||
app.add_plugins((AssetPlugin::default(), ScenePlugin));
|
||||
app.register_type::<ComponentA>();
|
||||
|
||||
let asset_server = app.world.resource::<AssetServer>();
|
||||
let asset_server = app.world().resource::<AssetServer>();
|
||||
|
||||
// Build scene.
|
||||
let scene = asset_server.add(DynamicScene::default());
|
||||
|
@ -573,14 +573,14 @@ mod tests {
|
|||
|
||||
// Spawn scene.
|
||||
for _ in 0..count {
|
||||
app.world.spawn((ComponentA, scene.clone()));
|
||||
app.world_mut().spawn((ComponentA, scene.clone()));
|
||||
}
|
||||
|
||||
app.update();
|
||||
check(&mut app.world, count);
|
||||
check(app.world_mut(), count);
|
||||
|
||||
// Despawn scene.
|
||||
app.world.run_system_once(
|
||||
app.world_mut().run_system_once(
|
||||
|mut commands: Commands, query: Query<Entity, With<ComponentA>>| {
|
||||
for entity in query.iter() {
|
||||
commands.entity(entity).despawn_recursive();
|
||||
|
@ -589,6 +589,6 @@ mod tests {
|
|||
);
|
||||
|
||||
app.update();
|
||||
check(&mut app.world, 0);
|
||||
check(app.world_mut(), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ impl Plugin for SpritePlugin {
|
|||
),
|
||||
);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<ImageBindGroups>()
|
||||
.init_resource::<SpecializedRenderPipelines<SpritePipeline>>()
|
||||
|
@ -125,7 +125,7 @@ impl Plugin for SpritePlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<SpritePipeline>();
|
||||
}
|
||||
}
|
||||
|
@ -202,11 +202,14 @@ mod test {
|
|||
app.add_systems(Update, calculate_bounds_2d);
|
||||
|
||||
// Add entities
|
||||
let entity = app.world.spawn((Sprite::default(), image_handle)).id();
|
||||
let entity = app
|
||||
.world_mut()
|
||||
.spawn((Sprite::default(), image_handle))
|
||||
.id();
|
||||
|
||||
// Verify that the entity does not have an AABB
|
||||
assert!(!app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.contains::<Aabb>());
|
||||
|
@ -216,7 +219,7 @@ mod test {
|
|||
|
||||
// Verify the AABB exists
|
||||
assert!(app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.contains::<Aabb>());
|
||||
|
@ -241,7 +244,7 @@ mod test {
|
|||
|
||||
// Add entities
|
||||
let entity = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn((
|
||||
Sprite {
|
||||
custom_size: Some(Vec2::ZERO),
|
||||
|
@ -256,7 +259,7 @@ mod test {
|
|||
|
||||
// Get the initial AABB
|
||||
let first_aabb = *app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.get::<Aabb>()
|
||||
|
@ -264,7 +267,7 @@ mod test {
|
|||
|
||||
// Change `custom_size` of sprite
|
||||
let mut binding = app
|
||||
.world
|
||||
.world_mut()
|
||||
.get_entity_mut(entity)
|
||||
.expect("Could not find entity");
|
||||
let mut sprite = binding
|
||||
|
@ -277,7 +280,7 @@ mod test {
|
|||
|
||||
// Get the re-calculated AABB
|
||||
let second_aabb = *app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.get::<Aabb>()
|
||||
|
|
|
@ -24,13 +24,15 @@ impl Plugin for ColorMaterialPlugin {
|
|||
app.add_plugins(Material2dPlugin::<ColorMaterial>::default())
|
||||
.register_asset_reflect::<ColorMaterial>();
|
||||
|
||||
app.world.resource_mut::<Assets<ColorMaterial>>().insert(
|
||||
&Handle::<ColorMaterial>::default(),
|
||||
ColorMaterial {
|
||||
color: Color::srgb(1.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
app.world_mut()
|
||||
.resource_mut::<Assets<ColorMaterial>>()
|
||||
.insert(
|
||||
&Handle::<ColorMaterial>::default(),
|
||||
ColorMaterial {
|
||||
color: Color::srgb(1.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ where
|
|||
fn build(&self, app: &mut App) {
|
||||
app.init_asset::<M>();
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.add_render_command::<Transparent2d, DrawMaterial2d<M>>()
|
||||
.init_resource::<ExtractedMaterials2d<M>>()
|
||||
|
@ -176,7 +176,7 @@ where
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<Material2dPipeline<M>>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ impl Plugin for Mesh2dRenderPlugin {
|
|||
);
|
||||
load_internal_asset!(app, MESH2D_SHADER_HANDLE, "mesh2d.wgsl", Shader::from_wgsl);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.init_resource::<RenderMesh2dInstances>()
|
||||
.init_resource::<SpecializedMeshPipelines<Mesh2dPipeline>>()
|
||||
|
@ -115,9 +115,9 @@ impl Plugin for Mesh2dRenderPlugin {
|
|||
fn finish(&self, app: &mut bevy_app::App) {
|
||||
let mut mesh_bindings_shader_defs = Vec::with_capacity(1);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(per_object_buffer_batch_size) = GpuArrayBuffer::<Mesh2dUniform>::batch_size(
|
||||
render_app.world.resource::<RenderDevice>(),
|
||||
render_app.world().resource::<RenderDevice>(),
|
||||
) {
|
||||
mesh_bindings_shader_defs.push(ShaderDefVal::UInt(
|
||||
"PER_OBJECT_BUFFER_BATCH_SIZE".into(),
|
||||
|
@ -127,7 +127,7 @@ impl Plugin for Mesh2dRenderPlugin {
|
|||
|
||||
render_app
|
||||
.insert_resource(GpuArrayBuffer::<Mesh2dUniform>::new(
|
||||
render_app.world.resource::<RenderDevice>(),
|
||||
render_app.world().resource::<RenderDevice>(),
|
||||
))
|
||||
.init_resource::<Mesh2dPipeline>();
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ impl Plugin for TextPlugin {
|
|||
),
|
||||
);
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.add_systems(
|
||||
ExtractSchedule,
|
||||
extract_text2d_sprite.after(SpriteSystem::ExtractSprites),
|
||||
|
|
|
@ -301,7 +301,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let entity = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn((Text2dBundle {
|
||||
text: Text::from_section(FIRST_TEXT, default()),
|
||||
..default()
|
||||
|
@ -316,7 +316,7 @@ mod tests {
|
|||
let (mut app, entity) = setup();
|
||||
|
||||
assert!(!app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.contains::<Aabb>());
|
||||
|
@ -325,7 +325,7 @@ mod tests {
|
|||
app.update();
|
||||
|
||||
let aabb = app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.get::<Aabb>()
|
||||
|
@ -347,14 +347,14 @@ mod tests {
|
|||
app.update();
|
||||
|
||||
let first_aabb = *app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.get::<Aabb>()
|
||||
.expect("Could not find initial AABB");
|
||||
|
||||
let mut entity_ref = app
|
||||
.world
|
||||
.world_mut()
|
||||
.get_entity_mut(entity)
|
||||
.expect("Could not find entity");
|
||||
*entity_ref
|
||||
|
@ -365,7 +365,7 @@ mod tests {
|
|||
app.update();
|
||||
|
||||
let second_aabb = *app
|
||||
.world
|
||||
.world()
|
||||
.get_entity(entity)
|
||||
.expect("Could not find entity")
|
||||
.get::<Aabb>()
|
||||
|
|
|
@ -121,7 +121,7 @@ mod tests {
|
|||
let mut entity = None;
|
||||
|
||||
for transform in transforms {
|
||||
let mut e = app.world.spawn(TransformBundle::from(transform));
|
||||
let mut e = app.world_mut().spawn(TransformBundle::from(transform));
|
||||
|
||||
if let Some(entity) = entity {
|
||||
e.set_parent(entity);
|
||||
|
@ -134,10 +134,10 @@ mod tests {
|
|||
|
||||
app.update();
|
||||
|
||||
let transform = *app.world.get::<GlobalTransform>(leaf_entity).unwrap();
|
||||
let transform = *app.world().get::<GlobalTransform>(leaf_entity).unwrap();
|
||||
|
||||
let mut state = SystemState::<TransformHelper>::new(&mut app.world);
|
||||
let helper = state.get(&app.world);
|
||||
let mut state = SystemState::<TransformHelper>::new(app.world_mut());
|
||||
let helper = state.get(app.world());
|
||||
|
||||
let computed_transform = helper.compute_global_transform(leaf_entity).unwrap();
|
||||
|
||||
|
|
|
@ -416,7 +416,7 @@ mod test {
|
|||
let mut child = Entity::from_raw(0);
|
||||
let mut grandchild = Entity::from_raw(1);
|
||||
let parent = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn((
|
||||
Transform::from_translation(translation),
|
||||
GlobalTransform::IDENTITY,
|
||||
|
@ -434,13 +434,16 @@ mod test {
|
|||
app.update();
|
||||
|
||||
// check the `Children` structure is spawned
|
||||
assert_eq!(&**app.world.get::<Children>(parent).unwrap(), &[child]);
|
||||
assert_eq!(&**app.world.get::<Children>(child).unwrap(), &[grandchild]);
|
||||
assert_eq!(&**app.world().get::<Children>(parent).unwrap(), &[child]);
|
||||
assert_eq!(
|
||||
&**app.world().get::<Children>(child).unwrap(),
|
||||
&[grandchild]
|
||||
);
|
||||
// Note that at this point, the `GlobalTransform`s will not have updated yet, due to `Commands` delay
|
||||
app.update();
|
||||
|
||||
let mut state = app.world.query::<&GlobalTransform>();
|
||||
for global in state.iter(&app.world) {
|
||||
let mut state = app.world_mut().query::<&GlobalTransform>();
|
||||
for global in state.iter(app.world()) {
|
||||
assert_eq!(global, &GlobalTransform::from_translation(translation));
|
||||
}
|
||||
}
|
||||
|
@ -468,16 +471,16 @@ mod test {
|
|||
}
|
||||
|
||||
let (temp_child, temp_grandchild) = setup_world(&mut temp);
|
||||
let (child, grandchild) = setup_world(&mut app.world);
|
||||
let (child, grandchild) = setup_world(app.world_mut());
|
||||
|
||||
assert_eq!(temp_child, child);
|
||||
assert_eq!(temp_grandchild, grandchild);
|
||||
|
||||
app.world
|
||||
app.world_mut()
|
||||
.spawn(TransformBundle::IDENTITY)
|
||||
.push_children(&[child]);
|
||||
std::mem::swap(
|
||||
&mut *app.world.get_mut::<Parent>(child).unwrap(),
|
||||
&mut *app.world_mut().get_mut::<Parent>(child).unwrap(),
|
||||
&mut *temp.get_mut::<Parent>(grandchild).unwrap(),
|
||||
);
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ impl Plugin for UiPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ pub enum RenderUiSystem {
|
|||
pub fn build_ui_render(app: &mut App) {
|
||||
load_internal_asset!(app, UI_SHADER_HANDLE, "ui.wgsl", Shader::from_wgsl);
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -116,7 +116,7 @@ pub fn build_ui_render(app: &mut App) {
|
|||
// Render graph
|
||||
let ui_graph_2d = get_ui_graph(render_app);
|
||||
let ui_graph_3d = get_ui_graph(render_app);
|
||||
let mut graph = render_app.world.resource_mut::<RenderGraph>();
|
||||
let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||
|
||||
if let Some(graph_2d) = graph.get_sub_graph_mut(Core2d) {
|
||||
graph_2d.add_sub_graph(SubGraphUi, ui_graph_2d);
|
||||
|
@ -135,8 +135,8 @@ pub fn build_ui_render(app: &mut App) {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_ui_graph(render_app: &mut App) -> RenderGraph {
|
||||
let ui_pass_node = UiPassNode::new(&mut render_app.world);
|
||||
fn get_ui_graph(render_app: &mut SubApp) -> RenderGraph {
|
||||
let ui_pass_node = UiPassNode::new(render_app.world_mut());
|
||||
let mut ui_graph = RenderGraph::default();
|
||||
ui_graph.add_node(NodeUi::UiPass, ui_pass_node);
|
||||
ui_graph
|
||||
|
|
|
@ -62,7 +62,7 @@ where
|
|||
app.init_asset::<M>()
|
||||
.add_plugins(ExtractComponentPlugin::<Handle<M>>::extract_visible());
|
||||
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.add_render_command::<TransparentUi, DrawUiMaterial<M>>()
|
||||
.init_resource::<ExtractedUiMaterials<M>>()
|
||||
|
@ -89,7 +89,7 @@ where
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.init_resource::<UiMaterialPipeline<M>>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,11 +107,11 @@ impl Plugin for WindowPlugin {
|
|||
|
||||
if let Some(primary_window) = &self.primary_window {
|
||||
let initial_focus = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn(primary_window.clone())
|
||||
.insert(PrimaryWindow)
|
||||
.id();
|
||||
if let Some(mut focus) = app.world.get_resource_mut::<Focus>() {
|
||||
if let Some(mut focus) = app.world_mut().get_resource_mut::<Focus>() {
|
||||
**focus = Some(initial_focus);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,9 +158,9 @@ impl Plugin for WinitPlugin {
|
|||
// Otherwise, we want to create a window before `bevy_render` initializes the renderer
|
||||
// so that we have a surface to use as a hint. This improves compatibility with `wgpu`
|
||||
// backends, especially WASM/WebGL2.
|
||||
let mut create_window = SystemState::<CreateWindowParams>::from_world(&mut app.world);
|
||||
create_windows(&event_loop, create_window.get_mut(&mut app.world));
|
||||
create_window.apply(&mut app.world);
|
||||
let mut create_window = SystemState::<CreateWindowParams>::from_world(app.world_mut());
|
||||
create_windows(&event_loop, create_window.get_mut(app.world_mut()));
|
||||
create_window.apply(app.world_mut());
|
||||
}
|
||||
|
||||
// `winit`'s windows are bound to the event loop that created them, so the event loop must
|
||||
|
@ -270,11 +270,11 @@ pub fn winit_runner(mut app: App) {
|
|||
}
|
||||
|
||||
let event_loop = app
|
||||
.world
|
||||
.world_mut()
|
||||
.remove_non_send_resource::<EventLoop<UserEvent>>()
|
||||
.unwrap();
|
||||
|
||||
app.world
|
||||
app.world_mut()
|
||||
.insert_non_send_resource(event_loop.create_proxy());
|
||||
|
||||
let mut runner_state = WinitAppRunnerState::default();
|
||||
|
@ -284,17 +284,17 @@ pub fn winit_runner(mut app: App) {
|
|||
let mut redraw_event_reader = ManualEventReader::<RequestRedraw>::default();
|
||||
|
||||
let mut focused_windows_state: SystemState<(Res<WinitSettings>, Query<&Window>)> =
|
||||
SystemState::new(&mut app.world);
|
||||
SystemState::new(app.world_mut());
|
||||
|
||||
let mut event_writer_system_state: SystemState<(
|
||||
EventWriter<WindowResized>,
|
||||
NonSend<WinitWindows>,
|
||||
Query<(&mut Window, &mut CachedWindow)>,
|
||||
NonSend<AccessKitAdapters>,
|
||||
)> = SystemState::new(&mut app.world);
|
||||
)> = SystemState::new(app.world_mut());
|
||||
|
||||
let mut create_window =
|
||||
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
|
||||
SystemState::<CreateWindowParams<Added<Window>>>::from_world(app.world_mut());
|
||||
let mut winit_events = Vec::default();
|
||||
// set up the event loop
|
||||
let event_handler = move |event, event_loop: &EventLoopWindowTarget<UserEvent>| {
|
||||
|
@ -350,7 +350,7 @@ fn handle_winit_event(
|
|||
}
|
||||
runner_state.redraw_requested = true;
|
||||
|
||||
if let Some(app_exit_events) = app.world.get_resource::<Events<AppExit>>() {
|
||||
if let Some(app_exit_events) = app.world().get_resource::<Events<AppExit>>() {
|
||||
if app_exit_event_reader.read(app_exit_events).last().is_some() {
|
||||
event_loop.exit();
|
||||
return;
|
||||
|
@ -360,7 +360,7 @@ fn handle_winit_event(
|
|||
|
||||
match event {
|
||||
Event::AboutToWait => {
|
||||
let (config, windows) = focused_windows_state.get(&app.world);
|
||||
let (config, windows) = focused_windows_state.get(app.world());
|
||||
let focused = windows.iter().any(|window| window.focused);
|
||||
let mut should_update = match config.update_mode(focused) {
|
||||
UpdateMode::Continuous => {
|
||||
|
@ -394,7 +394,7 @@ fn handle_winit_event(
|
|||
|
||||
if should_update {
|
||||
let visible = windows.iter().any(|window| window.visible);
|
||||
let (_, winit_windows, _, _) = event_writer_system_state.get_mut(&mut app.world);
|
||||
let (_, winit_windows, _, _) = event_writer_system_state.get_mut(app.world_mut());
|
||||
if visible && runner_state.active != ActiveState::WillSuspend {
|
||||
for window in winit_windows.windows.values() {
|
||||
window.request_redraw();
|
||||
|
@ -431,7 +431,7 @@ fn handle_winit_event(
|
|||
event, window_id, ..
|
||||
} => {
|
||||
let (mut window_resized, winit_windows, mut windows, access_kit_adapters) =
|
||||
event_writer_system_state.get_mut(&mut app.world);
|
||||
event_writer_system_state.get_mut(app.world_mut());
|
||||
|
||||
let Some(window) = winit_windows.get_window_entity(window_id) else {
|
||||
warn!("Skipped event {event:?} for unknown winit Window Id {window_id:?}");
|
||||
|
@ -643,8 +643,8 @@ fn handle_winit_event(
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let mut windows = app.world.query::<(&mut Window, &mut CachedWindow)>();
|
||||
if let Ok((window_component, mut cache)) = windows.get_mut(&mut app.world, window) {
|
||||
let mut windows = app.world_mut().query::<(&mut Window, &mut CachedWindow)>();
|
||||
if let Ok((window_component, mut cache)) = windows.get_mut(app.world_mut(), window) {
|
||||
if window_component.is_changed() {
|
||||
cache.window = window_component.clone();
|
||||
}
|
||||
|
@ -667,8 +667,8 @@ fn handle_winit_event(
|
|||
#[cfg(any(target_os = "android", target_os = "ios", target_os = "macos"))]
|
||||
{
|
||||
if runner_state.active == ActiveState::NotYetStarted {
|
||||
create_windows(event_loop, create_window.get_mut(&mut app.world));
|
||||
create_window.apply(&mut app.world);
|
||||
create_windows(event_loop, create_window.get_mut(app.world_mut()));
|
||||
create_window.apply(app.world_mut());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,9 +683,9 @@ fn handle_winit_event(
|
|||
// Get windows that are cached but without raw handles. Those window were already created, but got their
|
||||
// handle wrapper removed when the app was suspended.
|
||||
let mut query = app
|
||||
.world
|
||||
.world_mut()
|
||||
.query_filtered::<(Entity, &Window), (With<CachedWindow>, Without<bevy_window::RawHandleWrapper>)>();
|
||||
if let Ok((entity, window)) = query.get_single(&app.world) {
|
||||
if let Ok((entity, window)) = query.get_single(app.world()) {
|
||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
let window = window.clone();
|
||||
|
||||
|
@ -695,7 +695,7 @@ fn handle_winit_event(
|
|||
mut adapters,
|
||||
mut handlers,
|
||||
accessibility_requested,
|
||||
) = create_window.get_mut(&mut app.world);
|
||||
) = create_window.get_mut(app.world_mut());
|
||||
|
||||
let winit_window = winit_windows.create_window(
|
||||
event_loop,
|
||||
|
@ -711,7 +711,7 @@ fn handle_winit_event(
|
|||
display_handle: winit_window.display_handle().unwrap().as_raw(),
|
||||
};
|
||||
|
||||
app.world.entity_mut(entity).insert(wrapper);
|
||||
app.world_mut().entity_mut(entity).insert(wrapper);
|
||||
}
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
}
|
||||
|
@ -753,9 +753,13 @@ fn run_app_update_if_should(
|
|||
{
|
||||
// Remove the `RawHandleWrapper` from the primary window.
|
||||
// This will trigger the surface destruction.
|
||||
let mut query = app.world.query_filtered::<Entity, With<PrimaryWindow>>();
|
||||
let entity = query.single(&app.world);
|
||||
app.world.entity_mut(entity).remove::<RawHandleWrapper>();
|
||||
let mut query = app
|
||||
.world_mut()
|
||||
.query_filtered::<Entity, With<PrimaryWindow>>();
|
||||
let entity = query.single(app.world());
|
||||
app.world_mut()
|
||||
.entity_mut(entity)
|
||||
.remove::<RawHandleWrapper>();
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
}
|
||||
}
|
||||
|
@ -766,7 +770,7 @@ fn run_app_update_if_should(
|
|||
app.update();
|
||||
|
||||
// decide when to run the next update
|
||||
let (config, windows) = focused_windows_state.get(&app.world);
|
||||
let (config, windows) = focused_windows_state.get(app.world());
|
||||
let focused = windows.iter().any(|window| window.focused);
|
||||
match config.update_mode(focused) {
|
||||
UpdateMode::Continuous => {
|
||||
|
@ -787,13 +791,13 @@ fn run_app_update_if_should(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(app_redraw_events) = app.world.get_resource::<Events<RequestRedraw>>() {
|
||||
if let Some(app_redraw_events) = app.world().get_resource::<Events<RequestRedraw>>() {
|
||||
if redraw_event_reader.read(app_redraw_events).last().is_some() {
|
||||
runner_state.redraw_requested = true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(app_exit_events) = app.world.get_resource::<Events<AppExit>>() {
|
||||
if let Some(app_exit_events) = app.world().get_resource::<Events<AppExit>>() {
|
||||
if app_exit_event_reader.read(app_exit_events).last().is_some() {
|
||||
event_loop.exit();
|
||||
}
|
||||
|
@ -802,8 +806,8 @@ fn run_app_update_if_should(
|
|||
|
||||
// create any new windows
|
||||
// (even if app did not update, some may have been created by plugin setup)
|
||||
create_windows(event_loop, create_window.get_mut(&mut app.world));
|
||||
create_window.apply(&mut app.world);
|
||||
create_windows(event_loop, create_window.get_mut(app.world_mut()));
|
||||
create_window.apply(app.world_mut());
|
||||
}
|
||||
|
||||
fn react_to_resize(
|
||||
|
|
|
@ -197,83 +197,83 @@ pub(crate) fn forward_winit_events(buffered_events: &mut Vec<WinitEvent>, app: &
|
|||
for winit_event in buffered_events.iter() {
|
||||
match winit_event.clone() {
|
||||
WinitEvent::ApplicationLifetime(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::CursorEntered(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::CursorLeft(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::CursorMoved(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::FileDragAndDrop(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::Ime(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::ReceivedCharacter(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::RequestRedraw(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowBackendScaleFactorChanged(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowCloseRequested(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowCreated(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowDestroyed(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowFocused(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowMoved(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowOccluded(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowResized(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowScaleFactorChanged(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::WindowThemeChanged(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::MouseButtonInput(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::MouseMotion(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::MouseWheel(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::TouchpadMagnify(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::TouchpadRotate(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::TouchInput(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
WinitEvent::KeyboardInput(e) => {
|
||||
app.world.send_event(e);
|
||||
app.world_mut().send_event(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
app.world
|
||||
app.world_mut()
|
||||
.resource_mut::<Events<WinitEvent>>()
|
||||
.send_batch(buffered_events.drain(..));
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ pub const COLORED_MESH2D_SHADER_HANDLE: Handle<Shader> =
|
|||
impl Plugin for ColoredMesh2dPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
// Load our custom shader
|
||||
let mut shaders = app.world.resource_mut::<Assets<Shader>>();
|
||||
let mut shaders = app.world_mut().resource_mut::<Assets<Shader>>();
|
||||
shaders.insert(
|
||||
&COLORED_MESH2D_SHADER_HANDLE,
|
||||
Shader::from_wgsl(COLORED_MESH2D_SHADER, file!()),
|
||||
|
|
|
@ -11,7 +11,7 @@ fn my_runner(mut app: App) {
|
|||
println!("Type stuff into the console");
|
||||
for line in io::stdin().lines() {
|
||||
{
|
||||
let mut input = app.world.resource_mut::<Input>();
|
||||
let mut input = app.world_mut().resource_mut::<Input>();
|
||||
input.0 = line.unwrap();
|
||||
}
|
||||
app.update();
|
||||
|
|
|
@ -33,14 +33,14 @@ fn main() {
|
|||
//
|
||||
// Note that we modify `MainScheduleOrder` directly in `main` and not in a startup system. The reason for this is
|
||||
// that the `MainScheduleOrder` cannot be modified from systems that are run as part of the `Main` schedule.
|
||||
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
|
||||
let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
|
||||
main_schedule_order.insert_after(Update, SingleThreadedUpdate);
|
||||
|
||||
// Adding a custom startup schedule works similarly, but needs to use `insert_startup_after`
|
||||
// instead of `insert_after`.
|
||||
app.add_schedule(Schedule::new(CustomStartup));
|
||||
|
||||
let mut main_schedule_order = app.world.resource_mut::<MainScheduleOrder>();
|
||||
let mut main_schedule_order = app.world_mut().resource_mut::<MainScheduleOrder>();
|
||||
main_schedule_order.insert_startup_after(PreStartup, CustomStartup);
|
||||
|
||||
app.add_systems(SingleThreadedUpdate, single_threaded_update_system)
|
||||
|
|
|
@ -54,7 +54,7 @@ fn main() {
|
|||
* Stepping::continue_frame() is called
|
||||
* System has been configured to always run"#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.add_schedule(Update).enable();
|
||||
app.update();
|
||||
|
||||
|
@ -65,7 +65,7 @@ fn main() {
|
|||
Stepping, step means run the next system across all the schedules
|
||||
that have been added to the Stepping resource."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.step_frame();
|
||||
app.update();
|
||||
|
||||
|
@ -89,7 +89,7 @@ fn main() {
|
|||
case, we previously performed a step, running one system in Update.
|
||||
This continue will cause all remaining systems in Update to run."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.continue_frame();
|
||||
app.update();
|
||||
|
||||
|
@ -102,7 +102,7 @@ fn main() {
|
|||
systems."#
|
||||
);
|
||||
for _ in 0..4 {
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.step_frame();
|
||||
app.update();
|
||||
}
|
||||
|
@ -116,10 +116,10 @@ fn main() {
|
|||
execute all systems in the frame. Stepping::always_run() allows
|
||||
us to granularly allow systems to run when stepping is enabled."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.always_run(Update, update_system_two);
|
||||
for _ in 0..3 {
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.step_frame();
|
||||
app.update();
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ fn main() {
|
|||
Stepping::never_run() allows us to disable systems while Stepping
|
||||
is enabled."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.never_run(Update, update_system_two);
|
||||
stepping.continue_frame();
|
||||
app.update();
|
||||
|
@ -155,14 +155,14 @@ fn main() {
|
|||
During the final continue pre_update_system() and
|
||||
update_system_three() run."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.set_breakpoint(Update, update_system_two);
|
||||
stepping.continue_frame();
|
||||
app.update();
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.step_frame();
|
||||
app.update();
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.continue_frame();
|
||||
app.update();
|
||||
|
||||
|
@ -172,7 +172,7 @@ fn main() {
|
|||
through all systems
|
||||
Result: All systems will run"#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.clear_breakpoint(Update, update_system_two);
|
||||
stepping.continue_frame();
|
||||
app.update();
|
||||
|
@ -184,7 +184,7 @@ fn main() {
|
|||
call Stepping::step_frame() or Stepping::continue_frame() to run
|
||||
systems in the Update schedule."#
|
||||
);
|
||||
let mut stepping = app.world.resource_mut::<Stepping>();
|
||||
let mut stepping = app.world_mut().resource_mut::<Stepping>();
|
||||
stepping.disable();
|
||||
app.update();
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ impl Plugin for SteppingPlugin {
|
|||
// We need an independent schedule so we have access to all other
|
||||
// schedules through the `Stepping` resource
|
||||
app.init_schedule(DebugSchedule);
|
||||
let mut order = app.world.resource_mut::<MainScheduleOrder>();
|
||||
let mut order = app.world_mut().resource_mut::<MainScheduleOrder>();
|
||||
order.insert_after(Update, DebugSchedule);
|
||||
|
||||
// create our stepping resource
|
||||
|
|
|
@ -84,7 +84,7 @@ impl Plugin for GameOfLifeComputePlugin {
|
|||
prepare_bind_group.in_set(RenderSet::PrepareBindGroups),
|
||||
);
|
||||
|
||||
let mut render_graph = render_app.world.resource_mut::<RenderGraph>();
|
||||
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||
render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
|
||||
render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Plugin for PostProcessPlugin {
|
|||
));
|
||||
|
||||
// We need to get the render app from the main app
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -97,7 +97,7 @@ impl Plugin for PostProcessPlugin {
|
|||
|
||||
fn finish(&self, app: &mut App) {
|
||||
// We need to get the render app from the main app
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -33,11 +33,11 @@ impl Plugin for GpuFeatureSupportChecker {
|
|||
fn build(&self, _app: &mut App) {}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let render_device = render_app.world.resource::<RenderDevice>();
|
||||
let render_device = render_app.world().resource::<RenderDevice>();
|
||||
|
||||
// Check if the device support the required feature. If not, exit the example.
|
||||
// In a real application, you should setup a fallback for the missing feature
|
||||
|
|
|
@ -157,7 +157,7 @@ struct LogVisibleLights;
|
|||
|
||||
impl Plugin for LogVisibleLights {
|
||||
fn build(&self, app: &mut App) {
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,29 +45,29 @@ fn runner(mut app: App) {
|
|||
}
|
||||
"f" => {
|
||||
println!("FAST: setting relative speed to 2x");
|
||||
app.world
|
||||
app.world_mut()
|
||||
.resource_mut::<Time<Virtual>>()
|
||||
.set_relative_speed(2.0);
|
||||
}
|
||||
"n" => {
|
||||
println!("NORMAL: setting relative speed to 1x");
|
||||
app.world
|
||||
app.world_mut()
|
||||
.resource_mut::<Time<Virtual>>()
|
||||
.set_relative_speed(1.0);
|
||||
}
|
||||
"s" => {
|
||||
println!("SLOW: setting relative speed to 0.5x");
|
||||
app.world
|
||||
app.world_mut()
|
||||
.resource_mut::<Time<Virtual>>()
|
||||
.set_relative_speed(0.5);
|
||||
}
|
||||
"p" => {
|
||||
println!("PAUSE: pausing virtual clock");
|
||||
app.world.resource_mut::<Time<Virtual>>().pause();
|
||||
app.world_mut().resource_mut::<Time<Virtual>>().pause();
|
||||
}
|
||||
"u" => {
|
||||
println!("UNPAUSE: resuming virtual clock");
|
||||
app.world.resource_mut::<Time<Virtual>>().unpause();
|
||||
app.world_mut().resource_mut::<Time<Virtual>>().unpause();
|
||||
}
|
||||
"q" => {
|
||||
println!("QUITTING!");
|
||||
|
|
|
@ -62,7 +62,7 @@ fn did_hurt_enemy() {
|
|||
|
||||
// Setup test entities
|
||||
let enemy_id = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn(Enemy {
|
||||
hit_points: 5,
|
||||
score_value: 3,
|
||||
|
@ -73,8 +73,8 @@ fn did_hurt_enemy() {
|
|||
app.update();
|
||||
|
||||
// Check resulting changes
|
||||
assert!(app.world.get::<Enemy>(enemy_id).is_some());
|
||||
assert_eq!(app.world.get::<Enemy>(enemy_id).unwrap().hit_points, 4);
|
||||
assert!(app.world().get::<Enemy>(enemy_id).is_some());
|
||||
assert_eq!(app.world().get::<Enemy>(enemy_id).unwrap().hit_points, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -93,7 +93,7 @@ fn did_despawn_enemy() {
|
|||
|
||||
// Setup test entities
|
||||
let enemy_id = app
|
||||
.world
|
||||
.world_mut()
|
||||
.spawn(Enemy {
|
||||
hit_points: 1,
|
||||
score_value: 1,
|
||||
|
@ -104,10 +104,10 @@ fn did_despawn_enemy() {
|
|||
app.update();
|
||||
|
||||
// Check enemy was despawned
|
||||
assert!(app.world.get::<Enemy>(enemy_id).is_none());
|
||||
assert!(app.world().get::<Enemy>(enemy_id).is_none());
|
||||
|
||||
// Get `EnemyDied` event reader
|
||||
let enemy_died_events = app.world.resource::<Events<EnemyDied>>();
|
||||
let enemy_died_events = app.world().resource::<Events<EnemyDied>>();
|
||||
let mut enemy_died_reader = enemy_died_events.get_reader();
|
||||
let enemy_died = enemy_died_reader.read(enemy_died_events).next().unwrap();
|
||||
|
||||
|
@ -132,16 +132,18 @@ fn spawn_enemy_using_input_resource() {
|
|||
app.update();
|
||||
|
||||
// Check resulting changes, one entity has been spawned with `Enemy` component
|
||||
assert_eq!(app.world.query::<&Enemy>().iter(&app.world).len(), 1);
|
||||
assert_eq!(app.world_mut().query::<&Enemy>().iter(app.world()).len(), 1);
|
||||
|
||||
// Clear the `just_pressed` status for all `KeyCode`s
|
||||
app.world.resource_mut::<ButtonInput<KeyCode>>().clear();
|
||||
app.world_mut()
|
||||
.resource_mut::<ButtonInput<KeyCode>>()
|
||||
.clear();
|
||||
|
||||
// Run systems
|
||||
app.update();
|
||||
|
||||
// Check resulting changes, no new entity has been spawned
|
||||
assert_eq!(app.world.query::<&Enemy>().iter(&app.world).len(), 1);
|
||||
assert_eq!(app.world_mut().query::<&Enemy>().iter(app.world()).len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -159,7 +161,7 @@ fn update_score_on_event() {
|
|||
app.add_systems(Update, update_score);
|
||||
|
||||
// Send an `EnemyDied` event
|
||||
app.world
|
||||
app.world_mut()
|
||||
.resource_mut::<Events<EnemyDied>>()
|
||||
.send(EnemyDied(3));
|
||||
|
||||
|
@ -167,5 +169,5 @@ fn update_score_on_event() {
|
|||
app.update();
|
||||
|
||||
// Check resulting changes
|
||||
assert_eq!(app.world.resource::<Score>().0, 3);
|
||||
assert_eq!(app.world().resource::<Score>().0, 3);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue