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

Fix GLTF scene dependencies and make full scene renders predictable #10745

Merged
merged 4 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ impl<'a> LoadContext<'a> {

/// This will add the given `asset` as a "labeled [`Asset`]" with the `label` label.
///
/// Warning: this will not assign dependencies to the given `asset`. If adding an asset
cart marked this conversation as resolved.
Show resolved Hide resolved
/// with dependencies generated from calls such as [`LoadContext::load`], use
/// [`LoadContext::labeled_asset_scope`] or [`LoadContext::begin_labeled_asset`] to generate a
/// new [`LoadContext`] to track the dependencies for the labeled asset.
///
/// See [`AssetPath`] for more on labeled assets.
pub fn add_labeled_asset<A: Asset>(&mut self, label: String, asset: A) -> Handle<A> {
self.labeled_asset_scope(label, |_| asset)
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_asset/src/server/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ impl AssetInfos {
self.infos.get(&id)
}

pub(crate) fn contains_key(&self, id: UntypedAssetId) -> bool {
self.infos.contains_key(&id)
}

pub(crate) fn get_mut(&mut self, id: UntypedAssetId) -> Option<&mut AssetInfo> {
self.infos.get_mut(&id)
}
Expand Down
37 changes: 25 additions & 12 deletions crates/bevy_asset/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ impl AssetServer {
.load_with_meta_loader_and_reader(&base_path, meta, &*loader, &mut *reader, true, false)
.await
{
Ok(mut loaded_asset) => {
Ok(loaded_asset) => {
let final_handle = if let Some(label) = path.label_cow() {
match loaded_asset.labeled_assets.get(&label) {
Some(labeled_asset) => labeled_asset.handle.clone(),
Expand All @@ -472,17 +472,7 @@ impl AssetServer {
handle.unwrap()
};

for (_, labeled_asset) in loaded_asset.labeled_assets.drain() {
self.send_asset_event(InternalAssetEvent::Loaded {
id: labeled_asset.handle.id(),
loaded_asset: labeled_asset.asset,
});
}

self.send_asset_event(InternalAssetEvent::Loaded {
id: base_handle.id(),
loaded_asset,
});
self.send_loaded_asset(base_handle.id(), loaded_asset);
Ok(final_handle)
}
Err(err) => {
Expand All @@ -494,6 +484,16 @@ impl AssetServer {
}
}

/// Sends a load event for the given `loaded_asset` and does the same recursively for all
/// labeled assets.
fn send_loaded_asset(&self, id: UntypedAssetId, mut loaded_asset: ErasedLoadedAsset) {
for (_, labeled_asset) in loaded_asset.labeled_assets.drain() {
self.send_loaded_asset(labeled_asset.handle.id(), labeled_asset.asset);
}

self.send_asset_event(InternalAssetEvent::Loaded { id, loaded_asset });
}

/// Kicks off a reload of the asset stored at the given path. This will only reload the asset if it currently loaded.
pub fn reload<'a>(&self, path: impl Into<AssetPath<'a>>) {
let server = self.clone();
Expand Down Expand Up @@ -711,6 +711,13 @@ impl AssetServer {
.unwrap_or(RecursiveDependencyLoadState::NotLoaded)
}

/// Returns true if the asset and all of its dependencies (recursive) have been loaded.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth linking to this from the standard is_loaded method.

pub fn is_loaded_with_dependencies(&self, id: impl Into<UntypedAssetId>) -> bool {
let id = id.into();
self.load_state(id) == LoadState::Loaded
&& self.recursive_dependency_load_state(id) == RecursiveDependencyLoadState::Loaded
}

/// Returns an active handle for the given path, if the asset at the given path has already started loading,
/// or is still "alive".
pub fn get_handle<'a, A: Asset>(&self, path: impl Into<AssetPath<'a>>) -> Option<Handle<A>> {
Expand All @@ -726,6 +733,12 @@ impl AssetServer {
self.data.infos.read().get_id_handle(id)
}

/// Returns `true` if the given `id` corresponds to an asset that is managed by this [`AssetServer`].
/// Otherwise, returns false.
pub fn is_managed(&self, id: impl Into<UntypedAssetId>) -> bool {
self.data.infos.read().contains_key(id.into())
}

/// Returns an active untyped handle for the given path, if the asset at the given path has already started loading,
/// or is still "alive".
pub fn get_handle_untyped<'a>(&self, path: impl Into<AssetPath<'a>>) -> Option<UntypedHandle> {
Expand Down
13 changes: 9 additions & 4 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ async fn load_gltf<'a, 'b, 'c>(
let mut world = World::default();
let mut node_index_to_entity_map = HashMap::new();
let mut entity_to_skin_index_map = HashMap::new();

let mut scene_load_context = load_context.begin_labeled_asset();
world
.spawn(SpatialBundle::INHERITED_IDENTITY)
.with_children(|parent| {
Expand All @@ -554,6 +554,7 @@ async fn load_gltf<'a, 'b, 'c>(
&node,
parent,
load_context,
&mut scene_load_context,
&mut node_index_to_entity_map,
&mut entity_to_skin_index_map,
&mut active_camera_found,
Expand Down Expand Up @@ -606,8 +607,8 @@ async fn load_gltf<'a, 'b, 'c>(
joints: joint_entities,
});
}

let scene_handle = load_context.add_labeled_asset(scene_label(&scene), Scene::new(world));
let loaded_scene = scene_load_context.finish(Scene::new(world), None);
let scene_handle = load_context.add_loaded_labeled_asset(scene_label(&scene), loaded_scene);

if let Some(name) = scene.name() {
named_scenes.insert(name.to_string(), scene_handle.clone());
Expand Down Expand Up @@ -856,6 +857,7 @@ fn load_material(
fn load_node(
gltf_node: &gltf::Node,
world_builder: &mut WorldChildBuilder,
root_load_context: &LoadContext,
load_context: &mut LoadContext,
node_index_to_entity_map: &mut HashMap<usize, Entity>,
entity_to_skin_index_map: &mut HashMap<Entity, usize>,
Expand Down Expand Up @@ -942,7 +944,9 @@ fn load_node(
// added when iterating over all the gltf materials (since the default material is
// not explicitly listed in the gltf).
// It also ensures an inverted scale copy is instantiated if required.
if !load_context.has_labeled_asset(&material_label) {
if !root_load_context.has_labeled_asset(&material_label)
&& !load_context.has_labeled_asset(&material_label)
{
load_material(&material, load_context, is_scale_inverted);
}

Expand Down Expand Up @@ -1074,6 +1078,7 @@ fn load_node(
if let Err(err) = load_node(
&child,
parent,
root_load_context,
load_context,
node_index_to_entity_map,
entity_to_skin_index_map,
Expand Down
Loading