From d0e26bdaa2afb6c6ba8c20aceddb33b5bc351b19 Mon Sep 17 00:00:00 2001 From: Lee-Orr Date: Thu, 7 Mar 2024 17:50:15 -0500 Subject: [PATCH] define types for timeline --- studio/src/anim/camera.rs | 2 +- studio/src/anim/mod.rs | 35 ++------- studio/src/anim/timeline_animation.rs | 105 ++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 studio/src/anim/timeline_animation.rs diff --git a/studio/src/anim/camera.rs b/studio/src/anim/camera.rs index eab3be6..9642876 100644 --- a/studio/src/anim/camera.rs +++ b/studio/src/anim/camera.rs @@ -4,7 +4,7 @@ use space_editor::space_prefab::editor_registry::EditorRegistryExt; use crate::math::{InvLerp, Lerp}; -use super::GlobalSeekTime; +use super::timeline_animation::GlobalSeekTime; pub struct CameraAnimPlugin; impl Plugin for CameraAnimPlugin { diff --git a/studio/src/anim/mod.rs b/studio/src/anim/mod.rs index ce98564..b523e33 100644 --- a/studio/src/anim/mod.rs +++ b/studio/src/anim/mod.rs @@ -11,6 +11,7 @@ pub use retargeting::*; mod camera; mod retargeting; +pub mod timeline_animation; pub struct AnimPlugin; impl Plugin for AnimPlugin { @@ -29,19 +30,18 @@ impl Plugin for AnimPlugin { .editor_registry::(); app.add_systems(Update, process_skinned_meshes); - app.insert_resource(GlobalSeekTime(0.)); - app.add_plugins((retargeting::RetargetingPlugin, camera::CameraAnimPlugin)); + app.add_plugins(( + retargeting::RetargetingPlugin, + camera::CameraAnimPlugin, + timeline_animation::TimelinePlugin, + )); #[cfg(feature = "wasm")] app.add_systems(Update, wasm::update_global_seek_time); } } -#[derive(Resource, Clone, Copy, Debug, Default, Deref, DerefMut, Reflect)] -#[reflect(Resource)] -pub struct GlobalSeekTime(pub f32); - #[derive(Component, Clone, Copy, Debug, Default, Reflect)] #[reflect(Component)] pub struct Skeleton; @@ -149,26 +149,3 @@ fn process_skinned_meshes( } } } - -#[cfg(feature = "wasm")] -mod wasm { - use bevy::prelude::*; - use wasm_bindgen::prelude::*; - - use crate::wasm::{StaticBuffer, WasmMessageBuffer}; - - use super::GlobalSeekTime; - - static SEEK_TIME: WasmMessageBuffer = WasmMessageBuffer::new(); - - #[wasm_bindgen(js_name = seekTime)] - pub fn seek_time(timestamp: f32) { - SEEK_TIME.write_message(timestamp); - } - - pub(super) fn update_global_seek_time(mut r_seek_time: ResMut) { - if let Some(timestamp) = SEEK_TIME.take_message() { - **r_seek_time = timestamp; - } - } -} diff --git a/studio/src/anim/timeline_animation.rs b/studio/src/anim/timeline_animation.rs new file mode 100644 index 0000000..17c1e00 --- /dev/null +++ b/studio/src/anim/timeline_animation.rs @@ -0,0 +1,105 @@ +use bevy::{ + ecs::{ + entity::{EntityMapper, MapEntities}, + reflect::ReflectMapEntities, + }, + prelude::*, +}; +use space_editor::space_prefab::editor_registry::EditorRegistryExt; + +pub struct TimelinePlugin; + +impl Plugin for TimelinePlugin { + fn build(&self, app: &mut App) { + app.register_type::() + .editor_registry::() + .register_type::() + .editor_registry::(); + + app.insert_resource(GlobalSeekTime(0.)); + } +} + +#[derive(Resource, Clone, Copy, Debug, Default, Deref, DerefMut, Reflect)] +#[reflect(Resource)] +pub struct GlobalSeekTime(pub f32); + +#[derive(Component, Clone, Debug, Reflect, PartialEq)] +#[reflect(Component, MapEntities)] +pub struct TimedAnimationClip { + clip: Handle, + start_time: f32, + duration: f32, + incoming_transition_duration: f32, + target: Entity, +} + +impl PartialOrd for TimedAnimationClip { + fn partial_cmp(&self, other: &Self) -> Option { + match self.start_time.partial_cmp(&other.start_time) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.duration.partial_cmp(&other.duration) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.clip.partial_cmp(&other.clip) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self + .incoming_transition_duration + .partial_cmp(&other.incoming_transition_duration) + { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + self.target.partial_cmp(&other.target) + } +} + +impl Default for TimedAnimationClip { + fn default() -> Self { + Self { + clip: Default::default(), + start_time: Default::default(), + duration: Default::default(), + incoming_transition_duration: Default::default(), + target: Entity::PLACEHOLDER, + } + } +} + +impl MapEntities for TimedAnimationClip { + fn map_entities(&mut self, entity_mapper: &mut EntityMapper) { + self.target = entity_mapper.get_or_reserve(self.target); + } +} + +#[derive(Component, Clone, Debug, Default, Reflect)] +#[reflect(Component)] +pub struct AnimationTarget; + +#[cfg(feature = "wasm")] +mod wasm { + use bevy::prelude::*; + use wasm_bindgen::prelude::*; + + use crate::wasm::{StaticBuffer, WasmMessageBuffer}; + + use super::GlobalSeekTime; + + static SEEK_TIME: WasmMessageBuffer = WasmMessageBuffer::new(); + + #[wasm_bindgen(js_name = seekTime)] + pub fn seek_time(timestamp: f32) { + SEEK_TIME.write_message(timestamp); + } + + pub(super) fn update_global_seek_time(mut r_seek_time: ResMut) { + if let Some(timestamp) = SEEK_TIME.take_message() { + **r_seek_time = timestamp; + } + } +}