diff --git a/egui/src/math/mod.rs b/egui/src/math/mod.rs index c6ddff28..4fdd179e 100644 --- a/egui/src/math/mod.rs +++ b/egui/src/math/mod.rs @@ -1,6 +1,6 @@ //! Vectors, positions, rectangles etc. -use std::ops::{Add, Mul, RangeInclusive}; +use std::ops::{Add, Div, Mul, RangeInclusive, Sub}; // ---------------------------------------------------------------------------- @@ -13,27 +13,64 @@ pub use {pos2::*, rect::*, vec2::*}; // ---------------------------------------------------------------------------- -/// Linear interpolation. -pub fn lerp(range: RangeInclusive, t: f32) -> T -where - f32: Mul, - T: Add + Copy, +pub trait One { + fn one() -> Self; +} +impl One for f32 { + fn one() -> Self { + 1.0 + } +} +impl One for f64 { + fn one() -> Self { + 1.0 + } +} + +pub trait Real: + Copy + + PartialEq + + PartialOrd + + One + + Add + + Sub + + Mul + + Div { - (1.0 - t) * *range.start() + t * *range.end() +} + +impl Real for f32 {} +impl Real for f64 {} + +// ---------------------------------------------------------------------------- + +/// Linear interpolation. +pub fn lerp(range: RangeInclusive, t: T) -> R +where + T: Real + Mul, + R: Copy + Add, +{ + (T::one() - t) * *range.start() + t * *range.end() } /// Linearly remap a value from one range to another, /// so that when `x == from.start()` returns `to.start()` /// and when `x == from.end()` returns `to.end()`. -pub fn remap(x: f32, from: RangeInclusive, to: RangeInclusive) -> f32 { +pub fn remap(x: T, from: RangeInclusive, to: RangeInclusive) -> T +where + T: Real, +{ #![allow(clippy::float_cmp)] debug_assert!(from.start() != from.end()); - let t = (x - from.start()) / (from.end() - from.start()); + let t = (x - *from.start()) / (*from.end() - *from.start()); lerp(to, t) } /// Like `remap`, but also clamps the value so that the returned value is always in the `to` range. -pub fn remap_clamp(x: f32, from: RangeInclusive, to: RangeInclusive) -> f32 { +pub fn remap_clamp(x: T, from: RangeInclusive, to: RangeInclusive) -> T +where + T: Real, +{ #![allow(clippy::float_cmp)] if from.end() < from.start() { return remap_clamp(x, *from.end()..=*from.start(), *to.end()..=*to.start()); @@ -44,9 +81,9 @@ pub fn remap_clamp(x: f32, from: RangeInclusive, to: RangeInclusive) - *to.end() } else { debug_assert!(from.start() != from.end()); - let t = (x - from.start()) / (from.end() - from.start()); + let t = (x - *from.start()) / (*from.end() - *from.start()); // Ensure no numerical inaccuracies sneak in: - if 1.0 <= t { + if T::one() <= t { *to.end() } else { lerp(to, t)