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

Reuse and hot reload folder handles #10210

Merged
merged 5 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 0 additions & 17 deletions crates/bevy_asset/src/server/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,6 @@ impl std::fmt::Debug for AssetInfos {
}

impl AssetInfos {
pub(crate) fn create_loading_handle<A: Asset>(&mut self) -> Handle<A> {
unwrap_with_context(
Self::create_handle_internal(
&mut self.infos,
&self.handle_providers,
&mut self.living_labeled_assets,
self.watching_for_changes,
TypeId::of::<A>(),
None,
None,
true,
),
std::any::type_name::<A>(),
)
.typed_debug_checked()
}

pub(crate) fn create_loading_handle_untyped(
&mut self,
type_id: TypeId,
Expand Down
55 changes: 48 additions & 7 deletions crates/bevy_asset/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crossbeam_channel::{Receiver, Sender};
use futures_lite::StreamExt;
use info::*;
use parking_lot::RwLock;
use std::path::PathBuf;
use std::{any::TypeId, path::Path, sync::Arc};
use thiserror::Error;

Expand Down Expand Up @@ -460,15 +461,33 @@ impl AssetServer {
/// Loads all assets from the specified folder recursively. The [`LoadedFolder`] asset (when it loads) will
/// contain handles to all assets in the folder. You can wait for all assets to load by checking the [`LoadedFolder`]'s
/// [`RecursiveDependencyLoadState`].
///
/// Loading the same folder multiple times will return the same handle. If the `file_watcher`
/// feature is enabled, [`LoadedFolder`] handles will reload when a file in the folder is
/// removed, added or moved. This includes files in subdirectories and moving, adding,
/// or removing complete subdirectories.
#[must_use = "not using the returned strong handle may result in the unexpected release of the assets"]
pub fn load_folder<'a>(&self, path: impl Into<AssetPath<'a>>) -> Handle<LoadedFolder> {
let handle = {
let mut infos = self.data.infos.write();
infos.create_loading_handle::<LoadedFolder>()
};
let id = handle.id().untyped();
let path = path.into().into_owned();
let (handle, should_load) = self
.data
.infos
.write()
.get_or_create_path_handle::<LoadedFolder>(
path.clone(),
HandleLoadingMode::Request,
None,
);
if !should_load {
return handle;
}
let id = handle.id().untyped();
self.load_folder_internal(id, path);

handle
}

pub(crate) fn load_folder_internal(&self, id: UntypedAssetId, path: AssetPath) {
fn load_folder<'a>(
source: AssetSourceId<'static>,
path: &'a Path,
Expand Down Expand Up @@ -503,6 +522,7 @@ impl AssetServer {
})
}

let path = path.into_owned();
let server = self.clone();
IoTaskPool::get()
.spawn(async move {
Expand Down Expand Up @@ -542,8 +562,6 @@ impl AssetServer {
}
})
.detach();

handle
}

fn send_asset_event(&self, event: InternalAssetEvent) {
Expand Down Expand Up @@ -795,6 +813,19 @@ pub fn handle_internal_asset_events(world: &mut World) {
}
}

let reload_parent_folders = |path: PathBuf, source: &AssetSourceId<'static>| {
let mut current_folder = path;
while let Some(parent) = current_folder.parent() {
current_folder = parent.to_path_buf();
let parent_asset_path =
AssetPath::from(current_folder.clone()).with_source(source.clone());
if let Some(folder_handle) = infos.get_path_handle(parent_asset_path.clone()) {
info!("Reloading folder {parent_asset_path} because the content has changed");
server.load_folder_internal(folder_handle.id(), parent_asset_path);
}
}
};

let mut paths_to_reload = HashSet::new();
let mut handle_event = |source: AssetSourceId<'static>, event: AssetSourceEvent| {
match event {
Expand All @@ -805,6 +836,16 @@ pub fn handle_internal_asset_events(world: &mut World) {
queue_ancestors(&path, &infos, &mut paths_to_reload);
paths_to_reload.insert(path);
}
AssetSourceEvent::RenamedFolder { old, new } => {
reload_parent_folders(old, &source);
reload_parent_folders(new, &source);
}
AssetSourceEvent::AddedAsset(path)
| AssetSourceEvent::RemovedAsset(path)
| AssetSourceEvent::RemovedFolder(path)
| AssetSourceEvent::AddedFolder(path) => {
reload_parent_folders(path, &source);
}
_ => {}
}
};
Expand Down