diff --git a/crates/blenvy/src/blueprints/hot_reload.rs b/crates/blenvy/src/blueprints/hot_reload.rs index 2268433..8c84d20 100644 --- a/crates/blenvy/src/blueprints/hot_reload.rs +++ b/crates/blenvy/src/blueprints/hot_reload.rs @@ -1,34 +1,51 @@ -use crate::{BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintInfo, SpawnBlueprint}; -use bevy::asset::AssetEvent; +use crate::{BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintChildrenReady, BlueprintInfo, BlueprintInstanceReady, InBlueprint, SpawnBlueprint, SubBlueprintsSpawnTracker}; +use bevy::asset::{AssetEvent, UntypedAssetId}; use bevy::prelude::*; use bevy::scene::SceneInstance; +use bevy::utils::hashbrown::HashMap; + + +/// Resource mapping asset paths (ideally untyped ids, but more complex) to a list of blueprint instance entity ids +#[derive(Debug, Clone, Resource, Default)] +pub(crate) struct AssetToBlueprintInstancesMapper{ + // pub(crate) untyped_id_to_blueprint_entity_ids: HashMap> + pub(crate) untyped_id_to_blueprint_entity_ids: HashMap> +} pub(crate) fn react_to_asset_changes( - mut gltf_events: EventReader>, + mut gltf_events: EventReader>, // FIXME: Problem: we need to react to any asset change, not just gltf files ! // mut untyped_events: EventReader>, - mut blueprint_assets: Query<( + blueprint_assets: Query<( Entity, Option<&Name>, &BlueprintInfo, - &mut BlueprintAssetsLoadState, Option<&Children>, )>, + // blueprint_children_entities: Query<&InBlueprint>, => can only be used if the entites are tagged, right now that is optional...perhaps do not make it optional + assets_to_blueprint_instances: Res, + asset_server: Res, mut commands: Commands, + ) { for event in gltf_events.read() { // LoadedUntypedAsset match event { AssetEvent::Modified { id } => { - // React to the image being modified + // React to the gltf file being modified // println!("Modified gltf {:?}", asset_server.get_path(*id)); - for (entity, entity_name, _blueprint_info, mut assets_to_load, children) in - blueprint_assets.iter_mut() - { - for tracker in assets_to_load.asset_infos.iter_mut() { - if asset_server.get_path(*id).is_some() { - if tracker.path == asset_server.get_path(*id).unwrap().to_string() { + if let Some(asset_path) = asset_server.get_path(*id) { + // let untyped = asset_server.get_handle_untyped(asset_path.clone()); + // println!("matching untyped handle {:?}", untyped); + // let bla = untyped.unwrap().id(); + // asset_server.get + if let Some(entities) = assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.get(&asset_path.to_string()) { + for entity in entities.iter() { + println!("matching blueprint instance {}", entity); + if let Ok((entity, entity_name, _blueprint_info, children)) = blueprint_assets.get(*entity) { println!("HOLY MOLY IT DETECTS !!, now respawn {:?}", entity_name); + + // TODO: only remove those that are "in blueprint" if children.is_some() { for child in children.unwrap().iter() { commands.entity(*child).despawn_recursive(); @@ -36,12 +53,12 @@ pub(crate) fn react_to_asset_changes( } commands .entity(entity) + .remove::() .remove::() .remove::() .remove::() + .remove::() .insert(SpawnBlueprint); - - break; } } } diff --git a/crates/blenvy/src/blueprints/mod.rs b/crates/blenvy/src/blueprints/mod.rs index 8b4e3aa..7e0ba37 100644 --- a/crates/blenvy/src/blueprints/mod.rs +++ b/crates/blenvy/src/blueprints/mod.rs @@ -19,7 +19,7 @@ pub use copy_components::*; pub(crate) mod hot_reload; pub(crate) use hot_reload::*; -use bevy::{prelude::*, utils::HashMap}; +use bevy::{prelude::*, utils::hashbrown::HashMap}; use crate::{BlenvyConfig, GltfComponentsSet}; @@ -65,7 +65,8 @@ fn aabbs_enabled(blenvy_config: Res) -> bool { } fn hot_reload(watching_for_changes: Res) -> bool { - watching_for_changes.0 + // println!("hot reload ? {}", watching_for_changes.0); + return watching_for_changes.0 } trait BlenvyApp { @@ -91,6 +92,9 @@ const ASSET_ERROR: &str = ""; // TODO impl Plugin for BlueprintsPlugin { fn build(&self, app: &mut App) { app.register_watching_for_changes() + .insert_resource(AssetToBlueprintInstancesMapper { + untyped_id_to_blueprint_entity_ids: HashMap::new(), + }) .add_event::() .register_type::() .register_type::() diff --git a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs index 771611a..efdf7c3 100644 --- a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs +++ b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs @@ -4,9 +4,7 @@ use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashM use serde_json::Value; use crate::{ - AnimationInfos, AssetLoadTracker, BlenvyConfig, BlueprintAnimationPlayerLink, - BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, - BlueprintAssetsNotLoaded, SceneAnimationPlayerLink, SceneAnimations, + AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlenvyConfig, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, SceneAnimationPlayerLink, SceneAnimations }; /// this is a flag component for our levels/game world @@ -39,11 +37,7 @@ impl BlueprintInfo { #[reflect(Component)] pub struct SpawnBlueprint; -#[derive(Component, Debug)] -/// flag component added when a Blueprint instance ist Ready : ie : -/// - its assets have loaded -/// - it has finished spawning -pub struct BlueprintInstanceReady; + #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] @@ -112,6 +106,9 @@ pub struct BlueprintSpawning; use gltf::Gltf as RawGltf; + + + /* Overview of the Blueprint Spawning process - Blueprint Load Assets @@ -135,6 +132,8 @@ pub(crate) fn blueprints_prepare_spawn( >, mut commands: Commands, asset_server: Res, + // for hot reload + mut assets_to_blueprint_instances: ResMut ) { for (entity, blueprint_info, entity_name) in blueprint_instances_to_spawn.iter() { info!( @@ -186,6 +185,18 @@ pub(crate) fn blueprints_prepare_spawn( handle: untyped_handle.clone(), }); } + + // FIXME: dang, too early, asset server has not yet started loading yet + // let path_id = asset_server.get_path_id(&asset.path).expect("we should have alread checked for this asset"); + let path_id = asset.path.clone(); + // TODO: make this dependant on if hot reload is enabled or not + if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.contains_key(&path_id) { + assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.insert(path_id.clone(), vec![]); + } + // only insert if not already present in mapping + if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids[&path_id].contains(&entity) { + assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.get_mut(&path_id).unwrap().push(entity); + } } } } @@ -659,6 +670,7 @@ pub(crate) fn blueprints_cleanup_spawned_scene( commands .entity(original) + .remove::() // we are done with this step, we can remove the `BlueprintChildrenReady` tag component .insert(BlueprintReadyForPostProcess); // Tag the entity so any systems dealing with post processing can know it is now their "turn" commands.entity(blueprint_root_entity).despawn_recursive(); // Remove the root entity that comes from the spawned-in scene @@ -669,6 +681,12 @@ pub(crate) fn blueprints_cleanup_spawned_scene( #[reflect(Component)] pub struct BlueprintReadyForFinalizing; +#[derive(Component, Debug)] +/// flag component added when a Blueprint instance ist Ready : ie : +/// - its assets have loaded +/// - it has finished spawning +pub struct BlueprintInstanceReady; + pub(crate) fn blueprints_finalize_instances( blueprint_instances: Query< ( @@ -684,6 +702,8 @@ pub(crate) fn blueprints_finalize_instances( all_children: Query<&Children>, mut blueprint_events: EventWriter, mut commands: Commands, + + all_names: Query<&Name> ) { for (entity, name, blueprint_info, parent_blueprint, hide_until_ready) in blueprint_instances.iter() @@ -691,6 +711,7 @@ pub(crate) fn blueprints_finalize_instances( info!("Finalizing blueprint instance {:?}", name); commands .entity(entity) + .remove::() .remove::() .remove::() .remove::() @@ -720,7 +741,8 @@ pub(crate) fn blueprints_finalize_instances( } } if all_spawned { - // println!("ALLLLL SPAAAAWNED for {} named {:?}", track_root.0, root_name); + let root_name = all_names.get(track_root.0); + println!("ALLLLL SPAAAAWNED for {} named {:?}", track_root.0, root_name); commands.entity(track_root.0).insert(BlueprintChildrenReady); } }