Mercurial > touhou
diff interpreters/src/th06/interpolator.rs @ 787:7f9b3f5001c2
interpreters: Make Interpolator generic over N
This was a workaround for Rust < 1.51 which didn’t support const generics yet,
but we’ve had tat for close to five years now!
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Mon, 15 Dec 2025 11:34:58 +0100 |
| parents | 21b186be2590 |
| children |
line wrap: on
line diff
--- a/interpreters/src/th06/interpolator.rs +++ b/interpreters/src/th06/interpolator.rs @@ -17,80 +17,71 @@ } } -macro_rules! generate_interpolator { - ($name:ident, $n:tt) => { - #[derive(Debug, Clone)] - pub(crate) struct $name<T> { - start_values: [T; $n], - end_values: [T; $n], - start_frame: u32, - end_frame: u32, - formula: Formula, - } - - impl<T> $name<T> - where f32: From<T>, - T: From<f32>, - T: std::ops::Sub<Output = T>, - T: std::ops::Add<Output = T>, - T: Copy, - T: Default, - { - pub fn new(start_values: [T; $n], start_frame: u32, end_values: [T; $n], end_frame: u32, formula: Formula) -> $name<T> { - $name { - start_values, - end_values, - start_frame, - end_frame, - formula, - } - } - - pub fn set_start(&mut self, frame: u32, values: [T; $n]) { - self.start_values = values; - self.start_frame = frame; - } - - pub fn set_end(&mut self, frame: u32, values: [T; $n]) { - self.end_values = values; - self.end_frame = frame; - } - - pub fn set_end_values(&mut self, values: [T; $n]) { - self.end_values = values; - } - - pub fn set_end_frame(&mut self, frame: u32) { - self.end_frame = frame; - } - - // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here. - pub fn values(&self, frame: u32) -> [f32; $n] { - if frame + 1 >= self.end_frame { - // XXX: skip the last interpolation step. - // This bug is replicated from the original game. - //self.start_frame = self.end_frame; - //self.end_values - let mut values: [f32; $n] = [Default::default(); $n]; - for (i, value) in self.end_values.iter().enumerate() { - values[i] = f32::from(*value); - } - values - } else { - let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32; - coeff = self.formula.apply(coeff); - let mut values: [f32; $n] = [Default::default(); $n]; - for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() { - values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start))); - } - values - } - } - } - }; +#[derive(Debug, Clone)] +pub(crate) struct Interpolator<T, const N: usize> { + start_values: [T; N], + end_values: [T; N], + start_frame: u32, + end_frame: u32, + formula: Formula, } -generate_interpolator!(Interpolator1, 1); -generate_interpolator!(Interpolator2, 2); -generate_interpolator!(Interpolator3, 3); -//generate_interpolator!(Interpolator4, 4); +impl<T, const N: usize> Interpolator<T, N> +where f32: From<T>, + T: From<f32>, + T: std::ops::Sub<Output = T>, + T: std::ops::Add<Output = T>, + T: Copy, + T: Default, +{ + pub fn new(start_values: [T; N], start_frame: u32, end_values: [T; N], end_frame: u32, formula: Formula) -> Interpolator<T, N> { + Interpolator { + start_values, + end_values, + start_frame, + end_frame, + formula, + } + } + + pub fn set_start(&mut self, frame: u32, values: [T; N]) { + self.start_values = values; + self.start_frame = frame; + } + + pub fn set_end(&mut self, frame: u32, values: [T; N]) { + self.end_values = values; + self.end_frame = frame; + } + + pub fn set_end_values(&mut self, values: [T; N]) { + self.end_values = values; + } + + pub fn set_end_frame(&mut self, frame: u32) { + self.end_frame = frame; + } + + // XXX: Make it return [T; N] instead, we don’t want to only do f32 here. + pub fn values(&self, frame: u32) -> [f32; N] { + if frame + 1 >= self.end_frame { + // XXX: skip the last interpolation step. + // This bug is replicated from the original game. + //self.start_frame = self.end_frame; + //self.end_values + let mut values: [f32; N] = [Default::default(); N]; + for (i, value) in self.end_values.iter().enumerate() { + values[i] = f32::from(*value); + } + values + } else { + let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32; + coeff = self.formula.apply(coeff); + let mut values: [f32; N] = [Default::default(); N]; + for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() { + values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start))); + } + values + } + } +}
