mirror of
https://github.com/storytold/bevy-mocap.git
synced 2026-10-28 08:47:47 +00:00
loading animation
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap},
|
pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
use bevy_facial_mocap::{CSVAnimationLoader, CSVAnimationLoaderSettings};
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -9,10 +12,15 @@ fn main() {
|
|||||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_plugins(WorldInspectorPlugin::new())
|
.add_plugins(WorldInspectorPlugin::new())
|
||||||
|
.init_asset_loader::<CSVAnimationLoader>()
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
|
.add_systems(Update, setup_animation)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct AnimationRunning(Handle<AnimationClip>);
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera3dBundle {
|
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),
|
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()
|
..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 std::{num::ParseFloatError, str::FromStr};
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
animation::{AnimationClip, EntityPath, Keyframes, VariableCurve},
|
animation::{self, AnimationClip, EntityPath, Keyframes, VariableCurve}, asset::{meta::Settings, Asset, AssetLoader, AsyncReadExt}, core::Name, reflect::Reflect
|
||||||
asset::{Asset, AssetLoader, AsyncReadExt},
|
|
||||||
reflect::Reflect,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Reflect, Default,
|
Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Reflect, Default,
|
||||||
@@ -222,10 +220,10 @@ impl From<CSVAnimation> for VariableCurve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CSVAnimation> for AnimationClip {
|
impl CSVAnimation {
|
||||||
fn from(val: CSVAnimation) -> Self {
|
fn generate_clip(self, path: &EntityPath) -> AnimationClip {
|
||||||
let mut clip = Self::default();
|
let mut clip = AnimationClip::default();
|
||||||
clip.add_curve_to_path(EntityPath::default(), val.into());
|
clip.add_curve_to_path(path.clone(), self.into());
|
||||||
|
|
||||||
clip
|
clip
|
||||||
}
|
}
|
||||||
@@ -249,17 +247,38 @@ impl std::fmt::Display for CSVAnimationLoaderError {
|
|||||||
|
|
||||||
impl std::error::Error 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 {
|
impl AssetLoader for CSVAnimationLoader {
|
||||||
type Asset = AnimationClip;
|
type Asset = AnimationClip;
|
||||||
|
|
||||||
type Settings = ();
|
type Settings = CSVAnimationLoaderSettings;
|
||||||
|
|
||||||
type Error = CSVAnimationLoaderError;
|
type Error = CSVAnimationLoaderError;
|
||||||
|
|
||||||
fn load<'a>(
|
fn load<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
reader: &'a mut bevy::asset::io::Reader,
|
reader: &'a mut bevy::asset::io::Reader,
|
||||||
_settings: &'a Self::Settings,
|
settings: &'a Self::Settings,
|
||||||
_load_context: &'a mut bevy::asset::LoadContext,
|
_load_context: &'a mut bevy::asset::LoadContext,
|
||||||
) -> bevy::utils::BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
|
) -> bevy::utils::BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
@@ -270,7 +289,10 @@ impl AssetLoader for CSVAnimationLoader {
|
|||||||
.map_err(CSVAnimationLoaderError::Io)?;
|
.map_err(CSVAnimationLoaderError::Io)?;
|
||||||
let csv_animation =
|
let csv_animation =
|
||||||
CSVAnimation::parse(&csv).map_err(CSVAnimationLoaderError::CSVParseError)?;
|
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",
|
00:00:01:01.00, 0, 0, 0",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let clip: AnimationClip = animation.into();
|
let clip: AnimationClip = animation.generate_clip(&EntityPath::default());
|
||||||
assert!(clip.duration() - 1.33333 < 0.1);
|
assert!(clip.duration() - 1.33333 < 0.1);
|
||||||
let curves = clip
|
let curves = clip
|
||||||
.get_curves_by_path(&EntityPath::default())
|
.get_curves_by_path(&EntityPath::default())
|
||||||
|
|||||||
Reference in New Issue
Block a user