use bevy::{ecs::component::Component, math::Vec3}; use crate::Velocity; /// Controls how Velocity is reduced #[derive(Component)] pub enum VelocityReducer { /// Sync mode, only applies the current Velocity to translation each time, does not reduce itself Sync, /// Move mode, directly zeroes out the velocity (momentum is transferred to translation) Move, /// Constant reduction mode, reduces by a fixed amount each time until it becomes Vec3::ZERO Reduce(Vec3), /// Lerp, reduces velocity using linear interpolation each time until it becomes Vec3::ZERO Lerp(f32), /// Function, calls a custom function to process velocity Func(Box Vec3 + Send + Sync + 'static>), } impl VelocityReducer { /// Calculates velocity reduction, writing the result back to the Velocity component pub fn calculate(&self, origin: &mut Velocity) { self.calculate_vec(&mut *origin); } /// Calculates velocity reduction, writing the result back to Vec3 pub fn calculate_vec(&self, origin_vec: &mut Vec3) { match self { VelocityReducer::Sync => { // DO NOTHING } VelocityReducer::Move => { *origin_vec = Vec3::ZERO; } VelocityReducer::Reduce(vec3) => { let mut vec = *origin_vec - *vec3; // Handle direction: if the sign flips, clamp to zero if (origin_vec.x >= 0.0 && vec.x < 0.0) || (origin_vec.x <= 0.0 && vec.x > 0.0) { vec.x = 0.0; } if (origin_vec.y >= 0.0 && vec.y < 0.0) || (origin_vec.y <= 0.0 && vec.y > 0.0) { vec.y = 0.0; } if (origin_vec.z >= 0.0 && vec.z < 0.0) || (origin_vec.z <= 0.0 && vec.z > 0.0) { vec.z = 0.0; } *origin_vec = vec; } VelocityReducer::Lerp(lerp) => { let lerp = lerp.clamp(0., 1.); *origin_vec = origin_vec.lerp(Vec3::ZERO, lerp); } VelocityReducer::Func(fn_mut) => { *origin_vec = fn_mut(*origin_vec); } } } }