1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Convenience structures for representing a transition from one value to another.
//!
//! The `Transition` struct is useful in animation, especially since it allows
//! you to customize the interpolation function via what's called a "Progress Mapper", i.e
//! an object that also acts as a function which, given a "progress" value, returns
//! the LERP factor to use.
//!
//! This is especially powerful since it allows for any kind of interpolation curve :
//! exponential, logarithmic, sines, squares... One could even imagine a Progress Mapper based
//! on Bézier curves.

// WISH: Another kind of Transition that not only takes two ends, but any
// number of them. There should be two :
// - TransitionFrames, that take I: IntoIterator<Item=T>
// - RefTransitionFrames, that take I: IntoIterator<Item=&T>

use num_traits::{Zero, One};
use std::ops::Range;
use crate::ops::{Lerp, Clamp};

/// A functor that maps a progress value to a LERP factor.
pub trait ProgressMapper<Progress=f32> {
    /// Maps an unconstrained progress value to a LERP factor.
    ///
    /// The input progress value should be between zero and one, but is not required to.  
    /// The returned LERP factor should be between zero and one, but is not required to.
    fn map_progress(&self, progress: Progress) -> Progress;
}

/// A pass-through functor that returns progress values directly as LERP factors.
#[derive(Debug, Copy, Clone, Default, Hash, PartialEq, Eq)]
#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
pub struct IdentityProgressMapper;

impl<Progress> ProgressMapper<Progress> for IdentityProgressMapper {
    #[inline]
    fn map_progress(&self, progress: Progress) -> Progress {
        progress
    }
}

/// A function pointer container that can map a progress value to a LERP factor.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
// #[cfg_attr(feature="serde", derive(Serialize, Deserialize))] NOTE: Fails with cargo test.
pub struct ProgressMapperFn<T>(pub fn(T) -> T);

/// The default value for a `ProgressMapperFn` is the identity function.
impl<T> Default for ProgressMapperFn<T> {
    fn default() -> Self {
        fn identity<T>(x: T) -> T { x }
        ProgressMapperFn(identity)
    }
}

impl<T> From<fn(T) -> T> for ProgressMapperFn<T> {
    fn from(f: fn(T) -> T) -> Self {
        ProgressMapperFn(f)
    }
}

// Many progress
// Much wow
impl<Progress> ProgressMapper<Progress> for ProgressMapperFn<Progress> {
    fn map_progress(&self, progress: Progress) -> Progress {
        self.0(progress)
    }
}



/// A convenience structure for storing a progression from one value to another.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
pub struct Transition<T, F, Progress=f32> {
    /// The value when progress gets close to 0.
    pub start: T,
    /// The value when progress gets close to 1.
    pub end: T,
    /// Expected to be between 0 and 1.
    pub progress: Progress,
    /// Functor that maps the current progress value to a LERP factor.
    pub progress_mapper: F,
}
impl<T: Default, F: Default, Progress: Zero> Default for Transition<T, F, Progress> {
    fn default() -> Self {
        Self {
            start: T::default(),
            end: T::default(),
            progress: Progress::zero(),
            progress_mapper: F::default(),
        }
    }
}
impl<T, F: Default, Progress: Zero> From<Range<T>> for Transition<T, F, Progress> {
    fn from(r: Range<T>) -> Self {
        Transition { start: r.start, end: r.end, progress: Zero::zero(), progress_mapper: F::default() }
    }
}
impl<T, F, Progress> Transition<T, F, Progress> {
    /// Creates a new `Transition` from `start` and `end` values and `progress_mapper`, setting `progress` to zero.
    pub fn with_mapper(start: T, end: T, progress_mapper: F) -> Self where Progress: Zero {
        Self { start, end, progress_mapper, progress: Zero::zero() }
    }
    /// Creates a new `Transition` from `start`, `end`, `progress_mapper` and `progress` values.
    pub fn with_mapper_and_progress(start: T, end: T, progress_mapper: F, progress: Progress) -> Self {
        Self { start, end, progress_mapper, progress }
    }
    /// Converts this into a `Range`, dropping the `progress` and `progress_mapper` values.
    pub fn into_range(self) -> Range<T> {
        let Self { start, end, .. } = self;
        Range { start, end }
    }
}
impl<T, F, Progress> Transition<T, F, Progress> where F: ProgressMapper<Progress> {
    /// Gets the transition's current state, clamping progress to [0;1].
    pub fn into_current(self) -> T where T: Lerp<Progress,Output=T>, Progress: Clamp + Zero + One {
        Lerp::lerp(self.start, self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state using the `progress` value as-is.
    pub fn into_current_unclamped(self) -> T where T: Lerp<Progress,Output=T> {
        Lerp::lerp_unclamped(self.start, self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state, clamping progress to [0;1].
    pub fn into_current_precise(self) -> T where T: Lerp<Progress,Output=T>, Progress: Clamp + Zero + One {
        Lerp::lerp_precise(self.start, self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state using the `progress` value as-is.
    pub fn into_current_unclamped_precise(self) -> T where T: Lerp<Progress,Output=T> {
        Lerp::lerp_unclamped_precise(self.start, self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state, clamping progress to [0;1].
    pub fn current<'a>(&'a self) -> T where &'a T: Lerp<Progress,Output=T>, Progress: Copy + Clamp + Zero + One {
        Lerp::lerp(&self.start, &self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state using the `progress` value as-is.
    pub fn current_unclamped<'a>(&'a self) -> T where &'a T: Lerp<Progress,Output=T>, Progress: Copy {
        Lerp::lerp_unclamped(&self.start, &self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state, clamping progress to [0;1].
    pub fn current_precise<'a>(&'a self) -> T where &'a T: Lerp<Progress,Output=T>, Progress: Copy + Clamp + Zero + One {
        Lerp::lerp_precise(&self.start, &self.end, self.progress_mapper.map_progress(self.progress))
    }
    /// Gets the transition's current state using the `progress` value as-is.
    pub fn current_unclamped_precise<'a>(&'a self) -> T where &'a T: Lerp<Progress,Output=T>, Progress: Copy {
        Lerp::lerp_unclamped_precise(&self.start, &self.end, self.progress_mapper.map_progress(self.progress))
    }
}

/// A convenience structure for storing a linear progression from one value to another.
pub type LinearTransition<T,Progress=f32> = Transition<T, IdentityProgressMapper, Progress>;

impl<T, Progress> LinearTransition<T, Progress> {
    /// Creates a new `LinearTransition` from `start` and `end` values, setting `progress` to zero.
    pub fn new(start: T, end: T) -> Self where Progress: Zero {
        Self { start, end, progress: Zero::zero(), progress_mapper: Default::default() }
    }
    /// Creates a new `LinearTransition` from `start`, `end` and `progress` values.
    pub fn with_progress(start: T, end: T, progress: Progress) -> Self {
        Self { start, end, progress, progress_mapper: Default::default() }
    }
}