checs 0.5.1

An Entity-Component-System library.
Documentation
use checs::derive_storage;
use checs::ComponentVec;
use checs::Storage;
use checs::World;

#[test]
fn derive_storage_macro_rules() {
    derive_storage!(
        #[derive(Default)]
        struct Storage {
            ints: ComponentVec<i32>,
        }
    );

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    _ = world.insert(e0, 42);
    _ = world.get::<i32>(e0);
    _ = world.get_mut::<i32>(e0);
    _ = world.remove(e0);
}

#[test]
#[cfg(feature = "proc")]
fn derive_storage() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    _ = world.insert(e0, 42);
    _ = world.get::<i32>(e0);
    _ = world.get_mut::<i32>(e0);
    _ = world.remove(e0);
}

#[test]
fn world_insert() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();

    let i = world.insert(e0, 42);
    assert_eq!(i, None);

    let i = world.insert(e0, 99);
    assert_eq!(i, Some(42));

    let i = world.insert(e0, 17);
    assert_eq!(i, Some(99));
}

#[test]
fn world_insert_many_trait() {
    use checs::InsertMany;

    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
        bools: ComponentVec<bool>,
        floats: ComponentVec<f32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();

    let (i, b) = world.insert_many(e0, (42, false));
    assert_eq!(i, None);
    assert_eq!(b, None);

    let (f, i) = world.insert_many(e0, (3.1415, 99));
    assert_eq!(f, None);
    assert_eq!(i, Some(42));

    let (b, f) = world.insert_many(e0, (false, 2.718281828));
    assert_eq!(b, Some(false));
    assert_eq!(f, Some(3.1415));
}

#[test]
fn world_get() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    world.insert(e0, 42);

    let actual = world.get::<i32>(e0);

    assert_eq!(actual, Some(&42));
}

#[test]
fn world_delete() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    world.insert(e0, 42);

    assert_eq!(world.get(e0), Some(&42));

    world.remove::<i32>(e0);

    assert_eq!(world.get(e0), None);
}

#[test]
fn world_spawn() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    world.insert(e0, 42);
    let e1 = world.spawn();
    world.insert(e1, 17);

    let mut iter = world.storage().ints.iter();

    assert_eq!(iter.next(), Some((e0, &42)));
    assert_eq!(iter.next(), Some((e1, &17)));
    assert_eq!(iter.next(), None);
}

#[test]
fn world_spawn_with() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
        bools: ComponentVec<bool>,
        floats: ComponentVec<f32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn_with((42, false));
    let _e1 = world.spawn_with((99, 3.1415));
    let e2 = world.spawn_with((17, true, 2.718281828));

    use checs::iter::LendingIterator;
    use checs::query::IntoQuery;

    let storage = &mut world.storage();

    let mut iter = (&storage.ints, &storage.bools).into_query();

    assert_eq!(iter.next(), Some((e0, (&42, &false))));
    assert_eq!(iter.next(), Some((e2, (&17, &true))));
    assert_eq!(iter.next(), None);
}

#[test]
fn spawn_macro() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
        bools: ComponentVec<bool>,
        floats: ComponentVec<f32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = checs::spawn!(world, 42, false);
    let _e1 = checs::spawn!(world, 99, 3.1415);
    let e2 = checs::spawn!(world, 17, true, 2.718281828);

    use checs::iter::LendingIterator;
    use checs::query::IntoQuery;

    let storage = &mut world.storage();

    let mut iter = (&storage.ints, &storage.bools).into_query();

    assert_eq!(iter.next(), Some((e0, (&42, &false))));
    assert_eq!(iter.next(), Some((e2, (&17, &true))));
    assert_eq!(iter.next(), None);
}

#[test]
fn world_release() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    world.insert(e0, 42);
    let e1 = world.spawn();
    world.insert(e1, 17);

    {
        let mut iter = world.storage().ints.iter();

        assert_eq!(iter.next(), Some((e0, &42)));
        assert_eq!(iter.next(), Some((e1, &17)));
        assert_eq!(iter.next(), None);
    }

    world.despawn(e0).unwrap();

    {
        let mut iter = world.storage().ints.iter();

        assert_eq!(iter.next(), Some((e1, &17)));
        assert_eq!(iter.next(), None);
    }

    world.despawn(e1).unwrap();

    {
        let mut iter = world.storage().ints.iter();

        assert_eq!(iter.next(), None);
    }
}

#[test]
fn world_release_all() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = checs::spawn!(world, 42);
    let e1 = checs::spawn!(world, 17);
    let e2 = checs::spawn!(world, 99);

    {
        let mut iter = world.storage().ints.iter();

        assert_eq!(iter.next(), Some((e0, &42)));
        assert_eq!(iter.next(), Some((e1, &17)));
        assert_eq!(iter.next(), Some((e2, &99)));
        assert_eq!(iter.next(), None);
    }

    world.despawn_all::<i32>().unwrap();

    {
        let mut iter = world.storage().ints.iter();

        assert_eq!(iter.next(), None);
    }
}

#[test]
fn world_despawn_entities() {
    #[derive(Default, Storage)]
    struct Storage {
        ints: ComponentVec<i32>,
        floats: ComponentVec<f32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = checs::spawn!(world, 42, 0.0);
    let e1 = checs::spawn!(world, 17, 0.1);
    let e2 = checs::spawn!(world, 99, 0.2);
    let e3 = checs::spawn!(world, 0, 0.3);

    let result = world.despawn_entities(&[e0, e3]);

    assert_eq!(result, Ok(()));

    assert_eq!(world.get::<i32>(e0), None);
    assert_eq!(world.get::<f32>(e0), None);
    assert_eq!(world.get(e1), Some(&17));
    assert_eq!(world.get(e1), Some(&0.1));
    assert_eq!(world.get(e2), Some(&99));
    assert_eq!(world.get(e2), Some(&0.2));
    assert_eq!(world.get::<i32>(e3), None);
    assert_eq!(world.get::<f32>(e3), None);

    let result = world.despawn_entities(&[e2, e3, e1]);

    // Calling `despawn_entities` deletes all entities until an error is encountered. So `e2` is
    // despawned correctly...
    assert_eq!(world.get::<i32>(e2), None);
    assert_eq!(world.get::<f32>(e2), None);

    // ...but it returns an error, because `e3` had already been freed...
    assert_eq!(result, Err(checs::entity::Error::DoubleFree));

    // ...and `e1` is never even processed.
    assert_eq!(world.get(e1), Some(&17));
    assert_eq!(world.get(e1), Some(&0.1));
}

#[test]
fn world_into_query() {
    #[derive(Default, Storage)]
    struct Storage {
        bools: ComponentVec<bool>,
        floats: ComponentVec<f32>,
    }

    let mut world = World::<Storage>::new();

    let e0 = world.spawn();
    world.insert(e0, 3.1415);
    world.insert(e0, false);

    let e1 = world.spawn();
    world.insert(e1, true);

    let e2 = world.spawn();
    world.insert(e2, 2.71828);

    let storage = &mut world.storage();

    {
        use checs::iter::LendingIterator;
        use checs::query::IntoQuery;

        let mut iter = (&storage.floats, &storage.bools).into_query();
        assert_eq!(iter.next(), Some((e0, (&3.1415, &false))));
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = storage.floats.iter();
        assert_eq!(iter.next(), Some((e0, &3.1415)));
        assert_eq!(iter.next(), Some((e2, &2.71828)));
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = storage.bools.iter();
        assert_eq!(iter.next(), Some((e0, &false)));
        assert_eq!(iter.next(), Some((e1, &true)));
        assert_eq!(iter.next(), None);
    }
}