Skip to content

Commit

Permalink
Merge pull request #795 from AmbientRun/anim-refactor
Browse files Browse the repository at this point in the history
Refactor animations
  • Loading branch information
FredrikNoren authored Sep 5, 2023
2 parents 8549067 + 7cc51d6 commit 64209c0
Show file tree
Hide file tree
Showing 15 changed files with 525 additions and 561 deletions.
55 changes: 31 additions & 24 deletions crates/animation/src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ use ambient_ecs::{
children, components,
generated::animation::components::{
animation_errors, apply_animation_player, apply_base_pose, bind_ids, blend, clip_duration,
freeze_at_percentage, freeze_at_time, is_animation_player, looping, mask_bind_ids,
mask_weights, play_clip_from_url, retarget_animation_scaled, retarget_model_from_url,
speed, start_time,
clip_loaded, freeze_at_percentage, freeze_at_time, is_animation_player, looping,
mask_bind_ids, mask_weights, play_clip_from_url, retarget_animation_scaled,
retarget_model_from_url, speed, start_time,
},
query, ComponentDesc, Debuggable, EntityId, SystemGroup, World,
};
use ambient_model::{animation_binder, ModelFromUrl};
use ambient_native_std::{
asset_cache::{AssetCache, AsyncAssetKeyExt},
asset_url::{AnimationAssetType, TypedAssetUrl},
download_asset::AssetResult,
};
use anyhow::Context;
use glam::{Quat, Vec3};
Expand Down Expand Up @@ -202,6 +203,7 @@ pub fn animation_player_systems() -> SystemGroup {
query(play_clip_from_url().changed()).to_system(|q, world, qs, _| {
let runtime = world.resource(runtime()).clone();
for (id, url) in q.collect_cloned(world, qs) {
world.remove_component(id, clip_loaded()).ok();
let async_run = world.resource(async_run()).clone();
let assets = world.resource(asset_cache()).clone();
let url = match TypedAssetUrl::<AnimationAssetType>::from_str(&url) {
Expand All @@ -226,35 +228,40 @@ pub fn animation_player_systems() -> SystemGroup {
} else {
AnimationRetargeting::None
};
runtime.spawn(async move {
let clip = AnimationClipRetargetedFromModel {
clip: url,
translation_retargeting: retargeting,
retarget_model,
}
.get(&assets)
.await;
let duration = clip.as_ref().map(|clip| clip.duration()).unwrap_or(0.);
let binders = clip
.as_ref()
.map(|clip| {
clip.tracks
let clip_ref = AnimationClipRetargetedFromModel {
clip: url,
translation_retargeting: retargeting,
retarget_model,
};
let apply_clip =
move |world: &mut World, clip: AssetResult<Arc<AnimationClip>>| {
if let Ok(clip) = clip {
world
.add_component(id, clip_duration(), clip.duration())
.ok();
let binders = clip
.tracks
.iter()
.filter_map(|x| match &x.target {
AnimationTarget::BinderId(binder) => Some(binder.clone()),
AnimationTarget::Entity(_entity) => None,
})
.collect::<Vec<_>>()
})
.unwrap_or_default();
async_run.run(move |world| {
world.add_component(id, clip_duration(), duration).ok();
world.add_component(id, bind_ids(), binders).ok();
if let Ok(clip) = clip {
.collect::<Vec<_>>();
world.add_component(id, bind_ids(), binders).ok();
world.add_component(id, play_clip(), clip).ok();
}
world.add_component(id, clip_loaded(), ()).ok();
};
if let Some(clip) = clip_ref.peek(&assets) {
apply_clip(world, clip);
} else {
runtime.spawn(async move {
let clip = clip_ref.get(&assets).await;
async_run.run(move |world| {
apply_clip(world, clip);
});
});
});
}
}
}),
query(play_clip_from_url().changed())
Expand Down
2 changes: 1 addition & 1 deletion crates/ecs/src/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mod raw {
};
use glam::{Mat4, Quat, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4};
use std::time::Duration;
components ! ("animation" , { # [doc = "**Is animation player**: This entity is treated as an animation player. Attach an animation node as a child for it to play.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Is animation player"] , Description ["This entity is treated as an animation player. Attach an animation node as a child for it to play."]] is_animation_player : () , # [doc = "**Animation errors**: A list of errors that were produced trying to play the animation.\n\n*Attributes*: MaybeResource, Debuggable"] @ [MaybeResource , Debuggable , Name ["Animation errors"] , Description ["A list of errors that were produced trying to play the animation."]] animation_errors : Vec :: < String > , # [doc = "**Apply animation player**: Apply the designated animation player to this entity and its sub-tree.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Apply animation player"] , Description ["Apply the designated animation player to this entity and its sub-tree."]] apply_animation_player : EntityId , # [doc = "**Play clip from URL**: Make this entity a 'play animation clip' node. The value is the URL to the clip we'd like to play.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Play clip from URL"] , Description ["Make this entity a 'play animation clip' node. The value is the URL to the clip we'd like to play."]] play_clip_from_url : String , # [doc = "**Looping**: When this is true, the animation clip will repeat infinitely.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Looping"] , Description ["When this is true, the animation clip will repeat infinitely."]] looping : bool , # [doc = "**Speed**: Animation playback speed. Default is 1, higher values speeds up the animation.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Speed"] , Description ["Animation playback speed. Default is 1, higher values speeds up the animation."]] speed : f32 , # [doc = "**Start time**: Start time of an animation node.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Start time"] , Description ["Start time of an animation node."]] start_time : Duration , # [doc = "**Freeze at percentage**: Sample the input animation at a certain percentage of the animation track length.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Freeze at percentage"] , Description ["Sample the input animation at a certain percentage of the animation track length."]] freeze_at_percentage : f32 , # [doc = "**Freeze at time**: Sample the input animation at a certain time (in seconds).\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Freeze at time"] , Description ["Sample the input animation at a certain time (in seconds)."]] freeze_at_time : f32 , # [doc = "**Clip duration**: The clip duration is loaded from the clip, and then applied to the entity.\n\n*Attributes*: MaybeResource, Debuggable"] @ [MaybeResource , Debuggable , Name ["Clip duration"] , Description ["The clip duration is loaded from the clip, and then applied to the entity."]] clip_duration : f32 , # [doc = "**Blend**: Blend two animations together. The values is the blend weight. Use `children` to set the animations. Blend 0 means we only sample from the first animation, 1 means only the second one, and values in between blend between them.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Blend"] , Description ["Blend two animations together. The values is the blend weight. Use `children` to set the animations. Blend 0 means we only sample from the first animation, 1 means only the second one, and values in between blend between them."]] blend : f32 , # [doc = "**Mask bind ids**: List of bind ids that will be masked.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Mask bind ids"] , Description ["List of bind ids that will be masked."]] mask_bind_ids : Vec :: < String > , # [doc = "**Mask weights**: Weights for each bind id in `mask_bind_ids`.\n\n*Attributes*: MaybeResource, Debuggable, Networked"] @ [MaybeResource , Debuggable , Networked , Name ["Mask weights"] , Description ["Weights for each bind id in `mask_bind_ids`."]] mask_weights : Vec :: < f32 > , # [doc = "**Retarget Model from URL**: Retarget the animation using the model at the given URL.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Retarget Model from URL"] , Description ["Retarget the animation using the model at the given URL."]] retarget_model_from_url : String , # [doc = "**Retarget animation scaled**: Retarget animation scaled. True means normalize hip.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Retarget animation scaled"] , Description ["Retarget animation scaled. True means normalize hip."]] retarget_animation_scaled : bool , # [doc = "**Apply base pose**: Apply the base pose to this clip.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Apply base pose"] , Description ["Apply the base pose to this clip."]] apply_base_pose : () , # [doc = "**Bind id**: Animation bind ID.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Bind id"] , Description ["Animation bind ID."]] bind_id : String , # [doc = "**Bind ids**: Animation bind IDs.\n\n*Attributes*: Debuggable, Store"] @ [Debuggable , Store , Name ["Bind ids"] , Description ["Animation bind IDs."]] bind_ids : Vec :: < String > , });
components ! ("animation" , { # [doc = "**Is animation player**: This entity is treated as an animation player. Attach an animation node as a child for it to play.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Is animation player"] , Description ["This entity is treated as an animation player. Attach an animation node as a child for it to play."]] is_animation_player : () , # [doc = "**Animation errors**: A list of errors that were produced trying to play the animation.\n\n*Attributes*: Debuggable"] @ [Debuggable , Name ["Animation errors"] , Description ["A list of errors that were produced trying to play the animation."]] animation_errors : Vec :: < String > , # [doc = "**Apply animation player**: Apply the designated animation player to this entity and its sub-tree.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Apply animation player"] , Description ["Apply the designated animation player to this entity and its sub-tree."]] apply_animation_player : EntityId , # [doc = "**Play clip from URL**: Make this entity a 'play animation clip' node. The value is the URL to the clip we'd like to play.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Play clip from URL"] , Description ["Make this entity a 'play animation clip' node. The value is the URL to the clip we'd like to play."]] play_clip_from_url : String , # [doc = "**Looping**: When this is true, the animation clip will repeat infinitely.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Looping"] , Description ["When this is true, the animation clip will repeat infinitely."]] looping : bool , # [doc = "**Speed**: Animation playback speed. Default is 1, higher values speeds up the animation.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Speed"] , Description ["Animation playback speed. Default is 1, higher values speeds up the animation."]] speed : f32 , # [doc = "**Start time**: Start time of an animation node.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Start time"] , Description ["Start time of an animation node."]] start_time : Duration , # [doc = "**Freeze at percentage**: Sample the input animation at a certain percentage of the animation track length.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Freeze at percentage"] , Description ["Sample the input animation at a certain percentage of the animation track length."]] freeze_at_percentage : f32 , # [doc = "**Freeze at time**: Sample the input animation at a certain time (in seconds).\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Freeze at time"] , Description ["Sample the input animation at a certain time (in seconds)."]] freeze_at_time : f32 , # [doc = "**Clip duration**: The clip duration is loaded from the clip, and then applied to the entity.\n\n*Attributes*: Debuggable"] @ [Debuggable , Name ["Clip duration"] , Description ["The clip duration is loaded from the clip, and then applied to the entity."]] clip_duration : f32 , # [doc = "**Clip loaded**: The clip has been loaded.\n\n*Attributes*: Debuggable"] @ [Debuggable , Name ["Clip loaded"] , Description ["The clip has been loaded."]] clip_loaded : () , # [doc = "**Blend**: Blend two animations together. The values is the blend weight. Use `children` to set the animations. Blend 0 means we only sample from the first animation, 1 means only the second one, and values in between blend between them.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Blend"] , Description ["Blend two animations together. The values is the blend weight. Use `children` to set the animations. Blend 0 means we only sample from the first animation, 1 means only the second one, and values in between blend between them."]] blend : f32 , # [doc = "**Mask bind ids**: List of bind ids that will be masked.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Mask bind ids"] , Description ["List of bind ids that will be masked."]] mask_bind_ids : Vec :: < String > , # [doc = "**Mask weights**: Weights for each bind id in `mask_bind_ids`.\n\n*Attributes*: Debuggable, Networked"] @ [Debuggable , Networked , Name ["Mask weights"] , Description ["Weights for each bind id in `mask_bind_ids`."]] mask_weights : Vec :: < f32 > , # [doc = "**Retarget Model from URL**: Retarget the animation using the model at the given URL.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Retarget Model from URL"] , Description ["Retarget the animation using the model at the given URL."]] retarget_model_from_url : String , # [doc = "**Retarget animation scaled**: Retarget animation scaled. True means normalize hip.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Retarget animation scaled"] , Description ["Retarget animation scaled. True means normalize hip."]] retarget_animation_scaled : bool , # [doc = "**Apply base pose**: Apply the base pose to this clip.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Apply base pose"] , Description ["Apply the base pose to this clip."]] apply_base_pose : () , # [doc = "**Bind id**: Animation bind ID.\n\n*Attributes*: Debuggable, Networked, Store"] @ [Debuggable , Networked , Store , Name ["Bind id"] , Description ["Animation bind ID."]] bind_id : String , # [doc = "**Bind ids**: Animation bind IDs.\n\n*Attributes*: Debuggable, Store"] @ [Debuggable , Store , Name ["Bind ids"] , Description ["Animation bind IDs."]] bind_ids : Vec :: < String > , });
}
}
#[allow(unused)]
Expand Down
Loading

0 comments on commit 64209c0

Please sign in to comment.