diff --git a/Cargo.toml b/Cargo.toml index 62be72f770747..309fffc571941 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,6 +103,10 @@ debug_asset_server = ["bevy_internal/debug_asset_server"] # Enable animation support, and glTF animation loading animation = ["bevy_internal/animation"] +spirv = ["bevy_internal/spirv"] + +webgpu = ["bevy_internal/webgpu"] + [dependencies] bevy_dylib = { path = "crates/bevy_dylib", version = "0.8.0-dev", default-features = false, optional = true } bevy_internal = { path = "crates/bevy_internal", version = "0.8.0-dev", default-features = false } @@ -121,6 +125,8 @@ bytemuck = "1.7" # Needed to poll Task examples futures-lite = "1.11.3" crossbeam-channel = "0.5.0" +wasm-bindgen-futures = "0.4" +async-trait = "0.1" [[example]] name = "hello_world" diff --git a/crates/bevy_animation/Cargo.toml b/crates/bevy_animation/Cargo.toml index 2ef00a7c53c6c..5bca481aa6f5a 100644 --- a/crates/bevy_animation/Cargo.toml +++ b/crates/bevy_animation/Cargo.toml @@ -20,3 +20,6 @@ bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.8.0-dev" } bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.8.0-dev" } + +# other +async-trait = "0.1" diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 7882ad4d2f274..406815f455002 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -4,6 +4,7 @@ use std::ops::Deref; +use async_trait::async_trait; use bevy_app::{App, CoreStage, Plugin}; use bevy_asset::{AddAsset, Assets, Handle}; use bevy_core::Name; @@ -289,8 +290,9 @@ pub fn animation_player( #[derive(Default)] pub struct AnimationPlugin {} +#[async_trait] impl Plugin for AnimationPlugin { - fn build(&self, app: &mut App) { + async fn build(&self, app: &mut App) { app.add_asset::() .register_type::() .add_system_to_stage( diff --git a/crates/bevy_app/Cargo.toml b/crates/bevy_app/Cargo.toml index 2dd25147e42f9..fde0412f35c33 100644 --- a/crates/bevy_app/Cargo.toml +++ b/crates/bevy_app/Cargo.toml @@ -25,6 +25,7 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.8.0-dev" } # other serde = { version = "1.0", features = ["derive"], optional = true } ron = { version = "0.7.0", optional = true } +async-trait = "0.1" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index cdf1984c8b01e..2a46e08c9fef8 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -53,7 +53,7 @@ pub struct App { /// the application's event loop and advancing the [`Schedule`]. /// Typically, it is not configured manually, but set by one of Bevy's built-in plugins. /// See `bevy::winit::WinitPlugin` and [`ScheduleRunnerPlugin`](crate::schedule_runner::ScheduleRunnerPlugin). - pub runner: Box, + pub runner: Box, /// A container of [`Stage`]s set to be run in a linear order. pub schedule: Schedule, sub_apps: HashMap, SubApp>, @@ -62,7 +62,7 @@ pub struct App { /// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns. struct SubApp { app: App, - runner: Box, + runner: Box, } impl Default for App { @@ -744,7 +744,7 @@ impl App { /// App::new() /// .set_runner(my_runner); /// ``` - pub fn set_runner(&mut self, run_fn: impl Fn(App) + 'static) -> &mut Self { + pub fn set_runner(&mut self, run_fn: impl Fn(App) + Send + 'static) -> &mut Self { self.runner = Box::new(run_fn); self } @@ -763,12 +763,12 @@ impl App { /// # /// App::new().add_plugin(bevy_log::LogPlugin::default()); /// ``` - pub fn add_plugin(&mut self, plugin: T) -> &mut Self + pub async fn add_plugin(&mut self, plugin: T) -> &mut Self where T: Plugin, { debug!("added plugin: {}", plugin.name()); - plugin.build(self); + plugin.build(self).await; self } @@ -795,10 +795,10 @@ impl App { /// App::new() /// .add_plugins(MinimalPlugins); /// ``` - pub fn add_plugins(&mut self, mut group: T) -> &mut Self { + pub async fn add_plugins(&mut self, mut group: T) -> &mut Self { let mut plugin_group_builder = PluginGroupBuilder::default(); group.build(&mut plugin_group_builder); - plugin_group_builder.finish(self); + plugin_group_builder.finish(self).await; self } @@ -813,6 +813,7 @@ impl App { /// /// ``` /// # use bevy_app::{prelude::*, PluginGroupBuilder}; + /// # use async_trait::async_trait; /// # /// # // Dummies created to avoid using bevy_internal which pulls in too many dependencies. /// # struct DefaultPlugins; @@ -823,8 +824,9 @@ impl App { /// # } /// # /// # struct MyOwnPlugin; + /// # #[async_trait] /// # impl Plugin for MyOwnPlugin { - /// # fn build(&self, app: &mut App){;} + /// # async fn build(&self, app: &mut App){;} /// # } /// # /// App::new() @@ -832,7 +834,7 @@ impl App { /// group.add_before::(MyOwnPlugin) /// }); /// ``` - pub fn add_plugins_with(&mut self, mut group: T, func: F) -> &mut Self + pub async fn add_plugins_with(&mut self, mut group: T, func: F) -> &mut Self where T: PluginGroup, F: FnOnce(&mut PluginGroupBuilder) -> &mut PluginGroupBuilder, @@ -840,7 +842,7 @@ impl App { let mut plugin_group_builder = PluginGroupBuilder::default(); group.build(&mut plugin_group_builder); func(&mut plugin_group_builder); - plugin_group_builder.finish(self); + plugin_group_builder.finish(self).await; self } @@ -863,7 +865,7 @@ impl App { &mut self, label: impl AppLabel, app: App, - sub_app_runner: impl Fn(&mut World, &mut App) + 'static, + sub_app_runner: impl Fn(&mut World, &mut App) + Send + 'static, ) -> &mut Self { self.sub_apps.insert( Box::new(label), diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index e6e70cf856029..24c1b88b8e152 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -1,13 +1,15 @@ use crate::App; +use async_trait::async_trait; use std::any::Any; /// A collection of Bevy app logic and configuration. /// /// Plugins configure an [`App`]. When an [`App`] registers a plugin, /// the plugin's [`Plugin::build`] function is run. +#[async_trait] pub trait Plugin: Any + Send + Sync { /// Configures the [`App`] to which this plugin is added. - fn build(&self, app: &mut App); + async fn build(&self, app: &mut App); /// Configures a name for the [`Plugin`] which is primarily used for debugging. fn name(&self) -> &str { std::any::type_name::() diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index d707634fd8503..9b745c101ea48 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -127,12 +127,12 @@ impl PluginGroupBuilder { /// Consumes the [`PluginGroupBuilder`] and [builds](Plugin::build) the contained [`Plugin`]s /// in the order specified. - pub fn finish(self, app: &mut App) { + pub async fn finish(self, app: &mut App) { for ty in &self.order { if let Some(entry) = self.plugins.get(ty) { if entry.enabled { debug!("added plugin: {}", entry.plugin.name()); - entry.plugin.build(app); + entry.plugin.build(app).await; } } } @@ -141,22 +141,27 @@ impl PluginGroupBuilder { #[cfg(test)] mod tests { + use async_trait::async_trait; + use super::PluginGroupBuilder; use crate::{App, Plugin}; struct PluginA; + #[async_trait] impl Plugin for PluginA { - fn build(&self, _: &mut App) {} + async fn build(&self, _: &mut App) {} } struct PluginB; + #[async_trait] impl Plugin for PluginB { - fn build(&self, _: &mut App) {} + async fn build(&self, _: &mut App) {} } struct PluginC; + #[async_trait] impl Plugin for PluginC { - fn build(&self, _: &mut App) {} + async fn build(&self, _: &mut App) {} } #[test] diff --git a/crates/bevy_app/src/schedule_runner.rs b/crates/bevy_app/src/schedule_runner.rs index aa63ce1a8b3d0..8157d03f50954 100644 --- a/crates/bevy_app/src/schedule_runner.rs +++ b/crates/bevy_app/src/schedule_runner.rs @@ -5,6 +5,7 @@ use crate::{ use bevy_ecs::event::{Events, ManualEventReader}; use bevy_utils::{Duration, Instant}; +use async_trait::async_trait; #[cfg(target_arch = "wasm32")] use std::{cell::RefCell, rc::Rc}; #[cfg(target_arch = "wasm32")] @@ -63,8 +64,9 @@ impl ScheduleRunnerSettings { #[derive(Default)] pub struct ScheduleRunnerPlugin; +#[async_trait] impl Plugin for ScheduleRunnerPlugin { - fn build(&self, app: &mut App) { + async fn build(&self, app: &mut App) { let settings = app .world .get_resource_or_insert_with(ScheduleRunnerSettings::default) diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index 5ccf6ac63f5c9..0dc072320f0f4 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -32,6 +32,7 @@ downcast-rs = "1.2.0" notify = { version = "=5.0.0-pre.11", optional = true } parking_lot = "0.11.0" rand = "0.8.0" +async-trait = "0.1" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2" } diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 23ec2cf3dee66..7ed7cd105f6da 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -391,8 +391,12 @@ mod tests { #[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"] struct MyAsset; let mut app = App::new(); - app.add_plugin(bevy_core::CorePlugin) - .add_plugin(crate::AssetPlugin); + futures_lite::future::block_on(async { + app.add_plugin(bevy_core::CorePlugin) + .await + .add_plugin(crate::AssetPlugin) + .await + }); app.add_asset::(); let mut assets_before = app.world.resource_mut::>(); let handle = assets_before.add(MyAsset); diff --git a/crates/bevy_asset/src/debug_asset_server.rs b/crates/bevy_asset/src/debug_asset_server.rs index b7e3c71c85c89..ffc31f7e109af 100644 --- a/crates/bevy_asset/src/debug_asset_server.rs +++ b/crates/bevy_asset/src/debug_asset_server.rs @@ -1,3 +1,4 @@ +use async_trait::async_trait; use bevy_app::{App, Plugin}; use bevy_ecs::{ event::Events, @@ -56,8 +57,9 @@ impl Default for HandleMap { } } +#[async_trait] impl Plugin for DebugAssetServerPlugin { - fn build(&self, app: &mut bevy_app::App) { + async fn build(&self, app: &mut bevy_app::App) { IoTaskPool::init(|| { TaskPoolBuilder::default() .num_threads(2) @@ -70,7 +72,8 @@ impl Plugin for DebugAssetServerPlugin { asset_folder: "crates".to_string(), watch_for_changes: true, }) - .add_plugin(AssetPlugin); + .add_plugin(AssetPlugin) + .await; app.insert_non_send_resource(DebugAssetApp(debug_asset_app)); app.add_system(run_debug_asset_app); } diff --git a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs index 8224edd3893da..aeffe7a07ecbc 100644 --- a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs +++ b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs @@ -1,4 +1,5 @@ use crate::{Asset, Assets}; +use async_trait::async_trait; use bevy_app::prelude::*; use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics, MAX_DIAGNOSTIC_NAME_WIDTH}; use bevy_ecs::system::{Res, ResMut}; @@ -16,8 +17,9 @@ impl Default for AssetCountDiagnosticsPlugin { } } +#[async_trait] impl Plugin for AssetCountDiagnosticsPlugin { - fn build(&self, app: &mut App) { + async fn build(&self, app: &mut App) { app.add_startup_system(Self::setup_system) .add_system(Self::diagnostic_system); } diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index b5ba1a1854d02..a1a2e59c04ac1 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -21,6 +21,7 @@ pub mod prelude { pub use asset_server::*; pub use assets::*; +use async_trait::async_trait; pub use bevy_utils::BoxedFuture; pub use handle::*; pub use info::*; @@ -78,8 +79,9 @@ pub fn create_platform_default_asset_io(app: &mut App) -> Box { Box::new(source) } +#[async_trait] impl Plugin for AssetPlugin { - fn build(&self, app: &mut App) { + async fn build(&self, app: &mut App) { if !app.world.contains_resource::() { let source = create_platform_default_asset_io(app); let asset_server = AssetServer::with_boxed_io(source); diff --git a/crates/bevy_audio/Cargo.toml b/crates/bevy_audio/Cargo.toml index 3e7603f82c700..e93759c90d98f 100644 --- a/crates/bevy_audio/Cargo.toml +++ b/crates/bevy_audio/Cargo.toml @@ -20,6 +20,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" } anyhow = "1.0.4" rodio = { version = "0.15", default-features = false } parking_lot = "0.11.0" +async-trait = "0.1" [target.'cfg(target_arch = "wasm32")'.dependencies] rodio = { version = "0.15", default-features = false, features = ["wasm-bindgen"] } diff --git a/crates/bevy_audio/src/lib.rs b/crates/bevy_audio/src/lib.rs index e3663e1adf41e..c656b39a105a0 100644 --- a/crates/bevy_audio/src/lib.rs +++ b/crates/bevy_audio/src/lib.rs @@ -7,13 +7,15 @@ //! # use bevy_app::{App, AppExit}; //! # use bevy_internal::MinimalPlugins; //! fn main() { +//! # async { //! App::new() -//! .add_plugins(MinimalPlugins) -//! .add_plugin(AssetPlugin) -//! .add_plugin(AudioPlugin) +//! .add_plugins(MinimalPlugins).await +//! .add_plugin(AssetPlugin).await +//! .add_plugin(AudioPlugin).await //! # .add_system(stop) //! .add_startup_system(play_background_audio) //! .run(); +//! # }; //! } //! //! fn play_background_audio(asset_server: Res, audio: Res