Created
August 8, 2018 13:27
-
-
Save kiranandcode/ede34d54fbcec80730b6773d965a1aec to your computer and use it in GitHub Desktop.
Example Implementation of additive changes in rust - needs polishing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ops::{Add, AddAssign, Sub}; | |
pub trait Lerpable<T> { | |
fn at_progress(&self, progress: f32) -> T; | |
} | |
pub trait Diffable<T, U : Lerpable<T>> { | |
fn diff(start: &T, end: &T) -> U; | |
} | |
pub struct AddativeDiff<T, U : Lerpable<T>> { | |
end_state: T, | |
last_state: Option<T>, | |
last_progress: f32, | |
// the diff | |
diff: U | |
} | |
impl<T : Diffable<T,U> + Sub<Output=T> + Clone + Default, U: Lerpable<T>> AddativeDiff<T, U> { | |
fn new(start: &T, end: T) -> Self { | |
let diff = T::diff(start, &end); | |
AddativeDiff { | |
end_state: end, | |
last_state: None, | |
last_progress: 0.0, | |
diff | |
} | |
} | |
fn at_progress(&mut self, progress: f32) -> Result<T, &'static str> { | |
if self.last_progress > progress && self.last_state.is_some() { | |
Err("Invalid time range provided for additive diff") | |
} else if progress > 100.0 { | |
self.last_progress = progress; | |
Err("Completed") | |
} | |
else { | |
if let Some(prev_state) = self.last_state.take() { | |
self.last_progress = progress; | |
let next_state = self.diff.at_progress(progress); | |
self.last_state = Some(next_state.clone()); | |
let delta = next_state - prev_state ; | |
Ok(delta) | |
} else { | |
self.last_progress = progress; | |
let next_state = self.diff.at_progress(progress); | |
self.last_state = Some(next_state.clone()); | |
Ok(Default::default()) | |
} | |
} | |
} | |
} | |
pub struct f32Diff(f64, f64); | |
impl Lerpable<f64> for f32Diff { | |
fn at_progress(&self, progress:f32) -> f64 { | |
self.0 + self.1 * ((progress/100.0) as f64) | |
} | |
} | |
impl Diffable<f64, f32Diff> for f64 { | |
fn diff(start: &f64, end: &f64) -> f32Diff { | |
f32Diff(*start, *end - *start) | |
} | |
} | |
struct Property<T : Diffable<T,U> + Sub<Output=T> + Clone + Default, U: Lerpable<T>> { | |
model_value: T, | |
view_value: T, | |
last_progress: f32, | |
diffs: Vec<(f32, AddativeDiff<T,U>)> | |
} | |
impl<T : Diffable<T,U> + Sub<Output=T> + AddAssign<T> + Clone + Default, U: Lerpable<T>> Property<T,U> { | |
fn new(value: T) -> Self { | |
Property { | |
model_value: value.clone(), | |
view_value: value, | |
last_progress: 0.0, | |
diffs: Vec::new() | |
} | |
} | |
fn set_target(&mut self, value : T) { | |
let diff = AddativeDiff::new(&self.model_value, value.clone()); | |
self.diffs.push((self.last_progress, diff)); | |
self.model_value = value.clone(); | |
} | |
fn model(&self) -> &T { | |
&self.model_value | |
} | |
fn view(&self) -> &T { | |
&self.view_value | |
} | |
fn update(&mut self, progress: f32) { | |
let diffs = &mut self.diffs; | |
let view_value = &mut self.view_value; | |
let mut shrm = Vec::new(); | |
for (ind,(srt_prg, diff)) in diffs.iter_mut().enumerate() { | |
let eff_prgr = progress - *srt_prg; | |
if let Ok(delta) = diff.at_progress(eff_prgr) { | |
*view_value += delta; | |
} else { | |
shrm.push(ind); | |
} | |
} | |
for ind in shrm { | |
diffs.remove(ind); | |
} | |
self.last_progress = progress; | |
} | |
} | |
fn main() { | |
let mut start = Property::new(10.0); | |
start.set_target(100.0); | |
for i in (0..281) { | |
start.update(i as f32); | |
if i == 130 { | |
start.set_target(300.0); | |
} else if i == 180 { | |
start.set_target(10.0); | |
} | |
println!("d{:?}: {:?}", i, start.view()); | |
} | |
println!("Hello world"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment