- avoid updating seek time from UI if source of seek time is studio, to avoid re-processing timeline info

- move generating animation to first thing in a frame, and notifying about timeline changes to last, to ensure that it happens before the time updates
- re-generate the animation tweens whenever you start playing or manually seek a new time in the timeline to prevent inconsistencies
This commit is contained in:
Lee-Orr
2024-03-22 16:37:10 -04:00
parent 11dc7c7945
commit 64b647881e
2 changed files with 27 additions and 23 deletions
@@ -45,6 +45,7 @@ implements TreeSelectionProvider {
@state() clipEnd = 0;
@state() playHead = 0;
@state() studioPlayTime = 0;
@state() playing = false;
@state() tracks : Record<string, {name?: string, target_type: studio.SceneElement, animation_target: studio.AnimationTarget }> = {};
@@ -64,7 +65,7 @@ implements TreeSelectionProvider {
}
protected override update(changes: PropertyValues<this>): void {
if (changes.has("playHead"))
if (changes.has("playHead") && Math.abs(this.studioPlayTime - this.playHead) > 0.0001)
studio.seekTime(this.playHead);
if (changes.has("selectedTrack")) {
@@ -81,10 +82,15 @@ implements TreeSelectionProvider {
super.update(changes);
}
setPlayTime(time: number) : void {
studio.seekTime(time);
}
@on("window:seek-time-changed")
onSeekTimeChanged({ detail: {time, playing} }: SeekTimeChanged ): void {
console.log("Seek Time Changed", time, playing);
this.playHead = time;
this.studioPlayTime = time;
this.playing = playing;
if (this.playHead < this.timelineStart) {
+20 -22
View File
@@ -2,7 +2,7 @@ use std::{str::FromStr, time::Duration};
use bevy::{
prelude::*,
utils::{hashbrown::HashMap, HashSet},
utils::{hashbrown::HashMap},
};
use bevy_tweening::{
@@ -44,6 +44,7 @@ impl Plugin for TimelinePlugin {
})
.add_event::<TweenCompleted>();
app.add_systems(First, generate_transform_animation);
app.add_systems(PreUpdate, (process_timeline_events, update_tick).chain());
app.add_systems(
@@ -54,12 +55,12 @@ impl Plugin for TimelinePlugin {
),
);
app.add_systems(PostUpdate, generate_transform_animation);
// app.add_systems(PostUpdate, generate_transform_animation);
#[cfg(feature = "wasm")]
{
app.add_systems(
First,
Last,
(
wasm::update_global_seek_time,
wasm::update_keyframe_interaction,
@@ -347,37 +348,33 @@ fn process_keyframe_events(
fn generate_transform_animation(
mut commands: Commands,
changed: Query<
&Keyframe,
(
With<TransformKeyframe>,
Or<(Changed<Keyframe>, Changed<Transform>)>,
),
>,
keyframes: Query<
(&Keyframe, &Transform, &TransformKeyframe, Entity),
Without<MarkedForDeletion>,
>,
added_targets: Query<(Entity, &AnimationTarget), Added<AnimationTarget>>,
valid_targets: Query<(Entity, &AnimationTarget)>,
removed: Query<&Keyframe, With<MarkedForDeletion>>,
mut e_timeline_event: EventReader<TimelineInteractionEvent>
) {
let mut playing = false;
for e in e_timeline_event.read() {
if matches!(e,TimelineInteractionEvent::Play | TimelineInteractionEvent::Seek(_)) {
playing = true;
continue;
}
}
if !playing {
return;
}
let available_targets = valid_targets
.iter()
.map(|(e, a)| (*a, e))
.collect::<HashMap<_, _>>();
let changed_targets = changed
.iter()
.map(|keyframe| keyframe.target)
.chain(removed.iter().map(|keyframe| {
info!("Processing a removed keyframe {keyframe:?}");
keyframe.target
}))
.chain(added_targets.iter().map(|(_, a)| *a))
.collect::<HashSet<_>>();
let keyframes = keyframes
.iter()
.filter(|(keyframe, _, _, _)| changed_targets.contains(&keyframe.target))
.group_by(|(keyframe, _, _, _)| keyframe.target);
for (target, keyframes) in &keyframes {
@@ -635,6 +632,7 @@ mod wasm {
mut e_timeline_event: EventWriter<TimelineInteractionEvent>,
) {
if let Some(timestamp) = SEEK_TIME.take_message() {
info!("Updating Seek Time {timestamp:?}");
e_timeline_event.send(timestamp);
}
}