From dc538d5f9aeb7635278cf40d12df489ef59419a2 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Mon, 17 Nov 2025 23:39:55 -0600 Subject: [PATCH] feat: spring-like ghost tracking --- crates/unified/src/client/parts.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/unified/src/client/parts.rs b/crates/unified/src/client/parts.rs index 1d1d3a7fe5c7a8299b93277c67b132589434f51b..83121184e7d203a0d22e3ae7fbe9c20d185beb34 100644 --- a/crates/unified/src/client/parts.rs +++ b/crates/unified/src/client/parts.rs @@ -116,6 +116,8 @@ struct SnapResource(Option, Option); struct DragGhost; #[derive(Component)] struct GhostTarget(pub Quat); +#[derive(Component)] +struct GhostVelocity(pub Vec3); const TRANSLATION_SMOOTH: f32 = 0.3; const ROTATION_SMOOTH: f32 = 0.1; @@ -145,7 +147,7 @@ fn on_part_click( } let mut s = sprite.0.clone(); s.color = Color::srgba(0.7, 0.7, 0.7, 1.0); - commands.spawn((DragGhost, GhostTarget(sprite.1.rotation), *sprite.1, s)); + commands.spawn((DragGhost, GhostVelocity(Vec3::ZERO), GhostTarget(sprite.1.rotation), *sprite.1, s)); drag.0 = Some(ev.event().event_target()); } @@ -189,7 +191,7 @@ fn on_part_release( /// This code is super cursed, and it will break at the lightest breeze fn update_drag_ghosts( ghost: Single< - (&mut Transform, &mut GhostTarget), + (&mut Transform, &mut GhostVelocity, &mut GhostTarget), ( With, Without, @@ -211,7 +213,7 @@ fn update_drag_ghosts( ) { const CUTOFF: f32 = 25.0; // px - let (mut ghost, mut ghost_target) = ghost.into_inner(); + let (mut ghost, mut ghost_velocity, mut ghost_target) = ghost.into_inner(); let Some(cursor) = cursor.0 else { return }; let mut best_distance = f32::INFINITY; @@ -345,8 +347,12 @@ fn update_drag_ghosts( } ghost_target.0 = best_target.rotation; ghost.rotation = ghost.rotation.slerp(ghost_target.0, ROTATION_SMOOTH); - let dx = TRANSLATION_SMOOTH * (best_target.translation - ghost.translation); - ghost.translation += dx; + let disp = ghost.translation - best_target.translation; + const K: f32 = 0.07; + const C: f32 = 0.5; + let a = (-K*disp - C*ghost_velocity.0)/2.0; + ghost.translation += ghost_velocity.0; + ghost_velocity.0 += a; rsnap.0 = snap; rsnap.1 = best_self_snap;