diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index 366f05f..a89619c 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -120,6 +120,10 @@ impl Plugin for BlueprintsPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() + .register_type::>() + .register_type::>>() + .insert_resource(BluePrintsConfig { format: self.format, library_folder: self.library_folder.clone(), @@ -140,11 +144,29 @@ impl Plugin for BlueprintsPlugin { .add_systems( Update, ( - spawn_from_blueprints, - compute_scene_aabbs.run_if(aabbs_enabled), - apply_deferred.run_if(aabbs_enabled), + ( + prepare_blueprints, + check_for_loaded, + spawn_from_blueprints, + apply_deferred + ) + .chain(), + ( + compute_scene_aabbs, + apply_deferred + ) + .chain() + .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..f8f5e26 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,105 @@ 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(); + 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 { + loaded_amount += 1; + }else{ + all_loaded = false; + } + } + let progress:f32 = loaded_amount as f32 / total as f32; + 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,9 +130,9 @@ 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() { @@ -65,10 +157,10 @@ pub(crate) fn materials_inject( .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 + 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 3701fa5..8603479 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use bevy::{gltf::Gltf, prelude::*}; +use bevy::{gltf::Gltf, prelude::*, utils::HashMap}; use crate::{Animations, BluePrintsConfig}; @@ -46,22 +46,169 @@ pub struct AddToGameWorld; /// helper component, just to transfer child data pub(crate) struct OriginalChildren(pub Vec); -/// main spawning functions, +#[derive(Component, Reflect, Default, Debug)] +#[reflect(Component)] +pub struct BlueprintsList(pub HashMap>); + +#[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; +/// flag component +#[derive(Component)] +pub(crate) struct BlueprintAssetsNotLoaded; + +/// spawning prepare function, /// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint -pub(crate) fn spawn_from_blueprints( +pub(crate) fn prepare_blueprints( spawn_placeholders: Query< ( Entity, &BlueprintName, - Option<&Transform>, Option<&Parent>, Option<&Library>, - Option<&AddToGameWorld>, Option<&Name>, + Option<&BlueprintsList>, ), (Added, Added, Without), >, + mut commands: Commands, + asset_server: Res, + blueprints_config: Res, +) { + for ( + entity, + blupeprint_name, + original_parent, + library_override, + name, + + blueprints_list, + ) in spawn_placeholders.iter() + { + debug!( + "requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", + blupeprint_name.0, name, entity, original_parent + ); + + // println!("main model path {:?}", model_path); + if blueprints_list.is_some() { + let blueprints_list = blueprints_list.unwrap(); + // println!("blueprints list {:?}", blueprints_list.0.keys()); + let mut asset_infos:Vec> = vec![]; + + for (blueprint_name, _) in blueprints_list.0.iter() { + /*if blueprint_name == what { + println!("WHOLY MOLLY !") + }*/ + // println!("library path {:?}", library_path); + let mut library_path = &blueprints_config.library_folder; // TODO: we cannot use the overriden library path + // FIXME: hack + if blueprint_name == "World" { + library_path= &library_override.unwrap().0; + } + + let model_file_name = format!("{}.{}", &blueprint_name, &blueprints_config.format); + let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str())); + + let model_handle: Handle = asset_server.load(model_path.clone()); + let model_id = model_handle.id(); + let loaded = asset_server.is_loaded_with_dependencies(model_id); + if !loaded { + 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(AssetsToLoad{ + all_loaded: false, + asset_infos: asset_infos, + progress: 0.0 + //..Default::default() + }) + .insert(BlueprintAssetsNotLoaded); + }else { + commands + .entity(entity) + .insert(BlueprintAssetsLoaded); + } + } + else { // in case there are no blueprintsList + commands + .entity(entity) + .insert(BlueprintAssetsLoaded); + } + } +} + +pub(crate) fn check_for_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 { + loaded_amount += 1; + }else{ + all_loaded = false; + } + } + let progress:f32 = loaded_amount as f32 / total as f32; + // println!("progress: {}",progress); + assets_to_load.progress = progress; + + if all_loaded { + assets_to_load.all_loaded = true; + commands.entity(entity) + .insert(BlueprintAssetsLoaded) + .remove::(); + } + } +} + +pub(crate) fn spawn_from_blueprints( + spawn_placeholders: Query< + ( + Entity, + &BlueprintName, + Option<&Transform>, + Option<&Parent>, + Option<&Library>, + Option<&AddToGameWorld>, + Option<&Name>, + ), + (With, Added, Without), + >, + mut commands: Commands, mut game_world: Query>, @@ -70,7 +217,8 @@ pub(crate) fn spawn_from_blueprints( blueprints_config: Res, children: Query<&Children>, -) { +){ + for ( entity, blupeprint_name, @@ -79,20 +227,14 @@ pub(crate) fn spawn_from_blueprints( library_override, add_to_world, name, + ) in spawn_placeholders.iter() { - debug!( - "need to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", + info!( + "attempting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", blupeprint_name.0, name, entity, original_parent ); - let mut original_children: Vec = vec![]; - if let Ok(c) = children.get(entity) { - for child in c.iter() { - original_children.push(*child); - } - } - let what = &blupeprint_name.0; let model_file_name = format!("{}.{}", &what, &blueprints_config.format); @@ -101,8 +243,8 @@ pub(crate) fn spawn_from_blueprints( library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0); let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str())); - debug!("attempting to spawn {:?}", model_path); - let model_handle: Handle = asset_server.load(model_path); + // info!("attempting to spawn {:?}", model_path); + let model_handle: Handle = asset_server.load(model_path);// FIXME: kinda weird now let gltf = assets_gltf .get(&model_handle) @@ -123,6 +265,12 @@ pub(crate) fn spawn_from_blueprints( transforms = *transform.unwrap(); } + let mut original_children: Vec = vec![]; + if let Ok(c) = children.get(entity) { + for child in c.iter() { + original_children.push(*child); + } + } commands.entity(entity).insert(( SceneBundle { scene: scene.clone(), @@ -143,4 +291,4 @@ pub(crate) fn spawn_from_blueprints( commands.entity(world).add_child(entity); } } -} +} \ No newline at end of file diff --git a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs index 2caa625..db84f89 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs @@ -1,12 +1,13 @@ use std::any::TypeId; +use bevy::gltf::Gltf; use bevy::prelude::*; use bevy::scene::SceneInstance; // use bevy::utils::hashbrown::HashSet; use super::{AnimationPlayerLink, Animations}; use super::{SpawnHere, Spawned}; -use crate::{CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren}; +use crate::{AssetsToLoad, BlueprintAssetsLoaded, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren}; /// this system is in charge of doing any necessary post processing after a blueprint scene has been spawned /// - it removes one level of useless nesting @@ -89,6 +90,8 @@ pub(crate) fn spawned_blueprint_post_process( commands.entity(original).remove::(); commands.entity(original).remove::(); commands.entity(original).remove::>(); + commands.entity(original).remove::>();// also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ? + commands.entity(original).remove::(); commands.entity(root_entity).despawn_recursive(); } } diff --git a/examples/bevy_gltf_blueprints/animation/src/game/in_game.rs b/examples/bevy_gltf_blueprints/animation/src/game/in_game.rs index fcf711b..454ce27 100644 --- a/examples/bevy_gltf_blueprints/animation/src/game/in_game.rs +++ b/examples/bevy_gltf_blueprints/animation/src/game/in_game.rs @@ -30,7 +30,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/bevy_gltf_blueprints/basic/src/game/in_game.rs b/examples/bevy_gltf_blueprints/basic/src/game/in_game.rs index 3af11d5..231137b 100644 --- a/examples/bevy_gltf_blueprints/basic/src/game/in_game.rs +++ b/examples/bevy_gltf_blueprints/basic/src/game/in_game.rs @@ -20,7 +20,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/bevy_gltf_blueprints/basic_xpbd_physics/src/game/in_game.rs b/examples/bevy_gltf_blueprints/basic_xpbd_physics/src/game/in_game.rs index 3fa60da..6853655 100644 --- a/examples/bevy_gltf_blueprints/basic_xpbd_physics/src/game/in_game.rs +++ b/examples/bevy_gltf_blueprints/basic_xpbd_physics/src/game/in_game.rs @@ -20,7 +20,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/bevy_gltf_blueprints/materials/src/game/in_game.rs b/examples/bevy_gltf_blueprints/materials/src/game/in_game.rs index e5fc8b8..6bdf1d9 100644 --- a/examples/bevy_gltf_blueprints/materials/src/game/in_game.rs +++ b/examples/bevy_gltf_blueprints/materials/src/game/in_game.rs @@ -21,7 +21,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/in_game.rs b/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/in_game.rs index 75be98a..11ee36d 100644 --- a/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/in_game.rs +++ b/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/in_game.rs @@ -21,7 +21,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/level_transitions.rs b/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/level_transitions.rs index 41d5c90..4dcb69c 100644 --- a/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/level_transitions.rs +++ b/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles/src/game/level_transitions.rs @@ -76,7 +76,7 @@ pub fn trigger_level_transition( } else if target_level == "Level2" { level = game_assets.level2.clone().unwrap(); } else { - level = game_assets.world.clone(); + level = game_assets.world.clone().unwrap(); } info!("spawning new level"); commands.spawn(( diff --git a/examples/bevy_registry_export/basic/src/game/in_game.rs b/examples/bevy_registry_export/basic/src/game/in_game.rs index 75be98a..11ee36d 100644 --- a/examples/bevy_registry_export/basic/src/game/in_game.rs +++ b/examples/bevy_registry_export/basic/src/game/in_game.rs @@ -21,7 +21,7 @@ pub fn setup_game( SceneBundle { // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene scene: models - .get(game_assets.world.id()) + .get(game_assets.world.clone().unwrap().id()) .expect("main level should have been loaded") .scenes[0] .clone(), diff --git a/examples/common/src/assets/assets_game.rs b/examples/common/src/assets/assets_game.rs index 988e964..5bb5986 100644 --- a/examples/common/src/assets/assets_game.rs +++ b/examples/common/src/assets/assets_game.rs @@ -5,8 +5,8 @@ use bevy_asset_loader::prelude::*; #[derive(AssetCollection, Resource)] pub struct GameAssets { - #[asset(key = "world")] - pub world: Handle, + #[asset(key = "world", optional)] + pub world: Option>, #[asset(key = "world_dynamic", optional)] pub world_dynamic: Option>, @@ -16,8 +16,8 @@ pub struct GameAssets { #[asset(key = "level2", optional)] pub level2: Option>, - #[asset(key = "models", collection(typed, mapped))] - pub models: HashMap>, + #[asset(key = "models", collection(typed, mapped), optional)] + pub models: Option>>, #[asset(key = "materials", collection(typed, mapped), optional)] pub materials: Option>>, diff --git a/testing/bevy_example/assets/assets_game.assets.ron b/testing/bevy_example/assets/assets_game.assets.ron index 5b1e969..40825c0 100644 --- a/testing/bevy_example/assets/assets_game.assets.ron +++ b/testing/bevy_example/assets/assets_game.assets.ron @@ -1,6 +1,6 @@ ({ - "world":File (path: "models/World.glb"), + /*"world":File (path: "models/World.glb"), "models": Folder ( path: "models/library", - ), + ),*/ }) \ No newline at end of file diff --git a/testing/bevy_example/src/core/mod.rs b/testing/bevy_example/src/core/mod.rs index 1ef7f3e..7c16989 100644 --- a/testing/bevy_example/src/core/mod.rs +++ b/testing/bevy_example/src/core/mod.rs @@ -11,6 +11,7 @@ impl Plugin for CorePlugin { legacy_mode: false, library_folder: "models/library".into(), format: GltfFormat::GLB, + material_library:true, aabbs: true, ..Default::default() }, diff --git a/testing/bevy_example/src/game/in_game.rs b/testing/bevy_example/src/game/in_game.rs index 75be98a..03ecb47 100644 --- a/testing/bevy_example/src/game/in_game.rs +++ b/testing/bevy_example/src/game/in_game.rs @@ -1,5 +1,5 @@ -use bevy::prelude::*; -use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, GameWorldTag}; +use bevy::{prelude::*, utils::hashbrown::HashMap}; +use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, BlueprintsList, GameWorldTag, Library, SpawnHere}; use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning}; use bevy_rapier3d::prelude::Velocity; @@ -7,31 +7,19 @@ use rand::Rng; pub fn setup_game( mut commands: Commands, - game_assets: Res, - models: Res>, + asset_server: Res, mut next_game_state: ResMut>, ) { - commands.insert_resource(AmbientLight { - color: Color::WHITE, - brightness: 0.2, - }); // here we actually spawn our game world/level - commands.spawn(( - SceneBundle { - // note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene - scene: models - .get(game_assets.world.id()) - .expect("main level should have been loaded") - .scenes[0] - .clone(), + SceneBundle{ + scene: asset_server.load("models/World.glb#Scene0"), ..default() }, bevy::prelude::Name::from("world"), GameWorldTag, InAppRunning, )); - next_game_state.set(GameState::InGame) } diff --git a/testing/bevy_example/src/game/mod.rs b/testing/bevy_example/src/game/mod.rs index 99b9b3f..d537091 100644 --- a/testing/bevy_example/src/game/mod.rs +++ b/testing/bevy_example/src/game/mod.rs @@ -97,13 +97,15 @@ impl Plugin for GamePlugin { fn build(&self, app: &mut App) { app.add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame))) .add_systems(Update, validate_export) - .add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once .add_systems(OnEnter(AppState::MenuRunning), start_game) .add_systems(OnEnter(AppState::AppRunning), setup_game) + /* .add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once + + .add_systems( Update, exit_game.run_if(on_timer(Duration::from_secs_f32(0.5))), - ) // shut down the app after this time + ) // shut down the app after this time*/ ; } } diff --git a/tools/gltf_auto_export/auto_export/export_main_scenes.py b/tools/gltf_auto_export/auto_export/export_main_scenes.py index 8bdb018..25cfd37 100644 --- a/tools/gltf_auto_export/auto_export/export_main_scenes.py +++ b/tools/gltf_auto_export/auto_export/export_main_scenes.py @@ -4,7 +4,7 @@ import bpy from ..helpers.generate_and_export import generate_and_export from .export_gltf import (generate_gltf_export_preferences, export_gltf) from ..modules.bevy_dynamic import is_object_dynamic, is_object_static -from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into +from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into, inject_blueprints_list_into_main_scene # export all main scenes @@ -29,6 +29,8 @@ def export_main_scene(scene, folder_path, addon_prefs, library_collections): } if export_blueprints : + inject_blueprints_list_into_main_scene(scene) + if export_separate_dynamic_and_static_objects: #print("SPLIT STATIC AND DYNAMIC") # first export static objects diff --git a/tools/gltf_auto_export/helpers/helpers_collections.py b/tools/gltf_auto_export/helpers/helpers_collections.py index edb3214..a1cd927 100644 --- a/tools/gltf_auto_export/helpers/helpers_collections.py +++ b/tools/gltf_auto_export/helpers/helpers_collections.py @@ -36,16 +36,23 @@ def get_marked_collections(scene, addon_prefs): return (collection_names, marked_collections) # gets all collections within collections that might also be relevant -def get_sub_collections(collections, parent, children_per_collection): +def get_sub_collections(collections, parent=None, children_per_collection=None): + if parent == None: + parent = CollectionNode() + if children_per_collection == None: + children_per_collection = {} + collection_names = set() used_collections = [] for root_collection in collections: - node = Node(name=root_collection.name, parent=parent) + print("collections", collections) + node = CollectionNode(name=root_collection.name, parent=parent) parent.children.append(node) #print("root collection", root_collection.name) for collection in traverse_tree(root_collection): # TODO: filter out COLLECTIONS that have the flatten flag (unlike the flatten flag on colleciton instances themselves) + print("sub", collection) node_name = collection.name children_per_collection[node_name] = [] #print(" scanning", collection.name) @@ -53,12 +60,17 @@ def get_sub_collections(collections, parent, children_per_collection): #print("FLATTEN", object.name, 'Flatten' in object) if object.instance_type == 'COLLECTION' : # and not 'Flatten' in object: collection_name = object.instance_collection.name + print("sub obj", collection_name) + # FIXME: not sure: + children_per_collection[node_name].append(collection_name) + (sub_names, sub_collections) = get_sub_collections([object.instance_collection], node, children_per_collection) + print("gna", sub_names, sub_collections) if len(list(sub_names)) > 0: + print("toto") children_per_collection[node_name] += (list(sub_names)) #print(" found sub collection in use", object.name, object.instance_collection) - if not collection_name in collection_names: collection_names.add(collection_name) used_collections.append(object.instance_collection) @@ -77,7 +89,7 @@ def flatten_collection_tree(node, children_per_collection): children_per_collection[node.name] = list(set( children_per_collection[node.name])) -class Node : +class CollectionNode : def __init__(self, name="", parent=None): self.name = name self.children = [] @@ -93,7 +105,7 @@ def get_exportable_collections(main_scenes, library_scenes, addon_prefs): all_collections = [] all_collection_names = [] - root_node = Node() + root_node = CollectionNode() root_node.name = "root" children_per_collection = {} diff --git a/tools/gltf_auto_export/helpers/helpers_scenes.py b/tools/gltf_auto_export/helpers/helpers_scenes.py index e5b4dfb..5d49357 100644 --- a/tools/gltf_auto_export/helpers/helpers_scenes.py +++ b/tools/gltf_auto_export/helpers/helpers_scenes.py @@ -1,5 +1,6 @@ +import json import bpy -from .helpers_collections import (set_active_collection) +from .helpers_collections import (CollectionNode, get_sub_collections, get_used_collections, set_active_collection) from .object_makers import (make_empty) @@ -149,3 +150,40 @@ def get_scenes(addon_prefs): return [level_scene_names, level_scenes, library_scene_names, library_scenes] + + +def inject_blueprints_list_into_main_scene(scene): + print("injecting assets data") + root_collection = scene.collection + assets_list = None + for object in scene.objects: + if object.name == "assets_list"+scene.name: + assets_list = object + break + + if assets_list is None: + assets_list = make_empty('assets_list_'+scene.name, [0,0,0], [0,0,0], [0,0,0], root_collection) + + + # find all blueprints used in a scene + # TODO: export a tree rather than a flat list ? because you could have potential clashing items in flat lists (amongst other issues) + (collection_names, collections) = get_used_collections(scene) + root_node = CollectionNode() + root_node.name = "root" + children_per_collection = {} + + #print("collection_names", collection_names, "collections", collections) + (bla, bli ) = get_sub_collections(collections, root_node, children_per_collection) + #print("sfdsfsdf", bla, bli, "root", root_node, "children_per_collection", children_per_collection) + # with sub collections + # (collection_names, collections) = get_sub_collections(all_collections, root_node, children_per_collection) + # + # what about marked assets ? + #assets_list["blueprints_direct"] = list(collection_names) + assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})" + #'({"a":[]})' + #'([])' + # + # + + print("assets list", assets_list["BlueprintsList"], children_per_collection) diff --git a/tools/gltf_auto_export/tests/test_bevy_integration.py b/tools/gltf_auto_export/tests/test_bevy_integration.py index afd5255..d91c148 100644 --- a/tools/gltf_auto_export/tests/test_bevy_integration.py +++ b/tools/gltf_auto_export/tests/test_bevy_integration.py @@ -20,7 +20,7 @@ def setup_data(request): #other_materials_path = os.path.join("../../testing", "other_materials") print("\nPerforming teardown...") - if os.path.exists(models_path): + '''if os.path.exists(models_path): shutil.rmtree(models_path) """if os.path.exists(materials_path): @@ -34,7 +34,7 @@ def setup_data(request): screenshot_observed_path = os.path.join(root_path, "screenshot.png") if os.path.exists(screenshot_observed_path): - os.remove(screenshot_observed_path) + os.remove(screenshot_observed_path)''' request.addfinalizer(finalizer)