specs_transform 0.5.0

transform 2d and 3d component for specs
extern crate num_traits;
extern crate specs;
extern crate specs_bundler;
extern crate specs_transform;

use num_traits::Float;
use specs::{WorldExt, Builder, DispatcherBuilder, Join, System, World, WriteStorage};
use specs_bundler::Bundler;
use specs_transform::{
    GlobalTransform2D, GlobalTransform3D, Parent, Transform2D, Transform3D, TransformBundle,
    TransformSystem,
};

use std::marker::PhantomData;

pub struct Test2DSystem<T: 'static + Sync + Send + Copy + Float>(PhantomData<T>);

impl<T: 'static + Sync + Send + Copy + Float> Test2DSystem<T> {
    #[inline(always)]
    pub fn new() -> Self {
        Test2DSystem(PhantomData)
    }
}

impl<'a, T: 'static + Sync + Send + Copy + Float> System<'a> for Test2DSystem<T> {
    type SystemData = (WriteStorage<'a, Transform2D<T>>,);

    fn run(&mut self, mut locals_2d: Self::SystemData) {
        for local in (&mut locals_2d.0).join() {
            local.position[0] = local.position[0] + T::one();
            local.position[1] = local.position[1] + T::one();
        }
    }
}

pub struct Test3DSystem<T: 'static + Sync + Send + Copy + Float>(PhantomData<T>);

impl<T: 'static + Sync + Send + Copy + Float> Test3DSystem<T> {
    #[inline(always)]
    pub fn new() -> Self {
        Test3DSystem(PhantomData)
    }
}

impl<'a, T: 'static + Sync + Send + Copy + Float> System<'a> for Test3DSystem<T> {
    type SystemData = (WriteStorage<'a, Transform3D<T>>,);

    fn run(&mut self, mut locals_3d: Self::SystemData) {
        for local in (&mut locals_3d.0).join() {
            local.position[0] = local.position[0] + T::one();
            local.position[1] = local.position[1] + T::one();
            local.position[2] = local.position[2] + T::one();
        }
    }
}

pub struct TestSystem<T: 'static + Sync + Send + Copy + Float>(PhantomData<T>);

impl<T: 'static + Sync + Send + Copy + Float> TestSystem<T> {
    #[inline(always)]
    pub fn new() -> Self {
        TestSystem(PhantomData)
    }
}

impl<'a, T: 'static + Sync + Send + Copy + Float> System<'a> for TestSystem<T> {
    type SystemData = (
        WriteStorage<'a, Transform2D<T>>,
        WriteStorage<'a, Transform3D<T>>,
    );

    fn run(&mut self, (mut locals_2d, mut locals_3d): Self::SystemData) {
        for local in (&mut locals_2d).join() {
            local.position[0] = local.position[0] + T::one();
            local.position[1] = local.position[1] + T::one();
        }
        for local in (&mut locals_3d).join() {
            local.position[0] = local.position[0] + T::one();
            local.position[1] = local.position[1] + T::one();
            local.position[2] = local.position[2] + T::one();
        }
    }
}

#[test]
fn test_parent_child_2d() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .with(
            Test2DSystem::<f32>::new(),
            "test_system",
            &[TransformSystem::<f32>::name()],
        )
        .build();

    let parent = world
        .create_entity()
        .with(Transform2D::<f32>::default())
        .build();

    let _ = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform2D::<f32>::default())
        .build();

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform2D<f32>>();
    let globals: Vec<&GlobalTransform2D<f32>> = (&globals_read).join().collect();

    assert_eq!(globals[1].as_ref(), &[1.0, 0.0, 0.0, 1.0, 2.0, 2.0]);
}

#[test]
fn test_parent_child_3d() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .with(
            Test3DSystem::<f32>::new(),
            "test_system",
            &[TransformSystem::<f32>::name()],
        )
        .build();

    let parent = world
        .create_entity()
        .with(Transform3D::<f32>::default())
        .build();

    let entity = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform3D::<f32>::default())
        .build();

    println!("Creating {:?} -> {:?}", parent, entity);

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform3D<f32>>();
    let globals: Vec<&GlobalTransform3D<f32>> = (&globals_read).join().collect();

    assert_eq!(
        globals[1].as_ref(),
        &[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0, 2.0, 1.0,]
    );
}

#[test]
fn test_3d_parent_2d_child() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .with(
            TestSystem::<f32>::new(),
            "test_system",
            &[TransformSystem::<f32>::name()],
        )
        .build();

    let parent = world
        .create_entity()
        .with(Transform3D::<f32>::default())
        .build();

    let _ = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform2D::<f32>::default())
        .build();

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform2D<f32>>();
    let globals: Vec<&GlobalTransform2D<f32>> = (&globals_read).join().collect();

    assert_eq!(globals[0].as_ref(), &[1.0, 0.0, 0.0, 1.0, 2.0, 2.0]);
}

#[test]
fn test_2d_parent_3d_child() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .with(
            TestSystem::<f32>::new(),
            "test_system",
            &[TransformSystem::<f32>::name()],
        )
        .build();

    let parent = world
        .create_entity()
        .with(Transform2D::<f32>::default())
        .build();

    let _ = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform3D::<f32>::default())
        .build();

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform3D<f32>>();
    let globals: Vec<&GlobalTransform3D<f32>> = (&globals_read).join().collect();

    assert_eq!(
        globals[0].as_ref(),
        &[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0, 1.0, 1.0,]
    );
}

#[test]
fn test_global_2d_always_exits() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .build();

    let parent = world
        .create_entity()
        .with(Transform2D::<f32>::default().with_position([1.0, 1.0]))
        .build();

    let _ = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform2D::<f32>::default().with_position([1.0, 1.0]))
        .build();

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform2D<f32>>();
    let globals: Vec<&GlobalTransform2D<f32>> = (&globals_read).join().collect();

    assert_eq!(
        globals[0].as_ref(),
        &[1.0, 0.0, 0.0, 1.0, 1.0, 1.0]
    );

    assert_eq!(
        globals[1].as_ref(),
        &[1.0, 0.0, 0.0, 1.0, 2.0, 2.0]
    );
}

#[test]
fn test_global_3d_always_exits() {
    let mut world = World::new();

    let mut dispatcher = Bundler::new(&mut world, DispatcherBuilder::new())
        .bundle(TransformBundle::<f32>::default())
        .unwrap()
        .build();

    let parent = world
        .create_entity()
        .with(Transform3D::<f32>::default().with_position([1.0, 1.0, 1.0]))
        .build();

    let _ = world
        .create_entity()
        .with(Parent::new(parent))
        .with(Transform3D::<f32>::default().with_position([1.0, 1.0, 1.0]))
        .build();

    dispatcher.dispatch(&mut world); // first frame init
    dispatcher.dispatch(&mut world);

    world.maintain();

    let globals_read = world.read_storage::<GlobalTransform3D<f32>>();
    let globals: Vec<&GlobalTransform3D<f32>> = (&globals_read).join().collect();

    assert_eq!(
        globals[0].as_ref(),
        &[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0,]
    );

    assert_eq!(
        globals[1].as_ref(),
        &[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0, 2.0, 1.0,]
    );
}