# HG changeset patch # User Emmanuel Gil Peyrot # Date 1562494790 -7200 # Node ID 9e40bd5cc26d9ec270c3d0f23de986c2eea6a6df # Parent a58103f2f264061b5fc60ea17630eee17c3ec2aa Move interpolators in another module. diff --git a/src/th06/anm0_vm.rs b/src/th06/anm0_vm.rs --- a/src/th06/anm0_vm.rs +++ b/src/th06/anm0_vm.rs @@ -6,85 +6,10 @@ use crate::th06::anm0::{ Call, Instruction, }; +use crate::th06::interpolator::{Interpolator1, Interpolator2, Interpolator3, Formula}; use std::cell::RefCell; use std::rc::Rc; -#[derive(Debug, Clone, Copy, PartialEq)] -enum Formula { - Linear, - Power2, - InvertPower2, -} - -impl Formula { - fn apply(&self, x: f32) -> f32 { - match self { - Formula::Linear => x, - Formula::Power2 => x * x, - Formula::InvertPower2 => 2. * x - x * x, - } - } -} - -macro_rules! generate_interpolator { - ($name:ident, $n:tt) => { - #[derive(Debug, Clone)] - struct $name { - start_values: [T; $n], - end_values: [T; $n], - start_frame: u16, - end_frame: u16, - formula: Formula, - } - - impl $name - where f32: From, - T: From, - T: std::ops::Sub, - T: std::ops::Add, - T: Copy, - T: Default, - { - pub fn new(start_values: [T; $n], start_frame: u16, end_values: [T; $n], end_frame: u16, formula: Formula) -> $name { - $name { - start_values, - end_values, - start_frame, - end_frame, - formula, - } - } - - // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here. - pub fn values(&self, frame: u16) -> [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 - } - } - } - }; -} - -generate_interpolator!(Interpolator1, 1); -generate_interpolator!(Interpolator2, 2); -generate_interpolator!(Interpolator3, 3); - /// Base visual element. #[derive(Debug, Clone, Default)] pub struct Sprite { diff --git a/src/th06/interpolator.rs b/src/th06/interpolator.rs new file mode 100644 --- /dev/null +++ b/src/th06/interpolator.rs @@ -0,0 +1,77 @@ +//! Animation runner. + +#[derive(Debug, Clone, Copy, PartialEq)] +pub(crate) enum Formula { + Linear, + Power2, + InvertPower2, +} + +impl Formula { + fn apply(&self, x: f32) -> f32 { + match self { + Formula::Linear => x, + Formula::Power2 => x * x, + Formula::InvertPower2 => 2. * x - x * x, + } + } +} + +macro_rules! generate_interpolator { + ($name:ident, $n:tt) => { + #[derive(Debug, Clone)] + pub(crate) struct $name { + start_values: [T; $n], + end_values: [T; $n], + start_frame: u16, + end_frame: u16, + formula: Formula, + } + + impl $name + where f32: From, + T: From, + T: std::ops::Sub, + T: std::ops::Add, + T: Copy, + T: Default, + { + pub fn new(start_values: [T; $n], start_frame: u16, end_values: [T; $n], end_frame: u16, formula: Formula) -> $name { + $name { + start_values, + end_values, + start_frame, + end_frame, + formula, + } + } + + // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here. + pub fn values(&self, frame: u16) -> [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 + } + } + } + }; +} + +generate_interpolator!(Interpolator1, 1); +generate_interpolator!(Interpolator2, 2); +generate_interpolator!(Interpolator3, 3); diff --git a/src/th06/mod.rs b/src/th06/mod.rs --- a/src/th06/mod.rs +++ b/src/th06/mod.rs @@ -3,3 +3,4 @@ pub mod pbg3; pub mod anm0; pub mod anm0_vm; +pub mod interpolator;