From 7bce388f738f851edbc3a268d61319ff19a4b698 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 2 Jan 2022 23:18:52 -0300 Subject: [PATCH 01/32] Document root, handle, info and path --- crates/bevy_asset/src/handle.rs | 33 +++++++++++++++++++++++++++------ crates/bevy_asset/src/info.rs | 18 ++++++++++++++++-- crates/bevy_asset/src/lib.rs | 11 ++++++++--- crates/bevy_asset/src/path.rs | 12 ++++++++++++ 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index d519f1acfff66..693f2855b621e 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -15,7 +15,7 @@ use bevy_utils::Uuid; use crossbeam_channel::{Receiver, Sender}; use serde::{Deserialize, Serialize}; -/// A unique, stable asset id +/// An unique, stable asset id. #[derive( Debug, Clone, @@ -32,7 +32,9 @@ use serde::{Deserialize, Serialize}; )] #[reflect_value(Serialize, Deserialize, PartialEq, Hash)] pub enum HandleId { + /// A handle id of a loaded asset. Id(Uuid, u64), + /// A handle id of a pending asset. AssetPathId(AssetPathId), } @@ -49,25 +51,28 @@ impl<'a> From> for HandleId { } impl HandleId { + /// Creates a random id for an Asset of type `T`. #[inline] pub fn random() -> Self { HandleId::Id(T::TYPE_UUID, rand::random()) } + /// Creates the default id for an Asset of type `T`. #[inline] pub fn default() -> Self { HandleId::Id(T::TYPE_UUID, 0) } + /// Creates an arbitrary asset id without an explicit type bound. #[inline] pub const fn new(type_uuid: Uuid, id: u64) -> Self { HandleId::Id(type_uuid, id) } } -/// A handle into a specific Asset of type `T` +/// A handle into a specific Asset of type `T`. /// -/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets) +/// Handles contain an unique id that corresponds to a specific asset in the [Assets](crate::Assets) /// collection. /// /// # Accessing the Asset @@ -136,6 +141,7 @@ impl Handle { } } + /// Creates a weak handle into an Asset identified by `id`. #[inline] pub fn weak(id: HandleId) -> Self { Self { @@ -145,7 +151,7 @@ impl Handle { } } - /// Get a copy of this handle as a Weak handle + /// Recasts this handle as a weak handle of an Asset `U`. pub fn as_weak(&self) -> Handle { Handle { id: self.id, @@ -154,10 +160,12 @@ impl Handle { } } + /// Returns `true` if this is a weak handle. pub fn is_weak(&self) -> bool { matches!(self.handle_type, HandleType::Weak) } + /// Returns `true` if this is a strong handle. pub fn is_strong(&self) -> bool { matches!(self.handle_type, HandleType::Strong(_)) } @@ -174,12 +182,14 @@ impl Handle { self.handle_type = HandleType::Strong(sender); } + /// Creates a weak copy of this handle. #[inline] #[must_use] pub fn clone_weak(&self) -> Self { Self::weak(self.id) } + /// Creates an untyped copy of this handle. pub fn clone_untyped(&self) -> HandleUntyped { match &self.handle_type { HandleType::Strong(sender) => HandleUntyped::strong(self.id, sender.clone()), @@ -187,6 +197,7 @@ impl Handle { } } + /// Creates a weak, untyped copy of this handle. pub fn clone_weak_untyped(&self) -> HandleUntyped { HandleUntyped::weak(self.id) } @@ -289,7 +300,7 @@ impl Clone for Handle { } } -/// A non-generic version of [Handle] +/// A non-generic version of [`Handle`]. /// /// This allows handles to be mingled in a cross asset context. For example, storing `Handle` and /// `Handle` in the same `HashSet`. @@ -297,11 +308,13 @@ impl Clone for Handle { /// To convert back to a typed handle, use the [typed](HandleUntyped::typed) method. #[derive(Debug)] pub struct HandleUntyped { + /// An unique identifier to an Asset. pub id: HandleId, handle_type: HandleType, } impl HandleUntyped { + /// Creates a weak untyped handle with an arbitrary id. pub const fn weak_from_u64(uuid: Uuid, id: u64) -> Self { Self { id: HandleId::new(uuid, id), @@ -317,6 +330,7 @@ impl HandleUntyped { } } + /// Create a weak untyped into an Asset identified by `id`. pub fn weak(id: HandleId) -> Self { Self { id, @@ -324,15 +338,18 @@ impl HandleUntyped { } } + /// Creates a weak copy of this handle. #[must_use] pub fn clone_weak(&self) -> Self { Self::weak(self.id) } + /// Returns `true` if this a weak handle. pub fn is_weak(&self) -> bool { matches!(self.handle_type, HandleType::Weak) } + /// Returns `true` if this is a strong handle. pub fn is_strong(&self) -> bool { matches!(self.handle_type, HandleType::Strong(_)) } @@ -345,9 +362,13 @@ impl HandleUntyped { self.clone_weak().typed() } - /// Convert this handle into a typed [Handle]. + /// Converts this handle into a typed [`Handle`] of an Asset `T`. /// /// The new handle will maintain the Strong or Weak status of the current handle. + /// + /// # Panics + /// + /// Will panic if type `T` doesn't match this handle's actual asset type. pub fn typed(mut self) -> Handle { if let HandleId::Id(type_uuid, _) = self.id { assert!( diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index 6005e92def189..8d9de35a9059d 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -3,42 +3,56 @@ use bevy_utils::{HashMap, HashSet, Uuid}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; +/// Metadata for an asset source. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SourceMeta { + /// A collection of asset metadata. pub assets: Vec, } +/// Metadata for an asset. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AssetMeta { + /// Asset label. pub label: Option, + /// Asset dependencies. pub dependencies: Vec>, + /// An unique identifier for an asset type. pub type_uuid: Uuid, } -/// Info about a specific asset, such as its path and its current load state +/// Information about an asset source, such as its path, load state and asset metadata. #[derive(Clone, Debug)] pub struct SourceInfo { + /// Metadata for the source. pub meta: Option, + /// The path of the source. pub path: PathBuf, + /// A map of assets and their type identifiers. pub asset_types: HashMap, + /// The load state of the source. pub load_state: LoadState, + /// A collection to track which assets were sent to their asset storages. pub committed_assets: HashSet, + /// Current versison of the source. pub version: usize, } impl SourceInfo { + /// Returns `true` if all assets tracked by the source were loaded into their asset storages. pub fn is_loaded(&self) -> bool { self.meta.as_ref().map_or(false, |meta| { self.committed_assets.len() == meta.assets.len() }) } + /// Gets the type identifier for an asset identified by `label_id`. pub fn get_asset_type(&self, label_id: LabelId) -> Option { self.asset_types.get(&label_id).cloned() } } -/// The load state of an asset +/// The load state of an asset. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum LoadState { /// The asset has not be loaded. diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index b5ba1a1854d02..025964e1bd875 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -14,6 +14,7 @@ mod io; mod loader; mod path; +/// The `bevy_asset` prelude. pub mod prelude { #[doc(hidden)] pub use crate::{AddAsset, AssetEvent, AssetServer, Assets, Handle, HandleUntyped}; @@ -38,12 +39,16 @@ pub enum AssetStage { AssetEvents, } -/// Adds support for Assets to an App. Assets are typed collections with change tracking, which are -/// added as App Resources. Examples of assets: textures, sounds, 3d models, maps, scenes +/// Adds support for Assets to an App. +/// +/// Assets are typed collections with change tracking, which are added as App Resources. Examples of +/// assets: textures, sounds, 3d models, maps, scenes #[derive(Default)] pub struct AssetPlugin; +/// `AssetPlugin` settings pub struct AssetServerSettings { + /// The base folder where assets are loaded from, relative to the executable. pub asset_folder: String, /// Whether to watch for changes in asset files. Requires the `filesystem_watcher` feature, /// and cannot be supported on the wasm32 arch nor android os. @@ -59,7 +64,7 @@ impl Default for AssetServerSettings { } } -/// Create an instance of the platform default `AssetIo` +/// Creates an instance of the platform's default `AssetIo`. /// /// This is useful when providing a custom `AssetIo` instance that needs to /// delegate to the default `AssetIo` for the platform. diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index cb39b3f5ca127..7bd0b7e4c2144 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -7,6 +7,7 @@ use std::{ path::{Path, PathBuf}, }; +/// Represents a path ti an asset in the file system. #[derive(Debug, Hash, Clone, Serialize, Deserialize)] pub struct AssetPath<'a> { path: Cow<'a, Path>, @@ -14,6 +15,7 @@ pub struct AssetPath<'a> { } impl<'a> AssetPath<'a> { + /// Creates a new asset path using borrowed information. #[inline] pub fn new_ref(path: &'a Path, label: Option<&'a str>) -> AssetPath<'a> { AssetPath { @@ -22,6 +24,7 @@ impl<'a> AssetPath<'a> { } } + /// Creates a new asset path. #[inline] pub fn new(path: PathBuf, label: Option) -> AssetPath<'a> { AssetPath { @@ -30,21 +33,25 @@ impl<'a> AssetPath<'a> { } } + /// Constructs an identifier from this asset path. #[inline] pub fn get_id(&self) -> AssetPathId { AssetPathId::from(self) } + /// Gets the sub-asset label. #[inline] pub fn label(&self) -> Option<&str> { self.label.as_ref().map(|label| label.as_ref()) } + /// Gets the path to the asset in the filesystem. #[inline] pub fn path(&self) -> &Path { &self.path } + /// Converts the borrowed path data to owned. #[inline] pub fn to_owned(&self) -> AssetPath<'static> { AssetPath { @@ -57,18 +64,21 @@ impl<'a> AssetPath<'a> { } } +/// An unique identifier to an asset path. #[derive( Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect, )] #[reflect_value(PartialEq, Hash, Serialize, Deserialize)] pub struct AssetPathId(SourcePathId, LabelId); +/// An unique identifier to the source path of an asset. #[derive( Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect, )] #[reflect_value(PartialEq, Hash, Serialize, Deserialize)] pub struct SourcePathId(u64); +/// An unique identifier to a sub-asset label. #[derive( Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect, )] @@ -104,10 +114,12 @@ impl<'a> From> for LabelId { } impl AssetPathId { + /// Gets the id of the source path. pub fn source_path_id(&self) -> SourcePathId { self.0 } + /// Gets the id of the sub-asset label. pub fn label_id(&self) -> LabelId { self.1 } From 4d5a87b8acf832d3b3f71f92f79aff79ada20d91 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Wed, 5 Jan 2022 17:08:51 -0300 Subject: [PATCH 02/32] Fix a couple mistakes --- crates/bevy_asset/src/handle.rs | 2 +- crates/bevy_asset/src/lib.rs | 2 +- crates/bevy_asset/src/path.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 693f2855b621e..ca9c4440fcbdf 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -15,7 +15,7 @@ use bevy_utils::Uuid; use crossbeam_channel::{Receiver, Sender}; use serde::{Deserialize, Serialize}; -/// An unique, stable asset id. +/// A unique, stable asset id. #[derive( Debug, Clone, diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 025964e1bd875..ae2e36ea0a80a 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -46,7 +46,7 @@ pub enum AssetStage { #[derive(Default)] pub struct AssetPlugin; -/// `AssetPlugin` settings +/// [`AssetServer`] settings pub struct AssetServerSettings { /// The base folder where assets are loaded from, relative to the executable. pub asset_folder: String, diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index 7bd0b7e4c2144..d47bca18e7617 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -7,7 +7,7 @@ use std::{ path::{Path, PathBuf}, }; -/// Represents a path ti an asset in the file system. +/// Represents a path to an asset in the file system. #[derive(Debug, Hash, Clone, Serialize, Deserialize)] pub struct AssetPath<'a> { path: Cow<'a, Path>, From de375dfd1dea95448586daa74e8a262891cea23b Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 06:57:35 -0300 Subject: [PATCH 03/32] Use monospaced links, fix typos --- crates/bevy_asset/src/handle.rs | 7 +++---- crates/bevy_asset/src/info.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index ca9c4440fcbdf..5a1d6563ecab1 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -70,10 +70,9 @@ impl HandleId { } } -/// A handle into a specific Asset of type `T`. +/// A handle into a specific [`Asset`] of type `T`. /// -/// Handles contain an unique id that corresponds to a specific asset in the [Assets](crate::Assets) -/// collection. +/// Handles contain a unique id that corresponds to a specific asset in the [`Assets`] collection. /// /// # Accessing the Asset /// @@ -362,7 +361,7 @@ impl HandleUntyped { self.clone_weak().typed() } - /// Converts this handle into a typed [`Handle`] of an Asset `T`. + /// Converts this handle into a typed [`Handle`] of an [`Asset`] `T`. /// /// The new handle will maintain the Strong or Weak status of the current handle. /// diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index 8d9de35a9059d..c3f3f20f15251 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -34,7 +34,7 @@ pub struct SourceInfo { pub load_state: LoadState, /// A collection to track which assets were sent to their asset storages. pub committed_assets: HashSet, - /// Current versison of the source. + /// Current version of the source. pub version: usize, } From 9ab5acf09a78e4692913d1ba6e4428d6656ff136 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 07:06:18 -0300 Subject: [PATCH 04/32] Remove SourceMeta --- crates/bevy_asset/src/asset_server.rs | 6 ++---- crates/bevy_asset/src/info.rs | 13 +++---------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index da1fc3b0cb57d..6e7ecdc0277d0 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -2,7 +2,7 @@ use crate::{ path::{AssetPath, AssetPathId, SourcePathId}, Asset, AssetIo, AssetIoError, AssetLifecycle, AssetLifecycleChannel, AssetLifecycleEvent, AssetLoader, Assets, Handle, HandleId, HandleUntyped, LabelId, LoadContext, LoadState, - RefChange, RefChangeChannel, SourceInfo, SourceMeta, + RefChange, RefChangeChannel, SourceInfo, }; use anyhow::Result; use bevy_ecs::system::{Res, ResMut}; @@ -344,9 +344,7 @@ impl AssetServer { // TODO: queue free old assets source_info.asset_types.clear(); - source_info.meta = Some(SourceMeta { - assets: load_context.get_asset_metas(), - }); + source_info.meta = Some(load_context.get_asset_metas()); // load asset dependencies and prepare asset type hashmap for (label, loaded_asset) in &mut load_context.labeled_assets { diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index c3f3f20f15251..476f79c3b1569 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -3,13 +3,6 @@ use bevy_utils::{HashMap, HashSet, Uuid}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -/// Metadata for an asset source. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SourceMeta { - /// A collection of asset metadata. - pub assets: Vec, -} - /// Metadata for an asset. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AssetMeta { @@ -24,8 +17,8 @@ pub struct AssetMeta { /// Information about an asset source, such as its path, load state and asset metadata. #[derive(Clone, Debug)] pub struct SourceInfo { - /// Metadata for the source. - pub meta: Option, + /// Metadata for each asset in the asset source. + pub meta: Option>, /// The path of the source. pub path: PathBuf, /// A map of assets and their type identifiers. @@ -42,7 +35,7 @@ impl SourceInfo { /// Returns `true` if all assets tracked by the source were loaded into their asset storages. pub fn is_loaded(&self) -> bool { self.meta.as_ref().map_or(false, |meta| { - self.committed_assets.len() == meta.assets.len() + self.committed_assets.len() == meta.len() }) } From be09fc0c0e6b27b2023f156aa6bceb17251fc145 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 07:12:42 -0300 Subject: [PATCH 05/32] Rename Handle::as_weak() to cast() --- crates/bevy_asset/src/handle.rs | 2 +- crates/bevy_text/src/glyph_brush.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 5a1d6563ecab1..be2a23e3b5efb 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -151,7 +151,7 @@ impl Handle { } /// Recasts this handle as a weak handle of an Asset `U`. - pub fn as_weak(&self) -> Handle { + pub fn cast(&self) -> Handle { Handle { id: self.id, handle_type: HandleType::Weak, diff --git a/crates/bevy_text/src/glyph_brush.rs b/crates/bevy_text/src/glyph_brush.rs index ca7331901775d..cc6d9cd7067c8 100644 --- a/crates/bevy_text/src/glyph_brush.rs +++ b/crates/bevy_text/src/glyph_brush.rs @@ -96,7 +96,7 @@ impl GlyphBrush { let section_data = sections_data[sg.section_index]; if let Some(outlined_glyph) = section_data.1.font.outline_glyph(glyph) { let bounds = outlined_glyph.px_bounds(); - let handle_font_atlas: Handle = section_data.0.as_weak(); + let handle_font_atlas: Handle = section_data.0.cast(); let font_atlas_set = font_atlas_set_storage .get_or_insert_with(handle_font_atlas, FontAtlasSet::default); From 7ad845b94a1bde3ceab47dc87bd779dfca0ec321 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 07:20:53 -0300 Subject: [PATCH 06/32] Rename LoadContext::get_asset_metas() to generate_asset_metas() --- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_asset/src/loader.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 6e7ecdc0277d0..473c68b216b54 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -344,7 +344,7 @@ impl AssetServer { // TODO: queue free old assets source_info.asset_types.clear(); - source_info.meta = Some(load_context.get_asset_metas()); + source_info.meta = Some(load_context.generate_asset_metas()); // load asset dependencies and prepare asset type hashmap for (label, loaded_asset) in &mut load_context.labeled_assets { diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 5d6b87d8388ba..617ba2dec6a35 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -128,7 +128,8 @@ impl<'a> LoadContext<'a> { self.asset_io.load_path(path.as_ref()).await } - pub fn get_asset_metas(&self) -> Vec { + /// Generates metadata for the assets managed by this load context. + pub fn generate_asset_metas(&self) -> Vec { let mut asset_metas = Vec::new(); for (label, asset) in &self.labeled_assets { asset_metas.push(AssetMeta { From 098b9bb45d6f0dadfcfaf386de885e037696b587 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 07:29:33 -0300 Subject: [PATCH 07/32] Rename Handle::as_weak() in examples/ui/font_atlas_debug.rs --- examples/ui/font_atlas_debug.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ui/font_atlas_debug.rs b/examples/ui/font_atlas_debug.rs index 27f04ccd067df..95a2bf396068f 100644 --- a/examples/ui/font_atlas_debug.rs +++ b/examples/ui/font_atlas_debug.rs @@ -36,7 +36,7 @@ fn atlas_render_system( font_atlas_sets: Res>, texture_atlases: Res>, ) { - if let Some(set) = font_atlas_sets.get(&state.handle.as_weak::()) { + if let Some(set) = font_atlas_sets.get(&state.handle.cast::()) { if let Some((_size, font_atlas)) = set.iter().next() { let x_offset = state.atlas_count as f32; if state.atlas_count == font_atlas.len() as u32 { From 12ed78f6117298c2599e8cdc0c7f1beb5dc50d2e Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 6 Jan 2022 14:33:24 -0300 Subject: [PATCH 08/32] Document loader module --- crates/bevy_asset/src/loader.rs | 63 +++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 617ba2dec6a35..c9e7245185cd2 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -10,18 +10,42 @@ use crossbeam_channel::{Receiver, Sender}; use downcast_rs::{impl_downcast, Downcast}; use std::path::Path; -/// A loader for an asset source +/// A loader for an asset source. +/// +/// Types implementing this trait are used by the asset server to load assets into their respective +/// asset storages. pub trait AssetLoader: Send + Sync + 'static { + /// Processess the asset in an asynchronous closure. fn load<'a>( &'a self, bytes: &'a [u8], load_context: &'a mut LoadContext, ) -> BoxedFuture<'a, Result<(), anyhow::Error>>; + + /// Returns a list of extensions supported by this asset loader. fn extensions(&self) -> &[&str]; } +/// An essential piece of data of an application. +/// +/// Assets are the building blocks of games. They can be anything, from images and sounds to scenes +/// and scripts. In Bevy, an asset is any struct that has an unique type id, as shown below: +/// +/// ```rust +/// #[derive(Debug, Deserialize, TypeUuid)] +/// #[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"] +/// pub struct CustomAsset { +/// pub value: i32, +/// } +/// ``` +/// +/// See the `assets/custom_asset.rs` example in the repository for more details. +/// +/// In order to load assets into your game you must either add them manually to an asset storage +/// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`]. pub trait Asset: TypeUuid + AssetDynamic {} +/// A untyped version of the [`Asset`] trait. pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {} impl_downcast!(AssetDynamic); @@ -29,12 +53,14 @@ impl Asset for T where T: TypeUuid + AssetDynamic + TypeUuidDynamic {} impl AssetDynamic for T where T: Send + Sync + 'static + TypeUuidDynamic {} +/// A complete asset processed in an [`AssetLoader`]. pub struct LoadedAsset { pub(crate) value: Option, pub(crate) dependencies: Vec>, } impl LoadedAsset { + /// Creates a new loaded asset. pub fn new(value: T) -> Self { Self { value: Some(value), @@ -42,17 +68,20 @@ impl LoadedAsset { } } + /// Adds a dependency on another asset at the provided path. pub fn add_dependency(&mut self, asset_path: AssetPath) { self.dependencies.push(asset_path.to_owned()); } #[must_use] + /// Adds a dependency on another asset at the provided path. pub fn with_dependency(mut self, asset_path: AssetPath) -> Self { self.add_dependency(asset_path); self } #[must_use] + /// Adds dependencies on other assets at the provided paths. pub fn with_dependencies(mut self, mut asset_paths: Vec>) -> Self { for asset_path in asset_paths.drain(..) { self.add_dependency(asset_path); @@ -77,6 +106,15 @@ impl From> for BoxedLoadedAsset { } } +/// An asynchronous context where an [`Asset`] is processed. +/// +/// The load context is created by the [`AssetServer`] to process an asset source after loading its +/// contents into memory. It is then passed to the appropriate [`AssetLoader`] based on the file +/// extension of the asset's path. +/// +/// An asset source can define one or more assets from a single source path. The main asset is set +/// using [`LoadContext::set_default_asset`] and sub-assets are defined with +/// [`LoadContext::set_labeled_asset`]. pub struct LoadContext<'a> { pub(crate) ref_change_channel: &'a RefChangeChannel, pub(crate) asset_io: &'a dyn AssetIo, @@ -101,18 +139,22 @@ impl<'a> LoadContext<'a> { } } + /// Gets the source path for this load context. pub fn path(&self) -> &Path { self.path } + /// Returns `true` if the load context contains an asset with the specified label. pub fn has_labeled_asset(&self, label: &str) -> bool { self.labeled_assets.contains_key(&Some(label.to_string())) } + /// Sets the primary asset loaded from the asset source. pub fn set_default_asset(&mut self, asset: LoadedAsset) { self.labeled_assets.insert(None, asset.into()); } + /// Sets a secondary asset loaded from the asset source. pub fn set_labeled_asset(&mut self, label: &str, asset: LoadedAsset) -> Handle { assert!(!label.is_empty()); self.labeled_assets @@ -120,10 +162,13 @@ impl<'a> LoadContext<'a> { self.get_handle(AssetPath::new_ref(self.path(), Some(label))) } + /// Gets a handle to an asset of type `T` from its id. pub fn get_handle, T: Asset>(&self, id: I) -> Handle { Handle::strong(id.into(), self.ref_change_channel.sender.clone()) } + /// Reads the contents of the file at the specified path through the [`AssetIo`] associated + /// with this context. pub async fn read_asset_bytes>(&self, path: P) -> Result, AssetIoError> { self.asset_io.load_path(path.as_ref()).await } @@ -141,33 +186,45 @@ impl<'a> LoadContext<'a> { asset_metas } + /// Gets the asset I/O associated with this load context. pub fn asset_io(&self) -> &dyn AssetIo { self.asset_io } } -/// The result of loading an asset of type `T` +/// The result of loading an asset of type `T`. #[derive(Debug)] pub struct AssetResult { + /// The asset itself. pub asset: Box, + /// The unique id of the asset. pub id: HandleId, + /// Change version. pub version: usize, } -/// A channel to send and receive [`AssetResult`]s +/// An event channel used by asset server to update the asset storage of a `T` asset. #[derive(Debug)] pub struct AssetLifecycleChannel { + /// The sender endpoint of the channel. pub sender: Sender>, + /// The receiver endpoint of the channel. pub receiver: Receiver>, } +/// Events for the [`AssetLifecycleChannel`]. pub enum AssetLifecycleEvent { + /// An asset was created. Create(AssetResult), + /// An asset was freed. Free(HandleId), } +/// A trait for sending lifecycle notifications from assets in the asset server. pub trait AssetLifecycle: Downcast + Send + Sync + 'static { + /// Notifies the asset server that a new asset was created. fn create_asset(&self, id: HandleId, asset: Box, version: usize); + /// Notifies the asset server that an asset was freed. fn free_asset(&self, id: HandleId); } impl_downcast!(AssetLifecycle); From 0f0cbba452cd9be93640292b490ee8f1f441ffaf Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Fri, 7 Jan 2022 16:20:22 -0300 Subject: [PATCH 09/32] Document io and filesytem_watcher modules --- crates/bevy_asset/src/filesystem_watcher.rs | 6 ++++-- crates/bevy_asset/src/io/android_asset_io.rs | 10 ++++++++++ crates/bevy_asset/src/io/file_asset_io.rs | 13 +++++++++++++ crates/bevy_asset/src/io/mod.rs | 20 ++++++++++++++++++-- crates/bevy_asset/src/io/wasm_asset_io.rs | 10 ++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/filesystem_watcher.rs b/crates/bevy_asset/src/filesystem_watcher.rs index 19b131780a078..737f8e63ad0c1 100644 --- a/crates/bevy_asset/src/filesystem_watcher.rs +++ b/crates/bevy_asset/src/filesystem_watcher.rs @@ -2,8 +2,9 @@ use crossbeam_channel::Receiver; use notify::{Event, RecommendedWatcher, RecursiveMode, Result, Watcher}; use std::path::Path; -/// Watches for changes to assets on the filesystem. This is used by the `AssetServer` to reload -/// them +/// Watches for changes to files on the local filesystem. +/// +/// This is used by the [`AssetServer`] to reload assets when their source paths are changed. pub struct FilesystemWatcher { pub watcher: RecommendedWatcher, pub receiver: Receiver>, @@ -21,6 +22,7 @@ impl Default for FilesystemWatcher { } impl FilesystemWatcher { + /// Watch for changes recursively at the provided path. pub fn watch>(&mut self, path: P) -> Result<()> { self.watcher.watch(path.as_ref(), RecursiveMode::Recursive) } diff --git a/crates/bevy_asset/src/io/android_asset_io.rs b/crates/bevy_asset/src/io/android_asset_io.rs index fc049b77a91a6..bbdf94d6a9c80 100644 --- a/crates/bevy_asset/src/io/android_asset_io.rs +++ b/crates/bevy_asset/src/io/android_asset_io.rs @@ -7,6 +7,16 @@ use std::{ path::{Path, PathBuf}, }; +/// I/O implementation for Android devices. +/// +/// Implementation details: +/// +/// - `load_path` uses the [AssetManager] to load files. +/// - `read_directory` always returns an empty itrator. +/// - `get_metadata` will probably return an error. +/// - Watching for changes is not supported. The watcher methods will do nothing. +/// +/// [AssetManager]: https://developer.android.com/reference/android/content/res/AssetManager pub struct AndroidAssetIo { root_path: PathBuf, } diff --git a/crates/bevy_asset/src/io/file_asset_io.rs b/crates/bevy_asset/src/io/file_asset_io.rs index 14dcf0a153a92..d77c4633804ab 100644 --- a/crates/bevy_asset/src/io/file_asset_io.rs +++ b/crates/bevy_asset/src/io/file_asset_io.rs @@ -21,6 +21,9 @@ use std::{ path::{Path, PathBuf}, }; +/// I/O implementation for the local filesystem. +/// +/// This asset I/O is fully featured but it's not available on `android` and `wasm` targets. pub struct FileAssetIo { root_path: PathBuf, #[cfg(feature = "filesystem_watcher")] @@ -28,6 +31,10 @@ pub struct FileAssetIo { } impl FileAssetIo { + /// Creates a new `FileAssetIo` at a path relative to the I/O's root path, optionally watching + /// for changes. + /// + /// See `get_root_path` below. pub fn new>(path: P, watch_for_changes: bool) -> Self { let file_asset_io = FileAssetIo { #[cfg(feature = "filesystem_watcher")] @@ -50,6 +57,11 @@ impl FileAssetIo { file_asset_io } + /// Returns the root path of the asset I/O. + /// + /// If the `CARGO_MANIFEST_DIR` environment variable is defined, which is set by cargo when + /// building, the asset I/O's root path will be the crate's root directory (where `Cargo.toml` + /// is at). Otherwise, the root path is the directory of the executable. pub fn get_root_path() -> PathBuf { if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { PathBuf::from(manifest_dir) @@ -144,6 +156,7 @@ impl AssetIo for FileAssetIo { } } +/// Watches for file changes in the local file system. #[cfg(all( feature = "filesystem_watcher", all(not(target_arch = "wasm32"), not(target_os = "android")) diff --git a/crates/bevy_asset/src/io/mod.rs b/crates/bevy_asset/src/io/mod.rs index e3d3e24047703..625800b59a664 100644 --- a/crates/bevy_asset/src/io/mod.rs +++ b/crates/bevy_asset/src/io/mod.rs @@ -25,28 +25,43 @@ use std::{ }; use thiserror::Error; -/// Errors that occur while loading assets +/// Errors that occur while loading assets. #[derive(Error, Debug)] pub enum AssetIoError { + /// Path not found. #[error("path not found: {0}")] NotFound(PathBuf), + + /// Encountered an I/O error while loading an asset. #[error("encountered an io error while loading asset: {0}")] Io(#[from] io::Error), + + /// Failed to watch patch. #[error("failed to watch path: {0}")] PathWatchError(PathBuf), } -/// Handles load requests from an `AssetServer` +/// Handles load requests from an `AssetServer`. pub trait AssetIo: Downcast + Send + Sync + 'static { + /// Returns a future to load the full file data at the provided path. fn load_path<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result, AssetIoError>>; + + /// Returns an iterator of directory entry names at the provided path. fn read_directory( &self, path: &Path, ) -> Result>, AssetIoError>; + + /// Returns metadata about the filesystem entry at the provided path. fn get_metadata(&self, path: &Path) -> Result; + + /// Tells the asset I/O to watch for changes recursively at the provided path. fn watch_path_for_changes(&self, path: &Path) -> Result<(), AssetIoError>; + + /// Enables change tracking in this asset I/O. fn watch_for_changes(&self) -> Result<(), AssetIoError>; + /// Returns `true` if the path is a directory. fn is_dir(&self, path: &Path) -> bool { self.get_metadata(path) .as_ref() @@ -54,6 +69,7 @@ pub trait AssetIo: Downcast + Send + Sync + 'static { .unwrap_or(false) } + /// Returns `true` if the path is a file. fn is_file(&self, path: &Path) -> bool { self.get_metadata(path) .as_ref() diff --git a/crates/bevy_asset/src/io/wasm_asset_io.rs b/crates/bevy_asset/src/io/wasm_asset_io.rs index 4e0d812738d6f..91fe067128c68 100644 --- a/crates/bevy_asset/src/io/wasm_asset_io.rs +++ b/crates/bevy_asset/src/io/wasm_asset_io.rs @@ -10,6 +10,16 @@ use wasm_bindgen::JsCast; use wasm_bindgen_futures::JsFuture; use web_sys::Response; +/// I/O implementation for web builds. +/// +/// Implementation details: +/// +/// - `load_path` makes [fetch()] requests. +/// - `read_directory` always returns an empty iterator. +/// - `get_metadata` will always return an error. +/// - Watching for changes is not supported. The watcher methods will do nothing. +/// +/// [fetch()]: https://developer.mozilla.org/en-US/docs/Web/API/fetch pub struct WasmAssetIo { root_path: PathBuf, } From dc057cb55d2d4c3d1378f9d4772096c06859c0e5 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Fri, 7 Jan 2022 16:20:38 -0300 Subject: [PATCH 10/32] Fix typo in loader.rs --- crates/bevy_asset/src/loader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index c9e7245185cd2..8113ab2c478db 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -15,7 +15,7 @@ use std::path::Path; /// Types implementing this trait are used by the asset server to load assets into their respective /// asset storages. pub trait AssetLoader: Send + Sync + 'static { - /// Processess the asset in an asynchronous closure. + /// Processes the asset in an asynchronous closure. fn load<'a>( &'a self, bytes: &'a [u8], From ebe8b950e54871f1ebd58ff9709634852420d564 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 9 Jan 2022 00:21:27 -0300 Subject: [PATCH 11/32] Finish assets module --- crates/bevy_asset/src/assets.rs | 64 +++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 23ec2cf3dee66..2b6f80cad1633 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -12,12 +12,15 @@ use bevy_utils::HashMap; use crossbeam_channel::Sender; use std::fmt::Debug; -/// Events that happen on assets of type `T` +/// Events that happen on assets of type `T`. /// -/// Events sent via the [Assets] struct will always be sent with a _Weak_ handle +/// Events sent via the [`Assets`] struct will always be sent with a _Weak_ handle. pub enum AssetEvent { + #[allow(missing_docs)] Created { handle: Handle }, + #[allow(missing_docs)] Modified { handle: Handle }, + #[allow(missing_docs)] Removed { handle: Handle }, } @@ -81,6 +84,7 @@ impl Assets { /// Adds an asset to the collection, returning a Strong handle to that asset. /// /// # Events + /// /// * [`AssetEvent::Created`] pub fn add(&mut self, asset: T) -> Handle { let id = HandleId::random::(); @@ -110,8 +114,9 @@ impl Assets { /// new asset will be inserted. /// /// # Events - /// * [`AssetEvent::Created`]: Sent if the asset did not yet exist with the given handle - /// * [`AssetEvent::Modified`]: Sent if the asset with given handle already existed + /// + /// * [`AssetEvent::Created`]: Sent if the asset did not yet exist with the given handle. + /// * [`AssetEvent::Modified`]: Sent if the asset with given handle already existed. pub fn set_untracked>(&mut self, handle: H, asset: T) { let id: HandleId = handle.into(); if self.assets.insert(id, asset).is_some() { @@ -125,7 +130,7 @@ impl Assets { } } - /// Get the asset for the given handle. + /// Gets the asset for the given handle. /// /// This is the main method for accessing asset data from an [Assets] collection. If you need /// mutable access to the asset, use [`get_mut`](Assets::get_mut). @@ -150,15 +155,16 @@ impl Assets { self.assets.get_mut(&id) } - /// Gets a _Strong_ handle pointing to the same asset as the given one + /// Gets a _Strong_ handle pointing to the same asset as the given one. pub fn get_handle>(&self, handle: H) -> Handle { Handle::strong(handle.into(), self.ref_change_sender.clone()) } - /// Get mutable access to an asset for the given handle, inserting a new value if none exists. + /// Gets mutable access to an asset for the given handle, inserting a new value if none exists. /// /// # Events - /// * [`AssetEvent::Created`]: Sent if the asset did not yet exist with the given handle + /// + /// * [`AssetEvent::Created`]: Sent if the asset did not yet exist with the given handle. pub fn get_or_insert_with>( &mut self, handle: H, @@ -179,12 +185,12 @@ impl Assets { borrowed } - /// Get an iterator over all assets in the collection. + /// Gets an iterator over all assets in the collection. pub fn iter(&self) -> impl Iterator { self.assets.iter().map(|(k, v)| (*k, v)) } - /// Get a mutable iterator over all assets in the collection. + /// Gets a mutable iterator over all assets in the collection. pub fn iter_mut(&mut self) -> impl Iterator { self.assets.iter_mut().map(|(k, v)| { self.events.send(AssetEvent::Modified { @@ -194,16 +200,17 @@ impl Assets { }) } - /// Get an iterator over all [`HandleId`]'s in the collection. + /// Gets an iterator over all [`HandleId`]'s in the collection. pub fn ids(&self) -> impl Iterator + '_ { self.assets.keys().cloned() } - /// Remove an asset for the given handle. + /// Removes an asset for the given handle. /// /// The asset is returned if it existed in the collection, otherwise `None`. /// /// # Events + /// /// * [`AssetEvent::Removed`] pub fn remove>(&mut self, handle: H) -> Option { let id: HandleId = handle.into(); @@ -238,6 +245,7 @@ impl Assets { self.assets.shrink_to_fit(); } + /// A system that sends [`AssetEvent`]s around the application. pub fn asset_event_system( mut events: EventWriter>, mut assets: ResMut>, @@ -249,40 +257,60 @@ impl Assets { } } - /// Gets the number of assets in the collection + /// Gets the number of assets in the collection. pub fn len(&self) -> usize { self.assets.len() } - /// Returns true if there are no stored assets + /// Returns true if there are no stored assets. pub fn is_empty(&self) -> bool { self.assets.is_empty() } } -/// [App] extension methods for adding new asset types +/// [`App`] extension methods for adding new asset types. pub trait AddAsset { + /// Registers `T` as a supported asset in the application. + /// + /// Adding the same type again after it has been added does nothing. fn add_asset(&mut self) -> &mut Self where T: Asset; + + /// Registers `T` as a supported internal asset in the application. + /// + /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded + /// using the conventional API. See [`DebugAssetServerPlugin`]. + /// + /// Adding the same type again after it has been added does nothing. fn add_debug_asset(&mut self) -> &mut Self where T: Asset; + + /// Adds an asset loader `T` using default values. + /// + /// The default values may come from the `World` or from `T::default()`. fn init_asset_loader(&mut self) -> &mut Self where T: AssetLoader + FromWorld; + + /// Adds an asset loader `T` for internal assets using default values. + /// + /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded + /// using the conventional API. See [`DebugAssetServerPlugin`]. + /// + /// The default values may come from the `World` or from `T::default()`. fn init_debug_asset_loader(&mut self) -> &mut Self where T: AssetLoader + FromWorld; + + /// Adds the provided asset loader to the application. fn add_asset_loader(&mut self, loader: T) -> &mut Self where T: AssetLoader; } impl AddAsset for App { - /// Add an [`Asset`] to the [`App`]. - /// - /// Adding the same [`Asset`] again after it has been added does nothing. fn add_asset(&mut self) -> &mut Self where T: Asset, From 8ecfd5df4cb4d4ef73b4860d2b75c9c4c7db5ffc Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 9 Jan 2022 00:27:19 -0300 Subject: [PATCH 12/32] Fix typo in io/mod.rs --- crates/bevy_asset/src/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/io/mod.rs b/crates/bevy_asset/src/io/mod.rs index 625800b59a664..196dd0f651287 100644 --- a/crates/bevy_asset/src/io/mod.rs +++ b/crates/bevy_asset/src/io/mod.rs @@ -36,7 +36,7 @@ pub enum AssetIoError { #[error("encountered an io error while loading asset: {0}")] Io(#[from] io::Error), - /// Failed to watch patch. + /// Failed to watch path. #[error("failed to watch path: {0}")] PathWatchError(PathBuf), } From 4ced5e3b2612b2ffc1d47786c2c01130c6fe0f47 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Mon, 10 Jan 2022 14:13:24 -0300 Subject: [PATCH 13/32] Document asset_server module --- crates/bevy_asset/src/asset_server.rs | 42 +++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 473c68b216b54..b2f9efd4e9400 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -14,17 +14,29 @@ use parking_lot::{Mutex, RwLock}; use std::{path::Path, sync::Arc}; use thiserror::Error; -/// Errors that occur while loading assets with an `AssetServer` +/// Errors that occur while loading assets with an `AssetServer`. #[derive(Error, Debug)] pub enum AssetServerError { + /// Asset folder is not a directory. #[error("asset folder path is not a directory: {0}")] AssetFolderNotADirectory(String), + + /// No asset loader was found for the specified extensions. #[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))] - MissingAssetLoader { extensions: Vec }, + MissingAssetLoader { + #[allow(missing_docs)] + extensions: Vec, + }, + + /// The handle type does not match the type of the loaded asset. #[error("the given type does not match the type of the loaded asset")] IncorrectHandleType, + + /// Encountered an error while processing an asset. #[error("encountered an error while loading an asset: {0}")] AssetLoaderError(anyhow::Error), + + /// Encountered an error while reading an asset from disk. #[error("encountered an error while reading an asset: {0}")] AssetIoError(#[from] AssetIoError), } @@ -48,6 +60,9 @@ pub(crate) struct AssetRefCounter { pub(crate) mark_unused_assets: Arc>>, } +/// Internal data for the asset server. +/// +/// [`AssetServer`] is the public API for interacting with the asset server. pub struct AssetServerInternal { pub(crate) asset_io: Box, pub(crate) asset_ref_counter: AssetRefCounter, @@ -58,17 +73,19 @@ pub struct AssetServerInternal { handle_to_path: Arc>>>, } -/// Loads assets from the filesystem on background threads +/// Loads assets from the filesystem on background threads. #[derive(Clone)] pub struct AssetServer { pub(crate) server: Arc, } impl AssetServer { + /// Creates a new asset server with the provided asset I/O. pub fn new(source_io: T) -> Self { Self::with_boxed_io(Box::new(source_io)) } + /// Creates a new asset server with a pointer to an asset I/O. pub fn with_boxed_io(asset_io: Box) -> Self { AssetServer { server: Arc::new(AssetServerInternal { @@ -104,6 +121,7 @@ impl AssetServer { Assets::new(self.server.asset_ref_counter.channel.sender.clone()) } + /// Adds the provided loader as an asset loader for `T` assets. pub fn add_loader(&self, loader: T) where T: AssetLoader, @@ -126,11 +144,13 @@ impl AssetServer { Ok(()) } + /// Gets a handle for an asset with the provided id. pub fn get_handle>(&self, id: I) -> Handle { let sender = self.server.asset_ref_counter.channel.sender.clone(); Handle::strong(id.into(), sender) } + /// Gets an untyped handle for an asset with the provided id. pub fn get_handle_untyped>(&self, id: I) -> HandleUntyped { let sender = self.server.asset_ref_counter.channel.sender.clone(); HandleUntyped::strong(id.into(), sender) @@ -179,6 +199,7 @@ impl AssetServer { }) } + /// Gets the source path of an asset from the provided handle. pub fn get_handle_path>(&self, handle: H) -> Option> { self.server .handle_to_path @@ -187,6 +208,7 @@ impl AssetServer { .cloned() } + /// Gets the load state of an asset from the provided handle. pub fn get_load_state>(&self, handle: H) -> LoadState { match handle.into() { HandleId::AssetPathId(id) => { @@ -199,6 +221,7 @@ impl AssetServer { } } + /// Gets the overall load state of a group of assets from the provided handles. pub fn get_group_load_state(&self, handles: impl IntoIterator) -> LoadState { let mut load_state = LoadState::Loaded; for handle_id in handles { @@ -219,11 +242,11 @@ impl AssetServer { load_state } - /// Queue an [`Asset`] at the provided relative path for asynchronous loading. + /// Queues an [`Asset`] at the provided relative path for asynchronous loading. /// - /// The absolute Path to the asset is `"ROOT/ASSET_FOLDER_NAME/path"`. + /// The absolute path to the asset is `"ROOT/ASSET_FOLDER_NAME/path"`. /// - /// By default the ROOT is the directory of the Application, but this can be overridden by + /// By default the `ROOT` is the directory of the Application, but this can be overridden by /// setting the `"CARGO_MANIFEST_DIR"` environment variable /// (see ) /// to another directory. When the application is run through Cargo, then @@ -363,6 +386,9 @@ impl AssetServer { Ok(asset_path_id) } + /// Queues the [`Asset`] at the provided path for loading and returns an untyped handle. + /// + /// See [`load`]. #[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] pub fn load_untyped<'a, P: Into>>(&self, path: P) -> HandleUntyped { let handle_id = self.load_untracked(path.into(), false); @@ -398,6 +424,7 @@ impl AssetServer { asset_path.into() } + /// Loads one or more assets from the folder at the provided path. #[must_use = "not using the returned strong handles may result in the unexpected release of the assets"] pub fn load_folder>( &self, @@ -427,6 +454,7 @@ impl AssetServer { Ok(handles) } + /// Frees unused assets from their asset storages. pub fn free_unused_assets(&self) { let mut potential_frees = self.server.asset_ref_counter.mark_unused_assets.lock(); @@ -453,6 +481,7 @@ impl AssetServer { } } + /// Iterates through asset references and marks assets with no active handles as unused. pub fn mark_unused_assets(&self) { let receiver = &self.server.asset_ref_counter.channel.receiver; let mut ref_counts = self.server.asset_ref_counter.ref_counts.write(); @@ -557,6 +586,7 @@ fn free_unused_assets_system_impl(asset_server: &AssetServer) { asset_server.mark_unused_assets(); } +/// A system for freeing assets that have no active handles. pub fn free_unused_assets_system(asset_server: Res) { free_unused_assets_system_impl(&asset_server); } From 0b8e486988ef47e3ee7a92b2454384db2905e2be Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Mon, 10 Jan 2022 14:52:54 -0300 Subject: [PATCH 14/32] Document diagnostic module --- .../src/diagnostic/asset_count_diagnostics_plugin.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 d5f64c8a455e8..f7d987ad95cb3 100644 --- a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs +++ b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs @@ -3,7 +3,7 @@ use bevy_app::prelude::*; use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics, MAX_DIAGNOSTIC_NAME_WIDTH}; use bevy_ecs::system::{Res, ResMut}; -/// Adds "asset count" diagnostic to an App +/// Adds an asset count diagnostic to an [´App`] for assets of type `T`. pub struct AssetCountDiagnosticsPlugin { marker: std::marker::PhantomData, } @@ -24,10 +24,14 @@ impl Plugin for AssetCountDiagnosticsPlugin { } impl AssetCountDiagnosticsPlugin { + /// Gets unique id of this diagnostic. + /// + /// The diagnostic id is the type uuid of `T`. pub fn diagnostic_id() -> DiagnosticId { DiagnosticId(T::TYPE_UUID) } + /// Registers the asset count diagnostic for the current application. pub fn setup_system(mut diagnostics: ResMut) { let asset_type_name = std::any::type_name::(); let max_length = MAX_DIAGNOSTIC_NAME_WIDTH - "asset_count ".len(); @@ -47,6 +51,7 @@ impl AssetCountDiagnosticsPlugin { )); } + /// Updates the asset count of `T` assets. pub fn diagnostic_system(mut diagnostics: ResMut, assets: Res>) { diagnostics.add_measurement(Self::diagnostic_id(), || assets.len() as f64); } From 3eb0afbb816f95f885c3be43559cc325f446bdf1 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 11 Jan 2022 15:56:23 -0300 Subject: [PATCH 15/32] Review and crate-level documentation --- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_asset/src/diagnostic/mod.rs | 2 ++ crates/bevy_asset/src/handle.rs | 13 +++++++------ crates/bevy_asset/src/io/mod.rs | 12 +++++++++++- crates/bevy_asset/src/lib.rs | 12 ++++++++++++ 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index b2f9efd4e9400..b5cb7ccc1a0fb 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -388,7 +388,7 @@ impl AssetServer { /// Queues the [`Asset`] at the provided path for loading and returns an untyped handle. /// - /// See [`load`]. + /// See [`load`](#method.load). #[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] pub fn load_untyped<'a, P: Into>>(&self, path: P) -> HandleUntyped { let handle_id = self.load_untracked(path.into(), false); diff --git a/crates/bevy_asset/src/diagnostic/mod.rs b/crates/bevy_asset/src/diagnostic/mod.rs index f093527f9755a..5aed4a8749040 100644 --- a/crates/bevy_asset/src/diagnostic/mod.rs +++ b/crates/bevy_asset/src/diagnostic/mod.rs @@ -1,2 +1,4 @@ +//! Diagnotic providers. + mod asset_count_diagnostics_plugin; pub use asset_count_diagnostics_plugin::AssetCountDiagnosticsPlugin; diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index be2a23e3b5efb..70b2349a10408 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -34,6 +34,7 @@ use serde::{Deserialize, Serialize}; pub enum HandleId { /// A handle id of a loaded asset. Id(Uuid, u64), + /// A handle id of a pending asset. AssetPathId(AssetPathId), } @@ -51,13 +52,13 @@ impl<'a> From> for HandleId { } impl HandleId { - /// Creates a random id for an Asset of type `T`. + /// Creates a random id for an asset of type `T`. #[inline] pub fn random() -> Self { HandleId::Id(T::TYPE_UUID, rand::random()) } - /// Creates the default id for an Asset of type `T`. + /// Creates the default id for an asset of type `T`. #[inline] pub fn default() -> Self { HandleId::Id(T::TYPE_UUID, 0) @@ -78,7 +79,7 @@ impl HandleId { /// /// A handle is _not_ the asset itself, but should be seen as a pointer to the asset. Modifying a /// handle's `id` only modifies which asset is being pointed to. To get the actual asset, try using -/// [`Assets::get`](crate::Assets::get) or [`Assets::get_mut`](crate::Assets::get_mut). +/// [`Assets::get`] or [`Assets::get_mut`]. /// /// # Strong and Weak /// @@ -104,7 +105,7 @@ pub struct Handle where T: Asset, { - /// The ID of the asset as contained within its respective [Assets](crate::Assets) collection + /// The ID of the asset as contained within its respective [`Assets`] collection pub id: HandleId, #[reflect(ignore)] handle_type: HandleType, @@ -171,7 +172,7 @@ impl Handle { /// Makes this handle Strong if it wasn't already. /// - /// This method requires the corresponding [Assets](crate::Assets) collection + /// This method requires the corresponding [`Assets`](crate::Assets) collection. pub fn make_strong(&mut self, assets: &Assets) { if self.is_strong() { return; @@ -329,7 +330,7 @@ impl HandleUntyped { } } - /// Create a weak untyped into an Asset identified by `id`. + /// Create a weak, untyped handle into an Asset identified by `id`. pub fn weak(id: HandleId) -> Self { Self { id, diff --git a/crates/bevy_asset/src/io/mod.rs b/crates/bevy_asset/src/io/mod.rs index 196dd0f651287..7efbd7ca8882f 100644 --- a/crates/bevy_asset/src/io/mod.rs +++ b/crates/bevy_asset/src/io/mod.rs @@ -41,7 +41,17 @@ pub enum AssetIoError { PathWatchError(PathBuf), } -/// Handles load requests from an `AssetServer`. +/// A storage provider for an [`AssetServer`]. +/// +/// An asset I/O is the backend actually providing data for the asset loaders managed by the asset +/// server. An average user will probably be just fine with the default [`FileAssetIo`], but you +/// can easily use your own custom I/O to, for example, load assets from cloud storage or create a +/// seamless VFS layout using custom containers. +/// +/// See the [`custom_asset_io`] example in the repository for more details. +/// +/// [`AssetServer`]: struct.AssetServer.html +/// [`custom_asset_io`]: https://github.com/bevyengine/bevy/tree/latest/examples/asset/custom_asset_io.rs pub trait AssetIo: Downcast + Send + Sync + 'static { /// Returns a future to load the full file data at the provided path. fn load_path<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result, AssetIoError>>; diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index ae2e36ea0a80a..512784f98a80f 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -1,3 +1,13 @@ +//! Built-in plugin for asset support. +//! +//! This plugin allows a bevy app to work with assets from the filesystem (or [another source]), +//! providing an [asset server] for loading an processing [`Asset`]s and storing them in an +//! [asset storage] to be accesed by systems. +//! +//! [another source]: trait.AssetIo.html +//! [asset server]: struct.AssetServer.html +//! [asset storage]: struct.Assets.html + mod asset_server; mod assets; #[cfg(feature = "debug_asset_server")] @@ -35,7 +45,9 @@ use bevy_ecs::schedule::{StageLabel, SystemStage}; /// The names of asset stages in an App Schedule #[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] pub enum AssetStage { + /// The stage where asset storages are updated. LoadAssets, + /// The stage where asset events are generated. AssetEvents, } From e61305ee3c346abbb8e113ee3af9e9a98d225059 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 11 Jan 2022 15:57:46 -0300 Subject: [PATCH 16/32] Add #[warn(missing_docs)] lint --- crates/bevy_asset/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 512784f98a80f..f32287e47cdd2 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -8,6 +8,8 @@ //! [asset server]: struct.AssetServer.html //! [asset storage]: struct.Assets.html +#![warn(missing_docs)] + mod asset_server; mod assets; #[cfg(feature = "debug_asset_server")] From 31e9a711997d2f76d3eddd52a7e80ca952de469e Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 11 Jan 2022 16:05:01 -0300 Subject: [PATCH 17/32] Update type uuid when recasting a handle --- crates/bevy_asset/src/handle.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 70b2349a10408..29eaa9f8bd812 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -153,8 +153,14 @@ impl Handle { /// Recasts this handle as a weak handle of an Asset `U`. pub fn cast(&self) -> Handle { + let id = if let HandleId::Id(_, id) = self.id { + HandleId::Id(U::TYPE_UUID, id) + } else { + self.id + }; + Handle { - id: self.id, + id, handle_type: HandleType::Weak, marker: PhantomData, } From 5359424b1e07ebae716cdcc136c637e1ffbebb42 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 11 Jan 2022 16:39:01 -0300 Subject: [PATCH 18/32] Run cargo fmt --- crates/bevy_asset/src/info.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index 476f79c3b1569..b84869f12739a 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -34,9 +34,9 @@ pub struct SourceInfo { impl SourceInfo { /// Returns `true` if all assets tracked by the source were loaded into their asset storages. pub fn is_loaded(&self) -> bool { - self.meta.as_ref().map_or(false, |meta| { - self.committed_assets.len() == meta.len() - }) + self.meta + .as_ref() + .map_or(false, |meta| self.committed_assets.len() == meta.len()) } /// Gets the type identifier for an asset identified by `label_id`. From 79fe66b24948a3ee1246985d704eadf527bd72c4 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Wed, 12 Jan 2022 20:18:47 -0300 Subject: [PATCH 19/32] Enhancements and fixes --- crates/bevy_asset/src/asset_server.rs | 42 ++++++++++++++++--- crates/bevy_asset/src/assets.rs | 5 ++- .../asset_count_diagnostics_plugin.rs | 2 +- crates/bevy_asset/src/diagnostic/mod.rs | 2 +- crates/bevy_asset/src/filesystem_watcher.rs | 3 +- crates/bevy_asset/src/lib.rs | 6 +-- 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index b5cb7ccc1a0fb..605d4557dd3be 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -73,8 +73,28 @@ pub struct AssetServerInternal { handle_to_path: Arc>>>, } -/// Loads assets from the filesystem on background threads. #[derive(Clone)] +/// Loads assets from the filesystem on the background. +/// +/// The asset server is the primary way of loading assets in bevy. It keeps track of +/// the load state of the assets it manages and can even reload them from the +/// filesystem [if you tell it to]! +/// +/// The asset server is a _resource_, so in order to accesss it in a system you +/// need a `Res` accessor, like this: +/// +/// ```rust +/// fn my_system(mut commands: Commands, asset_server: Res) +/// { +/// let asset_handle = asset_server.load("cool_picture.png"); +/// // do something with the asset handle... +/// } +/// ``` +/// +/// See the [`asset_loading`] example for more information. +/// +/// [if you tell it to]: AssetServer::watch_for_changes +/// [`asset_loading`]: https://github.com/bevyengine/bevy/tree/latest/examples/asset/asset_loading.rs pub struct AssetServer { pub(crate) server: Arc, } @@ -144,13 +164,13 @@ impl AssetServer { Ok(()) } - /// Gets a handle for an asset with the provided id. + /// Gets a strong handle for an asset with the provided id. pub fn get_handle>(&self, id: I) -> Handle { let sender = self.server.asset_ref_counter.channel.sender.clone(); Handle::strong(id.into(), sender) } - /// Gets an untyped handle for an asset with the provided id. + /// Gets an untyped, strong handle for an asset with the provided id. pub fn get_handle_untyped>(&self, id: I) -> HandleUntyped { let sender = self.server.asset_ref_counter.channel.sender.clone(); HandleUntyped::strong(id.into(), sender) @@ -222,6 +242,9 @@ impl AssetServer { } /// Gets the overall load state of a group of assets from the provided handles. + /// + /// This method will only return [`LoadState::Loaded`] if all assets in the + /// group were loaded succesfully. pub fn get_group_load_state(&self, handles: impl IntoIterator) -> LoadState { let mut load_state = LoadState::Loaded; for handle_id in handles { @@ -388,7 +411,7 @@ impl AssetServer { /// Queues the [`Asset`] at the provided path for loading and returns an untyped handle. /// - /// See [`load`](#method.load). + /// See [`load`](AssetServer::load). #[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] pub fn load_untyped<'a, P: Into>>(&self, path: P) -> HandleUntyped { let handle_id = self.load_untracked(path.into(), false); @@ -424,7 +447,14 @@ impl AssetServer { asset_path.into() } - /// Loads one or more assets from the folder at the provided path. + /// Loads assets from the specified folder recursively. + /// + /// # Errors + /// + /// - If the provided path is not a directory, it will fail with + /// [`AssetServerError::AssetFolderNotADirectory`]. + /// - If something unexpected happened while loading an asset, other + /// [`AssetServerError`]s may be returned. #[must_use = "not using the returned strong handles may result in the unexpected release of the assets"] pub fn load_folder>( &self, @@ -454,7 +484,7 @@ impl AssetServer { Ok(handles) } - /// Frees unused assets from their asset storages. + /// Frees unused assets, unloading them from memory. pub fn free_unused_assets(&self) { let mut potential_frees = self.server.asset_ref_counter.mark_unused_assets.lock(); diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 2b6f80cad1633..365e81a5b2648 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -12,7 +12,7 @@ use bevy_utils::HashMap; use crossbeam_channel::Sender; use std::fmt::Debug; -/// Events that happen on assets of type `T`. +/// Events that involve assets of type `T`. /// /// Events sent via the [`Assets`] struct will always be sent with a _Weak_ handle. pub enum AssetEvent { @@ -245,7 +245,8 @@ impl Assets { self.assets.shrink_to_fit(); } - /// A system that sends [`AssetEvent`]s around the application. + /// A system that creates [`AssetEvent`]s at the end of the frame based on changes in the + /// asset storage. pub fn asset_event_system( mut events: EventWriter>, mut assets: ResMut>, 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 f7d987ad95cb3..470f3503e15cf 100644 --- a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs +++ b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs @@ -3,7 +3,7 @@ use bevy_app::prelude::*; use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics, MAX_DIAGNOSTIC_NAME_WIDTH}; use bevy_ecs::system::{Res, ResMut}; -/// Adds an asset count diagnostic to an [´App`] for assets of type `T`. +/// Adds an asset count diagnostic to an [`App`] for assets of type `T`. pub struct AssetCountDiagnosticsPlugin { marker: std::marker::PhantomData, } diff --git a/crates/bevy_asset/src/diagnostic/mod.rs b/crates/bevy_asset/src/diagnostic/mod.rs index 5aed4a8749040..b985a00607baa 100644 --- a/crates/bevy_asset/src/diagnostic/mod.rs +++ b/crates/bevy_asset/src/diagnostic/mod.rs @@ -1,4 +1,4 @@ -//! Diagnotic providers. +//! Diagnostic providers. mod asset_count_diagnostics_plugin; pub use asset_count_diagnostics_plugin::AssetCountDiagnosticsPlugin; diff --git a/crates/bevy_asset/src/filesystem_watcher.rs b/crates/bevy_asset/src/filesystem_watcher.rs index 737f8e63ad0c1..0a6120a70115f 100644 --- a/crates/bevy_asset/src/filesystem_watcher.rs +++ b/crates/bevy_asset/src/filesystem_watcher.rs @@ -4,7 +4,8 @@ use std::path::Path; /// Watches for changes to files on the local filesystem. /// -/// This is used by the [`AssetServer`] to reload assets when their source paths are changed. +/// When hot-reloading is enabled, the [`AssetServer`] uses this to reload assets when their source +/// files are modified. pub struct FilesystemWatcher { pub watcher: RecommendedWatcher, pub receiver: Receiver>, diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index f32287e47cdd2..564d1ae111acf 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -2,7 +2,7 @@ //! //! This plugin allows a bevy app to work with assets from the filesystem (or [another source]), //! providing an [asset server] for loading an processing [`Asset`]s and storing them in an -//! [asset storage] to be accesed by systems. +//! [asset storage] to be accessed by systems. //! //! [another source]: trait.AssetIo.html //! [asset server]: struct.AssetServer.html @@ -44,7 +44,7 @@ pub use path::*; use bevy_app::{prelude::Plugin, App}; use bevy_ecs::schedule::{StageLabel, SystemStage}; -/// The names of asset stages in an App Schedule +/// The names of asset stages in an [`App`] schedule. #[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] pub enum AssetStage { /// The stage where asset storages are updated. @@ -60,7 +60,7 @@ pub enum AssetStage { #[derive(Default)] pub struct AssetPlugin; -/// [`AssetServer`] settings +/// [`AssetServer`] settings. pub struct AssetServerSettings { /// The base folder where assets are loaded from, relative to the executable. pub asset_folder: String, From 6415c76b73d51de50da352852da1505757221e85 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Wed, 12 Jan 2022 22:29:13 -0300 Subject: [PATCH 20/32] Rename AssetStage::LoadAssets to UpdateAssets --- crates/bevy_asset/src/assets.rs | 2 +- crates/bevy_asset/src/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 365e81a5b2648..f0f3c63327272 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -326,7 +326,7 @@ impl AddAsset for App { self.insert_resource(assets) .add_system_to_stage(AssetStage::AssetEvents, Assets::::asset_event_system) - .add_system_to_stage(AssetStage::LoadAssets, update_asset_storage_system::) + .add_system_to_stage(AssetStage::UpdateAssets, update_asset_storage_system::) .register_type::>() .add_event::>() } diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 564d1ae111acf..1840484042af2 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -48,7 +48,7 @@ use bevy_ecs::schedule::{StageLabel, SystemStage}; #[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] pub enum AssetStage { /// The stage where asset storages are updated. - LoadAssets, + UpdateAssets, /// The stage where asset events are generated. AssetEvents, } @@ -107,7 +107,7 @@ impl Plugin for AssetPlugin { app.add_stage_before( bevy_app::CoreStage::PreUpdate, - AssetStage::LoadAssets, + AssetStage::UpdateAssets, SystemStage::parallel(), ) .add_stage_after( @@ -125,6 +125,6 @@ impl Plugin for AssetPlugin { feature = "filesystem_watcher", all(not(target_arch = "wasm32"), not(target_os = "android")) ))] - app.add_system_to_stage(AssetStage::LoadAssets, io::filesystem_watcher_system); + app.add_system_to_stage(AssetStage::UpdateAssets, io::filesystem_watcher_system); } } From 9fae232087d66c1297e7d7423aa7345daf098679 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Thu, 13 Jan 2022 10:23:57 -0300 Subject: [PATCH 21/32] Mention multiple extensions support --- crates/bevy_asset/src/asset_server.rs | 14 +++++++++++--- crates/bevy_asset/src/loader.rs | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 605d4557dd3be..3e762881d568b 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -24,7 +24,9 @@ pub enum AssetServerError { /// No asset loader was found for the specified extensions. #[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))] MissingAssetLoader { - #[allow(missing_docs)] + /// The list of extensions detected on the asset source path that failed to load. + /// + /// The list may be empty if the asset path is invalid or doesn't have an extension. extensions: Vec, }, @@ -267,7 +269,10 @@ impl AssetServer { /// Queues an [`Asset`] at the provided relative path for asynchronous loading. /// - /// The absolute path to the asset is `"ROOT/ASSET_FOLDER_NAME/path"`. + /// The absolute path to the asset is `"ROOT/ASSET_FOLDER_NAME/path"`. Its extension is then + /// extracted to search for an [asset loader]. If an asset path contains multiple dots (e.g. + /// `foo.bar.baz`), each level is considered a separate extension and the asset server will try + /// to look for loaders of `bar.baz` and `baz` assets. /// /// By default the `ROOT` is the directory of the Application, but this can be overridden by /// setting the `"CARGO_MANIFEST_DIR"` environment variable @@ -281,7 +286,10 @@ impl AssetServer { /// /// The asset is loaded asynchronously, and will generally not be available by the time /// this calls returns. Use [`AssetServer::get_load_state`] to determine when the asset is - /// effectively loaded and available in the [`Assets`] collection. + /// effectively loaded and available in the [`Assets`] collection. The asset will always fail to + /// load if the provided path doesn't contain an extension. + /// + /// [asset loader]: AssetLoader #[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] pub fn load<'a, T: Asset, P: Into>>(&self, path: P) -> Handle { self.load_untyped(path).typed() diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 8113ab2c478db..7246167cad14c 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -22,7 +22,7 @@ pub trait AssetLoader: Send + Sync + 'static { load_context: &'a mut LoadContext, ) -> BoxedFuture<'a, Result<(), anyhow::Error>>; - /// Returns a list of extensions supported by this asset loader. + /// Returns a list of extensions supported by this asset loader, without the preceding dot. fn extensions(&self) -> &[&str]; } From c9eb8ae7c7626abb196b423b27d7ee8a8d2e26fb Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 20 Mar 2022 16:51:50 -0300 Subject: [PATCH 22/32] Document debug_asset_server --- crates/bevy_asset/src/assets.rs | 8 ++++++++ crates/bevy_asset/src/debug_asset_server.rs | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index f0f3c63327272..791786f2f057f 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -378,6 +378,10 @@ impl AddAsset for App { } } +/// Loads an internal asset. +/// +/// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded +/// using the conventional API. See [`DebugAssetServerPlugin`]. #[cfg(feature = "debug_asset_server")] #[macro_export] macro_rules! load_internal_asset { @@ -399,6 +403,10 @@ macro_rules! load_internal_asset { }}; } +/// Loads an internal asset. +/// +/// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded +/// using the conventional API. See [`DebugAssetServerPlugin`]. #[cfg(not(feature = "debug_asset_server"))] #[macro_export] macro_rules! load_internal_asset { diff --git a/crates/bevy_asset/src/debug_asset_server.rs b/crates/bevy_asset/src/debug_asset_server.rs index b7e3c71c85c89..cdb4cc0010efc 100644 --- a/crates/bevy_asset/src/debug_asset_server.rs +++ b/crates/bevy_asset/src/debug_asset_server.rs @@ -1,3 +1,7 @@ +//! Support for hot reloading internal assets. +//! +//! Internal assets (e.g. shaders) are bundled directly into an application and can't be hot +//! reloaded using the conventional API. use bevy_app::{App, Plugin}; use bevy_ecs::{ event::Events, @@ -16,8 +20,7 @@ use crate::{ HandleUntyped, }; -/// A "debug asset app", whose sole responsibility is hot reloading assets that are -/// "internal" / compiled-in to Bevy Plugins. +/// A helper [`App`] used for hot reloading internal assets, which are compiled-in to Bevy plugins. pub struct DebugAssetApp(App); impl Deref for DebugAssetApp { @@ -34,17 +37,23 @@ impl DerefMut for DebugAssetApp { } } +/// A label describing the system that runs [`DebugAssetApp`]. #[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)] pub struct DebugAssetAppRun; /// Facilitates the creation of a "debug asset app", whose sole responsibility is hot reloading /// assets that are "internal" / compiled-in to Bevy Plugins. -/// Pair with [`load_internal_asset`](crate::load_internal_asset) to load "hot reloadable" assets -/// The `debug_asset_server` feature flag must also be enabled for hot reloading to work. +/// +/// Pair with the [`load_internal_asset`](crate::load_internal_asset) macro to load hot-reloadable +/// assets. The `debug_asset_server` feature flag must also be enabled for hot reloading to work. /// Currently only hot reloads assets stored in the `crates` folder. #[derive(Default)] pub struct DebugAssetServerPlugin; + +/// A collection that maps internal assets in a [`DebugAssetApp`]'s asset server to their mirrors in +/// the main [`App`]. pub struct HandleMap { + /// The collection of asset handles. pub handles: HashMap, Handle>, } @@ -106,6 +115,7 @@ pub(crate) fn sync_debug_assets( /// Uses the return type of the given loader to register the given handle with the appropriate type /// and load the asset with the given `path` and parent `file_path`. +/// /// If this feels a bit odd ... thats because it is. This was built to improve the UX of the /// `load_internal_asset` macro. pub fn register_handle_with_loader( From 5534af514806a9b2ca28726816bead783c58db4d Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 20 Mar 2022 16:58:37 -0300 Subject: [PATCH 23/32] Fix typo and reflow docstring in AssetServer --- crates/bevy_asset/src/asset_server.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 3e762881d568b..9bf26dcc7e823 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -78,12 +78,11 @@ pub struct AssetServerInternal { #[derive(Clone)] /// Loads assets from the filesystem on the background. /// -/// The asset server is the primary way of loading assets in bevy. It keeps track of -/// the load state of the assets it manages and can even reload them from the -/// filesystem [if you tell it to]! +/// The asset server is the primary way of loading assets in bevy. It keeps track of the load state +/// of the assets it manages and can even reload them from the filesystem [if you tell it to]! /// -/// The asset server is a _resource_, so in order to accesss it in a system you -/// need a `Res` accessor, like this: +/// The asset server is a _resource_, so in order to accesss it in a system you need a `Res` +/// accessor, like this: /// /// ```rust /// fn my_system(mut commands: Commands, asset_server: Res) From df1f8640dee4b2c757b2529ff4e18dceaf368199 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 20 Mar 2022 17:06:21 -0300 Subject: [PATCH 24/32] Document remaining methods and clarify some of FileAssetIo --- crates/bevy_asset/src/asset_server.rs | 1 + crates/bevy_asset/src/io/file_asset_io.rs | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 9bf26dcc7e823..5272f2bb90f5e 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -121,6 +121,7 @@ impl AssetServer { } } + /// Returns the associated asset I/O. pub fn asset_io(&self) -> &dyn AssetIo { &*self.server.asset_io } diff --git a/crates/bevy_asset/src/io/file_asset_io.rs b/crates/bevy_asset/src/io/file_asset_io.rs index d77c4633804ab..f33bc91a5b85b 100644 --- a/crates/bevy_asset/src/io/file_asset_io.rs +++ b/crates/bevy_asset/src/io/file_asset_io.rs @@ -31,15 +31,15 @@ pub struct FileAssetIo { } impl FileAssetIo { - /// Creates a new `FileAssetIo` at a path relative to the I/O's root path, optionally watching - /// for changes. + /// Creates a new `FileAssetIo` at a path relative to the executable's directory, optionally + /// watching for changes. /// - /// See `get_root_path` below. + /// See `get_exe_root` below. pub fn new>(path: P, watch_for_changes: bool) -> Self { let file_asset_io = FileAssetIo { #[cfg(feature = "filesystem_watcher")] filesystem_watcher: Default::default(), - root_path: Self::get_root_path().join(path.as_ref()), + root_path: Self::get_exe_root().join(path.as_ref()), }; if watch_for_changes { #[cfg(any( @@ -57,12 +57,12 @@ impl FileAssetIo { file_asset_io } - /// Returns the root path of the asset I/O. + /// Returns the path of the parent directory of the appplication's executable. /// /// If the `CARGO_MANIFEST_DIR` environment variable is defined, which is set by cargo when - /// building, the asset I/O's root path will be the crate's root directory (where `Cargo.toml` - /// is at). Otherwise, the root path is the directory of the executable. - pub fn get_root_path() -> PathBuf { + /// the app is run through it, the root path will be the crate's root instead, or whatever + /// path was passed to that variable. + pub fn get_exe_root() -> PathBuf { if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { PathBuf::from(manifest_dir) } else { @@ -76,6 +76,7 @@ impl FileAssetIo { } } + /// Returns the base directory where assets are loaded from. pub fn root_path(&self) -> &PathBuf { &self.root_path } From 482d7a09554594bc1d4df5d94528a4c824ccd5d3 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Mon, 21 Mar 2022 10:40:30 -0300 Subject: [PATCH 25/32] Fix unresolved doc link --- crates/bevy_asset/src/assets.rs | 8 ++++---- crates/bevy_asset/src/filesystem_watcher.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 791786f2f057f..8c394a979dfb5 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -281,7 +281,7 @@ pub trait AddAsset { /// Registers `T` as a supported internal asset in the application. /// /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded - /// using the conventional API. See [`DebugAssetServerPlugin`]. + /// using the conventional API. See `DebugAssetServerPlugin`. /// /// Adding the same type again after it has been added does nothing. fn add_debug_asset(&mut self) -> &mut Self @@ -298,7 +298,7 @@ pub trait AddAsset { /// Adds an asset loader `T` for internal assets using default values. /// /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded - /// using the conventional API. See [`DebugAssetServerPlugin`]. + /// using the conventional API. See `DebugAssetServerPlugin`. /// /// The default values may come from the `World` or from `T::default()`. fn init_debug_asset_loader(&mut self) -> &mut Self @@ -381,7 +381,7 @@ impl AddAsset for App { /// Loads an internal asset. /// /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded -/// using the conventional API. See [`DebugAssetServerPlugin`]. +/// using the conventional API. See `DebugAssetServerPlugin`. #[cfg(feature = "debug_asset_server")] #[macro_export] macro_rules! load_internal_asset { @@ -406,7 +406,7 @@ macro_rules! load_internal_asset { /// Loads an internal asset. /// /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded -/// using the conventional API. See [`DebugAssetServerPlugin`]. +/// using the conventional API. See `DebugAssetServerPlugin`. #[cfg(not(feature = "debug_asset_server"))] #[macro_export] macro_rules! load_internal_asset { diff --git a/crates/bevy_asset/src/filesystem_watcher.rs b/crates/bevy_asset/src/filesystem_watcher.rs index 0a6120a70115f..5ee499e80e3ed 100644 --- a/crates/bevy_asset/src/filesystem_watcher.rs +++ b/crates/bevy_asset/src/filesystem_watcher.rs @@ -4,8 +4,8 @@ use std::path::Path; /// Watches for changes to files on the local filesystem. /// -/// When hot-reloading is enabled, the [`AssetServer`] uses this to reload assets when their source -/// files are modified. +/// When hot-reloading is enabled, the [`AssetServer`](crate::AssetServer) uses this to reload +/// assets when their source files are modified. pub struct FilesystemWatcher { pub watcher: RecommendedWatcher, pub receiver: Receiver>, From 0979c1a7a660b477437986d0bf97d4bc05c97ba9 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Mon, 21 Mar 2022 12:15:25 -0300 Subject: [PATCH 26/32] Fix doc tests --- crates/bevy_asset/src/asset_server.rs | 7 +++++-- crates/bevy_asset/src/loader.rs | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 5272f2bb90f5e..9f44afe94ed7a 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -85,10 +85,13 @@ pub struct AssetServerInternal { /// accessor, like this: /// /// ```rust +/// use bevy_asset::AssetServer; +/// use bevy_ecs::prelude::{Commands, Res}; + /// fn my_system(mut commands: Commands, asset_server: Res) /// { -/// let asset_handle = asset_server.load("cool_picture.png"); -/// // do something with the asset handle... +/// // Now you can do whatever you want with the asset server, such as loading an asset: +/// // let asset_handle: Handle = asset_server.load("cool_picture.png"); /// } /// ``` /// diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 7246167cad14c..84bb981303d87 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -32,6 +32,9 @@ pub trait AssetLoader: Send + Sync + 'static { /// and scripts. In Bevy, an asset is any struct that has an unique type id, as shown below: /// /// ```rust +/// use bevy_reflect::TypeUuid; +/// use serde::Deserialize; +/// /// #[derive(Debug, Deserialize, TypeUuid)] /// #[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"] /// pub struct CustomAsset { @@ -73,15 +76,15 @@ impl LoadedAsset { self.dependencies.push(asset_path.to_owned()); } - #[must_use] /// Adds a dependency on another asset at the provided path. + #[must_use] pub fn with_dependency(mut self, asset_path: AssetPath) -> Self { self.add_dependency(asset_path); self } - #[must_use] /// Adds dependencies on other assets at the provided paths. + #[must_use] pub fn with_dependencies(mut self, mut asset_paths: Vec>) -> Self { for asset_path in asset_paths.drain(..) { self.add_dependency(asset_path); From c922e393a188d35032df9548442171e8efca5f36 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 22 Mar 2022 00:12:13 -0300 Subject: [PATCH 27/32] Small fixes and clarifications --- crates/bevy_asset/src/asset_server.rs | 21 ++++++++++++++------- crates/bevy_asset/src/assets.rs | 5 +++-- crates/bevy_asset/src/diagnostic/mod.rs | 2 +- crates/bevy_asset/src/info.rs | 10 +++++----- crates/bevy_asset/src/loader.rs | 2 +- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 9f44afe94ed7a..c4e204a87fb8c 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -79,25 +79,29 @@ pub struct AssetServerInternal { /// Loads assets from the filesystem on the background. /// /// The asset server is the primary way of loading assets in bevy. It keeps track of the load state -/// of the assets it manages and can even reload them from the filesystem [if you tell it to]! +/// of the assets it manages and can even reload them from the filesystem with +/// [`AssetServer::watch_for_changes`]! /// /// The asset server is a _resource_, so in order to accesss it in a system you need a `Res` /// accessor, like this: /// -/// ```rust -/// use bevy_asset::AssetServer; +/// ```rust,no_run +/// use bevy_asset::{AssetServer, Handle}; /// use bevy_ecs::prelude::{Commands, Res}; - +/// +/// # #[derive(Debug, bevy_reflect::TypeUuid)] +/// # #[uuid = "00000000-0000-0000-0000-000000000000"] +/// # struct Image; +/// /// fn my_system(mut commands: Commands, asset_server: Res) /// { /// // Now you can do whatever you want with the asset server, such as loading an asset: -/// // let asset_handle: Handle = asset_server.load("cool_picture.png"); +/// let asset_handle: Handle = asset_server.load("cool_picture.png"); /// } /// ``` /// /// See the [`asset_loading`] example for more information. /// -/// [if you tell it to]: AssetServer::watch_for_changes /// [`asset_loading`]: https://github.com/bevyengine/bevy/tree/latest/examples/asset/asset_loading.rs pub struct AssetServer { pub(crate) server: Arc, @@ -146,7 +150,10 @@ impl AssetServer { Assets::new(self.server.asset_ref_counter.channel.sender.clone()) } - /// Adds the provided loader as an asset loader for `T` assets. + /// Adds the provided asset loader to the server. + /// + /// If `loader` has one or more supported extensions in conflict with loaders that came before + /// it, it will replace them. pub fn add_loader(&self, loader: T) where T: AssetLoader, diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 8c394a979dfb5..74e8ed87b6d8b 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -14,7 +14,8 @@ use std::fmt::Debug; /// Events that involve assets of type `T`. /// -/// Events sent via the [`Assets`] struct will always be sent with a _Weak_ handle. +/// Events sent via the [`Assets`] struct will always be sent with a _Weak_ handle, because the +/// asset may not exist by the time the event is handled. pub enum AssetEvent { #[allow(missing_docs)] Created { handle: Handle }, @@ -263,7 +264,7 @@ impl Assets { self.assets.len() } - /// Returns true if there are no stored assets. + /// Returns `true` if there are no stored assets. pub fn is_empty(&self) -> bool { self.assets.is_empty() } diff --git a/crates/bevy_asset/src/diagnostic/mod.rs b/crates/bevy_asset/src/diagnostic/mod.rs index b985a00607baa..6bc1ed390c881 100644 --- a/crates/bevy_asset/src/diagnostic/mod.rs +++ b/crates/bevy_asset/src/diagnostic/mod.rs @@ -1,4 +1,4 @@ -//! Diagnostic providers. +//! Diagnostic providers for `bevy_diagnostic`. mod asset_count_diagnostics_plugin; pub use asset_count_diagnostics_plugin::AssetCountDiagnosticsPlugin; diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index b84869f12739a..ec422208bbfba 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -48,15 +48,15 @@ impl SourceInfo { /// The load state of an asset. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum LoadState { - /// The asset has not be loaded. + /// The asset has not been loaded. NotLoaded, - /// The asset in the the process of loading. + /// The asset is in the process of loading. Loading, - /// The asset has loaded and is living inside an [`Assets`](crate::Assets) collection. + /// The asset has been loaded and is living inside an [`Assets`](crate::Assets) collection. Loaded, /// The asset failed to load. Failed, - /// The asset was previously loaded, however all handles were dropped and - /// the asset was removed from the [`Assets`](crate::Assets) collection. + /// The asset was previously loaded, however all handles were dropped and the asset was removed + /// from the [`Assets`](crate::Assets) collection. Unloaded, } diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 84bb981303d87..b3768b1369d76 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -48,7 +48,7 @@ pub trait AssetLoader: Send + Sync + 'static { /// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`]. pub trait Asset: TypeUuid + AssetDynamic {} -/// A untyped version of the [`Asset`] trait. +/// An untyped version of the [`Asset`] trait. pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {} impl_downcast!(AssetDynamic); From acc59b9f840ec6136e2b3afebb2c4236ad1bec52 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 10 Jul 2022 14:52:18 -0300 Subject: [PATCH 28/32] Document io/metadata module --- crates/bevy_asset/src/io/metadata.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/bevy_asset/src/io/metadata.rs b/crates/bevy_asset/src/io/metadata.rs index 67158a1ccfd1c..466c30590b702 100644 --- a/crates/bevy_asset/src/io/metadata.rs +++ b/crates/bevy_asset/src/io/metadata.rs @@ -4,17 +4,21 @@ use std::convert::{TryFrom, TryInto}; #[non_exhaustive] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum FileType { + /// A directory. Directory, + /// A file. File, } impl FileType { + /// Returns `true` if the entry is a directory. #[inline] pub const fn is_dir(&self) -> bool { matches!(self, Self::Directory) } #[inline] + /// Returns `true` if the entry is a file. pub const fn is_file(&self) -> bool { matches!(self, Self::File) } @@ -46,20 +50,24 @@ pub struct Metadata { } impl Metadata { + /// Creates new metadata information. pub fn new(file_type: FileType) -> Self { Self { file_type } } + /// Returns the file type. #[inline] pub const fn file_type(&self) -> FileType { self.file_type } + /// Returns `true` if the entry is a directory. #[inline] pub const fn is_dir(&self) -> bool { self.file_type.is_dir() } + /// Returns `true` if the entry is a file. #[inline] pub const fn is_file(&self) -> bool { self.file_type.is_file() From 4fc237b6c814c33b8ac6a540d5febe4a855beff9 Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 10 Jul 2022 14:56:08 -0300 Subject: [PATCH 29/32] Fix typo, rename Handle::cast, better FileAssetIo docs --- crates/bevy_asset/src/handle.rs | 2 +- crates/bevy_asset/src/io/file_asset_io.rs | 18 ++++++++++-------- examples/ui/font_atlas_debug.rs | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 29eaa9f8bd812..95135a535b060 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -152,7 +152,7 @@ impl Handle { } /// Recasts this handle as a weak handle of an Asset `U`. - pub fn cast(&self) -> Handle { + pub fn cast_weak(&self) -> Handle { let id = if let HandleId::Id(_, id) = self.id { HandleId::Id(U::TYPE_UUID, id) } else { diff --git a/crates/bevy_asset/src/io/file_asset_io.rs b/crates/bevy_asset/src/io/file_asset_io.rs index f33bc91a5b85b..59447dfac5031 100644 --- a/crates/bevy_asset/src/io/file_asset_io.rs +++ b/crates/bevy_asset/src/io/file_asset_io.rs @@ -34,12 +34,12 @@ impl FileAssetIo { /// Creates a new `FileAssetIo` at a path relative to the executable's directory, optionally /// watching for changes. /// - /// See `get_exe_root` below. + /// See `get_base_path` below. pub fn new>(path: P, watch_for_changes: bool) -> Self { let file_asset_io = FileAssetIo { #[cfg(feature = "filesystem_watcher")] filesystem_watcher: Default::default(), - root_path: Self::get_exe_root().join(path.as_ref()), + root_path: Self::get_base_path().join(path.as_ref()), }; if watch_for_changes { #[cfg(any( @@ -57,12 +57,12 @@ impl FileAssetIo { file_asset_io } - /// Returns the path of the parent directory of the appplication's executable. + /// Returns the base path of the assets directory, which is normally the executable's parent + /// directory. /// - /// If the `CARGO_MANIFEST_DIR` environment variable is defined, which is set by cargo when - /// the app is run through it, the root path will be the crate's root instead, or whatever - /// path was passed to that variable. - pub fn get_exe_root() -> PathBuf { + /// If the `CARGO_MANIFEST_DIR` environment variable is set, then its value will be used + /// instead. It's set by cargo when running with `cargo run`. + pub fn get_base_path() -> PathBuf { if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { PathBuf::from(manifest_dir) } else { @@ -76,7 +76,9 @@ impl FileAssetIo { } } - /// Returns the base directory where assets are loaded from. + /// Returns the root directory where assets are loaded from. + /// + /// See `get_base_path`. pub fn root_path(&self) -> &PathBuf { &self.root_path } diff --git a/examples/ui/font_atlas_debug.rs b/examples/ui/font_atlas_debug.rs index 95a2bf396068f..df8bdc96a9c5b 100644 --- a/examples/ui/font_atlas_debug.rs +++ b/examples/ui/font_atlas_debug.rs @@ -36,7 +36,7 @@ fn atlas_render_system( font_atlas_sets: Res>, texture_atlases: Res>, ) { - if let Some(set) = font_atlas_sets.get(&state.handle.cast::()) { + if let Some(set) = font_atlas_sets.get(&state.handle.cast_weak::()) { if let Some((_size, font_atlas)) = set.iter().next() { let x_offset = state.atlas_count as f32; if state.atlas_count == font_atlas.len() as u32 { From 31615acc2a6ba151825fab68bc8f766bef2c05af Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Sun, 10 Jul 2022 15:10:49 -0300 Subject: [PATCH 30/32] Revert breaking changes --- crates/bevy_asset/src/asset_server.rs | 6 ++++-- crates/bevy_asset/src/assets.rs | 2 +- crates/bevy_asset/src/handle.rs | 10 ++-------- crates/bevy_asset/src/info.rs | 17 ++++++++++++----- crates/bevy_asset/src/lib.rs | 6 +++--- crates/bevy_asset/src/loader.rs | 2 +- crates/bevy_text/src/glyph_brush.rs | 2 +- examples/ui/font_atlas_debug.rs | 2 +- 8 files changed, 25 insertions(+), 22 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index c4e204a87fb8c..6bc262499cda4 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -2,7 +2,7 @@ use crate::{ path::{AssetPath, AssetPathId, SourcePathId}, Asset, AssetIo, AssetIoError, AssetLifecycle, AssetLifecycleChannel, AssetLifecycleEvent, AssetLoader, Assets, Handle, HandleId, HandleUntyped, LabelId, LoadContext, LoadState, - RefChange, RefChangeChannel, SourceInfo, + RefChange, RefChangeChannel, SourceInfo, SourceMeta, }; use anyhow::Result; use bevy_ecs::system::{Res, ResMut}; @@ -408,7 +408,9 @@ impl AssetServer { // TODO: queue free old assets source_info.asset_types.clear(); - source_info.meta = Some(load_context.generate_asset_metas()); + source_info.meta = Some(SourceMeta { + assets: load_context.get_asset_metas(), + }); // load asset dependencies and prepare asset type hashmap for (label, loaded_asset) in &mut load_context.labeled_assets { diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 74e8ed87b6d8b..9ba30143dc964 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -327,7 +327,7 @@ impl AddAsset for App { self.insert_resource(assets) .add_system_to_stage(AssetStage::AssetEvents, Assets::::asset_event_system) - .add_system_to_stage(AssetStage::UpdateAssets, update_asset_storage_system::) + .add_system_to_stage(AssetStage::LoadAssets, update_asset_storage_system::) .register_type::>() .add_event::>() } diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 95135a535b060..fa0285b01e1b6 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -152,15 +152,9 @@ impl Handle { } /// Recasts this handle as a weak handle of an Asset `U`. - pub fn cast_weak(&self) -> Handle { - let id = if let HandleId::Id(_, id) = self.id { - HandleId::Id(U::TYPE_UUID, id) - } else { - self.id - }; - + pub fn as_weak(&self) -> Handle { Handle { - id, + id: self.id, handle_type: HandleType::Weak, marker: PhantomData, } diff --git a/crates/bevy_asset/src/info.rs b/crates/bevy_asset/src/info.rs index ec422208bbfba..fc757b70e7eb4 100644 --- a/crates/bevy_asset/src/info.rs +++ b/crates/bevy_asset/src/info.rs @@ -3,6 +3,13 @@ use bevy_utils::{HashMap, HashSet, Uuid}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; +/// Metadata for an asset source. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SourceMeta { + /// A collection of asset metadata. + pub assets: Vec, +} + /// Metadata for an asset. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AssetMeta { @@ -17,8 +24,8 @@ pub struct AssetMeta { /// Information about an asset source, such as its path, load state and asset metadata. #[derive(Clone, Debug)] pub struct SourceInfo { - /// Metadata for each asset in the asset source. - pub meta: Option>, + /// Metadata for the source. + pub meta: Option, /// The path of the source. pub path: PathBuf, /// A map of assets and their type identifiers. @@ -34,9 +41,9 @@ pub struct SourceInfo { impl SourceInfo { /// Returns `true` if all assets tracked by the source were loaded into their asset storages. pub fn is_loaded(&self) -> bool { - self.meta - .as_ref() - .map_or(false, |meta| self.committed_assets.len() == meta.len()) + self.meta.as_ref().map_or(false, |meta| { + self.committed_assets.len() == meta.assets.len() + }) } /// Gets the type identifier for an asset identified by `label_id`. diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 1840484042af2..564d1ae111acf 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -48,7 +48,7 @@ use bevy_ecs::schedule::{StageLabel, SystemStage}; #[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] pub enum AssetStage { /// The stage where asset storages are updated. - UpdateAssets, + LoadAssets, /// The stage where asset events are generated. AssetEvents, } @@ -107,7 +107,7 @@ impl Plugin for AssetPlugin { app.add_stage_before( bevy_app::CoreStage::PreUpdate, - AssetStage::UpdateAssets, + AssetStage::LoadAssets, SystemStage::parallel(), ) .add_stage_after( @@ -125,6 +125,6 @@ impl Plugin for AssetPlugin { feature = "filesystem_watcher", all(not(target_arch = "wasm32"), not(target_os = "android")) ))] - app.add_system_to_stage(AssetStage::UpdateAssets, io::filesystem_watcher_system); + app.add_system_to_stage(AssetStage::LoadAssets, io::filesystem_watcher_system); } } diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index b3768b1369d76..3d420e8f83429 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -177,7 +177,7 @@ impl<'a> LoadContext<'a> { } /// Generates metadata for the assets managed by this load context. - pub fn generate_asset_metas(&self) -> Vec { + pub fn get_asset_metas(&self) -> Vec { let mut asset_metas = Vec::new(); for (label, asset) in &self.labeled_assets { asset_metas.push(AssetMeta { diff --git a/crates/bevy_text/src/glyph_brush.rs b/crates/bevy_text/src/glyph_brush.rs index cc6d9cd7067c8..ca7331901775d 100644 --- a/crates/bevy_text/src/glyph_brush.rs +++ b/crates/bevy_text/src/glyph_brush.rs @@ -96,7 +96,7 @@ impl GlyphBrush { let section_data = sections_data[sg.section_index]; if let Some(outlined_glyph) = section_data.1.font.outline_glyph(glyph) { let bounds = outlined_glyph.px_bounds(); - let handle_font_atlas: Handle = section_data.0.cast(); + let handle_font_atlas: Handle = section_data.0.as_weak(); let font_atlas_set = font_atlas_set_storage .get_or_insert_with(handle_font_atlas, FontAtlasSet::default); diff --git a/examples/ui/font_atlas_debug.rs b/examples/ui/font_atlas_debug.rs index df8bdc96a9c5b..27f04ccd067df 100644 --- a/examples/ui/font_atlas_debug.rs +++ b/examples/ui/font_atlas_debug.rs @@ -36,7 +36,7 @@ fn atlas_render_system( font_atlas_sets: Res>, texture_atlases: Res>, ) { - if let Some(set) = font_atlas_sets.get(&state.handle.cast_weak::()) { + if let Some(set) = font_atlas_sets.get(&state.handle.as_weak::()) { if let Some((_size, font_atlas)) = set.iter().next() { let x_offset = state.atlas_count as f32; if state.atlas_count == font_atlas.len() as u32 { From 92d9ae2453915993543095be6f41c14824ae814a Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Mon, 11 Jul 2022 11:46:03 -0300 Subject: [PATCH 31/32] Put derive below docstring --- crates/bevy_asset/src/asset_server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 6bc262499cda4..56a8fc376b66b 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -75,7 +75,6 @@ pub struct AssetServerInternal { handle_to_path: Arc>>>, } -#[derive(Clone)] /// Loads assets from the filesystem on the background. /// /// The asset server is the primary way of loading assets in bevy. It keeps track of the load state @@ -103,6 +102,7 @@ pub struct AssetServerInternal { /// See the [`asset_loading`] example for more information. /// /// [`asset_loading`]: https://github.com/bevyengine/bevy/tree/latest/examples/asset/asset_loading.rs +#[derive(Clone)] pub struct AssetServer { pub(crate) server: Arc, } From 01b0b235237fd4d9ffbdcf7b25aec231357efcbe Mon Sep 17 00:00:00 2001 From: Mark Nokalt Date: Tue, 12 Jul 2022 12:30:27 -0300 Subject: [PATCH 32/32] Fix typos --- crates/bevy_asset/src/asset_server.rs | 6 +++--- crates/bevy_asset/src/handle.rs | 2 +- crates/bevy_asset/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 56a8fc376b66b..60b01f3a1a417 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -75,7 +75,7 @@ pub struct AssetServerInternal { handle_to_path: Arc>>>, } -/// Loads assets from the filesystem on the background. +/// Loads assets from the filesystem in the background. /// /// The asset server is the primary way of loading assets in bevy. It keeps track of the load state /// of the assets it manages and can even reload them from the filesystem with @@ -113,7 +113,7 @@ impl AssetServer { Self::with_boxed_io(Box::new(source_io)) } - /// Creates a new asset server with a pointer to an asset I/O. + /// Creates a new asset server with a boxed asset I/O. pub fn with_boxed_io(asset_io: Box) -> Self { AssetServer { server: Arc::new(AssetServerInternal { @@ -182,7 +182,7 @@ impl AssetServer { Handle::strong(id.into(), sender) } - /// Gets an untyped, strong handle for an asset with the provided id. + /// Gets an untyped strong handle for an asset with the provided id. pub fn get_handle_untyped>(&self, id: I) -> HandleUntyped { let sender = self.server.asset_ref_counter.channel.sender.clone(); HandleUntyped::strong(id.into(), sender) diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index fa0285b01e1b6..d5296b389da02 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -344,7 +344,7 @@ impl HandleUntyped { Self::weak(self.id) } - /// Returns `true` if this a weak handle. + /// Returns `true` if this is a weak handle. pub fn is_weak(&self) -> bool { matches!(self.handle_type, HandleType::Weak) } diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 564d1ae111acf..f70bc5c1f4fd4 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -1,7 +1,7 @@ //! Built-in plugin for asset support. //! //! This plugin allows a bevy app to work with assets from the filesystem (or [another source]), -//! providing an [asset server] for loading an processing [`Asset`]s and storing them in an +//! providing an [asset server] for loading and processing [`Asset`]s and storing them in an //! [asset storage] to be accessed by systems. //! //! [another source]: trait.AssetIo.html