diff --git a/crates/blenvy/src/blueprints/animation.rs b/crates/blenvy/src/blueprints/animation.rs index 5b2ab40..7d10889 100644 --- a/crates/blenvy/src/blueprints/animation.rs +++ b/crates/blenvy/src/blueprints/animation.rs @@ -23,6 +23,7 @@ pub struct BlueprintAnimationPlayerLink(pub Entity); pub struct SceneAnimations { pub named_animations: HashMap>, pub named_indices: HashMap, + pub graph: Handle, } #[derive(Component, Debug)] diff --git a/crates/blenvy/src/blueprints/mod.rs b/crates/blenvy/src/blueprints/mod.rs index 60da23c..8b4e3aa 100644 --- a/crates/blenvy/src/blueprints/mod.rs +++ b/crates/blenvy/src/blueprints/mod.rs @@ -56,9 +56,7 @@ pub struct BlueprintsPlugin { impl Default for BlueprintsPlugin { fn default() -> Self { - Self { - aabbs: false, - } + Self { aabbs: false } } } @@ -123,7 +121,7 @@ impl Plugin for BlueprintsPlugin { ( blueprints_prepare_spawn, blueprints_check_assets_loading, - blueprints_assets_ready, + blueprints_assets_loaded, blueprints_scenes_spawned, blueprints_cleanup_spawned_scene, // post process diff --git a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs index 1b613f1..c209e1e 100644 --- a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs +++ b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs @@ -4,8 +4,9 @@ use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashM use serde_json::Value; use crate::{ - AssetLoadTracker, BlenvyConfig, BlueprintAnimationPlayerLink, BlueprintAnimations, - BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, + AnimationInfos, AssetLoadTracker, BlenvyConfig, BlueprintAnimationPlayerLink, + BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, + BlueprintAssetsNotLoaded, SceneAnimationPlayerLink, SceneAnimations, }; /// this is a flag component for our levels/game world @@ -64,6 +65,10 @@ pub(crate) struct OriginalChildren(pub Vec); /// as it would first become invisible before re-appearing again pub struct HideUntilReady; +#[derive(Component)] +/// marker component, gets added to all children of a currently spawning blueprint instance, can be usefull to avoid manipulating still in progress entities +pub struct BlueprintDisabled; + #[derive(Event, Debug)] pub enum BlueprintEvent { /// event fired when a blueprint has finished loading all of its assets & before it attempts spawning @@ -245,7 +250,7 @@ pub(crate) fn blueprints_check_assets_loading( } } -pub(crate) fn blueprints_assets_ready( +pub(crate) fn blueprints_assets_loaded( spawn_placeholders: Query< ( Entity, @@ -255,6 +260,7 @@ pub(crate) fn blueprints_assets_ready( Option<&AddToGameWorld>, Option<&Name>, Option<&HideUntilReady>, + Option<&AnimationInfos>, ), ( With, @@ -279,6 +285,7 @@ pub(crate) fn blueprints_assets_ready( add_to_world, name, hide_until_ready, + animation_infos, ) in spawn_placeholders.iter() { /*info!( @@ -294,7 +301,7 @@ pub(crate) fn blueprints_assets_ready( // info!("attempting to spawn {:?}", model_path); let model_handle: Handle = asset_server.load(blueprint_info.path.clone()); // FIXME: kinda weird now - let gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| { + let blueprint_gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| { panic!( "gltf file {:?} should have been loaded", &blueprint_info.path @@ -302,13 +309,13 @@ pub(crate) fn blueprints_assets_ready( }); // WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one - let main_scene_name = gltf + let main_scene_name = blueprint_gltf .named_scenes .keys() .next() .expect("there should be at least one named scene in the gltf file to spawn"); - let scene = &gltf.named_scenes[main_scene_name]; + let scene = &blueprint_gltf.named_scenes[main_scene_name]; // transforms are optional, but still deal with them correctly let mut transforms: Transform = Transform::default(); @@ -329,13 +336,16 @@ pub(crate) fn blueprints_assets_ready( let mut named_animations: HashMap> = HashMap::new(); let mut animation_indices: HashMap = HashMap::new(); - for (key, clip) in gltf.named_animations.iter() { + for (key, clip) in blueprint_gltf.named_animations.iter() { named_animations.insert(key.to_string(), clip.clone()); let animation_index = graph.add_clip(clip.clone(), 1.0, graph.root); animation_indices.insert(key.to_string(), animation_index); } let graph = graphs.add(graph); + println!("Named animations : {:?}", named_animations.keys()); + println!("ANIMATION INFOS: {:?}", animation_infos); + commands.entity(entity).insert(( SceneBundle { scene: scene.clone(), @@ -344,6 +354,7 @@ pub(crate) fn blueprints_assets_ready( }, OriginalChildren(original_children), BlueprintAnimations { + // TODO: perhaps swap this out with SceneAnimations depending on whether we are spawning a level or a simple blueprint // these are animations specific to the blueprint named_animations, named_indices: animation_indices, @@ -466,6 +477,8 @@ pub(crate) fn blueprints_scenes_spawned( } } } + // Mark all components as "Disabled" (until Bevy gets this as first class feature) + commands.entity(child).insert(BlueprintDisabled); } } @@ -496,29 +509,30 @@ pub struct BlueprintReadyForPostProcess; /// - it copies the children of the blueprint scene into the original entity /// - it adds an `AnimationLink` component containing the entity that has the AnimationPlayer so that animations can be controlled from the original entity pub(crate) fn blueprints_cleanup_spawned_scene( - foo: Query< + blueprint_scenes: Query< ( Entity, &Children, &OriginalChildren, Option<&Name>, - Option<&SubBlueprintSpawnRoot>, &BlueprintAnimations, Option<&NoInBlueprint>, ), Added, >, - added_animation_players: Query<(Entity, &Parent), Added>, - - mut sub_blueprint_trackers: Query<&mut SubBlueprintsSpawnTracker, With>, + animation_players: Query<(Entity, &Parent), With>, all_children: Query<&Children>, + all_parents: Query<&Parent>, + with_animation_infos: Query<&AnimationInfos>, + // FIXME: meh + anims: Query<&BlueprintAnimations>, mut commands: Commands, all_names: Query<&Name>, ) { - for (original, children, original_children, name, track_root, animations, no_inblueprint) in - foo.iter() + for (original, children, original_children, name, animations, no_inblueprint) in + blueprint_scenes.iter() { info!("YOOO ready !! removing empty nodes {:?}", name); @@ -562,22 +576,67 @@ pub(crate) fn blueprints_cleanup_spawned_scene( } if animations.named_animations.keys().len() > 0 { - for (added, parent) in added_animation_players.iter() { + for (entity_with_player, parent) in animation_players.iter() { if parent.get() == blueprint_root_entity { + println!( + "FOUND ANIMATION PLAYER FOR {:?} {:?} ", + all_names.get(original), + all_names.get(entity_with_player) + ); // FIXME: stopgap solution: since we cannot use an AnimationPlayer at the root entity level // and we cannot update animation clips so that the EntityPaths point to one level deeper, // BUT we still want to have some marker/control at the root entity level, we add this commands .entity(original) - .insert((BlueprintAnimationPlayerLink(added),)); + .insert((BlueprintAnimationPlayerLink(entity_with_player),)); // FIXME : this is only valid for per-blueprint logic, no per scene animations // since v0.14 you need both AnimationTransitions and AnimationGraph components/handle on the same entity as the animationPlayer let transitions = AnimationTransitions::new(); commands - .entity(added) + .entity(entity_with_player) .insert((transitions, animations.graph.clone())); } } + // VERY convoluted, but it works + for child in all_children.iter_descendants(blueprint_root_entity) { + if with_animation_infos.get(child).is_ok() { + // player is already on the same entity as the animation_infos + if animation_players.get(child).is_ok() { + println!( + "found BLUEPRINT animation player for {:?} at {:?} Root: {:?}", + all_names.get(child), + all_names.get(child), + all_names.get(original) + ); + /*commands + .entity(original) + .insert((BlueprintAnimationPlayerLink(bla),)); */ + } else { + for parent in all_parents.iter_ancestors(child) { + if animation_players.get(parent).is_ok() { + println!( + "found SCENE animation player for {:?} at {:?} Root: {:?}", + all_names.get(child), + all_names.get(parent), + all_names.get(original) + ); + println!("INSERTING SCENE ANIMATIONS INTO"); + let original_animations = anims.get(original).unwrap(); + commands.entity(child).insert(( + SceneAnimationPlayerLink(parent), + SceneAnimations { + named_animations: original_animations + .named_animations + .clone(), + named_indices: original_animations.named_indices.clone(), + graph: original_animations.graph.clone(), + }, + )); + } + } + } + } + } } commands @@ -585,19 +644,54 @@ pub(crate) fn blueprints_cleanup_spawned_scene( .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 + } +} +#[derive(Component, Reflect, Debug)] +#[reflect(Component)] +pub struct BlueprintReadyForFinalizing; + +pub(crate) fn blueprints_finalize_instances( + blueprint_instances: Query< + ( + Entity, + Option<&Name>, + &BlueprintInfo, + Option<&SubBlueprintSpawnRoot>, + Option<&HideUntilReady>, + ), + (With, With), + >, + mut sub_blueprint_trackers: Query<&mut SubBlueprintsSpawnTracker, With>, + all_children: Query<&Children>, + mut blueprint_events: EventWriter, + mut commands: Commands, +) { + for (entity, name, blueprint_info, parent_blueprint, hide_until_ready) in + blueprint_instances.iter() + { + info!("Finalizing blueprint instance {:?}", name); + commands + .entity(entity) + .remove::() + .remove::() + .remove::() + //.remove::>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want + //.remove::(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ? + //.remove::(); + .insert(BlueprintInstanceReady); + + // Deal with sub blueprints // 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 // TODO: perhaps use observers for these - if let Some(track_root) = track_root { - let root_name = all_names.get(track_root.0); - println!("got some root {:?}", root_name); + if let Some(track_root) = parent_blueprint { if let Ok(mut tracker) = sub_blueprint_trackers.get_mut(track_root.0) { tracker .sub_blueprint_instances - .entry(original) + .entry(entity) .or_insert(true); - tracker.sub_blueprint_instances.insert(original, true); + tracker.sub_blueprint_instances.insert(entity, true); // TODO: ugh, my limited rust knowledge, this is bad code let mut all_spawned = true; @@ -613,37 +707,10 @@ pub(crate) fn blueprints_cleanup_spawned_scene( } } } - } -} -#[derive(Component, Reflect, Debug)] -#[reflect(Component)] -pub struct BlueprintReadyForFinalizing; - -pub(crate) fn blueprints_finalize_instances( - blueprint_instances: Query< - ( - Entity, - Option<&Name>, - &BlueprintInfo, - Option<&HideUntilReady>, - ), - (With, With), - >, - mut blueprint_events: EventWriter, - mut commands: Commands, -) { - for (entity, name, blueprint_info, hide_until_ready) in blueprint_instances.iter() { - info!("Finalizing blueprint instance {:?}", name); - commands - .entity(entity) - .remove::() - .remove::() - .remove::() - //.remove::>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want - //.remove::(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ? - //.remove::(); - .insert(BlueprintInstanceReady); + for child in all_children.iter_descendants(entity) { + commands.entity(child).remove::(); + } if hide_until_ready.is_some() { commands.entity(entity).insert(Visibility::Visible); diff --git a/testing/bevy_example/art/testing.blend b/testing/bevy_example/art/testing.blend index 51f1c26..416bf39 100644 Binary files a/testing/bevy_example/art/testing.blend and b/testing/bevy_example/art/testing.blend differ diff --git a/testing/bevy_example/assets/registry.json b/testing/bevy_example/assets/registry.json index 4bb1026..5a5ec38 100644 --- a/testing/bevy_example/assets/registry.json +++ b/testing/bevy_example/assets/registry.json @@ -3705,14 +3705,25 @@ "type": "object", "typeInfo": "Struct" }, - "bevy_example::game::animation::MarkerFox": { + "bevy_example::game::animation::MarkerAllFoxes": { "additionalProperties": false, "isComponent": true, "isResource": false, - "long_name": "bevy_example::game::animation::MarkerFox", + "long_name": "bevy_example::game::animation::MarkerAllFoxes", "properties": {}, "required": [], - "short_name": "MarkerFox", + "short_name": "MarkerAllFoxes", + "type": "object", + "typeInfo": "Struct" + }, + "bevy_example::game::animation::MarkerSpecificFox": { + "additionalProperties": false, + "isComponent": true, + "isResource": false, + "long_name": "bevy_example::game::animation::MarkerSpecificFox", + "properties": {}, + "required": [], + "short_name": "MarkerSpecificFox", "type": "object", "typeInfo": "Struct" }, @@ -13335,6 +13346,11 @@ "isResource": false, "long_name": "blenvy::blueprints::animation::SceneAnimations", "properties": { + "graph": { + "type": { + "$ref": "#/$defs/bevy_asset::handle::Handle" + } + }, "named_animations": { "type": { "$ref": "#/$defs/bevy_utils::hashbrown::HashMap, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>" @@ -13348,7 +13364,8 @@ }, "required": [ "named_animations", - "named_indices" + "named_indices", + "graph" ], "short_name": "SceneAnimations", "type": "object", diff --git a/testing/bevy_example/src/game/animation.rs b/testing/bevy_example/src/game/animation.rs index e478ff3..109fc33 100644 --- a/testing/bevy_example/src/game/animation.rs +++ b/testing/bevy_example/src/game/animation.rs @@ -9,7 +9,7 @@ use bevy::{animation::RepeatAnimation, gltf::Gltf, prelude::*}; use blenvy::{ AnimationInfos, AnimationMarkerReached, BlueprintAnimationPlayerLink, BlueprintAnimations, - SceneAnimationPlayerLink, SceneAnimations, + BlueprintDisabled, SceneAnimationPlayerLink, SceneAnimations, }; #[derive(Component, Reflect, Default, Debug)] @@ -29,15 +29,13 @@ pub struct Marker3; #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] -/// flag component for testing -pub struct MarkerFox; +/// flag component for testing; this is at the BLUEPRINT level +pub struct MarkerAllFoxes; -#[derive(Resource)] -pub struct AnimTest(Handle); - -pub fn setup_main_scene_animations(asset_server: Res, mut commands: Commands) { - commands.insert_resource(AnimTest(asset_server.load("levels/World.glb"))); -} +#[derive(Component, Reflect, Default, Debug)] +#[reflect(Component)] +/// flag component for testing; this is at the INSTANCE level +pub struct MarkerSpecificFox; /* #[allow(clippy::type_complexity)] @@ -81,19 +79,90 @@ pub fn animations( } }*/ +pub fn check_animations( + // (&BlueprintAnimationPlayerLink, &BlueprintAnimations) + foxes: Query< + ( + Entity, + Option<&BlueprintAnimationPlayerLink>, + Option<&SceneAnimationPlayerLink>, + ), + (With, Without), + >, + + foo: Query< + ( + Entity, + Option<&BlueprintAnimationPlayerLink>, + Option<&SceneAnimationPlayerLink>, + ), + (With, Without), + >, + bar: Query< + ( + Entity, + Option<&BlueprintAnimationPlayerLink>, + Option<&SceneAnimationPlayerLink>, + ), + (With, Without), + >, + baz: Query< + ( + Entity, + Option<&BlueprintAnimationPlayerLink>, + Option<&SceneAnimationPlayerLink>, + ), + (With, Without), + >, + + bli: Query<(Entity, &AnimationInfos)>, + anim_players: Query<(Entity, &AnimationPlayer)>, + all_names: Query<&Name>, +) { + /*for bla in foxes.iter() { + println!("MarkerAllFoxes {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2) + } + for bla in foo.iter() { + println!("Marker1 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2) + } + + for bla in bar.iter() { + println!("Marker2 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2) + } + for bla in baz.iter() { + println!("Marker3 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2) + } + println!(""); */ + /*for blo in bli.iter() { + println!("YOOOOO {:?}", all_names.get(blo.0)) + } + for anim in anim_players.iter() { + println!("Players {:?}", all_names.get(anim.0)) + }*/ +} + #[allow(clippy::type_complexity)] pub fn play_animations( - animated_fox: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With>, + animated_foxes: Query< + (&BlueprintAnimationPlayerLink, &BlueprintAnimations), + With, + >, + animated_fox: Query< + (&BlueprintAnimationPlayerLink, &BlueprintAnimations), + With, + >, - /*animated_marker1: Query< + animated_marker1: Query< (&SceneAnimationPlayerLink, &SceneAnimations), (With, With), >, + animated_marker2: Query< (&SceneAnimationPlayerLink, &SceneAnimations), (With, With), >, - animated_marker3: Query< + + with_blueprint_and_scene_animations: Query< ( &SceneAnimationPlayerLink, &SceneAnimations, @@ -101,15 +170,16 @@ pub fn play_animations( &BlueprintAnimations, ), (With, With), - >, */ + >, mut animation_players: Query<(&mut AnimationPlayer, &mut AnimationTransitions)>, keycode: Res>, ) { - if keycode.just_pressed(KeyCode::KeyP) { - println!("playing fox animation requested"); + if keycode.just_pressed(KeyCode::KeyQ) { + println!("playing fox blueprint animation requested"); for (link, animations) in animated_fox.iter() { - println!("animations {:?}", animations.named_animations); - println!("LINK target {}", link.0); + println!("BAR"); + + // println!("animations {:?}", animations.named_animations); let (mut animation_player, mut animation_transitions) = animation_players.get_mut(link.0).unwrap(); let anim_name = "Survey"; @@ -134,114 +204,155 @@ pub fn play_animations( println!("Playing animation {:?}", playing_animation); playing_animation.set_repeat(RepeatAnimation::Forever);*/ } + println!(""); } - /*if keycode.just_pressed(KeyCode::KeyM) { - for (link, animations) in animated_marker1.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); - let anim_name = "Blueprint1_move"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), - Duration::from_secs(5), - ) - .repeat(); - } - } - if keycode.just_pressed(KeyCode::KeyJ) { - for (link, animations) in animated_marker1.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); - let anim_name = "Blueprint1_jump"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), + if keycode.just_pressed(KeyCode::KeyP) { + println!("playing fox blueprint animation requested"); + for (link, animations) in animated_foxes.iter() { + println!("FOO"); + + // println!("animations {:?}", animations.named_animations); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); + let anim_name = "Run"; + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, Duration::from_secs(5), ) .repeat(); + + /*let Some((&playing_animation_index, _)) = animation_player.playing_animations().next() else { + continue; + }; + let playing_animation = animation_player.animation_mut(playing_animation_index).unwrap(); + println!("Playing animation {:?}", playing_animation); + playing_animation.set_repeat(RepeatAnimation::Forever);*/ } + println!(""); } - if keycode.just_pressed(KeyCode::KeyA) { - for (link, animations) in animated_marker2.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); - let anim_name = "Blueprint1_move"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), - Duration::from_secs(5), - ) - .repeat(); - } - } - if keycode.just_pressed(KeyCode::KeyB) { - for (link, animations) in animated_marker2.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); - let anim_name = "Blueprint1_jump"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), - Duration::from_secs(5), - ) - .repeat(); - } - } - - // play instance animation - if keycode.just_pressed(KeyCode::KeyW) { - for (link, animations, _, _) in animated_marker3.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); - let anim_name = "Blueprint8_move"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), - Duration::from_secs(5), - ) - .repeat(); - } - } - // play blueprint animation - if keycode.just_pressed(KeyCode::KeyX) { - for (_, _, link, animations) in animated_marker3.iter() { - println!("animations {:?}", animations.named_animations); - let mut animation_player = animation_players.get_mut(link.0).unwrap(); + if keycode.just_pressed(KeyCode::KeyO) { + println!("playing marker 3 blueprint animation requested"); + for (_, _, link, animations) in with_blueprint_and_scene_animations.iter() { + // This only works for entities that are spawned as part of the level, as scene animations are only there in that case + // println!("animations {:?}", animations.named_animations.keys()); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); let anim_name = "Walk"; - animation_player - .play_with_transition( - animations - .named_animations - .get(anim_name) - .expect("animation name should be in the list") - .clone(), + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, Duration::from_secs(5), ) .repeat(); } - }*/ + } + + if keycode.just_pressed(KeyCode::KeyI) { + println!("playing marker 3 scene animation requested"); + for (link, animations, _, _) in with_blueprint_and_scene_animations.iter() { + //println!("animations {:?}", animations.named_animations.keys()); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); + let anim_name = "Blueprint8_move"; + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, + Duration::from_secs(5), + ) + .repeat(); + } + } + + if keycode.just_pressed(KeyCode::KeyU) { + for (link, animations) in animated_marker1.iter() { + println!("animations {:?}", animations.named_animations); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); + + let anim_name = "Blueprint1_move"; + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, + Duration::from_secs(5), + ) + .repeat(); + } + } + if keycode.just_pressed(KeyCode::KeyY) { + for (link, animations) in animated_marker1.iter() { + println!("animations {:?}", animations.named_animations); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); + + let anim_name = "Blueprint1_jump"; + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, + Duration::from_secs(5), + ) + .repeat(); + } + } + if keycode.just_pressed(KeyCode::KeyT) { + for (link, animations) in animated_marker2.iter() { + println!("animations {:?}", animations.named_animations); + let (mut animation_player, mut animation_transitions) = + animation_players.get_mut(link.0).unwrap(); + + let anim_name = "Blueprint1_move"; + let animation_index = animations + .named_indices + .get(anim_name) + .expect("animation name should be in the list") + .clone(); + + animation_transitions + .play( + &mut animation_player, + animation_index, + Duration::from_secs(5), + ) + .repeat(); + } + } } pub fn react_to_animation_markers( diff --git a/testing/bevy_example/src/game/in_game.rs b/testing/bevy_example/src/game/in_game.rs index 1b3c3cc..8ee07b5 100644 --- a/testing/bevy_example/src/game/in_game.rs +++ b/testing/bevy_example/src/game/in_game.rs @@ -70,8 +70,8 @@ pub fn spawn_test( .spawn(( BluePrintBundle { blueprint: BlueprintInfo { - name: "Blueprint1".into(), - path: "blueprints/Blueprint1.glb".into(), + name: "Blueprint8_animated_no_bones".into(), + path: "blueprints/Blueprint6_animated.glb".into(), }, // FIXME ..Default::default() }, diff --git a/testing/bevy_example/src/game/mod.rs b/testing/bevy_example/src/game/mod.rs index b850203..909e350 100644 --- a/testing/bevy_example/src/game/mod.rs +++ b/testing/bevy_example/src/game/mod.rs @@ -169,7 +169,8 @@ impl Plugin for GamePlugin { app.register_type::() .register_type::() .register_type::() - .register_type::() + .register_type::() + .register_type::() .add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame))) .add_systems(Update, (validate_export, check_for_gltf_events)) @@ -178,12 +179,11 @@ impl Plugin for GamePlugin { .add_systems(OnEnter(AppState::MenuRunning), start_game) .add_systems(OnEnter(AppState::AppRunning), setup_game) - .add_systems(OnEnter(AppState::MenuRunning), setup_main_scene_animations) /* .add_systems(Update, (animations) .run_if(in_state(AppState::AppRunning)) .after(GltfBlueprintsSet::AfterSpawn) )*/ - .add_systems(Update, play_animations) + .add_systems(Update, (play_animations, check_animations)) //.add_systems(Update, react_to_animation_markers) /*.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once diff --git a/tools/blenvy/TODO.md b/tools/blenvy/TODO.md index 26a38f6..873fbad 100644 --- a/tools/blenvy/TODO.md +++ b/tools/blenvy/TODO.md @@ -228,7 +228,15 @@ Bevy Side: - [x] fix issues with deeply nested blueprints - perhaps reverse logic by using iter_ascendants - [x] fix materials handling - - [x] fix animations handling + - [ ] fix animations handling + - [x] fix/upgrade blueprint level animations + - [x] fix/upgrade scene level animations + - [ ] rename SceneAnimations to LevelAnimations (more coherent with the rest) + - [x] move sub blueprint handling to blueprints_finalize_instances +- [ ] look into component overriding , it seems broken: + - [ ] blueprint level/ collection level components are now visible in instances in Blender + - [ ] they do not seem to be transfered to the (instance) entity above: + could they be on the "empty node" ? - [ ] simplify testing example: - [x] remove use of rapier physics (or even the whole common boilerplate ?) @@ -238,16 +246,18 @@ Bevy Side: - [ ] add hot reloading - [x] basics - [x] make it enabled/disabled based on general flag + - [ ] make - [ ] cleanup internals -- [ ] review & change general component insertion & spawning ordering & logic + +- [x] review & change general component insertion & spawning ordering & logic - GltfComponentsSet::Injection => GltfBlueprintsSet::Spawn => GltfBlueprintsSet::AfterSpawn Injection => inject lights & co => spawn => afterSpawn => Injection => inject lights & co - [ ] add a way of overriding assets for collection instances => doubt this is possible - [ ] cleanup all the spurious debug messages -- [ ] fix animation handling - - [ ] how to deal with animation graphs ? +- [x] fix animation handling + - [x] how to deal with animation graphs ? - [ ] update main docs - [ ] rename project to Blenvy diff --git a/tools/blenvy/add_ons/auto_export/constants.py b/tools/blenvy/add_ons/auto_export/constants.py index 458359f..1f34ab2 100644 --- a/tools/blenvy/add_ons/auto_export/constants.py +++ b/tools/blenvy/add_ons/auto_export/constants.py @@ -9,4 +9,3 @@ custom_properties_to_filter_out = [ 'Blenvy_scene_type', 'blenvy_scene_type', 'Materials_path', 'Export_path' ] -#['_combine', 'template', 'components_meta', 'Components_meta', 'Blenvy_scene_type']