feat(animation): changes & some reverts of the latests experiments

This commit is contained in:
kaosat.dev 2024-04-05 00:17:07 +02:00
parent 0528286b12
commit 0998decb39
7 changed files with 74 additions and 83 deletions

View File

@ -48,9 +48,11 @@ pub struct AnimationInfos {
pub animations: Vec<AnimationInfo>, pub animations: Vec<AnimationInfo>,
} }
#[derive( Reflect, Default, Debug)]
pub struct AnimationMarker { pub struct AnimationMarker {
pub frame: u32, // pub frame: u32,
pub name: String, pub name: String,
pub handled_for_cycle: bool,
} }
/// Stores information about animation markers: practical for adding things like triggering events at specific keyframes etc /// 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)] #[reflect(Component)]
pub struct AnimationMarkers(pub HashMap<String, HashMap<u32, Vec<String>>>); pub struct AnimationMarkers(pub HashMap<String, HashMap<u32, Vec<String>>>);
// FIXME: ugh, ugly, there has to be a better way to do this ?
#[derive(Component, Default, Debug)]
pub struct AnimationMarkerTrackers(pub HashMap<String, HashMap<u32, Vec<AnimationMarkerTracker>>>);
#[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) /// 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 /// Provides some usefull information about which entity , wich animation, wich frame & which marker got triggered
#[derive(Event, Debug)] #[derive(Event, Debug)]
@ -132,15 +122,19 @@ pub fn trigger_instance_animation_markers_events(
let matching_animation_marker = &markers.0[animation_name]; let matching_animation_marker = &markers.0[animation_name];
if matching_animation_marker.contains_key(&frame) { if matching_animation_marker.contains_key(&frame) {
let matching_markers_per_frame = matching_animation_marker.get(&frame).unwrap(); 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); // println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame);
// emit an event AnimationMarkerReached(entity, animation_name, frame, marker_name) // 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 // 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 { animation_marker_events.send(AnimationMarkerReached {
entity: entity, entity: entity,
animation_name: animation_name.clone(), animation_name: animation_name.clone(),
frame: frame, 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()); let animation_clip = animation_clips.get(animation_player.animation_clip());
// FIXME: horrible code // FIXME: horrible code
let mut markers:Option<&AnimationMarkers>= None; for (_, markers, animation_infos, parent) in all_animation_infos.iter(){
let mut animation_infos:Option<&AnimationInfos>=None;
for (_, _markers, _animation_infos, parent) in all_animation_infos.iter(){
if parent.get() == entity { if parent.get() == entity {
markers = Some(_markers); if animation_clip.is_some() {
animation_infos = Some(_animation_infos);
// 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; 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(),
});
}
}
}
}
} }
} }

View File

@ -119,6 +119,7 @@ impl Plugin for BlueprintsPlugin {
.register_type::<BlueprintName>() .register_type::<BlueprintName>()
.register_type::<MaterialInfo>() .register_type::<MaterialInfo>()
.register_type::<SpawnHere>() .register_type::<SpawnHere>()
.register_type::<BlueprintAnimations>() .register_type::<BlueprintAnimations>()
.register_type::<InstanceAnimations>() .register_type::<InstanceAnimations>()
.register_type::<AnimationInfo>() .register_type::<AnimationInfo>()
@ -127,7 +128,9 @@ impl Plugin for BlueprintsPlugin {
.register_type::<AnimationMarkers>() .register_type::<AnimationMarkers>()
.register_type::<HashMap<u32, Vec<String>>>() .register_type::<HashMap<u32, Vec<String>>>()
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>() .register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
.add_event::<AnimationMarkerReached>() .add_event::<AnimationMarkerReached>()
.register_type::<BlueprintsList>() .register_type::<BlueprintsList>()
.register_type::<HashMap<String, Vec<String>>>() .register_type::<HashMap<String, Vec<String>>>()
.insert_resource(BluePrintsConfig { .insert_resource(BluePrintsConfig {

View File

@ -1,13 +1,12 @@
use std::time::Duration; use std::time::Duration;
use bevy_gltf_blueprints::{ use bevy_gltf_blueprints::{
AnimationInfos, AnimationMarkerReached, AnimationMarkerTrackers, AnimationMarkers, AnimationInfos, AnimationMarkerReached,
BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList, BlueprintAnimationPlayerLink, BlueprintAnimations,
GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations, InstanceAnimationPlayerLink, InstanceAnimations,
}; };
use bevy::{gltf::Gltf, prelude::*}; use bevy::{gltf::Gltf, prelude::*};
use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
#[derive(Component, Reflect, Default, Debug)] #[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)] #[reflect(Component)]

View File

@ -6,7 +6,6 @@ pub use in_game::*;
use std::{collections::HashMap, fs, time::Duration}; use std::{collections::HashMap, fs, time::Duration};
use bevy_gltf_blueprints::{ use bevy_gltf_blueprints::{
AnimationInfos, AnimationMarkerReached, AnimationMarkerTrackers, AnimationMarkers,
BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList,
GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations, GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations,
}; };

View File

@ -2,7 +2,6 @@ import json
import os import os
import bpy import bpy
from .get_standard_exporter_settings import get_standard_exporter_settings
from .preferences import (AutoExportGltfPreferenceNames) from .preferences import (AutoExportGltfPreferenceNames)
def generate_gltf_export_preferences(addon_prefs): def generate_gltf_export_preferences(addon_prefs):

View File

@ -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)

View File

@ -80,7 +80,7 @@ def copy_animation_data(source, target):
markers_formated += '}, ' markers_formated += '}, '
markers_formated += '}' markers_formated += '}'
target["AnimationMarkers"] = f'( {markers_formated} )' target["AnimationMarkers"] = f'( {markers_formated} )'
"""print("copying animation data for", source.name, target.animation_data) """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] properties = [p.identifier for p in source.animation_data.bl_rna.properties if not p.is_readonly]
for prop in properties: for prop in properties: