play/pause, update timeline

This commit is contained in:
Lee-Orr
2024-03-08 13:46:09 -05:00
parent 86f471de3c
commit 2419f82e09
5 changed files with 126 additions and 21 deletions
+96 -11
View File
@@ -23,14 +23,22 @@ impl Plugin for TimelinePlugin {
playing: false,
});
#[cfg(feature = "wasm")]
app.add_systems(
Update,
(
wasm::update_global_seek_time,
wasm::notify_seek_time_changes.map(bevy::utils::error),
),
app.add_systems(PreUpdate,
(process_timeline_events, update_tick).chain(),
);
#[cfg(feature = "wasm")]
{
app.add_systems(First,
wasm::update_global_seek_time);
app.add_systems(
Update,
(
wasm::notify_seek_time_changes.map(bevy::utils::error),
wasm::notify_updated_animation_targets.map(bevy::utils::error)
),
);
}
}
}
@@ -55,6 +63,7 @@ pub struct TimedAnimationClip {
start_time: f32,
duration: f32,
incoming_transition_duration: f32,
speed: f32,
target: Entity,
}
@@ -89,6 +98,7 @@ impl Default for TimedAnimationClip {
clip: Default::default(),
start_time: Default::default(),
duration: Default::default(),
speed: 1.0,
incoming_transition_duration: Default::default(),
target: Entity::PLACEHOLDER,
}
@@ -105,14 +115,31 @@ impl MapEntities for TimedAnimationClip {
#[reflect(Component)]
pub struct AnimationTarget;
fn process_timeline_events(mut e_timeline_event: EventReader<TimelineEvent>, mut r_global_seek_time: ResMut<GlobalSeekTime>) {
for event in e_timeline_event.read() {
match event {
TimelineEvent::Play => r_global_seek_time.playing = true,
TimelineEvent::Pause => r_global_seek_time.playing = false,
TimelineEvent::Seek(time) => r_global_seek_time.time = *time,
}
}
}
fn update_tick(mut r_global_seek_time: ResMut<GlobalSeekTime>, time: Res<Time>) {
if r_global_seek_time.playing {
r_global_seek_time.time += time.delta_seconds();
}
}
#[cfg(feature = "wasm")]
mod wasm {
use bevy::{prelude::*, window::PrimaryWindow};
use bevy::{prelude::*, utils::hashbrown::HashMap, window::PrimaryWindow};
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use crate::wasm::{StaticBuffer, WasmMessageBuffer};
use super::{GlobalSeekTime, TimelineEvent};
use super::{AnimationTarget, GlobalSeekTime, TimelineEvent};
static SEEK_TIME: WasmMessageBuffer<TimelineEvent> = WasmMessageBuffer::new();
@@ -138,26 +165,84 @@ mod wasm {
}
#[wasm_bindgen(typescript_custom_section)]
const SEEK_TIME_CHANGED_EVENT: &str = r#"
const TIMELINE_TYPES: &str = r#"
export interface SeekTimeChanged extends CustomEvent {
type: "seek-time-changed";
detail: number;
detail: {
time: number,
playing: bool
};
}
export interface UpdateAnimationTargets extends CustomEvent {
type: "update-animation-targets",
details: {
added: Record<string, { name?: string, target_type: 'camera' | 'transform' }>,
removed: string[]
}
}
declare global {
export interface GlobalEventHandlersEventMap {
"seek-time-changed": CameraKeyframesEvent;
"update-animation-targets": UpdateAnimationTargets;
}
}
"#;
const CAMERA : &str = "camera";
const TRANSFORM : &str = "transform";
#[derive(Serialize, Deserialize)]
struct AddedAnimationTargetRecordItem {
name: Option<String>,
target_type: String
}
#[derive(Serialize, Deserialize)]
struct UpdatedAnimationTargetsEvent {
added: HashMap<Entity, AddedAnimationTargetRecordItem>,
removed: Vec<Entity>
}
pub(super) fn notify_updated_animation_targets(
q_window: Query<&Window, With<PrimaryWindow>>,
q_cameras: Query<(Entity, Option<&Name>), (Added<AnimationTarget>, With<Camera>)>,
q_transforms: Query<(Entity, Option<&Name>), (Added<AnimationTarget>, With<Transform>, Without<Camera>)>,
mut removed: bevy::prelude::RemovedComponents<AnimationTarget>
) -> Result<(), String> {
let Ok(window) = q_window.get_single() else {
return Ok(());
};
let added = q_transforms.iter().map(|(entity, name)| {
(entity, AddedAnimationTargetRecordItem { name: name.map(|v| v.to_string()), target_type: TRANSFORM.to_owned()})
}).chain(q_cameras.iter().map(|(entity, name)| (entity, AddedAnimationTargetRecordItem { name: name.map(|v| v.to_string()), target_type: CAMERA.to_owned()}))).collect::<HashMap<_,_>>();
let removed = removed.read().collect::<Vec<_>>();
let event = UpdatedAnimationTargetsEvent { added, removed };
crate::wasm::dispatch_to_js(
window,
"update-animation-targets",
&serde_json::to_value(&event).map_err(|e| format!("{e}"))?,
)
}
pub(super) fn notify_seek_time_changes(
r_global_seek_time: Res<GlobalSeekTime>,
q_window: Query<&Window, With<PrimaryWindow>>,
) -> Result<(), String> {
if !r_global_seek_time.is_changed() {
return Ok(());
}
let Ok(window) = q_window.get_single() else {
return Ok(());
};
info!("Current Seek Time: {r_global_seek_time:?}");
crate::wasm::dispatch_to_js(
window,
+3 -7
View File
@@ -23,13 +23,7 @@ use wasm_bindgen::prelude::wasm_bindgen;
use wgpu::{TextureDescriptor, TextureUsages};
use crate::{
camera_controller::{CameraController, CameraControllerBundle},
change_tracking::{ChangeTracker, ChangeTrackingPlugin},
debug::DebugPoint,
headless::{is_headless, is_not_headless, HeadlessSettings},
math::{Combinable, Extrema},
screenshot::ScreenCapture,
MainCamera,
anim::timeline_animation::AnimationTarget, camera_controller::{CameraController, CameraControllerBundle}, change_tracking::{ChangeTracker, ChangeTrackingPlugin}, debug::DebugPoint, headless::{is_headless, is_not_headless, HeadlessSettings}, math::{Combinable, Extrema}, screenshot::ScreenCapture, MainCamera
};
pub struct ScenePlugin;
@@ -260,6 +254,7 @@ fn initialize(mut cmd: Commands) {
cmd.spawn((
Name::new("Main Camera"),
MainCamera,
AnimationTarget,
ChangeTracker,
Camera3dBundle {
transform: camera_xform,
@@ -316,6 +311,7 @@ fn initialiaze_headless(
cmd.spawn((
Name::new("Main Camera"),
MainCamera,
AnimationTarget,
Camera3dBundle {
transform: camera_xform,
tonemapping: Tonemapping::BlenderFilmic,