diff --git a/Cargo.toml b/Cargo.toml index 745a02e02df61..141cee12392a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -244,6 +244,9 @@ shader_format_spirv = ["bevy_internal/shader_format_spirv"] # Enable some limitations to be able to use WebGL2. If not enabled, it will default to WebGPU in Wasm. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU. webgl2 = ["bevy_internal/webgl"] +# Enables the built-in asset processor for processed assets. +asset_processor = ["bevy_internal/asset_processor"] + # Enables watching the filesystem for Bevy Asset hot-reloading file_watcher = ["bevy_internal/file_watcher"] @@ -1080,7 +1083,7 @@ wasm = true name = "asset_processing" path = "examples/asset/processing/processing.rs" doc-scrape-examples = true -required-features = ["file_watcher"] +required-features = ["file_watcher", "asset_processor"] [package.metadata.example.asset_processing] name = "Asset Processing" diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index 52717f627e936..922b622b89d8c 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -14,6 +14,7 @@ keywords = ["bevy"] file_watcher = ["notify-debouncer-full", "watch"] embedded_watcher = ["file_watcher"] multi-threaded = ["bevy_tasks/multi-threaded"] +asset_processor = [] watch = [] [dependencies] diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 8787d604cc741..58a2a191108c4 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -41,7 +41,7 @@ use crate::{ io::{embedded::EmbeddedAssetRegistry, AssetSourceBuilder, AssetSourceBuilders, AssetSourceId}, processor::{AssetProcessor, Process}, }; -use bevy_app::{App, First, MainScheduleOrder, Plugin, PostUpdate, Startup}; +use bevy_app::{App, First, MainScheduleOrder, Plugin, PostUpdate}; use bevy_ecs::{ reflect::AppTypeRegistry, schedule::{IntoSystemConfigs, IntoSystemSetConfigs, ScheduleLabel, SystemSet}, @@ -80,21 +80,21 @@ pub enum AssetMode { /// [`AssetReader`]: crate::io::AssetReader /// [`AssetSource`]: crate::io::AssetSource Unprocessed, - /// Loads assets from their final processed [`AssetReader`]. This should generally only be used when distributing apps. - /// Use [`AssetMode::ProcessedDev`] to develop apps that process assets, then switch to [`AssetMode::Processed`] when deploying the apps. + /// Assets will be "pre-processed". This enables assets to be imported / converted / optimized ahead of time. /// - /// [`AssetReader`]: crate::io::AssetReader - Processed, - /// Starts an [`AssetProcessor`] in the background that reads assets from their unprocessed [`AssetSource`] (defaults to the `assets` folder), - /// processes them according to their [`AssetMeta`], and writes them to their processed [`AssetSource`] (defaults to the `imported_assets/Default` folder). + /// Assets will be read from their unprocessed [`AssetSource`] (defaults to the `assets` folder), + /// processed according to their [`AssetMeta`], and written to their processed [`AssetSource`] (defaults to the `imported_assets/Default` folder). /// - /// Apps will load assets from the processed [`AssetSource`]. Asset loads will wait until the asset processor has finished processing the requested asset. + /// By default, this assumes the processor _has already been run_. It will load assets from their final processed [`AssetReader`]. /// - /// This should generally be used in combination with the `file_watcher` cargo feature to support hot-reloading and re-processing assets. + /// When developing an app, you should enable the `asset_processor` cargo feature, which will run the asset processor at startup. This should generally + /// be used in combination with the `file_watcher` cargo feature, which enables hot-reloading of assets that have changed. When both features are enabled, + /// changes to "original/source assets" will be detected, the asset will be re-processed, and then the final processed asset will be hot-reloaded in the app. /// /// [`AssetMeta`]: crate::meta::AssetMeta /// [`AssetSource`]: crate::io::AssetSource - ProcessedDev, + /// [`AssetReader`]: crate::io::AssetReader + Processed, } impl Default for AssetPlugin { @@ -146,28 +146,32 @@ impl Plugin for AssetPlugin { )); } AssetMode::Processed => { - let mut builders = app.world.resource_mut::(); - let sources = builders.build_sources(false, watch); - app.insert_resource(AssetServer::new( - sources, - AssetServerMode::Processed, - watch, - )); - } - AssetMode::ProcessedDev => { - let mut builders = app.world.resource_mut::(); - let processor = AssetProcessor::new(&mut builders); - let mut sources = builders.build_sources(false, watch); - sources.gate_on_processor(processor.data.clone()); - // the main asset server shares loaders with the processor asset server - app.insert_resource(AssetServer::new_with_loaders( - sources, - processor.server().data.loaders.clone(), - AssetServerMode::Processed, - watch, - )) - .insert_resource(processor) - .add_systems(Startup, AssetProcessor::start); + #[cfg(feature = "asset_processor")] + { + let mut builders = app.world.resource_mut::(); + let processor = AssetProcessor::new(&mut builders); + let mut sources = builders.build_sources(false, watch); + sources.gate_on_processor(processor.data.clone()); + // the main asset server shares loaders with the processor asset server + app.insert_resource(AssetServer::new_with_loaders( + sources, + processor.server().data.loaders.clone(), + AssetServerMode::Processed, + watch, + )) + .insert_resource(processor) + .add_systems(bevy_app::Startup, AssetProcessor::start); + } + #[cfg(not(feature = "asset_processor"))] + { + let mut builders = app.world.resource_mut::(); + let sources = builders.build_sources(false, watch); + app.insert_resource(AssetServer::new( + sources, + AssetServerMode::Processed, + watch, + )); + } } } } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 9644e87141acf..a7019d5461ea9 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -102,6 +102,9 @@ glam_assert = ["bevy_math/glam_assert"] default_font = ["bevy_text?/default_font"] +# Enables the built-in asset processor for processed assets. +asset_processor = ["bevy_asset?/asset_processor"] + # Enables watching the filesystem for Bevy Asset hot-reloading file_watcher = ["bevy_asset?/file_watcher"] diff --git a/docs/cargo_features.md b/docs/cargo_features.md index fcc808036c84b..4882b3801a060 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -43,6 +43,7 @@ The default feature set enables most of the expected features of a game engine, |feature name|description| |-|-| |accesskit_unix|Enable AccessKit on Unix backends (currently only works with experimental screen readers and forks.)| +|asset_processor|Enables the built-in asset processor for processed assets.| |async-io|Use async-io's implementation of block_on instead of futures-lite's implementation. This is preferred if your application uses async-io.| |basis-universal|Basis Universal compressed texture support| |bevy_ci_testing|Enable systems that allow for automated testing on CI| diff --git a/examples/asset/processing/processing.rs b/examples/asset/processing/processing.rs index b0b3912b5a471..eeba092372495 100644 --- a/examples/asset/processing/processing.rs +++ b/examples/asset/processing/processing.rs @@ -17,18 +17,19 @@ use thiserror::Error; fn main() { App::new() - // Enabling `processed_dev` will configure the AssetPlugin to use asset processing. - // This will run the AssetProcessor in the background, which will listen for changes to - // the `assets` folder, run them through configured asset processors, and write the results - // to the `imported_assets` folder. + // Using the "processed" mode will configure the AssetPlugin to use asset processing. + // If you also enable the `asset_processor` cargo feature, this will run the AssetProcessor + // in the background, run them through configured asset processors, and write the results to + // the `imported_assets` folder. If you also enable the `file_watcher` cargo feature, changes to the + // source assets will be detected and they will be reprocessed. // // The AssetProcessor will create `.meta` files automatically for assets in the `assets` folder, // which can then be used to configure how the asset will be processed. .add_plugins(( DefaultPlugins.set(AssetPlugin { + mode: AssetMode::Processed, // This is just overriding the default paths to scope this to the correct example folder // You can generally skip this in your own projects - mode: AssetMode::ProcessedDev, file_path: "examples/asset/processing/assets".to_string(), processed_file_path: "examples/asset/processing/imported_assets/Default" .to_string(),