feat(Blenvy): continued restructuring & upgrade of blueprint spawning logic
* updated simple test to include deep nested blueprint instance within blueprint instance case * restructured materials handling to use the new logic, removed clutter * experimenting with solutions to the deeply nested blueprint instances problem * moved out all obsolete code to "old" folder, keeeping around until all problems are solved * added hack-ish solution to the "aabb system as post process" implementation * various minor boilerprate changes
This commit is contained in:
parent
6dde9823ed
commit
fbcd025dc1
|
@ -0,0 +1,190 @@
|
|||
use std::path::Path;
|
||||
|
||||
use bevy::{
|
||||
asset::{AssetServer, Assets, Handle},
|
||||
ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::{Added, With},
|
||||
reflect::ReflectComponent,
|
||||
system::{Commands, Query, Res, ResMut},
|
||||
},
|
||||
gltf::Gltf,
|
||||
hierarchy::{Children, Parent},
|
||||
log::debug,
|
||||
pbr::StandardMaterial,
|
||||
reflect::Reflect,
|
||||
render::mesh::Mesh,
|
||||
};
|
||||
|
||||
use crate::{AssetLoadTracker, BlueprintAssetsLoadState, BlenvyConfig, BlueprintInstanceReady};
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// struct containing the name & path of the material to apply
|
||||
pub struct MaterialInfo {
|
||||
pub name: String,
|
||||
pub path: 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(
|
||||
blenvy_config: ResMut<BlenvyConfig>,
|
||||
material_infos: Query<(Entity, &MaterialInfo), Added<MaterialInfo>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
|
||||
for (entity, material_info) in material_infos.iter() {
|
||||
println!("Entity with material info {:?} {:?}", entity, material_info);
|
||||
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
||||
if blenvy_config
|
||||
.materials_cache
|
||||
.contains_key(&material_full_path)
|
||||
{
|
||||
debug!("material is cached, retrieving");
|
||||
blenvy_config
|
||||
.materials_cache
|
||||
.get(&material_full_path)
|
||||
.expect("we should have the material available");
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintMaterialAssetsLoaded);
|
||||
} else {
|
||||
let material_file_handle = asset_server.load_untyped(&material_info.path.clone()); // : Handle<Gltf>
|
||||
let material_file_id = material_file_handle.id();
|
||||
|
||||
let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
||||
name: material_info.name.clone(),
|
||||
path: material_info.path.clone(),
|
||||
id: material_file_id,
|
||||
loaded: false,
|
||||
handle: material_file_handle.clone(),
|
||||
}];
|
||||
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintAssetsLoadState {
|
||||
all_loaded: false,
|
||||
asset_infos,
|
||||
..Default::default()
|
||||
})
|
||||
.insert(BlueprintMaterialAssetsNotLoaded);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO, merge with blueprints_check_assets_loading, make generic ?
|
||||
pub(crate) fn check_for_material_loaded(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &mut BlueprintAssetsLoadState),
|
||||
With<BlueprintMaterialAssetsNotLoaded>,
|
||||
>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
let mut all_loaded = true;
|
||||
let mut loaded_amount = 0;
|
||||
let total = assets_to_load.asset_infos.len();
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
let asset_id = tracker.id;
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
tracker.loaded = loaded;
|
||||
if loaded {
|
||||
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::<BlueprintMaterialAssetsNotLoaded>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// system that injects / replaces materials from material library
|
||||
pub(crate) fn materials_inject2(
|
||||
mut blenvy_config: ResMut<BlenvyConfig>,
|
||||
material_infos: Query<
|
||||
(&MaterialInfo, &Children),
|
||||
(
|
||||
Added<BlueprintMaterialAssetsLoaded>,
|
||||
With<BlueprintMaterialAssetsLoaded>,
|
||||
),
|
||||
>,
|
||||
with_materials_and_meshes: Query<
|
||||
(),
|
||||
(
|
||||
With<Parent>,
|
||||
With<Handle<StandardMaterial>>,
|
||||
With<Handle<Mesh>>,
|
||||
),
|
||||
>,
|
||||
assets_gltf: Res<Assets<Gltf>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (material_info, children) in material_infos.iter() {
|
||||
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
||||
let mut material_found: Option<&Handle<StandardMaterial>> = None;
|
||||
|
||||
if blenvy_config
|
||||
.materials_cache
|
||||
.contains_key(&material_full_path)
|
||||
{
|
||||
debug!("material is cached, retrieving");
|
||||
let material = blenvy_config
|
||||
.materials_cache
|
||||
.get(&material_full_path)
|
||||
.expect("we should have the material available");
|
||||
material_found = Some(material);
|
||||
} else {
|
||||
let model_handle: Handle<Gltf> = asset_server.load(material_info.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_info.name as &str) {
|
||||
let material = mat_gltf
|
||||
.named_materials
|
||||
.get(&material_info.name as &str)
|
||||
.expect("this material should have been loaded");
|
||||
blenvy_config
|
||||
.materials_cache
|
||||
.insert(material_full_path, material.clone());
|
||||
material_found = Some(material);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(material) = material_found {
|
||||
for child in children.iter() {
|
||||
if with_materials_and_meshes.contains(*child) {
|
||||
debug!(
|
||||
"injecting material {}, path: {:?}",
|
||||
material_info.name,
|
||||
material_info.path.clone()
|
||||
);
|
||||
|
||||
commands.entity(*child).insert(material.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ use bevy::prelude::*;
|
|||
use bevy::scene::SceneInstance;
|
||||
// use bevy::utils::hashbrown::HashSet;
|
||||
|
||||
use crate::{BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, BlueprintReadyForPostProcess, BlueprintSpawned, BlueprintSpawning, SpawnTrackRoot, SubBlueprintsSpawnTracker};
|
||||
use crate::{BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, BlueprintReadyForPostProcess, BlueprintInstanceReady, BlueprintSpawning, SpawnTrackRoot, SubBlueprintsSpawnTracker};
|
||||
use crate::{SpawnHere, Spawned};
|
||||
use crate::{
|
||||
BlueprintEvent, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren
|
||||
|
@ -113,7 +113,7 @@ pub(crate) fn spawned_blueprint_post_process( // rename to '
|
|||
);
|
||||
|
||||
commands.entity(original)
|
||||
.insert(BlueprintSpawned)
|
||||
.insert(BlueprintInstanceReady)
|
||||
.remove::<BlueprintSpawning>()
|
||||
|
||||
|
|
@ -5,6 +5,7 @@ use crate::{BlenvyConfig, BlueprintReadyForFinalizing, BlueprintReadyForPostProc
|
|||
/// helper system that computes the compound aabbs of the scenes/blueprints
|
||||
pub fn compute_scene_aabbs(
|
||||
root_entities: Query<(Entity, &Name), (With<BlueprintReadyForPostProcess>, Without<Aabb>)>,
|
||||
other_entities: Query<Entity, (With<BlueprintReadyForPostProcess>, With<Aabb>)>,
|
||||
children: Query<&Children>,
|
||||
existing_aabbs: Query<&Aabb>,
|
||||
|
||||
|
@ -24,10 +25,16 @@ pub fn compute_scene_aabbs(
|
|||
commands.entity(root_entity).insert(*aabb).insert(BlueprintReadyForFinalizing);
|
||||
} else {
|
||||
let aabb = compute_descendant_aabb(root_entity, &children, &existing_aabbs);
|
||||
commands.entity(root_entity).insert(aabb).insert(BlueprintReadyForFinalizing);
|
||||
blenvy_config.aabb_cache.insert(name.to_string(), aabb);
|
||||
info!("generating aabb for {:?}", name);
|
||||
commands.entity(root_entity).insert(aabb).insert(BlueprintReadyForFinalizing);
|
||||
|
||||
}
|
||||
}
|
||||
for entity in other_entities.iter() {
|
||||
println!("stuff with AABB");
|
||||
commands.entity(entity).insert(BlueprintReadyForFinalizing); // FIXME ! Yikes !!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_descendant_aabb(
|
||||
|
|
|
@ -1,23 +1,6 @@
|
|||
use std::path::Path;
|
||||
use bevy::prelude::*;
|
||||
|
||||
use bevy::{
|
||||
asset::{AssetServer, Assets, Handle},
|
||||
ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::{Added, With},
|
||||
reflect::ReflectComponent,
|
||||
system::{Commands, Query, Res, ResMut},
|
||||
},
|
||||
gltf::Gltf,
|
||||
hierarchy::{Children, Parent},
|
||||
log::debug,
|
||||
pbr::StandardMaterial,
|
||||
reflect::Reflect,
|
||||
render::mesh::Mesh,
|
||||
};
|
||||
|
||||
use crate::{AssetLoadTracker, BlueprintAssetsLoadState, BlenvyConfig, BlueprintInstanceReady};
|
||||
use crate::{BlenvyConfig, BlueprintReadyForPostProcess};
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
|
@ -27,107 +10,21 @@ pub struct MaterialInfo {
|
|||
pub path: String,
|
||||
}
|
||||
|
||||
/// flag component
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintMaterialAssetsLoaded;
|
||||
/// flag component
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintMaterialAssetsNotLoaded;
|
||||
#[derive(Component, Default, Debug)]
|
||||
pub struct MaterialProcessed;
|
||||
|
||||
|
||||
/// system that injects / replaces materials from material library
|
||||
pub(crate) fn materials_inject(
|
||||
blenvy_config: ResMut<BlenvyConfig>,
|
||||
material_infos: Query<(Entity, &MaterialInfo), Added<MaterialInfo>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
|
||||
for (entity, material_info) in material_infos.iter() {
|
||||
println!("Entity with material info {:?} {:?}", entity, material_info);
|
||||
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
||||
if blenvy_config
|
||||
.materials_cache
|
||||
.contains_key(&material_full_path)
|
||||
{
|
||||
debug!("material is cached, retrieving");
|
||||
blenvy_config
|
||||
.materials_cache
|
||||
.get(&material_full_path)
|
||||
.expect("we should have the material available");
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintMaterialAssetsLoaded);
|
||||
} else {
|
||||
let material_file_handle = asset_server.load_untyped(&material_info.path.clone()); // : Handle<Gltf>
|
||||
let material_file_id = material_file_handle.id();
|
||||
|
||||
let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
||||
name: material_info.name.clone(),
|
||||
path: material_info.path.clone(),
|
||||
id: material_file_id,
|
||||
loaded: false,
|
||||
handle: material_file_handle.clone(),
|
||||
}];
|
||||
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintAssetsLoadState {
|
||||
all_loaded: false,
|
||||
asset_infos,
|
||||
..Default::default()
|
||||
})
|
||||
.insert(BlueprintMaterialAssetsNotLoaded);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO, merge with blueprints_check_assets_loading, make generic ?
|
||||
pub(crate) fn check_for_material_loaded(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &mut BlueprintAssetsLoadState),
|
||||
With<BlueprintMaterialAssetsNotLoaded>,
|
||||
>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
let mut all_loaded = true;
|
||||
let mut loaded_amount = 0;
|
||||
let total = assets_to_load.asset_infos.len();
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
let asset_id = tracker.id;
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
tracker.loaded = loaded;
|
||||
if loaded {
|
||||
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::<BlueprintMaterialAssetsNotLoaded>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// system that injects / replaces materials from material library
|
||||
pub(crate) fn materials_inject2(
|
||||
pub(crate) fn inject_materials(
|
||||
mut blenvy_config: ResMut<BlenvyConfig>,
|
||||
material_infos: Query<
|
||||
(&MaterialInfo, &Children),
|
||||
(
|
||||
(Entity, &MaterialInfo, &Children),
|
||||
Without<MaterialProcessed>
|
||||
// (With<BlueprintReadyForPostProcess>)
|
||||
/*(
|
||||
Added<BlueprintMaterialAssetsLoaded>,
|
||||
With<BlueprintMaterialAssetsLoaded>,
|
||||
),
|
||||
),*/
|
||||
>,
|
||||
with_materials_and_meshes: Query<
|
||||
(),
|
||||
|
@ -142,7 +39,7 @@ pub(crate) fn materials_inject2(
|
|||
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (material_info, children) in material_infos.iter() {
|
||||
for (entity, material_info, children) in material_infos.iter() {
|
||||
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
||||
let mut material_found: Option<&Handle<StandardMaterial>> = None;
|
||||
|
||||
|
@ -165,7 +62,7 @@ pub(crate) fn materials_inject2(
|
|||
let material = mat_gltf
|
||||
.named_materials
|
||||
.get(&material_info.name as &str)
|
||||
.expect("this material should have been loaded");
|
||||
.expect("this material should have been loaded at this stage, please make sure you are correctly preloading them");
|
||||
blenvy_config
|
||||
.materials_cache
|
||||
.insert(material_full_path, material.clone());
|
||||
|
@ -173,10 +70,12 @@ pub(crate) fn materials_inject2(
|
|||
}
|
||||
}
|
||||
|
||||
commands.entity(entity).insert(MaterialProcessed);
|
||||
|
||||
if let Some(material) = material_found {
|
||||
for child in children.iter() {
|
||||
if with_materials_and_meshes.contains(*child) {
|
||||
debug!(
|
||||
info!(
|
||||
"injecting material {}, path: {:?}",
|
||||
material_info.name,
|
||||
material_info.path.clone()
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
pub mod spawn_from_blueprints;
|
||||
pub use spawn_from_blueprints::*;
|
||||
|
||||
pub mod spawn_post_process;
|
||||
pub(crate) use spawn_post_process::*;
|
||||
|
||||
pub mod animation;
|
||||
pub use animation::*;
|
||||
|
||||
|
@ -70,10 +67,38 @@ fn aabbs_enabled(blenvy_config: Res<BlenvyConfig>) -> bool {
|
|||
blenvy_config.aabbs
|
||||
}
|
||||
|
||||
fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
|
||||
watching_for_changes.0
|
||||
}
|
||||
|
||||
|
||||
trait BlenvyApp {
|
||||
fn register_watching_for_changes(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl BlenvyApp for App {
|
||||
fn register_watching_for_changes(&mut self) -> &mut Self {
|
||||
let asset_server = self
|
||||
.world()
|
||||
.get_resource::<AssetServer>()
|
||||
.expect(ASSET_ERROR);
|
||||
|
||||
let watching_for_changes = asset_server.watching_for_changes();
|
||||
self.insert_resource(WatchingForChanges(watching_for_changes))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Resource, Default)]
|
||||
pub(crate) struct WatchingForChanges(pub(crate) bool);
|
||||
const ASSET_ERROR: &str = ""; // TODO
|
||||
|
||||
|
||||
impl Plugin for BlueprintsPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app
|
||||
.register_watching_for_changes()
|
||||
|
||||
|
||||
.register_type::<BlueprintInfo>()
|
||||
.register_type::<MaterialInfo>()
|
||||
.register_type::<SpawnHere>()
|
||||
|
@ -94,7 +119,6 @@ impl Plugin for BlueprintsPlugin {
|
|||
.add_event::<BlueprintEvent>()
|
||||
|
||||
|
||||
|
||||
.register_type::<HashMap<String, Vec<String>>>()
|
||||
.configure_sets(
|
||||
Update,
|
||||
|
@ -111,32 +135,16 @@ impl Plugin for BlueprintsPlugin {
|
|||
blueprints_scenes_spawned,
|
||||
blueprints_transfer_components,
|
||||
|
||||
|
||||
(compute_scene_aabbs, apply_deferred)
|
||||
.chain(),
|
||||
// .run_if(aabbs_enabled),
|
||||
apply_deferred,
|
||||
// post process
|
||||
inject_materials,
|
||||
compute_scene_aabbs,// .run_if(aabbs_enabled),
|
||||
|
||||
blueprints_finalize_instances,
|
||||
|
||||
|
||||
/*(
|
||||
materials_inject,
|
||||
check_for_material_loaded,
|
||||
materials_inject2,
|
||||
)
|
||||
.chain()*/
|
||||
)
|
||||
.chain()
|
||||
.in_set(GltfBlueprintsSet::Spawn),
|
||||
)
|
||||
/* .add_systems(
|
||||
Update,
|
||||
(spawned_blueprint_post_process, apply_deferred)
|
||||
.chain()
|
||||
.in_set(GltfBlueprintsSet::AfterSpawn),
|
||||
)*/
|
||||
|
||||
/* .add_systems(
|
||||
Update,
|
||||
(
|
||||
|
@ -144,9 +152,8 @@ impl Plugin for BlueprintsPlugin {
|
|||
trigger_blueprint_animation_markers_events,
|
||||
),
|
||||
)*/
|
||||
|
||||
.add_systems(Update, react_to_asset_changes)
|
||||
// .add_systems(Update, track_sub_blueprints)
|
||||
// hot reload
|
||||
.add_systems(Update, react_to_asset_changes.run_if(hot_reload))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,8 +80,9 @@ pub enum BlueprintEvent {
|
|||
},
|
||||
|
||||
///
|
||||
Ready {
|
||||
InstanceReady {
|
||||
entity: Entity,
|
||||
blueprint_name: String,
|
||||
blueprint_path: String,
|
||||
}
|
||||
|
||||
|
@ -102,12 +103,6 @@ pub struct DynamicBlueprintInstance;
|
|||
pub struct BlueprintSpawning;
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Debug, Default)]
|
||||
#[reflect(Component)]
|
||||
/// component gets added when a blueprint spawning is done
|
||||
pub struct BlueprintSpawned;
|
||||
|
||||
|
||||
use gltf::Gltf as RawGltf;
|
||||
|
||||
pub(crate) fn blueprints_prepare_spawn(
|
||||
|
@ -388,26 +383,44 @@ pub struct BlueprintChildrenReady;
|
|||
pub struct BlueprintReadyForPostProcess;
|
||||
|
||||
|
||||
|
||||
// TODO: disregard blueprints that have been spawned WAIT , we already have BlueprintSpawning
|
||||
pub(crate) fn blueprints_scenes_spawned(
|
||||
spawned_blueprint_scene_instances: Query<(Entity, Option<&Name>, Option<&Children>, Option<&SpawnTrackRoot>), (With<BlueprintSpawning>, Added<SceneInstance>)>,
|
||||
with_blueprint_infos : Query<(Entity, Option<&Name>), With<BlueprintInfo>>,
|
||||
|
||||
all_children: Query<&Children>,
|
||||
all_parents: Query<&Parent>,
|
||||
|
||||
mut sub_blueprint_trackers: Query<(Entity, &mut SubBlueprintsSpawnTracker, &BlueprintInfo)>,
|
||||
|
||||
mut commands: Commands,
|
||||
|
||||
all_names: Query<&Name>
|
||||
|
||||
) {
|
||||
for (entity, name, children, track_root) in spawned_blueprint_scene_instances.iter(){
|
||||
info!("Done spawning blueprint scene for entity named {:?} (track root: {:?})", name, track_root);
|
||||
let mut sub_blueprint_instances: Vec<Entity> = vec![];
|
||||
let mut sub_blueprint_instance_names: Vec<Name> = vec![];
|
||||
|
||||
let mut tracker_data: HashMap<Entity, bool> = HashMap::new();
|
||||
|
||||
for parent in all_parents.iter_ancestors(entity) {
|
||||
if with_blueprint_infos.get(parent).is_ok() {
|
||||
|
||||
println!("found a parent with blueprint_info {:?} for {:?}", all_names.get(parent), all_names.get(entity));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if children.is_some() {
|
||||
for child in all_children.iter_descendants(entity) {
|
||||
if with_blueprint_infos.get(child).is_ok() {
|
||||
sub_blueprint_instances.push(child);
|
||||
if let Ok(nname) = all_names.get(child) {
|
||||
sub_blueprint_instance_names.push(nname.clone());
|
||||
}
|
||||
|
||||
tracker_data.insert(child, false);
|
||||
|
||||
if track_root.is_some() {
|
||||
|
@ -424,7 +437,9 @@ pub(crate) fn blueprints_scenes_spawned(
|
|||
}
|
||||
}
|
||||
|
||||
println!("sub blueprint instances {:?}", sub_blueprint_instances);
|
||||
|
||||
|
||||
println!("sub blueprint instances {:?}", sub_blueprint_instance_names);
|
||||
|
||||
// TODO: how about when no sub blueprints are present
|
||||
if tracker_data.keys().len() > 0 {
|
||||
|
@ -439,9 +454,7 @@ pub(crate) fn blueprints_scenes_spawned(
|
|||
// could be done differently, by notifying each parent of a spawning blueprint that this child is done spawning ?
|
||||
// perhaps using component hooks or observers (ie , if a ComponentSpawning + Parent)
|
||||
|
||||
use crate::{
|
||||
CopyComponents,
|
||||
};
|
||||
use crate:: CopyComponents;
|
||||
use std::any::TypeId;
|
||||
|
||||
|
||||
|
@ -501,7 +514,6 @@ pub(crate) fn blueprints_transfer_components(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
commands.entity(original)
|
||||
.insert(BlueprintReadyForPostProcess); // Tag the entity so any systems dealing with post processing can now it is now their "turn"
|
||||
// commands.entity(original).remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
||||
|
@ -513,7 +525,8 @@ pub(crate) fn blueprints_transfer_components(
|
|||
// now check if the current entity is a child blueprint instance of another entity
|
||||
// this should always be done last, as children should be finished before the parent can be processed correctly
|
||||
if let Some(track_root) = track_root {
|
||||
// println!("got some root {:?}", root_name);
|
||||
let root_name = all_names.get(track_root.0);
|
||||
println!("got some root {:?}", root_name);
|
||||
if let Ok((s_entity, mut tracker, bp_info)) = sub_blueprint_trackers.get_mut(track_root.0) {
|
||||
tracker.sub_blueprint_instances.entry(original).or_insert(true);
|
||||
tracker.sub_blueprint_instances.insert(original, true);
|
||||
|
@ -535,44 +548,49 @@ pub(crate) fn blueprints_transfer_components(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct BlueprintReadyForFinalizing;
|
||||
|
||||
pub(crate) fn blueprints_finalize_instances(
|
||||
blueprint_instances: Query<(Entity, Option<&Name>), (With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>)>,
|
||||
blueprint_instances: Query<(Entity, Option<&Name>, &BlueprintInfo), (With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>)>,
|
||||
mut blueprint_events: EventWriter<BlueprintEvent>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, name) in blueprint_instances.iter() {
|
||||
for (entity, name, blueprint_info) in blueprint_instances.iter() {
|
||||
info!("Finalizing blueprint instance {:?}", name);
|
||||
commands.entity(entity)
|
||||
.remove::<SpawnHere>()
|
||||
.remove::<BlueprintSpawning>()
|
||||
.insert(BlueprintSpawned)
|
||||
.remove::<BlueprintReadyForPostProcess>()
|
||||
.insert(BlueprintInstanceReady)
|
||||
.insert(Visibility::Visible)
|
||||
;
|
||||
|
||||
blueprint_events.send(BlueprintEvent::InstanceReady {entity: entity, blueprint_name: blueprint_info.name.clone(), blueprint_path: blueprint_info.path.clone()});
|
||||
}
|
||||
}
|
||||
/*
|
||||
=> annoying issue with the "nested" useless root node created by blender
|
||||
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
||||
|
||||
BlueprintSpawning
|
||||
- Blueprint Load Assets
|
||||
- Blueprint Assets Ready: spawn Blueprint's scene
|
||||
- Blueprint Scene Ready:
|
||||
- get list of sub Blueprints if any, inject blueprints spawn tracker
|
||||
=> annoying issue with the "nested" useless root node created by blender
|
||||
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
||||
- Blueprint sub_blueprints Ready
|
||||
if all children are ready
|
||||
|
||||
- Blueprints post process
|
||||
- Blueprint Scene Ready (SceneInstance component is present):
|
||||
- get list of sub Blueprints if any, inject sub blueprints spawn tracker
|
||||
- Blueprint copy components to original entity, remove useless nodes
|
||||
- Blueprint post process
|
||||
- generate aabb (need full hierarchy in its final form)
|
||||
- materials ?
|
||||
- inject materials from library if needed
|
||||
- Blueprint Ready
|
||||
- bubble information up to parent blueprint instance
|
||||
- if all sub_blueprints are ready => Parent blueprint Instance is ready
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// HOT RELOAD
|
||||
|
||||
|
||||
|
|
Binary file not shown.
|
@ -215,12 +215,17 @@ Blender side:
|
|||
Bevy Side:
|
||||
- [x] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead
|
||||
- [ ] make blueprint instances invisible until spawning is done to avoid "spawn flash"?
|
||||
- [ ] should "blueprint spawned" only be triggered after all its sub blueprints have spawned ?
|
||||
- [ ] "blueprintInstance ready"/finished
|
||||
BlueprintAssetsLoaded
|
||||
BlueprintSceneSpawned
|
||||
BlueprintChildrenReady
|
||||
BlueprintReadyForPostProcess
|
||||
- [ ] restructure blueprint spawning
|
||||
- [x] "blueprint ready" only be triggered after all its sub blueprints are ready
|
||||
- [x] "blueprintInstance ready"/finished
|
||||
BlueprintAssetsLoaded
|
||||
BlueprintSceneSpawned
|
||||
BlueprintChildrenReady
|
||||
BlueprintReadyForPostProcess
|
||||
- [ ] fix issues with deeply nested blueprints
|
||||
- perhaps reverse logic by using iter_ascendants
|
||||
- [x] fix materials handling
|
||||
- [ ] fix animations handling
|
||||
|
||||
- [ ] simplify testing example:
|
||||
- [x] remove use of rapier physics (or even the whole common boilerplate ?)
|
||||
|
|
|
@ -122,9 +122,9 @@ def test_export_complex(setup_data):
|
|||
user_asset.path = "audio/fake.mp3"
|
||||
|
||||
# we have to cheat, since we cannot rely on the data injected when saving the library file (since we are not saving it as part of the tests)
|
||||
bpy.data.collections["External_blueprint"]["export_path"] = "blueprints/External_blueprint.glb"
|
||||
bpy.data.collections["External_blueprint2"]["export_path"] = "blueprints/External_blueprint2.glb"
|
||||
bpy.data.collections["External_blueprint3"]["export_path"] = "blueprints/External_blueprint3.glb"
|
||||
#bpy.data.collections["External_blueprint"]["export_path"] = "blueprints/External_blueprint.glb"
|
||||
#bpy.data.collections["External_blueprint2"]["export_path"] = "blueprints/External_blueprint2.glb"
|
||||
#bpy.data.collections["External_blueprint3"]["export_path"] = "blueprints/External_blueprint3.glb"
|
||||
|
||||
# do the actual exporting
|
||||
prepare_and_export()
|
||||
|
|
|
@ -106,7 +106,7 @@ def test_export_complex(setup_data):
|
|||
blenvy.auto_export.auto_export = True
|
||||
blenvy.auto_export.export_scene_settings = True
|
||||
blenvy.auto_export.export_blueprints = True
|
||||
#blenvy.auto_export.export_materials_library = True
|
||||
blenvy.auto_export.export_materials_library = True
|
||||
|
||||
bpy.data.scenes['World'].blenvy_scene_type = 'Level' # set scene as main/level scene
|
||||
bpy.data.scenes['Library'].blenvy_scene_type = 'Library' # set scene as Library scene
|
||||
|
|
Loading…
Reference in New Issue