mirror of
https://github.com/storytold/bevy-mocap.git
synced 2026-10-09 00:09:45 +00:00
loading animation
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use bevy::{
|
||||
pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap},
|
||||
prelude::*,
|
||||
};
|
||||
use bevy_facial_mocap::{CSVAnimationLoader, CSVAnimationLoaderSettings};
|
||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||
|
||||
fn main() {
|
||||
@@ -9,10 +12,15 @@ fn main() {
|
||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugins(WorldInspectorPlugin::new())
|
||||
.init_asset_loader::<CSVAnimationLoader>()
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, setup_animation)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct AnimationRunning(Handle<AnimationClip>);
|
||||
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
|
||||
@@ -42,3 +50,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
..default()
|
||||
});
|
||||
}
|
||||
|
||||
fn setup_animation(mut commands: Commands, asset_server: Res<AssetServer>, mut players: Query<Entity, (With<MorphWeights>, Without<AnimationRunning>)>) {
|
||||
for entity in &mut players {
|
||||
let handle = asset_server.load_with_settings("20240205_shapekey_BevyImplementationFaceCap_5/shapekey_BevyImplementationFaceCap_5_ScottiPhone_raw.morph_anim.csv", |s: &mut CSVAnimationLoaderSettings| { s.0.parts = vec![Name::new("pascal_Head")]; });
|
||||
let mut player = AnimationPlayer::default();
|
||||
player.play(handle.clone()).repeat();
|
||||
|
||||
commands.entity(entity).insert((AnimationRunning(handle), player));
|
||||
}
|
||||
}
|
||||
|
||||
+34
-12
@@ -1,11 +1,9 @@
|
||||
use std::{num::ParseFloatError, str::FromStr};
|
||||
|
||||
use bevy::{
|
||||
animation::{AnimationClip, EntityPath, Keyframes, VariableCurve},
|
||||
asset::{Asset, AssetLoader, AsyncReadExt},
|
||||
reflect::Reflect,
|
||||
animation::{self, AnimationClip, EntityPath, Keyframes, VariableCurve}, asset::{meta::Settings, Asset, AssetLoader, AsyncReadExt}, core::Name, reflect::Reflect
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Reflect, Default,
|
||||
@@ -222,10 +220,10 @@ impl From<CSVAnimation> for VariableCurve {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CSVAnimation> for AnimationClip {
|
||||
fn from(val: CSVAnimation) -> Self {
|
||||
let mut clip = Self::default();
|
||||
clip.add_curve_to_path(EntityPath::default(), val.into());
|
||||
impl CSVAnimation {
|
||||
fn generate_clip(self, path: &EntityPath) -> AnimationClip {
|
||||
let mut clip = AnimationClip::default();
|
||||
clip.add_curve_to_path(path.clone(), self.into());
|
||||
|
||||
clip
|
||||
}
|
||||
@@ -249,17 +247,38 @@ impl std::fmt::Display for CSVAnimationLoaderError {
|
||||
|
||||
impl std::error::Error for CSVAnimationLoaderError {}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CSVAnimationLoaderSettings(pub EntityPath);
|
||||
|
||||
impl Serialize for CSVAnimationLoaderSettings {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer {
|
||||
let names = self.0.parts.iter().map(|name| name.to_string()).collect::<Vec<String>>();
|
||||
names.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for CSVAnimationLoaderSettings {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de> {
|
||||
let names = Vec::<String>::deserialize(deserializer)?;
|
||||
Ok(CSVAnimationLoaderSettings(EntityPath { parts: names.into_iter().map(|name| Name::new(name)).collect() }))
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetLoader for CSVAnimationLoader {
|
||||
type Asset = AnimationClip;
|
||||
|
||||
type Settings = ();
|
||||
type Settings = CSVAnimationLoaderSettings;
|
||||
|
||||
type Error = CSVAnimationLoaderError;
|
||||
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut bevy::asset::io::Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
settings: &'a Self::Settings,
|
||||
_load_context: &'a mut bevy::asset::LoadContext,
|
||||
) -> bevy::utils::BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
|
||||
Box::pin(async move {
|
||||
@@ -270,7 +289,10 @@ impl AssetLoader for CSVAnimationLoader {
|
||||
.map_err(CSVAnimationLoaderError::Io)?;
|
||||
let csv_animation =
|
||||
CSVAnimation::parse(&csv).map_err(CSVAnimationLoaderError::CSVParseError)?;
|
||||
Ok(csv_animation.into())
|
||||
|
||||
let animation = csv_animation.generate_clip(&settings.0);
|
||||
|
||||
Ok(animation)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -423,7 +445,7 @@ mod tests {
|
||||
00:00:01:01.00, 0, 0, 0",
|
||||
)
|
||||
.unwrap();
|
||||
let clip: AnimationClip = animation.into();
|
||||
let clip: AnimationClip = animation.generate_clip(&EntityPath::default());
|
||||
assert!(clip.duration() - 1.33333 < 0.1);
|
||||
let curves = clip
|
||||
.get_curves_by_path(&EntityPath::default())
|
||||
|
||||
Reference in New Issue
Block a user