Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - docs: Full documentation for bevy_asset #3536

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7bce388
Document root, handle, info and path
manokara Jan 3, 2022
4d5a87b
Fix a couple mistakes
manokara Jan 5, 2022
de375df
Use monospaced links, fix typos
manokara Jan 6, 2022
9ab5acf
Remove SourceMeta
manokara Jan 6, 2022
be09fc0
Rename Handle::as_weak() to cast()
manokara Jan 6, 2022
7ad845b
Rename LoadContext::get_asset_metas() to generate_asset_metas()
manokara Jan 6, 2022
098b9bb
Rename Handle::as_weak() in examples/ui/font_atlas_debug.rs
manokara Jan 6, 2022
12ed78f
Document loader module
manokara Jan 6, 2022
0f0cbba
Document io and filesytem_watcher modules
manokara Jan 7, 2022
dc057cb
Fix typo in loader.rs
manokara Jan 7, 2022
ebe8b95
Finish assets module
manokara Jan 9, 2022
8ecfd5d
Fix typo in io/mod.rs
manokara Jan 9, 2022
4ced5e3
Document asset_server module
manokara Jan 10, 2022
0b8e486
Document diagnostic module
manokara Jan 10, 2022
3eb0afb
Review and crate-level documentation
manokara Jan 11, 2022
e61305e
Add #[warn(missing_docs)] lint
manokara Jan 11, 2022
31e9a71
Update type uuid when recasting a handle
manokara Jan 11, 2022
5359424
Run cargo fmt
manokara Jan 11, 2022
79fe66b
Enhancements and fixes
manokara Jan 12, 2022
6415c76
Rename AssetStage::LoadAssets to UpdateAssets
manokara Jan 13, 2022
9fae232
Mention multiple extensions support
manokara Jan 13, 2022
c9eb8ae
Document debug_asset_server
manokara Mar 20, 2022
5534af5
Fix typo and reflow docstring in AssetServer
manokara Mar 20, 2022
df1f864
Document remaining methods and clarify some of FileAssetIo
manokara Mar 20, 2022
482d7a0
Fix unresolved doc link
manokara Mar 21, 2022
0979c1a
Fix doc tests
manokara Mar 21, 2022
c922e39
Small fixes and clarifications
manokara Mar 22, 2022
acc59b9
Document io/metadata module
manokara Jul 10, 2022
4fc237b
Fix typo, rename Handle::cast, better FileAssetIo docs
manokara Jul 10, 2022
31615ac
Revert breaking changes
manokara Jul 10, 2022
92d9ae2
Put derive below docstring
manokara Jul 11, 2022
01b0b23
Fix typos
manokara Jul 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 85 additions & 7 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,31 @@ 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<String> },
MissingAssetLoader {
/// 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<String>,
},

/// 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),
}
Expand All @@ -48,6 +62,9 @@ pub(crate) struct AssetRefCounter {
pub(crate) mark_unused_assets: Arc<Mutex<Vec<HandleId>>>,
}

/// 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<dyn AssetIo>,
pub(crate) asset_ref_counter: AssetRefCounter,
Expand All @@ -58,17 +75,45 @@ pub struct AssetServerInternal {
handle_to_path: Arc<RwLock<HashMap<HandleId, AssetPath<'static>>>>,
}

/// Loads assets from the filesystem on background threads
/// 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
/// [`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,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<AssetServer>)
/// {
/// // Now you can do whatever you want with the asset server, such as loading an asset:
/// let asset_handle: Handle<Image> = asset_server.load("cool_picture.png");
/// }
/// ```
///
/// 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<AssetServerInternal>,
}

impl AssetServer {
/// Creates a new asset server with the provided asset I/O.
pub fn new<T: AssetIo>(source_io: T) -> Self {
Self::with_boxed_io(Box::new(source_io))
}

/// Creates a new asset server with a boxed asset I/O.
pub fn with_boxed_io(asset_io: Box<dyn AssetIo>) -> Self {
AssetServer {
server: Arc::new(AssetServerInternal {
Expand All @@ -83,6 +128,7 @@ impl AssetServer {
}
}

/// Returns the associated asset I/O.
pub fn asset_io(&self) -> &dyn AssetIo {
&*self.server.asset_io
}
Expand All @@ -104,6 +150,10 @@ impl AssetServer {
Assets::new(self.server.asset_ref_counter.channel.sender.clone())
}

/// 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<T>(&self, loader: T)
where
T: AssetLoader,
Expand All @@ -126,11 +176,13 @@ impl AssetServer {
Ok(())
}

/// Gets a strong handle for an asset with the provided id.
pub fn get_handle<T: Asset, I: Into<HandleId>>(&self, id: I) -> Handle<T> {
let sender = self.server.asset_ref_counter.channel.sender.clone();
Handle::strong(id.into(), sender)
}

/// Gets an untyped strong handle for an asset with the provided id.
pub fn get_handle_untyped<I: Into<HandleId>>(&self, id: I) -> HandleUntyped {
let sender = self.server.asset_ref_counter.channel.sender.clone();
HandleUntyped::strong(id.into(), sender)
Expand Down Expand Up @@ -179,6 +231,7 @@ impl AssetServer {
})
}

/// Gets the source path of an asset from the provided handle.
pub fn get_handle_path<H: Into<HandleId>>(&self, handle: H) -> Option<AssetPath<'_>> {
self.server
.handle_to_path
Expand All @@ -187,6 +240,7 @@ impl AssetServer {
.cloned()
}

/// Gets the load state of an asset from the provided handle.
pub fn get_load_state<H: Into<HandleId>>(&self, handle: H) -> LoadState {
match handle.into() {
HandleId::AssetPathId(id) => {
Expand All @@ -199,6 +253,10 @@ impl AssetServer {
}
}

/// Gets the overall load state of a group of assets from the provided handles.
manokara marked this conversation as resolved.
Show resolved Hide resolved
///
/// 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<Item = HandleId>) -> LoadState {
let mut load_state = LoadState::Loaded;
for handle_id in handles {
Expand All @@ -219,11 +277,14 @@ 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"`. 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
/// By default the `ROOT` is the directory of the Application, but this can be overridden by
/// setting the `"CARGO_MANIFEST_DIR"` environment variable
/// (see <https://doc.rust-lang.org/cargo/reference/environment-variables.html>)
/// to another directory. When the application is run through Cargo, then
Expand All @@ -235,7 +296,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<AssetPath<'a>>>(&self, path: P) -> Handle<T> {
self.load_untyped(path).typed()
Expand Down Expand Up @@ -365,6 +429,9 @@ impl AssetServer {
Ok(asset_path_id)
}

/// Queues the [`Asset`] at the provided path for loading and returns an untyped handle.
///
/// 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<AssetPath<'a>>>(&self, path: P) -> HandleUntyped {
let handle_id = self.load_untracked(path.into(), false);
Expand Down Expand Up @@ -400,6 +467,14 @@ impl AssetServer {
asset_path.into()
}

/// 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<P: AsRef<Path>>(
&self,
Expand Down Expand Up @@ -429,6 +504,7 @@ impl AssetServer {
Ok(handles)
}

/// 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();

Expand All @@ -455,6 +531,7 @@ impl AssetServer {
}
}

/// Iterates through asset references and marks assets with no active handles as unused.
manokara marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand Down Expand Up @@ -559,6 +636,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<AssetServer>) {
free_unused_assets_system_impl(&asset_server);
}
Expand Down
Loading