Skip to content

Commit

Permalink
Fix SmoothDelta modifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Shatur committed Oct 25, 2024
1 parent 841aa92 commit d49f798
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 89 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Logging for binding.

### Fixed

- `SmoothDelta` modifier.

### Changed

- Remove world access from conditions and modifiers. This means that you no longer can write game-specific conditions or modifiers. But it's much nicer (and faster) to just do it in observers instead.
Expand Down
117 changes: 28 additions & 89 deletions src/input_context/input_modifier/smooth_delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ pub struct SmoothDelta {
/// Multiplier for delta time.
pub speed: f32,

old_value: Vec3,

value_delta: Vec3,
prev_value: Vec3,
}

impl SmoothDelta {
Expand All @@ -29,8 +27,7 @@ impl SmoothDelta {
Self {
kind: kind.into(),
speed,
old_value: Default::default(),
value_delta: Default::default(),
prev_value: Default::default(),
}
}
}
Expand All @@ -42,21 +39,24 @@ impl InputModifier for SmoothDelta {
return self.apply(time, value.into());
}

let dim = value.dim();
let value = value.as_axis3d();
let target_value_delta = (value - self.old_value).normalize_or_zero();
self.old_value = value;
let target_value = value.as_axis3d();
if self.prev_value.distance_squared(target_value) < 1e-4 {
// Snap to the target if the distance is too small.
self.prev_value = target_value;
return value;
}

let alpha = (time.delta_seconds() * self.speed).min(1.0);
self.value_delta = match self.kind {
let alpha = time.delta_seconds() * self.speed;
let smoothed = match self.kind {
SmoothKind::EaseFunction(ease_function) => {
let ease_alpha = alpha.calc(ease_function);
self.value_delta.lerp(target_value_delta, ease_alpha)
self.prev_value.lerp(target_value, ease_alpha)
}
SmoothKind::Linear => self.value_delta.lerp(target_value_delta, alpha),
SmoothKind::Linear => self.prev_value.lerp(target_value, alpha),
};
self.prev_value = smoothed;

ActionValue::Axis3D(self.value_delta).convert(dim)
ActionValue::Axis3D(smoothed).convert(value.dim())
}
}

Expand Down Expand Up @@ -84,106 +84,45 @@ mod tests {
use super::*;

#[test]
fn linear_bool() {
let mut modifier = SmoothDelta::new(SmoothKind::Linear, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(100));

assert_eq!(modifier.apply(&time, false.into()), 0.0.into());
assert_eq!(modifier.apply(&time, true.into()), 0.1.into());
}

#[test]
fn ease_function_bool() {
let mut modifier = SmoothDelta::new(EaseFunction::QuadraticIn, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(200));

assert_eq!(modifier.apply(&time, false.into()), 0.0.into());
assert_eq!(modifier.apply(&time, true.into()), 0.040000003.into());
}

#[test]
fn linear_axis1d() {
fn linear() {
let mut modifier = SmoothDelta::new(SmoothKind::Linear, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(100));

assert_eq!(modifier.apply(&time, 0.5.into()), 0.1.into());
assert_eq!(modifier.apply(&time, 1.0.into()), 0.19.into());
assert_eq!(modifier.apply(&time, 0.5.into()), 0.05.into());
assert_eq!(modifier.apply(&time, 1.0.into()), 0.145.into());
}

#[test]
fn ease_function_axis1d() {
fn ease_function() {
let mut modifier = SmoothDelta::new(EaseFunction::QuadraticIn, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(200));

assert_eq!(modifier.apply(&time, 0.5.into()), 0.040000003.into());
assert_eq!(modifier.apply(&time, 1.0.into()), 0.0784.into());
assert_eq!(modifier.apply(&time, 0.5.into()), 0.020000001.into());
assert_eq!(modifier.apply(&time, 1.0.into()), 0.059200004.into());
}

#[test]
fn linear_axis2d() {
fn bool_as_axis1d() {
let mut modifier = SmoothDelta::new(SmoothKind::Linear, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(100));

assert_eq!(
modifier.apply(&time, Vec2::splat(0.5).into()),
Vec2::splat(0.07071068).into()
);
assert_eq!(
modifier.apply(&time, Vec2::ONE.into()),
Vec2::splat(0.1343503).into()
);
}

#[test]
fn ease_function_axis2d() {
let mut modifier = SmoothDelta::new(EaseFunction::QuadraticIn, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(200));

assert_eq!(
modifier.apply(&time, Vec2::splat(0.5).into()),
Vec2::splat(0.028284272).into()
);
assert_eq!(
modifier.apply(&time, Vec2::ONE.into()),
Vec2::splat(0.055437177).into()
);
assert_eq!(modifier.apply(&time, false.into()), 0.0.into());
assert_eq!(modifier.apply(&time, true.into()), 0.1.into());
}

#[test]
fn linear_axis3d() {
fn snapping() {
let mut modifier = SmoothDelta::new(SmoothKind::Linear, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(100));

assert_eq!(
modifier.apply(&time, Vec3::splat(0.5).into()),
Vec3::splat(0.057735026).into()
);
assert_eq!(
modifier.apply(&time, Vec3::ONE.into()),
Vec3::splat(0.10969655).into()
);
}

#[test]
fn ease_function_axis3d() {
let mut modifier = SmoothDelta::new(EaseFunction::QuadraticIn, 1.0);
let mut time = Time::default();
time.advance_by(Duration::from_millis(200));
modifier.prev_value = Vec3::X * 0.99;
assert_eq!(modifier.apply(&time, 1.0.into()), 1.0.into());

assert_eq!(
modifier.apply(&time, Vec3::splat(0.5).into()),
Vec3::splat(0.023094011).into()
);
assert_eq!(
modifier.apply(&time, Vec3::ONE.into()),
Vec3::splat(0.045264263).into()
);
modifier.prev_value = Vec3::X * 0.98;
assert_ne!(modifier.apply(&time, 1.0.into()), 1.0.into());
}
}

0 comments on commit d49f798

Please sign in to comment.