Compare commits

..

2 Commits

Author SHA1 Message Date
Mark Moissette 1b8c3de6a9
Merge 10e85fce26 into 1353e14802 2024-03-11 22:47:29 +00:00
kaosat.dev 10e85fce26 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
2024-03-11 23:45:41 +01:00
3 changed files with 139 additions and 28 deletions

View File

@ -151,7 +151,7 @@ impl Plugin for BlueprintsPlugin {
compute_scene_aabbs.run_if(aabbs_enabled), compute_scene_aabbs.run_if(aabbs_enabled),
apply_deferred.run_if(aabbs_enabled), apply_deferred.run_if(aabbs_enabled),
apply_deferred, apply_deferred,
materials_inject.run_if(materials_library_enabled), (materials_inject, check_for_material_loaded, materials_inject2).chain().run_if(materials_library_enabled),
) )
.chain() .chain()
.in_set(GltfBlueprintsSet::Spawn), .in_set(GltfBlueprintsSet::Spawn),

View File

@ -1,22 +1,19 @@
use std::path::Path; use std::path::Path;
use bevy::{ use bevy::{
asset::{AssetServer, Assets, Handle}, asset::{AssetId, AssetServer, Assets, Handle},
ecs::{ ecs::{
component::Component, component::Component, entity::Entity, query::{Added, With}, reflect::ReflectComponent, system::{Commands, Query, Res, ResMut}
query::{Added, With},
reflect::ReflectComponent,
system::{Commands, Query, Res, ResMut},
}, },
gltf::Gltf, gltf::Gltf,
hierarchy::{Children, Parent}, hierarchy::{Children, Parent},
log::debug, log::{debug, info},
pbr::StandardMaterial, pbr::StandardMaterial,
reflect::Reflect, reflect::Reflect,
render::mesh::Mesh, render::mesh::Mesh,
}; };
use crate::BluePrintsConfig; use crate::{AssetLoadTracker, AssetsToLoad, BluePrintsConfig};
#[derive(Component, Reflect, Default, Debug)] #[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)] #[reflect(Component)]
@ -26,10 +23,110 @@ pub struct MaterialInfo {
pub source: String, 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 /// system that injects / replaces materials from material library
pub(crate) fn materials_inject( pub(crate) fn materials_inject(
blueprints_config: ResMut<BluePrintsConfig>,
material_infos: Query<(Entity, &MaterialInfo), Added<MaterialInfo>>,
asset_server: Res<AssetServer>,
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<Gltf> = 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<AssetLoadTracker<Gltf>> = 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<Gltf>),With<BlueprintMaterialAssetsNotLoaded>>,
asset_server: Res<AssetServer>,
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::<BlueprintMaterialAssetsNotLoaded>();
}
}
}
/// system that injects / replaces materials from material library
pub(crate) fn materials_inject2(
mut blueprints_config: ResMut<BluePrintsConfig>, mut blueprints_config: ResMut<BluePrintsConfig>,
material_infos: Query<(&MaterialInfo, &Children), Added<MaterialInfo>>, material_infos: Query<(&MaterialInfo, &Children, ), (Added<BlueprintMaterialAssetsLoaded>, With<BlueprintMaterialAssetsLoaded>)>,
with_materials_and_meshes: Query< with_materials_and_meshes: Query<
(), (),
( (
@ -38,12 +135,13 @@ pub(crate) fn materials_inject(
With<Handle<Mesh>>, With<Handle<Mesh>>,
), ),
>, >,
models: Res<Assets<bevy::gltf::Gltf>>, assets_gltf: Res<Assets<Gltf>>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut commands: Commands, mut commands: Commands,
) { ) {
for (material_info, children) in material_infos.iter() { for (material_info, children) in material_infos.iter() {
println!("here");
let model_file_name = format!( let model_file_name = format!(
"{}_materials_library.{}", "{}_materials_library.{}",
&material_info.source, &blueprints_config.format &material_info.source, &blueprints_config.format
@ -59,16 +157,18 @@ pub(crate) fn materials_inject(
.material_library_cache .material_library_cache
.contains_key(&material_full_path) .contains_key(&material_full_path)
{ {
debug!("material is cached, retrieving"); info!("material is cached, retrieving");
let material = blueprints_config let material = blueprints_config
.material_library_cache .material_library_cache
.get(&material_full_path) .get(&material_full_path)
.expect("we should have the material available"); .expect("we should have the material available");
material_found = Some(material); material_found = Some(material);
} else { }else {
let my_gltf: Handle<Gltf> = asset_server.load(materials_path.clone()); let model_handle: Handle<Gltf> = asset_server.load(materials_path.clone());// FIXME: kinda weird now
let mat_gltf = models println!("loading material {:?} {}", materials_path, model_handle.id());
.get(my_gltf.id())
let mat_gltf = assets_gltf
.get(model_handle.id())
.expect("material should have been preloaded"); .expect("material should have been preloaded");
if mat_gltf.named_materials.contains_key(material_name) { if mat_gltf.named_materials.contains_key(material_name) {
let material = mat_gltf let material = mat_gltf

View File

@ -51,7 +51,6 @@ pub(crate) struct OriginalChildren(pub Vec<Entity>);
#[reflect(Component)] #[reflect(Component)]
pub struct BlueprintsList(pub HashMap<String,Vec<String>>); pub struct BlueprintsList(pub HashMap<String,Vec<String>>);
#[derive(Reflect, Default, Debug)] #[derive(Reflect, Default, Debug)]
pub(crate) struct BlueprintLoadTracker{ pub(crate) struct BlueprintLoadTracker{
pub name: String, pub name: String,
@ -66,6 +65,21 @@ pub(crate) struct BlueprintAssetsToLoad{
pub progress: f32 pub progress: f32
} }
#[derive(Default, Debug)]
pub(crate) struct AssetLoadTracker<T:bevy::prelude::Asset>{
pub name: String,
pub id: AssetId<T>,
pub loaded: bool,
pub handle: Handle<T>
}
#[derive(Component, Default, Debug)]
pub(crate) struct AssetsToLoad<T:bevy::prelude::Asset>{
pub all_loaded: bool,
pub asset_infos: Vec<AssetLoadTracker<T>>,
pub progress: f32
}
/// flag component /// flag component
#[derive(Component)] #[derive(Component)]
pub(crate) struct BlueprintAssetsLoaded; pub(crate) struct BlueprintAssetsLoaded;
@ -83,10 +97,7 @@ pub(crate) fn spawn_from_blueprints(
Option<&Parent>, Option<&Parent>,
Option<&Library>, Option<&Library>,
Option<&Name>, Option<&Name>,
Option<&BlueprintsList>, Option<&BlueprintsList>,
// Option<&BlueprintAssetsPreloaded>
), ),
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>), (Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
>, >,
@ -114,8 +125,8 @@ pub(crate) fn spawn_from_blueprints(
if blueprints_list.is_some() { if blueprints_list.is_some() {
let blueprints_list = blueprints_list.unwrap(); let blueprints_list = blueprints_list.unwrap();
// println!("blueprints list {:?}", blueprints_list.0.keys()); // println!("blueprints list {:?}", blueprints_list.0.keys());
let mut asset_infos:Vec<AssetLoadTracker<Gltf>> = vec![];
let mut asset_infos:Vec<BlueprintLoadTracker> = vec![];
for (blueprint_name, _) in blueprints_list.0.iter() { for (blueprint_name, _) in blueprints_list.0.iter() {
/*if blueprint_name == what { /*if blueprint_name == what {
println!("WHOLY MOLLY !") println!("WHOLY MOLLY !")
@ -134,22 +145,23 @@ pub(crate) fn spawn_from_blueprints(
let model_id = model_handle.id(); let model_id = model_handle.id();
let loaded = asset_server.is_loaded_with_dependencies(model_id); let loaded = asset_server.is_loaded_with_dependencies(model_id);
if !loaded { if !loaded {
asset_infos.push(BlueprintLoadTracker{ asset_infos.push(AssetLoadTracker {
name: model_path.to_string_lossy().into(), name: model_path.to_string_lossy().into(),
id: model_id, id: model_id,
loaded: false, loaded: false,
handle: model_handle.clone() handle: model_handle.clone()
}); })
} }
} }
// if not all assets are already loaded, inject a component to signal that we need them to be loaded // if not all assets are already loaded, inject a component to signal that we need them to be loaded
if asset_infos.len() > 0 { if asset_infos.len() > 0 {
commands commands
.entity(entity) .entity(entity)
.insert(BlueprintAssetsToLoad{ .insert(AssetsToLoad{
all_loaded: false, all_loaded: false,
asset_infos: asset_infos, asset_infos: asset_infos,
..Default::default() progress: 0.0
//..Default::default()
}) })
.insert(BlueprintAssetsNotLoaded); .insert(BlueprintAssetsNotLoaded);
}else { }else {
@ -163,7 +175,7 @@ pub(crate) fn spawn_from_blueprints(
pub(crate) fn check_for_loaded( pub(crate) fn check_for_loaded(
mut blueprint_assets_to_load: Query<(Entity, &mut BlueprintAssetsToLoad),With<BlueprintAssetsNotLoaded>>, mut blueprint_assets_to_load: Query<(Entity, &mut AssetsToLoad<Gltf>), With<BlueprintAssetsNotLoaded>>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut commands: Commands, mut commands: Commands,
){ ){
@ -218,7 +230,6 @@ pub(crate) fn actually_spawn_stuff(
children: Query<&Children>, children: Query<&Children>,
){ ){
for ( for (
entity, entity,
blupeprint_name, 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())); let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str()));
info!("attempting to spawn {:?}", model_path); info!("attempting to spawn {:?}", model_path);
let model_handle: Handle<Gltf> = asset_server.load(model_path); let model_handle: Handle<Gltf> = asset_server.load(model_path);// FIXME: kinda weird now
let gltf = assets_gltf let gltf = assets_gltf
.get(&model_handle) .get(&model_handle)