use std::f32::consts::{PI, TAU};
use super::{HoldSystem, prelude::ShadowParams};
use crate::{prelude::*, verb::Holding};
pub(super) fn plugin(app: &mut App) {
app.add_systems(
PhysicsSchedule,
set_velocities.in_set(HoldSystem::SetVelocities),
);
}
fn set_velocities(
time: Res<Time>,
mut q_prop: Query<(
&mut LinearVelocity,
&mut AngularVelocity,
&Position,
&Rotation,
)>,
mut q_actor: Query<(&ShadowParams, &Holding, &AvianPickupActor)>,
) {
let dt = time.delta_secs();
let inv_dt = dt.recip();
for (shadow, holding, actor) in q_actor.iter_mut() {
let prop = holding.0;
let Ok((mut velocity, mut angvel, position, rotation)) = q_prop.get_mut(prop) else {
error!("Prop entity was deleted or in an invalid state. Ignoring.");
continue;
};
let delta_position = shadow.target_position - position.0;
let delta_rotation = shadow.target_rotation * rotation.0.inverse();
let (axis, angle) = delta_rotation.to_axis_angle();
let angle = if angle > PI { angle - TAU } else { angle };
let delta_rotation_scaled_axis = axis * angle;
let vel_ease = f32::exp(-actor.hold.linear_velocity_easing);
velocity.0 = (delta_position * inv_dt * vel_ease).clamp_length_max(shadow.max_speed);
velocity.0 = zero_if_near_zero(velocity.0);
let angvel_ease = f32::exp(-actor.hold.angular_velocity_easing);
angvel.0 = (delta_rotation_scaled_axis * inv_dt * angvel_ease)
.clamp_length_max(shadow.max_angular);
angvel.0 = zero_if_near_zero(angvel.0);
}
}
fn zero_if_near_zero(vec: Vec3) -> Vec3 {
let arbitrary_cutoff = 1e-4;
if vec.length_squared() < arbitrary_cutoff {
Vec3::ZERO
} else {
vec
}
}