Skip to content

Instantly share code, notes, and snippets.

@Gopiandcode
Created August 8, 2018 13:27
Show Gist options
  • Save Gopiandcode/ede34d54fbcec80730b6773d965a1aec to your computer and use it in GitHub Desktop.
Save Gopiandcode/ede34d54fbcec80730b6773d965a1aec to your computer and use it in GitHub Desktop.
Example Implementation of additive changes in rust - needs polishing
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