From 10e85fce26cc956835239873734a6f22ae18731f Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Mon, 11 Mar 2024 23:45:41 +0100 Subject: [PATCH] feat(gltf_blueprints): added same kind of logic to the loading of material files * also made a more generic variant of the BlueprintAssetLoadTracker & swapped it out * minor tweaks --- crates/bevy_gltf_blueprints/src/lib.rs | 2 +- crates/bevy_gltf_blueprints/src/materials.rs | 130 ++++++++++++++++-- .../src/spawn_from_blueprints.rs | 35 +++-- 3 files changed, 139 insertions(+), 28 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index 0b8e2f6..266289a 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -151,7 +151,7 @@ impl Plugin for BlueprintsPlugin { compute_scene_aabbs.run_if(aabbs_enabled), apply_deferred.run_if(aabbs_enabled), apply_deferred, - materials_inject.run_if(materials_library_enabled), + (materials_inject, check_for_material_loaded, materials_inject2).chain().run_if(materials_library_enabled), ) .chain() .in_set(GltfBlueprintsSet::Spawn), diff --git a/crates/bevy_gltf_blueprints/src/materials.rs b/crates/bevy_gltf_blueprints/src/materials.rs index 5f0140a..6e615f1 100644 --- a/crates/bevy_gltf_blueprints/src/materials.rs +++ b/crates/bevy_gltf_blueprints/src/materials.rs @@ -1,22 +1,19 @@ use std::path::Path; use bevy::{ - asset::{AssetServer, Assets, Handle}, + asset::{AssetId, AssetServer, Assets, Handle}, ecs::{ - component::Component, - query::{Added, With}, - reflect::ReflectComponent, - system::{Commands, Query, Res, ResMut}, + component::Component, entity::Entity, query::{Added, With}, reflect::ReflectComponent, system::{Commands, Query, Res, ResMut} }, gltf::Gltf, hierarchy::{Children, Parent}, - log::debug, + log::{debug, info}, pbr::StandardMaterial, reflect::Reflect, render::mesh::Mesh, }; -use crate::BluePrintsConfig; +use crate::{AssetLoadTracker, AssetsToLoad, BluePrintsConfig}; #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] @@ -26,10 +23,110 @@ pub struct MaterialInfo { pub source: String, } +/// flag component +#[derive(Component)] +pub(crate) struct BlueprintMaterialAssetsLoaded; +/// flag component +#[derive(Component)] +pub(crate) struct BlueprintMaterialAssetsNotLoaded; + + + /// system that injects / replaces materials from material library pub(crate) fn materials_inject( + blueprints_config: ResMut, + material_infos: Query<(Entity, &MaterialInfo), Added>, + asset_server: Res, + mut commands: Commands, +) { + for (entity, material_info) in material_infos.iter() { + let model_file_name = format!( + "{}_materials_library.{}", + &material_info.source, &blueprints_config.format + ); + let materials_path = Path::new(&blueprints_config.material_library_folder) + .join(Path::new(model_file_name.as_str())); + let material_name = &material_info.name; + let material_full_path = materials_path.to_str().unwrap().to_string() + "#" + material_name; // TODO: yikes, cleanup + + if blueprints_config + .material_library_cache + .contains_key(&material_full_path) + { + debug!("material is cached, retrieving"); + blueprints_config + .material_library_cache + .get(&material_full_path) + .expect("we should have the material available"); + commands + .entity(entity) + .insert(BlueprintMaterialAssetsLoaded); + + } else { + let material_file_handle: Handle = asset_server.load(materials_path.clone()); + let material_file_id = material_file_handle.id(); + println!("loading material {} {}", material_full_path, material_file_id); + let mut asset_infos:Vec> = vec![]; + + asset_infos.push(AssetLoadTracker { + name: material_full_path, + id: material_file_id, + loaded: false, + handle: material_file_handle.clone() + }); + commands + .entity(entity) + .insert(AssetsToLoad{ + all_loaded: false, + asset_infos: asset_infos, + progress: 0.0 + //..Default::default() + }) + .insert(BlueprintMaterialAssetsNotLoaded); + /**/ + } + } +} + +// TODO, merge with check_for_loaded, make generic ? +pub(crate) fn check_for_material_loaded( + mut blueprint_assets_to_load: Query<(Entity, &mut AssetsToLoad),With>, + asset_server: Res, + mut commands: Commands, +){ + for (entity, mut assets_to_load) in blueprint_assets_to_load.iter_mut(){ + let mut all_loaded = true; + let mut loaded_amount = 0; + let total = assets_to_load.asset_infos.len(); + for tracker in assets_to_load.asset_infos.iter_mut(){ + let asset_id = tracker.id; + let loaded = asset_server.is_loaded_with_dependencies(asset_id); + tracker.loaded = loaded; + if loaded { + println!("loaded {} {}", tracker.name, tracker.id); + loaded_amount += 1; + }else{ + all_loaded = false; + } + } + let progress:f32 = loaded_amount as f32 / total as f32; + println!("progress (materials): {}",progress); + assets_to_load.progress = progress; + + if all_loaded { + assets_to_load.all_loaded = true; + commands.entity(entity) + .insert(BlueprintMaterialAssetsLoaded) + .remove::(); + } + } +} + + +/// system that injects / replaces materials from material library +pub(crate) fn materials_inject2( mut blueprints_config: ResMut, - material_infos: Query<(&MaterialInfo, &Children), Added>, + material_infos: Query<(&MaterialInfo, &Children, ), (Added, With)>, with_materials_and_meshes: Query< (), ( @@ -38,12 +135,13 @@ pub(crate) fn materials_inject( With>, ), >, - models: Res>, - + assets_gltf: Res>, asset_server: Res, + mut commands: Commands, ) { for (material_info, children) in material_infos.iter() { + println!("here"); let model_file_name = format!( "{}_materials_library.{}", &material_info.source, &blueprints_config.format @@ -59,16 +157,18 @@ pub(crate) fn materials_inject( .material_library_cache .contains_key(&material_full_path) { - debug!("material is cached, retrieving"); + info!("material is cached, retrieving"); let material = blueprints_config .material_library_cache .get(&material_full_path) .expect("we should have the material available"); material_found = Some(material); - } else { - let my_gltf: Handle = asset_server.load(materials_path.clone()); - let mat_gltf = models - .get(my_gltf.id()) + }else { + let model_handle: Handle = asset_server.load(materials_path.clone());// FIXME: kinda weird now + println!("loading material {:?} {}", materials_path, model_handle.id()); + + let mat_gltf = assets_gltf + .get(model_handle.id()) .expect("material should have been preloaded"); if mat_gltf.named_materials.contains_key(material_name) { let material = mat_gltf diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index f896723..a29ccb3 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -51,7 +51,6 @@ pub(crate) struct OriginalChildren(pub Vec); #[reflect(Component)] pub struct BlueprintsList(pub HashMap>); - #[derive(Reflect, Default, Debug)] pub(crate) struct BlueprintLoadTracker{ pub name: String, @@ -66,6 +65,21 @@ pub(crate) struct BlueprintAssetsToLoad{ pub progress: f32 } +#[derive(Default, Debug)] +pub(crate) struct AssetLoadTracker{ + pub name: String, + pub id: AssetId, + pub loaded: bool, + pub handle: Handle +} +#[derive(Component, Default, Debug)] +pub(crate) struct AssetsToLoad{ + pub all_loaded: bool, + pub asset_infos: Vec>, + pub progress: f32 +} + + /// flag component #[derive(Component)] pub(crate) struct BlueprintAssetsLoaded; @@ -83,10 +97,7 @@ pub(crate) fn spawn_from_blueprints( Option<&Parent>, Option<&Library>, Option<&Name>, - Option<&BlueprintsList>, - // Option<&BlueprintAssetsPreloaded> - ), (Added, Added, Without), >, @@ -114,8 +125,8 @@ pub(crate) fn spawn_from_blueprints( if blueprints_list.is_some() { let blueprints_list = blueprints_list.unwrap(); // println!("blueprints list {:?}", blueprints_list.0.keys()); + let mut asset_infos:Vec> = vec![]; - let mut asset_infos:Vec = vec![]; for (blueprint_name, _) in blueprints_list.0.iter() { /*if blueprint_name == what { println!("WHOLY MOLLY !") @@ -134,22 +145,23 @@ pub(crate) fn spawn_from_blueprints( let model_id = model_handle.id(); let loaded = asset_server.is_loaded_with_dependencies(model_id); if !loaded { - asset_infos.push(BlueprintLoadTracker{ + asset_infos.push(AssetLoadTracker { name: model_path.to_string_lossy().into(), id: model_id, loaded: false, handle: model_handle.clone() - }); + }) } } // if not all assets are already loaded, inject a component to signal that we need them to be loaded if asset_infos.len() > 0 { commands .entity(entity) - .insert(BlueprintAssetsToLoad{ + .insert(AssetsToLoad{ all_loaded: false, asset_infos: asset_infos, - ..Default::default() + progress: 0.0 + //..Default::default() }) .insert(BlueprintAssetsNotLoaded); }else { @@ -163,7 +175,7 @@ pub(crate) fn spawn_from_blueprints( pub(crate) fn check_for_loaded( - mut blueprint_assets_to_load: Query<(Entity, &mut BlueprintAssetsToLoad),With>, + mut blueprint_assets_to_load: Query<(Entity, &mut AssetsToLoad), With>, asset_server: Res, mut commands: Commands, ){ @@ -218,7 +230,6 @@ pub(crate) fn actually_spawn_stuff( children: Query<&Children>, ){ - for ( entity, blupeprint_name, @@ -244,7 +255,7 @@ pub(crate) fn actually_spawn_stuff( let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str())); info!("attempting to spawn {:?}", model_path); - let model_handle: Handle = asset_server.load(model_path); + let model_handle: Handle = asset_server.load(model_path);// FIXME: kinda weird now let gltf = assets_gltf .get(&model_handle)