From e53098db72307ecf4235b3ba5c37d60136efb3b4 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 8 Mar 2024 23:21:48 +0100 Subject: [PATCH 01/13] feat(auto_export): experimenting with injecting list/tree of sub blueprints to main scenes/levels --- .../auto_export/export_main_scenes.py | 4 +- .../helpers/helpers_collections.py | 22 +++++++--- .../helpers/helpers_scenes.py | 40 ++++++++++++++++++- .../tests/test_bevy_integration.py | 4 +- 4 files changed, 61 insertions(+), 9 deletions(-) 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) From 6f93b6e55a54cc3f09f3db61b23f239452a22836 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 8 Mar 2024 23:22:20 +0100 Subject: [PATCH 02/13] feat(blueprints): experimenting with the bevy side of things --- crates/bevy_gltf_blueprints/src/lib.rs | 4 ++++ crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index 366f05f..5f4f89a 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(), diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index 3701fa5..c9b03a9 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,6 +46,11 @@ pub struct AddToGameWorld; /// helper component, just to transfer child data pub(crate) struct OriginalChildren(pub Vec); + +#[derive(Component, Reflect, Default, Debug)] +#[reflect(Component)] +pub struct BlueprintsList(pub HashMap>); + /// main spawning functions, /// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint pub(crate) fn spawn_from_blueprints( From 3dd3557f53caa532eae178b1dbe0db0d47212bb9 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Mon, 11 Mar 2024 14:41:43 +0100 Subject: [PATCH 03/13] feat(gltf_blueprints): basics of functional dynamic loading of sub_blueprints --- crates/bevy_gltf_blueprints/src/lib.rs | 5 +- .../src/spawn_from_blueprints.rs | 171 ++++++++++++++++-- .../src/spawn_post_process.rs | 3 +- 3 files changed, 163 insertions(+), 16 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index 5f4f89a..0b8e2f6 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -144,7 +144,10 @@ impl Plugin for BlueprintsPlugin { .add_systems( Update, ( - spawn_from_blueprints, + (spawn_from_blueprints, + check_for_loaded, + actually_spawn_stuff, apply_deferred).chain(), + compute_scene_aabbs.run_if(aabbs_enabled), apply_deferred.run_if(aabbs_enabled), apply_deferred, diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index c9b03a9..f896723 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -51,22 +51,163 @@ pub(crate) struct OriginalChildren(pub Vec); #[reflect(Component)] pub struct BlueprintsList(pub HashMap>); -/// main spawning functions, + +#[derive(Reflect, Default, Debug)] +pub(crate) struct BlueprintLoadTracker{ + pub name: String, + pub id: AssetId, + pub loaded: bool, + pub handle: Handle +} +#[derive(Component, Default, Debug)] +pub(crate) struct BlueprintAssetsToLoad{ + 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( spawn_placeholders: Query< ( Entity, &BlueprintName, - Option<&Transform>, Option<&Parent>, Option<&Library>, - Option<&AddToGameWorld>, Option<&Name>, + + Option<&BlueprintsList>, + // Option<&BlueprintAssetsPreloaded> + ), (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!( + "preparing 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(BlueprintLoadTracker{ + 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{ + all_loaded: false, + asset_infos: asset_infos, + ..Default::default() + }) + .insert(BlueprintAssetsNotLoaded); + }else { + commands + .entity(entity) + .insert(BlueprintAssetsLoaded); + } + } + } +} + + +pub(crate) fn check_for_loaded( + mut blueprint_assets_to_load: Query<(Entity, &mut BlueprintAssetsToLoad),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 actually_spawn_stuff( + 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>, @@ -75,7 +216,9 @@ pub(crate) fn spawn_from_blueprints( blueprints_config: Res, children: Query<&Children>, -) { +){ + + for ( entity, blupeprint_name, @@ -84,20 +227,14 @@ pub(crate) fn spawn_from_blueprints( library_override, add_to_world, name, + ) in spawn_placeholders.iter() { - debug!( + info!( "need 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); @@ -106,7 +243,7 @@ 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); + info!("attempting to spawn {:?}", model_path); let model_handle: Handle = asset_server.load(model_path); let gltf = assets_gltf @@ -128,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(), @@ -148,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..ef12350 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs @@ -6,7 +6,7 @@ use bevy::scene::SceneInstance; use super::{AnimationPlayerLink, Animations}; use super::{SpawnHere, Spawned}; -use crate::{CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren}; +use crate::{BlueprintAssetsToLoad, 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 +89,7 @@ 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(root_entity).despawn_recursive(); } } From 10e85fce26cc956835239873734a6f22ae18731f Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Mon, 11 Mar 2024 23:45:41 +0100 Subject: [PATCH 04/13] 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) From bb0975bbe89efa6e0bd804c8c46d1e170ccc5de4 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Tue, 12 Mar 2024 10:10:23 +0100 Subject: [PATCH 05/13] refactor(): minor cleanups --- crates/bevy_gltf_blueprints/src/materials.rs | 10 +-------- .../src/spawn_from_blueprints.rs | 22 ++++--------------- .../src/spawn_post_process.rs | 5 +++-- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/materials.rs b/crates/bevy_gltf_blueprints/src/materials.rs index 6e615f1..f8f5e26 100644 --- a/crates/bevy_gltf_blueprints/src/materials.rs +++ b/crates/bevy_gltf_blueprints/src/materials.rs @@ -30,8 +30,6 @@ pub(crate) struct BlueprintMaterialAssetsLoaded; #[derive(Component)] pub(crate) struct BlueprintMaterialAssetsNotLoaded; - - /// system that injects / replaces materials from material library pub(crate) fn materials_inject( blueprints_config: ResMut, @@ -65,7 +63,6 @@ pub(crate) fn materials_inject( } 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 { @@ -103,14 +100,12 @@ pub(crate) fn check_for_material_loaded( 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 { @@ -141,7 +136,6 @@ pub(crate) fn materials_inject2( 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 @@ -157,7 +151,7 @@ pub(crate) fn materials_inject2( .material_library_cache .contains_key(&material_full_path) { - info!("material is cached, retrieving"); + debug!("material is cached, retrieving"); let material = blueprints_config .material_library_cache .get(&material_full_path) @@ -165,8 +159,6 @@ pub(crate) fn materials_inject2( material_found = Some(material); }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"); diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index a29ccb3..915c932 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -51,20 +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, - pub id: AssetId, - pub loaded: bool, - pub handle: Handle -} -#[derive(Component, Default, Debug)] -pub(crate) struct BlueprintAssetsToLoad{ - pub all_loaded: bool, - pub asset_infos: Vec, - pub progress: f32 -} - #[derive(Default, Debug)] pub(crate) struct AssetLoadTracker{ pub name: String, @@ -117,7 +103,7 @@ pub(crate) fn spawn_from_blueprints( ) in spawn_placeholders.iter() { debug!( - "preparing to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", + "requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", blupeprint_name.0, name, entity, original_parent ); @@ -194,7 +180,7 @@ pub(crate) fn check_for_loaded( } } let progress:f32 = loaded_amount as f32 / total as f32; - println!("progress: {}",progress); + // println!("progress: {}",progress); assets_to_load.progress = progress; if all_loaded { @@ -242,7 +228,7 @@ pub(crate) fn actually_spawn_stuff( ) in spawn_placeholders.iter() { info!( - "need to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", + "attempting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", blupeprint_name.0, name, entity, original_parent ); @@ -254,7 +240,7 @@ pub(crate) fn actually_spawn_stuff( 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())); - info!("attempting to spawn {:?}", 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 diff --git a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs index ef12350..16bbca9 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::{BlueprintAssetsToLoad, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren}; +use crate::{AssetsToLoad, 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,7 +90,7 @@ 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::>();// 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(root_entity).despawn_recursive(); } } From ea41c3c9cbc890127c0daedc2d1c32ad84796788 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Tue, 12 Mar 2024 23:41:05 +0100 Subject: [PATCH 06/13] refactor(): further cleanups --- crates/bevy_gltf_blueprints/src/lib.rs | 27 ++++++++++++++----- .../src/spawn_from_blueprints.rs | 11 +++++--- .../src/spawn_post_process.rs | 3 ++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index 266289a..a89619c 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -144,14 +144,29 @@ impl Plugin for BlueprintsPlugin { .add_systems( Update, ( - (spawn_from_blueprints, - check_for_loaded, - actually_spawn_stuff, apply_deferred).chain(), + ( + prepare_blueprints, + check_for_loaded, + spawn_from_blueprints, + apply_deferred + ) + .chain(), + ( + compute_scene_aabbs, + apply_deferred + ) + .chain() + .run_if(aabbs_enabled), - compute_scene_aabbs.run_if(aabbs_enabled), - apply_deferred.run_if(aabbs_enabled), apply_deferred, - (materials_inject, check_for_material_loaded, materials_inject2).chain().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/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index 915c932..8603479 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -46,7 +46,6 @@ pub struct AddToGameWorld; /// helper component, just to transfer child data pub(crate) struct OriginalChildren(pub Vec); - #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] pub struct BlueprintsList(pub HashMap>); @@ -75,7 +74,7 @@ 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, @@ -156,10 +155,14 @@ pub(crate) fn spawn_from_blueprints( .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, @@ -192,7 +195,7 @@ pub(crate) fn check_for_loaded( } } -pub(crate) fn actually_spawn_stuff( +pub(crate) fn spawn_from_blueprints( spawn_placeholders: Query< ( Entity, diff --git a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs index 16bbca9..db84f89 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs @@ -7,7 +7,7 @@ use bevy::scene::SceneInstance; use super::{AnimationPlayerLink, Animations}; use super::{SpawnHere, Spawned}; -use crate::{AssetsToLoad, 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 @@ -91,6 +91,7 @@ pub(crate) fn spawned_blueprint_post_process( 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(); } } From 5192518b12df35740164bd3bc443227ce0913cbd Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Tue, 12 Mar 2024 23:43:56 +0100 Subject: [PATCH 07/13] refactor(): made the various gltf assets loaded by bevy_asset_loader optional (to handle the case where they are not present) * updated all examples accordingly --- .../bevy_gltf_blueprints/animation/src/game/in_game.rs | 2 +- examples/bevy_gltf_blueprints/basic/src/game/in_game.rs | 2 +- .../basic_xpbd_physics/src/game/in_game.rs | 2 +- .../bevy_gltf_blueprints/materials/src/game/in_game.rs | 2 +- .../src/game/in_game.rs | 2 +- .../src/game/level_transitions.rs | 2 +- examples/bevy_registry_export/basic/src/game/in_game.rs | 2 +- examples/common/src/assets/assets_game.rs | 8 ++++---- 8 files changed, 11 insertions(+), 11 deletions(-) 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>>, From f5b063cd344d9ab8dc6141abab7c8958b5509512 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Tue, 12 Mar 2024 23:46:08 +0100 Subject: [PATCH 08/13] chore(testing): updated the testing bevy project --- .../assets/assets_game.assets.ron | 4 ++-- testing/bevy_example/src/core/mod.rs | 1 + testing/bevy_example/src/game/in_game.rs | 22 +++++-------------- testing/bevy_example/src/game/mod.rs | 6 +++-- 4 files changed, 12 insertions(+), 21 deletions(-) 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*/ ; } } From ddc17ed2c3520718854ee4ce439de25ca64bf3cd Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Tue, 12 Mar 2024 23:46:56 +0100 Subject: [PATCH 09/13] chore(auto_export): minor tweaks --- .../helpers/helpers_scenes.py | 24 ++++++++++--------- .../tests/test_bevy_integration.py | 5 ++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tools/gltf_auto_export/helpers/helpers_scenes.py b/tools/gltf_auto_export/helpers/helpers_scenes.py index 5d49357..1cebc61 100644 --- a/tools/gltf_auto_export/helpers/helpers_scenes.py +++ b/tools/gltf_auto_export/helpers/helpers_scenes.py @@ -73,6 +73,13 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par """we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object""" empty_obj['BlueprintName'] = '"'+collection_name+'"' if legacy_mode else '("'+collection_name+'")' empty_obj['SpawnHere'] = '()' + # we also inject a list of all sub blueprints, so that the bevy side can preload them + root_node = CollectionNode() + root_node.name = "root" + children_per_collection = {} + get_sub_collections([object.instance_collection], root_node, children_per_collection) + empty_obj["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})" + #empty_obj["Assets"] = {"Animations": [], "Materials": [], "Models":[], "Textures":[], "Audio":[], "Other":[]} # we copy custom properties over from our original object to our empty for component_name, component_value in object.items(): @@ -162,8 +169,7 @@ def inject_blueprints_list_into_main_scene(scene): 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) - + assets_list = make_empty('assets_list_'+scene.name+"_components", [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) @@ -174,16 +180,12 @@ def inject_blueprints_list_into_main_scene(scene): #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 ? + # what about audio assets ? + # what about materials ? + # object['MaterialInfo'] = '(name: "'+material.name+'", source: "'+current_project_name + '")' + #assets_list["blueprints_direct"] = list(collection_names) assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})" - #'({"a":[]})' - #'([])' - # - # - + assets_list["Materials"]= '()' 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 d91c148..02f7f2d 100644 --- a/tools/gltf_auto_export/tests/test_bevy_integration.py +++ b/tools/gltf_auto_export/tests/test_bevy_integration.py @@ -16,7 +16,7 @@ def setup_data(request): root_path = "../../testing/bevy_example" assets_root_path = os.path.join(root_path, "assets") models_path = os.path.join(assets_root_path, "models") - #materials_path = os.path.join("../../testing", "materials") + materials_path = os.path.join(assets_root_path, "materials") #other_materials_path = os.path.join("../../testing", "other_materials") print("\nPerforming teardown...") @@ -75,7 +75,8 @@ def test_export_complex(setup_data): export_scene_settings=True, export_blueprints=True, export_legacy_mode=False, - export_animations=True + export_animations=True, + export_materials_library=True ) # blueprint1 => has an instance, got changed, should export # blueprint2 => has NO instance, but marked as asset, should export From 877c29b63c655aab7ac985fe220007dec5679b68 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Wed, 13 Mar 2024 12:15:53 +0100 Subject: [PATCH 10/13] chore(): cargo fmt & co --- crates/bevy_gltf_blueprints/src/lib.rs | 18 +-- crates/bevy_gltf_blueprints/src/materials.rs | 47 ++++--- .../src/spawn_from_blueprints.rs | 118 ++++++++---------- .../src/spawn_post_process.rs | 7 +- testing/bevy_example/src/core/mod.rs | 2 +- testing/bevy_example/src/game/in_game.rs | 6 +- 6 files changed, 96 insertions(+), 102 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index a89619c..78642cd 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -122,8 +122,7 @@ impl Plugin for BlueprintsPlugin { .register_type::() .register_type::() .register_type::>() - .register_type::>>() - + .register_type::>>() .insert_resource(BluePrintsConfig { format: self.format, library_folder: self.library_folder.clone(), @@ -144,26 +143,21 @@ impl Plugin for BlueprintsPlugin { .add_systems( Update, ( - ( + ( prepare_blueprints, check_for_loaded, - spawn_from_blueprints, - apply_deferred + spawn_from_blueprints, + apply_deferred, ) .chain(), - ( - compute_scene_aabbs, - apply_deferred - ) + (compute_scene_aabbs, apply_deferred) .chain() .run_if(aabbs_enabled), - apply_deferred, - ( materials_inject, check_for_material_loaded, - materials_inject2 + materials_inject2, ) .chain() .run_if(materials_library_enabled), diff --git a/crates/bevy_gltf_blueprints/src/materials.rs b/crates/bevy_gltf_blueprints/src/materials.rs index f8f5e26..1c29dd8 100644 --- a/crates/bevy_gltf_blueprints/src/materials.rs +++ b/crates/bevy_gltf_blueprints/src/materials.rs @@ -3,7 +3,11 @@ use std::path::Path; use bevy::{ asset::{AssetId, AssetServer, Assets, Handle}, ecs::{ - component::Component, entity::Entity, 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}, @@ -59,25 +63,23 @@ pub(crate) fn materials_inject( 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![]; + 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() + handle: material_file_handle.clone(), }); commands .entity(entity) - .insert(AssetsToLoad{ + .insert(AssetsToLoad { all_loaded: false, asset_infos: asset_infos, - progress: 0.0 - //..Default::default() + progress: 0.0, //..Default::default() }) .insert(BlueprintMaterialAssetsNotLoaded); /**/ @@ -87,41 +89,50 @@ pub(crate) fn materials_inject( // 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>, + 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(){ +) { + 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(){ + 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{ + } else { all_loaded = false; } } - let progress:f32 = loaded_amount as f32 / total as f32; + 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) + 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, With)>, + material_infos: Query< + (&MaterialInfo, &Children), + ( + Added, + With, + ), + >, with_materials_and_meshes: Query< (), ( @@ -157,8 +168,8 @@ pub(crate) fn materials_inject2( .get(&material_full_path) .expect("we should have the material available"); material_found = Some(material); - }else { - let model_handle: Handle = asset_server.load(materials_path.clone());// FIXME: kinda weird now + } 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"); diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index 8603479..35098d9 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -48,23 +48,22 @@ pub(crate) struct OriginalChildren(pub Vec); #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] -pub struct BlueprintsList(pub HashMap>); +pub struct BlueprintsList(pub HashMap>); #[derive(Default, Debug)] -pub(crate) struct AssetLoadTracker{ +pub(crate) struct AssetLoadTracker { pub name: String, pub id: AssetId, pub loaded: bool, - pub handle: Handle + pub handle: Handle, } #[derive(Component, Default, Debug)] -pub(crate) struct AssetsToLoad{ +pub(crate) struct AssetsToLoad { pub all_loaded: bool, pub asset_infos: Vec>, - pub progress: f32 + pub progress: f32, } - /// flag component #[derive(Component)] pub(crate) struct BlueprintAssetsLoaded; @@ -91,15 +90,8 @@ pub(crate) fn prepare_blueprints( asset_server: Res, blueprints_config: Res, ) { - for ( - entity, - blupeprint_name, - original_parent, - library_override, - name, - - blueprints_list, - ) in spawn_placeholders.iter() + for (entity, blupeprint_name, original_parent, library_override, name, blueprints_list) in + spawn_placeholders.iter() { debug!( "requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}", @@ -110,19 +102,10 @@ pub(crate) fn prepare_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![]; + let library_path = + library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0); 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())); @@ -134,61 +117,60 @@ pub(crate) fn prepare_blueprints( name: model_path.to_string_lossy().into(), id: model_id, 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 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); + .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); + } 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>, + 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(){ +) { + 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(){ + 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{ + } else { all_loaded = false; } } - let progress:f32 = loaded_amount as f32 / total as f32; + 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) + commands + .entity(entity) .insert(BlueprintAssetsLoaded) .remove::(); } @@ -197,16 +179,20 @@ pub(crate) fn check_for_loaded( pub(crate) fn spawn_from_blueprints( spawn_placeholders: Query< - ( - Entity, - &BlueprintName, - Option<&Transform>, - Option<&Parent>, - Option<&Library>, - Option<&AddToGameWorld>, - Option<&Name>, - ), - (With, Added, Without), + ( + Entity, + &BlueprintName, + Option<&Transform>, + Option<&Parent>, + Option<&Library>, + Option<&AddToGameWorld>, + Option<&Name>, + ), + ( + With, + Added, + Without, + ), >, mut commands: Commands, @@ -217,8 +203,7 @@ pub(crate) fn spawn_from_blueprints( blueprints_config: Res, children: Query<&Children>, -){ - +) { for ( entity, blupeprint_name, @@ -227,7 +212,6 @@ pub(crate) fn spawn_from_blueprints( library_override, add_to_world, name, - ) in spawn_placeholders.iter() { info!( @@ -244,7 +228,7 @@ pub(crate) fn spawn_from_blueprints( 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);// FIXME: kinda weird now + let model_handle: Handle = asset_server.load(model_path); // FIXME: kinda weird now let gltf = assets_gltf .get(&model_handle) @@ -291,4 +275,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 db84f89..b53f4d7 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_post_process.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_post_process.rs @@ -7,7 +7,10 @@ use bevy::scene::SceneInstance; use super::{AnimationPlayerLink, Animations}; use super::{SpawnHere, Spawned}; -use crate::{AssetsToLoad, BlueprintAssetsLoaded, 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 @@ -90,7 +93,7 @@ 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::>(); // 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/testing/bevy_example/src/core/mod.rs b/testing/bevy_example/src/core/mod.rs index 7c16989..339ea40 100644 --- a/testing/bevy_example/src/core/mod.rs +++ b/testing/bevy_example/src/core/mod.rs @@ -11,7 +11,7 @@ impl Plugin for CorePlugin { legacy_mode: false, library_folder: "models/library".into(), format: GltfFormat::GLB, - material_library:true, + 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 03ecb47..ca9f8d1 100644 --- a/testing/bevy_example/src/game/in_game.rs +++ b/testing/bevy_example/src/game/in_game.rs @@ -1,5 +1,7 @@ use bevy::{prelude::*, utils::hashbrown::HashMap}; -use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, BlueprintsList, GameWorldTag, Library, SpawnHere}; +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; @@ -12,7 +14,7 @@ pub fn setup_game( ) { // here we actually spawn our game world/level commands.spawn(( - SceneBundle{ + SceneBundle { scene: asset_server.load("models/World.glb#Scene0"), ..default() }, From fa4386a1850159f744c6e5a1c98b52629f578072 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Thu, 14 Mar 2024 08:23:25 +0100 Subject: [PATCH 11/13] chore(): cleanups, clippy etc --- crates/bevy_gltf_blueprints/src/materials.rs | 23 ++++++++++--------- .../src/spawn_from_blueprints.rs | 17 ++++++++++---- testing/bevy_example/src/game/in_game.rs | 6 ++--- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/bevy_gltf_blueprints/src/materials.rs b/crates/bevy_gltf_blueprints/src/materials.rs index 1c29dd8..030ee90 100644 --- a/crates/bevy_gltf_blueprints/src/materials.rs +++ b/crates/bevy_gltf_blueprints/src/materials.rs @@ -1,7 +1,7 @@ use std::path::Path; use bevy::{ - asset::{AssetId, AssetServer, Assets, Handle}, + asset::{AssetServer, Assets, Handle}, ecs::{ component::Component, entity::Entity, @@ -11,7 +11,7 @@ use bevy::{ }, gltf::Gltf, hierarchy::{Children, Parent}, - log::{debug, info}, + log::debug, pbr::StandardMaterial, reflect::Reflect, render::mesh::Mesh, @@ -66,20 +66,21 @@ pub(crate) fn materials_inject( } 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![]; + let asset_infos: Vec> = vec![ + AssetLoadTracker { + name: material_full_path, + id: material_file_id, + loaded: false, + handle: material_file_handle.clone(), + } + ]; - 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() + asset_infos, + ..Default::default() }) .insert(BlueprintMaterialAssetsNotLoaded); /**/ diff --git a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs index 35098d9..cf679b7 100644 --- a/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs +++ b/crates/bevy_gltf_blueprints/src/spawn_from_blueprints.rs @@ -52,17 +52,24 @@ pub struct BlueprintsList(pub HashMap>); #[derive(Default, Debug)] pub(crate) struct AssetLoadTracker { + #[allow(dead_code)] pub name: String, pub id: AssetId, pub loaded: bool, + #[allow(dead_code)] pub handle: Handle, } -#[derive(Component, Default, Debug)] +#[derive(Component, Debug)] pub(crate) struct AssetsToLoad { pub all_loaded: bool, pub asset_infos: Vec>, pub progress: f32, } +impl Default for AssetsToLoad { + fn default() -> Self { + Self { all_loaded: Default::default(), asset_infos: Default::default(), progress: Default::default() } + } +} /// flag component #[derive(Component)] @@ -118,17 +125,17 @@ pub(crate) fn prepare_blueprints( 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 { + if !asset_infos.is_empty() { commands .entity(entity) .insert(AssetsToLoad { all_loaded: false, - asset_infos: asset_infos, - progress: 0.0, //..Default::default() + asset_infos, + ..Default::default() }) .insert(BlueprintAssetsNotLoaded); } else { diff --git a/testing/bevy_example/src/game/in_game.rs b/testing/bevy_example/src/game/in_game.rs index ca9f8d1..4873f4e 100644 --- a/testing/bevy_example/src/game/in_game.rs +++ b/testing/bevy_example/src/game/in_game.rs @@ -1,8 +1,8 @@ -use bevy::{prelude::*, utils::hashbrown::HashMap}; +use bevy::prelude::*; use bevy_gltf_blueprints::{ - BluePrintBundle, BlueprintName, BlueprintsList, GameWorldTag, Library, SpawnHere, + BluePrintBundle, BlueprintName, GameWorldTag, }; -use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning}; +use bevy_gltf_worlflow_examples_common_rapier::{GameState, InAppRunning}; use bevy_rapier3d::prelude::Velocity; use rand::Rng; From 2c4312b5bb615143f4194b62dea38e40dfdaaa44 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 15 Mar 2024 10:37:35 +0100 Subject: [PATCH 12/13] chore(): cleanup --- .../helpers/helpers_collections.py | 8 ++--- .../helpers/helpers_scenes.py | 6 ++-- tools/gltf_auto_export/tests/test_basic.py | 34 +++++++++++++++++-- .../tests/test_bevy_integration.py | 12 ++----- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/tools/gltf_auto_export/helpers/helpers_collections.py b/tools/gltf_auto_export/helpers/helpers_collections.py index a1cd927..219add2 100644 --- a/tools/gltf_auto_export/helpers/helpers_collections.py +++ b/tools/gltf_auto_export/helpers/helpers_collections.py @@ -46,13 +46,13 @@ def get_sub_collections(collections, parent=None, children_per_collection=None): used_collections = [] for root_collection in collections: - print("collections", collections) + #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) + #print("sub", collection) node_name = collection.name children_per_collection[node_name] = [] #print(" scanning", collection.name) @@ -60,14 +60,12 @@ def get_sub_collections(collections, parent=None, children_per_collection=None): #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) + #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) diff --git a/tools/gltf_auto_export/helpers/helpers_scenes.py b/tools/gltf_auto_export/helpers/helpers_scenes.py index 1cebc61..6275231 100644 --- a/tools/gltf_auto_export/helpers/helpers_scenes.py +++ b/tools/gltf_auto_export/helpers/helpers_scenes.py @@ -160,7 +160,7 @@ def get_scenes(addon_prefs): def inject_blueprints_list_into_main_scene(scene): - print("injecting assets data") + print("injecting assets/blueprints data into scene") root_collection = scene.collection assets_list = None for object in scene.objects: @@ -187,5 +187,5 @@ def inject_blueprints_list_into_main_scene(scene): #assets_list["blueprints_direct"] = list(collection_names) assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})" - assets_list["Materials"]= '()' - print("assets list", assets_list["BlueprintsList"], children_per_collection) + #assets_list["Materials"]= '()' + # print("assets list", assets_list["BlueprintsList"], children_per_collection) diff --git a/tools/gltf_auto_export/tests/test_basic.py b/tools/gltf_auto_export/tests/test_basic.py index 0ebe949..7d01954 100644 --- a/tools/gltf_auto_export/tests/test_basic.py +++ b/tools/gltf_auto_export/tests/test_basic.py @@ -19,6 +19,8 @@ def setup_data(request): def finalizer(): print("\nPerforming teardown...") + get_orphan_data() + if os.path.exists(models_path): shutil.rmtree(models_path) @@ -33,9 +35,14 @@ def setup_data(request): return None + +def get_orphan_data(): + orphan_meshes = [m.name for m in bpy.data.meshes if m.users == 0] + # print("orphan meshes before", orphan_meshes) + def test_export_do_not_export_blueprints(setup_data): auto_export_operator = bpy.ops.export_scenes.auto_gltf - + # first, configure things # we use the global settings for that export_props = { @@ -57,7 +64,6 @@ def test_export_do_not_export_blueprints(setup_data): def test_export_custom_blueprints_path(setup_data): auto_export_operator = bpy.ops.export_scenes.auto_gltf - # first, configure things # we use the global settings for that export_props = { @@ -210,3 +216,27 @@ def test_export_separate_dynamic_and_static_objects(setup_data): assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True assert os.path.exists(os.path.join(setup_data["models_path"], "World_dynamic.glb")) == True + + +def test_export_should_not_generate_orphan_data(setup_data): + auto_export_operator = bpy.ops.export_scenes.auto_gltf + + # first, configure things + # we use the global settings for that + export_props = { + "main_scene_names" : ['World'], + "library_scene_names": ['Library'] + } + stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings") + stored_settings.clear() + stored_settings.write(json.dumps(export_props)) + + auto_export_operator( + direct_mode=True, + export_output_folder="./models", + export_scene_settings=True, + export_blueprints=False, + ) + assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True + assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint1.glb")) == False + diff --git a/tools/gltf_auto_export/tests/test_bevy_integration.py b/tools/gltf_auto_export/tests/test_bevy_integration.py index 02f7f2d..efa30fe 100644 --- a/tools/gltf_auto_export/tests/test_bevy_integration.py +++ b/tools/gltf_auto_export/tests/test_bevy_integration.py @@ -20,21 +20,19 @@ 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): + if os.path.exists(materials_path): shutil.rmtree(materials_path) - if os.path.exists(other_materials_path): - shutil.rmtree(other_materials_path)""" diagnostics_file_path = os.path.join(root_path, "bevy_diagnostics.json") if os.path.exists(diagnostics_file_path): os.remove(diagnostics_file_path) 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) @@ -96,11 +94,7 @@ def test_export_complex(setup_data): # now run bevy command = "cargo run --features bevy/dynamic_linking" - # assert getattr(propertyGroup, 'a') == 0.5714026093482971 FNULL = open(os.devnull, 'w') #use this if you want to suppress output to stdout from the subprocess - filename = "my_file.dat" - args = command - #subprocess.call(args, stdout=FNULL, stderr=FNULL, shell=False, cwd=bevy_run_exec_path) return_code = subprocess.call(["cargo", "run", "--features", "bevy/dynamic_linking"], cwd=root_path) print("RETURN CODE OF BEVY APP", return_code) assert return_code == 0 From 53e68ad58fb706178c09b3d82608ecdd53f7cba2 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 15 Mar 2024 10:38:40 +0100 Subject: [PATCH 13/13] chore(): reset to correct testing config --- testing/bevy_example/assets/registry.json | 29 +++++++++++++++++++++++ testing/bevy_example/src/game/mod.rs | 5 ++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/testing/bevy_example/assets/registry.json b/testing/bevy_example/assets/registry.json index 65dea5f..33887c3 100644 --- a/testing/bevy_example/assets/registry.json +++ b/testing/bevy_example/assets/registry.json @@ -3576,6 +3576,22 @@ "type": "array", "typeInfo": "TupleStruct" }, + "bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList": { + "isComponent": true, + "isResource": false, + "items": false, + "prefixItems": [ + { + "type": { + "$ref": "#/$defs/bevy_utils::hashbrown::HashMap, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>" + } + } + ], + "short_name": "BlueprintsList", + "title": "bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList", + "type": "array", + "typeInfo": "TupleStruct" + }, "bevy_gltf_blueprints::spawn_from_blueprints::SpawnHere": { "additionalProperties": false, "isComponent": true, @@ -10834,6 +10850,19 @@ "type": "object", "typeInfo": "Value" }, + "bevy_utils::hashbrown::HashMap, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": { + "additionalProperties": { + "type": { + "$ref": "#/$defs/alloc::vec::Vec" + } + }, + "isComponent": false, + "isResource": false, + "short_name": "HashMap, DefaultHashBuilder>", + "title": "bevy_utils::hashbrown::HashMap, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>", + "type": "object", + "typeInfo": "Map" + }, "bevy_utils::smallvec::SmallVec<[bevy_ecs::entity::Entity; 8]>": { "isComponent": false, "isResource": false, diff --git a/testing/bevy_example/src/game/mod.rs b/testing/bevy_example/src/game/mod.rs index d537091..2cd7144 100644 --- a/testing/bevy_example/src/game/mod.rs +++ b/testing/bevy_example/src/game/mod.rs @@ -99,13 +99,12 @@ impl Plugin for GamePlugin { .add_systems(Update, validate_export) .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, 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 ; } }