amethyst / specs

Specs - Parallel ECS
https://amethyst.github.io/specs/
Apache License 2.0
2.49k stars 219 forks source link

systemdata and saveload_systemdata macros #704

Open abesto opened 4 years ago

abesto commented 4 years ago

Description

I've created two (procedural) macros to write system data structs more concisely. I'm opening this "feature request" to 1. share them, 2. offer them as contributions or at least inspirations. The implementations currently live in https://github.com/abesto/rktrl/blob/master/rktrl_macros/src/lib.rs.

Motivation

systemdata

Example usage

systemdata!(SpawnerSystemData(
    entities,
    write_storage(
        (serialize_me: SimpleMarker<SerializeMe>),
        AreaOfEffect,
        BlocksTile,
        [...]
        Viewshed,
    ),
    write((serialize_me_alloc: SimpleMarkerAllocator<SerializeMe>)),
    write_expect((rng: RandomNumberGenerator)),
    read_expect((spawn_requests: EventChannel<SpawnRequest>))
));

Generates roughly:

#[derive(SystemData)]
struct SpawnerSystemData<'a> {
    entities: Entities<'a>,

    serialize_me: WriteStorage<SimpleMarker<SerializeMe>, 'a>,
    area_of_effects: WriteStorage<AreaOfEffect, 'a>,
    [...]

    serialize_me_alloc: Write<SimpleMarkerAllocator<SerializeMe>, 'a>,
    [...]
}

saveload_systemdata

The implementation solves the 16 tuple size limit by chunking components into 16-sized tuples, so that actual saving would iterate over 16-tuples and save those one by one.

Example:

saveload_system_data!(
    components(
        AreaOfEffect,
        BlocksTile,
    )
    resources(Map, GameLog)
);

Generates roughly:

#[derive(SystemData)]
struct SaveSystemData<'a> {
    entities: Entities<'a>,
    components: ((ReadStorage<AreaOfEffect, 'a>, ReadStorage<BlocksTile, 'a>),),
    map: ReadExpect<Map, 'a>,
    game_log: ReadExpect<GameLog, 'a>
}

#[derive(SystemData)]
struct LoadSystemData<'a> {
    entities: Entities<'a>,
    components: ((WriteStorage<AreaOfEffect, 'a>, WriteStorage<BlocksTile, 'a>),),
    map: Write<Map, 'a>,
    game_log: Write<GameLog, 'a>
}

Drawbacks

Unresolved questions

I'm using this in my hobby project happily, but have zero experience with production-ready macros. That's where I expect most of the problems (unknown to me currently) to creep in. I guess there's also bikeshedding to be done around the syntax.


I'd be happy to "formally" contribute these macros as a PR if it makes sense, and to put in some work iterating on them based on feedback.