add deletion of keyframes

This commit is contained in:
Lee-Orr
2024-03-18 16:43:29 -04:00
parent 09a09af240
commit 4952c0c613
3 changed files with 71 additions and 30 deletions
@@ -101,6 +101,10 @@ export class AnimEditorElement extends LitElement {
keyframes[keyframe] = added[keyframe];
}
for (let keyframe of removed) {
delete keyframes[keyframe];
}
this.keyframes = keyframes;
let min = Infinity
+53 -29
View File
@@ -11,14 +11,13 @@ use bevy::{
use bevy_tweening::{
lens::{TransformPositionLens, TransformRotationLens, TransformScaleLens},
Animator, EaseMethod, Sequence, Targetable, Tracks, Tween,
TweenCompleted,
Animator, EaseMethod, Sequence, Targetable, Tracks, Tween, TweenCompleted,
};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use space_editor::space_prefab::editor_registry::EditorRegistryExt;
use crate::interaction::Selectable;
use crate::interaction::{MarkedForDeletion, Selectable};
pub struct TimelinePlugin;
@@ -53,6 +52,7 @@ impl Plugin for TimelinePlugin {
timeline_bound_component_animator_system::<Transform>,
),
);
app.add_systems(PostUpdate, generate_transform_animation);
@@ -77,6 +77,8 @@ impl Plugin for TimelinePlugin {
}
}
const MIN_KEYFRAME_DISTANCE: f32 = 0.01;
#[derive(Event, Clone, Copy, Debug)]
pub enum TimelineInteractionEvent {
Play,
@@ -88,7 +90,7 @@ pub enum TimelineInteractionEvent {
pub enum KeyframeInteractionEvent {
RecordKeyframe { target: Entity },
MoveKeyframeTime { target: Entity, time: f32 },
AddEntityTrack { target: Entity }
AddEntityTrack { target: Entity },
}
#[derive(Resource, Clone, Copy, Debug, Default, Reflect, Serialize, Deserialize)]
@@ -227,29 +229,50 @@ fn process_keyframe_events(
r_global_seek_time: Res<GlobalSeekTime>,
q_animation_targets: Query<(Entity, &Transform), With<AnimationTarget>>,
q_potential_targets: Query<Entity, (With<Transform>, Without<AnimationTarget>)>,
mut q_keyframes: Query<&mut Keyframe>,
mut q_keyframes: Query<(Entity, &mut Keyframe)>,
) {
for event in e_timeline_event.read() {
info!("Processing Keyframe Event {event:?}");
match event {
KeyframeInteractionEvent::RecordKeyframe { target } => {
if let Ok((target, transform)) = q_animation_targets.get(*target) {
commands.spawn((
SpatialBundle {
transform: *transform,
..Default::default()
},
Selectable,
Keyframe {
target,
time: r_global_seek_time.time,
},
TransformKeyframe::default(),
));
let mut existing = None;
for (entity, keyframe) in q_keyframes.iter_mut() {
if keyframe.target == target
&& (keyframe.time - r_global_seek_time.time).abs()
< MIN_KEYFRAME_DISTANCE
{
existing = Some(entity);
break;
}
}
if let Some(existing) = existing {
commands.entity(existing).insert((
*transform,
TransformKeyframe::default(),
Keyframe {
target,
time: r_global_seek_time.time,
},
));
} else {
commands.spawn((
SpatialBundle {
transform: *transform,
..Default::default()
},
Selectable,
Keyframe {
target,
time: r_global_seek_time.time,
},
TransformKeyframe::default(),
));
}
}
}
KeyframeInteractionEvent::MoveKeyframeTime { target, time } => {
if let Ok(mut keyframe) = q_keyframes.get_mut(*target) {
if let Ok((_, mut keyframe)) = q_keyframes.get_mut(*target) {
keyframe.time = *time;
}
}
@@ -260,7 +283,7 @@ fn process_keyframe_events(
} else {
warn!("Can't add animation target to entity");
}
},
}
}
}
}
@@ -268,11 +291,16 @@ fn process_keyframe_events(
fn generate_transform_animation(
mut commands: Commands,
changed: Query<&Keyframe, (With<TransformKeyframe>, Changed<Keyframe>)>,
keyframes: Query<(&Keyframe, &Transform, &TransformKeyframe, Entity)>,
keyframes: Query<(&Keyframe, &Transform, &TransformKeyframe, Entity), Without<MarkedForDeletion>>,
removed: Query<&Keyframe, With<MarkedForDeletion>>,
) {
let changed_targets = changed
.iter()
.map(|keyframe| keyframe.target)
.chain(removed.iter().map(|keyframe| {
info!("Processing a removed keyframe {keyframe:?}");
keyframe.target
}))
.collect::<HashSet<_>>();
let keyframes = keyframes
.iter()
@@ -467,13 +495,11 @@ mod wasm {
use wasm_bindgen::prelude::*;
use crate::{
scene::SceneElement,
wasm::{FromStr, StaticBuffer, WasmMessageBuffer},
interaction::MarkedForDeletion, scene::SceneElement, wasm::{FromStr, StaticBuffer, WasmMessageBuffer}
};
use super::{
AnimationTarget, EaseType, GlobalSeekTime, Keyframe, KeyframeInteractionEvent,
TimedAnimationClipAsset, TimelineInteractionEvent, TransformKeyframe,
AnimationTarget, EaseType, GlobalSeekTime, Keyframe, KeyframeInteractionEvent, TimedAnimationClipAsset, TimelineInteractionEvent, TransformKeyframe
};
static SEEK_TIME: WasmMessageBuffer<TimelineInteractionEvent> = WasmMessageBuffer::new();
@@ -522,9 +548,7 @@ mod wasm {
let Ok(target) = Entity::from_str(&entity) else {
return;
};
KEYFRAME_EVENT.write_message(vec![KeyframeInteractionEvent::AddEntityTrack {
target
}]);
KEYFRAME_EVENT.write_message(vec![KeyframeInteractionEvent::AddEntityTrack { target }]);
}
pub(super) fn update_global_seek_time(
@@ -734,7 +758,7 @@ mod wasm {
(Entity, &Keyframe, &TimedAnimationClipAsset),
Or<(Changed<Keyframe>, Changed<TimedAnimationClipAsset>)>,
>,
mut removed: bevy::prelude::RemovedComponents<Keyframe>,
removed: Query<Entity, With<MarkedForDeletion>>,
) -> Result<(), String> {
let Ok(window) = q_window.get_single() else {
return Ok(());
@@ -775,7 +799,7 @@ mod wasm {
}))
.collect::<Result<HashMap<_, _>, String>>()?;
let removed = removed.read().map(|v| format!("{v:?}")).collect::<Vec<_>>();
let removed = removed.iter().map(|v| format!("{v:?}")).collect::<Vec<_>>();
if added.is_empty() && removed.is_empty() {
return Ok(());
+14 -1
View File
@@ -27,6 +27,7 @@ impl Plugin for SelectionPlugin {
PostUpdate,
draw_selection_outline.run_if(resource_changed_or_removed::<Selection>()),
)
.add_systems(First, finalize_delete)
.add_systems(
OnEnter(SceneState::Active),
(apply_deferred, tag_scene_elements)
@@ -158,6 +159,9 @@ fn update_selection(
}
}
#[derive(Component)]
pub struct MarkedForDeletion;
fn process_delete_inputs(
mut cmd: Commands,
mut er_input: EventReader<InputAction>,
@@ -172,7 +176,7 @@ fn process_delete_inputs(
}) {
let entity = **r_selection;
cmd.entity(entity).despawn_recursive();
cmd.entity(entity).insert(MarkedForDeletion);
cmd.remove_resource::<Selection>();
ew_changes.send(NewChange {
change: Arc::new(RemovedEntity { entity }),
@@ -180,6 +184,15 @@ fn process_delete_inputs(
}
}
fn finalize_delete(
mut cmd: Commands,
q: Query<Entity, With<MarkedForDeletion>>
) {
for entity in &q {
cmd.entity(entity).despawn_recursive();
}
}
fn draw_selection_outline(
mut cmd: Commands,
q_selected: Query<&Children, With<Selected>>,