feat(gltf_blueprints): basics of functional dynamic loading of sub_blueprints
This commit is contained in:
parent
6f93b6e55a
commit
3dd3557f53
|
@ -144,7 +144,10 @@ impl Plugin for BlueprintsPlugin {
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
spawn_from_blueprints,
|
(spawn_from_blueprints,
|
||||||
|
check_for_loaded,
|
||||||
|
actually_spawn_stuff, apply_deferred).chain(),
|
||||||
|
|
||||||
compute_scene_aabbs.run_if(aabbs_enabled),
|
compute_scene_aabbs.run_if(aabbs_enabled),
|
||||||
apply_deferred.run_if(aabbs_enabled),
|
apply_deferred.run_if(aabbs_enabled),
|
||||||
apply_deferred,
|
apply_deferred,
|
||||||
|
|
|
@ -51,22 +51,163 @@ pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintsList(pub HashMap<String,Vec<String>>);
|
pub struct BlueprintsList(pub HashMap<String,Vec<String>>);
|
||||||
|
|
||||||
/// main spawning functions,
|
|
||||||
|
#[derive(Reflect, Default, Debug)]
|
||||||
|
pub(crate) struct BlueprintLoadTracker{
|
||||||
|
pub name: String,
|
||||||
|
pub id: AssetId<Gltf>,
|
||||||
|
pub loaded: bool,
|
||||||
|
pub handle: Handle<Gltf>
|
||||||
|
}
|
||||||
|
#[derive(Component, Default, Debug)]
|
||||||
|
pub(crate) struct BlueprintAssetsToLoad{
|
||||||
|
pub all_loaded: bool,
|
||||||
|
pub asset_infos: Vec<BlueprintLoadTracker>,
|
||||||
|
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
|
/// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint
|
||||||
pub(crate) fn spawn_from_blueprints(
|
pub(crate) fn spawn_from_blueprints(
|
||||||
spawn_placeholders: Query<
|
spawn_placeholders: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&BlueprintName,
|
&BlueprintName,
|
||||||
Option<&Transform>,
|
|
||||||
Option<&Parent>,
|
Option<&Parent>,
|
||||||
Option<&Library>,
|
Option<&Library>,
|
||||||
Option<&AddToGameWorld>,
|
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
|
|
||||||
|
Option<&BlueprintsList>,
|
||||||
|
// Option<&BlueprintAssetsPreloaded>
|
||||||
|
|
||||||
),
|
),
|
||||||
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
||||||
>,
|
>,
|
||||||
|
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
blueprints_config: Res<BluePrintsConfig>,
|
||||||
|
) {
|
||||||
|
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<BlueprintLoadTracker> = 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<Gltf> = 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<BlueprintAssetsNotLoaded>>,
|
||||||
|
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;
|
||||||
|
println!("progress: {}",progress);
|
||||||
|
assets_to_load.progress = progress;
|
||||||
|
|
||||||
|
if all_loaded {
|
||||||
|
assets_to_load.all_loaded = true;
|
||||||
|
commands.entity(entity)
|
||||||
|
.insert(BlueprintAssetsLoaded)
|
||||||
|
.remove::<BlueprintAssetsNotLoaded>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn actually_spawn_stuff(
|
||||||
|
spawn_placeholders: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
&BlueprintName,
|
||||||
|
Option<&Transform>,
|
||||||
|
Option<&Parent>,
|
||||||
|
Option<&Library>,
|
||||||
|
Option<&AddToGameWorld>,
|
||||||
|
Option<&Name>,
|
||||||
|
),
|
||||||
|
(With<BlueprintAssetsLoaded>, Added<BlueprintAssetsLoaded>, Without<BlueprintAssetsNotLoaded>),
|
||||||
|
>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut game_world: Query<Entity, With<GameWorldTag>>,
|
mut game_world: Query<Entity, With<GameWorldTag>>,
|
||||||
|
|
||||||
|
@ -75,7 +216,9 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
blueprints_config: Res<BluePrintsConfig>,
|
blueprints_config: Res<BluePrintsConfig>,
|
||||||
|
|
||||||
children: Query<&Children>,
|
children: Query<&Children>,
|
||||||
) {
|
){
|
||||||
|
|
||||||
|
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
blupeprint_name,
|
blupeprint_name,
|
||||||
|
@ -84,20 +227,14 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
library_override,
|
library_override,
|
||||||
add_to_world,
|
add_to_world,
|
||||||
name,
|
name,
|
||||||
|
|
||||||
) in spawn_placeholders.iter()
|
) in spawn_placeholders.iter()
|
||||||
{
|
{
|
||||||
debug!(
|
info!(
|
||||||
"need to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
"need to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||||
blupeprint_name.0, name, entity, original_parent
|
blupeprint_name.0, name, entity, original_parent
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut original_children: Vec<Entity> = vec![];
|
|
||||||
if let Ok(c) = children.get(entity) {
|
|
||||||
for child in c.iter() {
|
|
||||||
original_children.push(*child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let what = &blupeprint_name.0;
|
let what = &blupeprint_name.0;
|
||||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
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);
|
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()));
|
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<Gltf> = asset_server.load(model_path);
|
let model_handle: Handle<Gltf> = asset_server.load(model_path);
|
||||||
|
|
||||||
let gltf = assets_gltf
|
let gltf = assets_gltf
|
||||||
|
@ -128,6 +265,12 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
transforms = *transform.unwrap();
|
transforms = *transform.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut original_children: Vec<Entity> = vec![];
|
||||||
|
if let Ok(c) = children.get(entity) {
|
||||||
|
for child in c.iter() {
|
||||||
|
original_children.push(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
commands.entity(entity).insert((
|
commands.entity(entity).insert((
|
||||||
SceneBundle {
|
SceneBundle {
|
||||||
scene: scene.clone(),
|
scene: scene.clone(),
|
||||||
|
@ -148,4 +291,4 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
commands.entity(world).add_child(entity);
|
commands.entity(world).add_child(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ use bevy::scene::SceneInstance;
|
||||||
|
|
||||||
use super::{AnimationPlayerLink, Animations};
|
use super::{AnimationPlayerLink, Animations};
|
||||||
use super::{SpawnHere, Spawned};
|
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
|
/// 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
|
/// - it removes one level of useless nesting
|
||||||
|
@ -89,6 +89,7 @@ pub(crate) fn spawned_blueprint_post_process(
|
||||||
commands.entity(original).remove::<SpawnHere>();
|
commands.entity(original).remove::<SpawnHere>();
|
||||||
commands.entity(original).remove::<Spawned>();
|
commands.entity(original).remove::<Spawned>();
|
||||||
commands.entity(original).remove::<Handle<Scene>>();
|
commands.entity(original).remove::<Handle<Scene>>();
|
||||||
|
commands.entity(original).remove::<BlueprintAssetsToLoad>();// 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();
|
commands.entity(root_entity).despawn_recursive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue