use std::ops::{Add, AddAssign};
use undoredo::{Delta, Recorder, UndoRedo};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vector2<T> {
x: T,
y: T,
}
impl<T: Add<T, Output = T>> Add for Vector2<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl<T: AddAssign<T>> AddAssign for Vector2<T> {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
#[derive(Delta)]
#[undoredo(delta = EntitiesDelta)]
#[undoredo(half_delta = EntitiesHalfDelta)]
pub struct Entities<T> {
positions: Recorder<Vec<Vector2<T>>>,
velocities: Recorder<Vec<Vector2<T>>>,
healths: Recorder<Vec<i64>>,
turn_counter: Recorder<u64>,
#[undoredo(skip)]
#[allow(unused)]
not_in_delta: String,
}
impl<T: Add<T, Output = T> + AddAssign<T> + Copy + PartialOrd> Entities<T> {
pub fn new_entity(&mut self, position: Vector2<T>, velocity: Vector2<T>, health: i64) -> usize {
self.positions.push(position);
self.velocities.push(velocity);
self.healths.push(health)
}
pub fn update(&mut self) {
self.turn_counter.assign(*self.turn_counter.container() + 1);
for i in 0..self.positions.container().len() {
self.update_entity(i);
}
}
fn update_entity(&mut self, index: usize) {
let velocity = self.velocities[index];
self.positions
.modify(index, |position| *position += velocity);
self.healths.set(index, self.healths[index] - 1);
}
}
fn assert_entity(entities: &Entities<f64>, index: usize, pos: Vector2<f64>, health: i64) {
assert_eq!(entities.positions[index], pos);
assert_eq!(entities.healths[index], health);
}
fn main() {
let mut entities = Entities::<f64> {
positions: Recorder::new(Vec::new()),
velocities: Recorder::new(Vec::new()),
healths: Recorder::new(Vec::new()),
turn_counter: Recorder::new(0),
not_in_delta: "not_in_delta".to_string(),
};
let mut undoredo: UndoRedo<EntitiesDelta<f64>> = UndoRedo::new();
entities.new_entity(Vector2 { x: 0.0, y: 0.0 }, Vector2 { x: 1.0, y: 0.0 }, 100);
entities.new_entity(Vector2 { x: 0.0, y: 0.0 }, Vector2 { x: 0.0, y: 2.0 }, 100);
undoredo.commit(&mut entities);
entities.new_entity(
Vector2 { x: 100.0, y: 100.0 },
Vector2 { x: -1.0, y: -1.0 },
50,
);
undoredo.commit(&mut entities);
assert_eq!(entities.positions.container().len(), 3);
for _ in 0..3 {
entities.update();
undoredo.commit(&mut entities);
}
for _ in 0..5 {
entities.update();
}
undoredo.commit(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 8.0, y: 0.0 }, 92);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 16.0 }, 92);
assert_entity(&entities, 2, Vector2 { x: 92.0, y: 92.0 }, 42);
assert_eq!(*entities.turn_counter.container(), 8);
undoredo.undo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 3.0, y: 0.0 }, 97);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 6.0 }, 97);
assert_entity(&entities, 2, Vector2 { x: 97.0, y: 97.0 }, 47);
assert_eq!(*entities.turn_counter.container(), 3);
undoredo.undo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 2.0, y: 0.0 }, 98);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 4.0 }, 98);
assert_entity(&entities, 2, Vector2 { x: 98.0, y: 98.0 }, 48);
undoredo.undo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 1.0, y: 0.0 }, 99);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 2.0 }, 99);
assert_entity(&entities, 2, Vector2 { x: 99.0, y: 99.0 }, 49);
undoredo.undo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 0.0, y: 0.0 }, 100);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 0.0 }, 100);
assert_entity(&entities, 2, Vector2 { x: 100.0, y: 100.0 }, 50);
assert_eq!(*entities.turn_counter.container(), 0);
undoredo.undo(&mut entities);
assert!(entities.positions.container().len() == 2);
assert_entity(&entities, 0, Vector2 { x: 0.0, y: 0.0 }, 100);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 0.0 }, 100);
undoredo.redo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 0.0, y: 0.0 }, 100);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 0.0 }, 100);
assert_entity(&entities, 2, Vector2 { x: 100.0, y: 100.0 }, 50);
undoredo.redo(&mut entities);
assert_entity(&entities, 0, Vector2 { x: 1.0, y: 0.0 }, 99);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 2.0 }, 99);
assert_entity(&entities, 2, Vector2 { x: 99.0, y: 99.0 }, 49);
undoredo.redo(&mut entities);
assert_entity(&entities, 0, Vector2 { x: 2.0, y: 0.0 }, 98);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 4.0 }, 98);
assert_entity(&entities, 2, Vector2 { x: 98.0, y: 98.0 }, 48);
undoredo.redo(&mut entities);
assert_entity(&entities, 0, Vector2 { x: 3.0, y: 0.0 }, 97);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 6.0 }, 97);
assert_entity(&entities, 2, Vector2 { x: 97.0, y: 97.0 }, 47);
undoredo.redo(&mut entities);
assert!(entities.positions.container().len() == 3);
assert_entity(&entities, 0, Vector2 { x: 8.0, y: 0.0 }, 92);
assert_entity(&entities, 1, Vector2 { x: 0.0, y: 16.0 }, 92);
assert_entity(&entities, 2, Vector2 { x: 92.0, y: 92.0 }, 42);
assert_eq!(*entities.turn_counter.container(), 8);
}
#[test]
fn test() {
main();
}