From 0998decb3915932c88a89c606428d474a0a07695 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 5 Apr 2024 00:17:07 +0200 Subject: [PATCH] feat(animation): changes & some reverts of the latests experiments --- crates/bevy_gltf_blueprints/src/animation.rs | 134 +++++++++--------- crates/bevy_gltf_blueprints/src/lib.rs | 3 + testing/bevy_example/src/game/animation.rs | 7 +- testing/bevy_example/src/game/mod.rs | 1 - .../auto_export/export_gltf.py | 1 - .../get_standard_exporter_settings.py | 9 -- .../helpers/helpers_scenes.py | 2 +- 7 files changed, 74 insertions(+), 83 deletions(-) delete mode 100644 tools/gltf_auto_export/auto_export/get_standard_exporter_settings.py diff --git a/crates/bevy_gltf_blueprints/src/animation.rs b/crates/bevy_gltf_blueprints/src/animation.rs index 8e73aaa..0b3b96d 100644 --- a/crates/bevy_gltf_blueprints/src/animation.rs +++ b/crates/bevy_gltf_blueprints/src/animation.rs @@ -48,9 +48,11 @@ pub struct AnimationInfos { pub animations: Vec, } +#[derive( Reflect, Default, Debug)] pub struct AnimationMarker { - pub frame: u32, + // pub frame: u32, pub name: String, + pub handled_for_cycle: bool, } /// Stores information about animation markers: practical for adding things like triggering events at specific keyframes etc @@ -59,18 +61,6 @@ pub struct AnimationMarker { #[reflect(Component)] pub struct AnimationMarkers(pub HashMap>>); -// FIXME: ugh, ugly, there has to be a better way to do this ? -#[derive(Component, Default, Debug)] -pub struct AnimationMarkerTrackers(pub HashMap>>); - -#[derive(Default, Debug)] -pub struct AnimationMarkerTracker { - // pub frame:u32, - // pub name: String, - // pub processed_for_cycle: bool, - pub prev_frame: u32, -} - /// Event that gets triggered once a specific marker inside an animation has been reached (frame based) /// Provides some usefull information about which entity , wich animation, wich frame & which marker got triggered #[derive(Event, Debug)] @@ -132,15 +122,19 @@ pub fn trigger_instance_animation_markers_events( let matching_animation_marker = &markers.0[animation_name]; if matching_animation_marker.contains_key(&frame) { let matching_markers_per_frame = matching_animation_marker.get(&frame).unwrap(); + + let foo = animation_length_seconds - time_in_animation; + println!("foo {}", foo); // println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame); // emit an event AnimationMarkerReached(entity, animation_name, frame, marker_name) // FIXME: problem, this can fire multiple times in a row, depending on animation length , speed , etc - for marker_name in matching_markers_per_frame { + for marker in matching_markers_per_frame { + animation_marker_events.send(AnimationMarkerReached { entity: entity, animation_name: animation_name.clone(), frame: frame, - marker_name: marker_name.clone(), + marker_name: marker.clone(), }); } } @@ -167,61 +161,67 @@ pub fn trigger_blueprint_animation_markers_events( let animation_clip = animation_clips.get(animation_player.animation_clip()); // FIXME: horrible code - let mut markers:Option<&AnimationMarkers>= None; - let mut animation_infos:Option<&AnimationInfos>=None; - for (_, _markers, _animation_infos, parent) in all_animation_infos.iter(){ + for (_, markers, animation_infos, parent) in all_animation_infos.iter(){ if parent.get() == entity { - markers = Some(_markers); - animation_infos = Some(_animation_infos); + if animation_clip.is_some() { + + // println!("Entity {:?} markers {:?}", entity, markers); + // println!("Player {:?} {}", animation_player.elapsed(), animation_player.completions()); + // FIMXE: yikes ! very inneficient ! perhaps add boilerplate to the "start playing animation" code so we know what is playing + let animation_name = animations.named_animations.iter().find_map(|(key, value)| { + if value == animation_player.animation_clip() { + Some(key) + } else { + None + } + }); + if animation_name.is_some() { + let animation_name = animation_name.unwrap(); + let animation_length_seconds = animation_clip.unwrap().duration(); + let animation_length_frames = animation_infos + .animations + .iter() + .find(|anim| &anim.name == animation_name) + .unwrap() + .frames_length; + // TODO: we also need to take playback speed into account + let time_in_animation = animation_player.elapsed() + - (animation_player.completions() as f32) * animation_length_seconds; + let frame_seconds = + (animation_length_frames / animation_length_seconds) * time_in_animation; + // println!("frame seconds {}", frame_seconds); + let frame = frame_seconds.ceil() as u32; // FIXME , bad hack + + let matching_animation_marker = &markers.0[animation_name]; + + + if matching_animation_marker.contains_key(&frame) { + let matching_markers_per_frame = matching_animation_marker.get(&frame).unwrap(); + // println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame); + // emit an event AnimationMarkerReached(entity, animation_name, frame, marker_name) + // FIXME: complete hack-ish solution , otherwise this can fire multiple times in a row, depending on animation length , speed , etc + let diff = frame as f32 - frame_seconds; + if diff < 0.03 { + for marker in matching_markers_per_frame { + + animation_marker_events.send(AnimationMarkerReached { + entity: entity, + animation_name: animation_name.clone(), + frame: frame, + marker_name: marker.clone(), + }); + } + } + + } + } + } + + + break; } } - if animation_clip.is_some() && markers.is_some() && animation_infos.is_some() { - let markers = markers.unwrap(); - let animation_infos = animation_infos.unwrap(); - - // println!("Entity {:?} markers {:?}", entity, markers); - // println!("Player {:?} {}", animation_player.elapsed(), animation_player.completions()); - // FIMXE: yikes ! very inneficient ! perhaps add boilerplate to the "start playing animation" code so we know what is playing - let animation_name = animations.named_animations.iter().find_map(|(key, value)| { - if value == animation_player.animation_clip() { - Some(key) - } else { - None - } - }); - if animation_name.is_some() { - let animation_name = animation_name.unwrap(); - let animation_length_seconds = animation_clip.unwrap().duration(); - let animation_length_frames = animation_infos - .animations - .iter() - .find(|anim| &anim.name == animation_name) - .unwrap() - .frames_length; - // TODO: we also need to take playback speed into account - let time_in_animation = animation_player.elapsed() - - (animation_player.completions() as f32) * animation_length_seconds; - let frame_seconds = - (animation_length_frames as f32 / animation_length_seconds) * time_in_animation; - let frame = frame_seconds as u32; - - let matching_animation_marker = &markers.0[animation_name]; - if matching_animation_marker.contains_key(&frame) { - let matching_markers_per_frame = matching_animation_marker.get(&frame).unwrap(); - // println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame); - // emit an event AnimationMarkerReached(entity, animation_name, frame, marker_name) - // FIXME: problem, this can fire multiple times in a row, depending on animation length , speed , etc - for marker_name in matching_markers_per_frame { - animation_marker_events.send(AnimationMarkerReached { - entity: entity, - animation_name: animation_name.clone(), - frame: frame, - marker_name: marker_name.clone(), - }); - } - } - } - } + } } \ No newline at end of file diff --git a/crates/bevy_gltf_blueprints/src/lib.rs b/crates/bevy_gltf_blueprints/src/lib.rs index cef5b04..a1be51b 100644 --- a/crates/bevy_gltf_blueprints/src/lib.rs +++ b/crates/bevy_gltf_blueprints/src/lib.rs @@ -119,6 +119,7 @@ impl Plugin for BlueprintsPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() .register_type::() .register_type::() @@ -127,7 +128,9 @@ impl Plugin for BlueprintsPlugin { .register_type::() .register_type::>>() .register_type::>>>() + .add_event::() + .register_type::() .register_type::>>() .insert_resource(BluePrintsConfig { diff --git a/testing/bevy_example/src/game/animation.rs b/testing/bevy_example/src/game/animation.rs index 38aaf92..2fbfb9a 100644 --- a/testing/bevy_example/src/game/animation.rs +++ b/testing/bevy_example/src/game/animation.rs @@ -1,13 +1,12 @@ use std::time::Duration; use bevy_gltf_blueprints::{ - AnimationInfos, AnimationMarkerReached, AnimationMarkerTrackers, AnimationMarkers, - BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList, - GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations, + AnimationInfos, AnimationMarkerReached, + BlueprintAnimationPlayerLink, BlueprintAnimations, + InstanceAnimationPlayerLink, InstanceAnimations, }; use bevy::{gltf::Gltf, prelude::*}; -use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState}; #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] diff --git a/testing/bevy_example/src/game/mod.rs b/testing/bevy_example/src/game/mod.rs index ead2735..82c78c8 100644 --- a/testing/bevy_example/src/game/mod.rs +++ b/testing/bevy_example/src/game/mod.rs @@ -6,7 +6,6 @@ pub use in_game::*; use std::{collections::HashMap, fs, time::Duration}; use bevy_gltf_blueprints::{ - AnimationInfos, AnimationMarkerReached, AnimationMarkerTrackers, AnimationMarkers, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList, GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations, }; diff --git a/tools/gltf_auto_export/auto_export/export_gltf.py b/tools/gltf_auto_export/auto_export/export_gltf.py index 7b32e6a..221913b 100644 --- a/tools/gltf_auto_export/auto_export/export_gltf.py +++ b/tools/gltf_auto_export/auto_export/export_gltf.py @@ -2,7 +2,6 @@ import json import os import bpy -from .get_standard_exporter_settings import get_standard_exporter_settings from .preferences import (AutoExportGltfPreferenceNames) def generate_gltf_export_preferences(addon_prefs): diff --git a/tools/gltf_auto_export/auto_export/get_standard_exporter_settings.py b/tools/gltf_auto_export/auto_export/get_standard_exporter_settings.py deleted file mode 100644 index 4af09ef..0000000 --- a/tools/gltf_auto_export/auto_export/get_standard_exporter_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -import bpy - -def get_standard_exporter_settings(): - settings_key = 'glTF2ExportSettings' - for scene in bpy.data.scenes: - if settings_key in scene: - settings = scene[settings_key] - #print("standard exporter settings", settings, dict(settings)) - return dict(settings) \ No newline at end of file diff --git a/tools/gltf_auto_export/helpers/helpers_scenes.py b/tools/gltf_auto_export/helpers/helpers_scenes.py index 6eb061b..74e74cf 100644 --- a/tools/gltf_auto_export/helpers/helpers_scenes.py +++ b/tools/gltf_auto_export/helpers/helpers_scenes.py @@ -80,7 +80,7 @@ def copy_animation_data(source, target): markers_formated += '}, ' markers_formated += '}' target["AnimationMarkers"] = f'( {markers_formated} )' - + """print("copying animation data for", source.name, target.animation_data) properties = [p.identifier for p in source.animation_data.bl_rna.properties if not p.is_readonly] for prop in properties: