Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component Grouping #201

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by Cargo
/target/
/specs_derive/target/
Cargo.lock

# Generated by mdbook
Expand Down
18 changes: 11 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: rust
rust:
- nightly
- beta
- stable

branches:
Expand All @@ -10,14 +11,17 @@ branches:
- master

script:
- cargo build --verbose
- cargo test --verbose
- cargo build --verbose --no-default-features
- cargo test --verbose --no-default-features
- cargo build --verbose --features serialize
- cargo test --verbose --features serialize
- cargo clean
- cargo build --all --verbose
- cargo clean
- cargo test --all --verbose
- cargo clean
- cargo build --all --verbose --features serialize
- cargo clean
- cargo test --all --verbose --features serialize
- cargo clean
- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then
cargo bench --verbose --no-run;
cargo bench --all --verbose --no-run;
fi

after_success: |
Expand Down
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ exclude = ["bors.toml", ".travis.yml"]
[badges]
travis-ci = { repository = "slide-rs/specs" }

[workspace]
members = [ "specs_derive" ]

[dependencies]
atom = "0.3"
crossbeam = "0.2.10"
Expand All @@ -46,9 +49,10 @@ common = ["futures"]
serialize = ["serde", "serde_derive"]

[dev-dependencies]
cgmath = { version = "0.14", features = ["eders"] }
cgmath = { version = "0.14", features = ["eders"] }
rand = "0.3"
serde_json = "1.0"
specs_derive = { path = "specs_derive", version = "0.1", features = ["serialize"] }

[[example]]
name = "basic"
Expand All @@ -63,3 +67,7 @@ required-features = ["common"]
[[example]]
name = "serialize"
required-features = ["serialize"]

[[example]]
name = "derive"
required-features = ["serialize"]
184 changes: 184 additions & 0 deletions examples/derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@

#![recursion_limit="256"]

#[macro_use]
extern crate specs;
#[macro_use]
extern crate specs_derive;

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

fn main() {
use specs::{Component, ComponentGroup, DeconstructedGroup, DispatcherBuilder, Entities, Join, System, Split, VecStorage, WriteStorage, World, WorldDeserializer, WorldSerializer};
use serde::de::DeserializeSeed;

#[derive(Debug, Serialize, Deserialize)]
struct Comp1(String);
impl Component for Comp1 {
type Storage = VecStorage<Comp1>;
}

#[derive(Debug, Serialize, Deserialize)]
struct Comp2(f32);
impl Component for Comp2 {
type Storage = VecStorage<Comp2>;
}

#[derive(Debug, Serialize, Deserialize)]
struct Comp3(u32);
impl Component for Comp3 {
type Storage = VecStorage<Comp3>;
}

#[derive(Debug, Serialize, Deserialize)]
struct Comp4(u32);
impl Component for Comp4 {
type Storage = VecStorage<Comp4>;
}

#[derive(Debug, Serialize, Deserialize)]
struct Comp5(u32);
impl Component for Comp5 {
type Storage = VecStorage<Comp5>;
}

#[derive(ComponentGroup)]
#[allow(dead_code)]
struct SomeGroup {
#[group(serialize)]
field1: Comp1,

#[group(serialize)]
field2: Comp2,

field3: Comp3,

#[group(subgroup)]
test_sub: TestSub,
}

#[derive(ComponentGroup)]
#[allow(dead_code)]
struct TestSub {
#[group(serialize)]
field4: Comp4,

field5: Comp5,
}

struct RemovalSystem;
impl<'a> System<'a> for RemovalSystem {
type SystemData = (
Entities<'a>,
WriteStorage<'a, Comp1>,
WriteStorage<'a, Comp2>,
WriteStorage<'a, Comp3>,
WriteStorage<'a, Comp4>,
WriteStorage<'a, Comp5>,
);

fn run(&mut self, mut data: Self::SystemData) {
// Remove all components
for (entity, _) in (&*data.0, &data.1.check()).join() {
data.1.remove(entity);
}
for (entity, _) in (&*data.0, &data.2.check()).join() {
data.2.remove(entity);
}
for (entity, _) in (&*data.0, &data.3.check()).join() {
data.3.remove(entity);
}
for (entity, _) in (&*data.0, &data.4.check()).join() {
data.4.remove(entity);
}
for (entity, _) in (&*data.0, &data.5.check()).join() {
data.5.remove(entity);
}
}
}

// Running
let mut world = World::new();
world.register_group::<SomeGroup>();

world.create_entity().with(Comp1("Nice".to_owned())).with(Comp4(500)).with(Comp5(501)).build();
world.create_entity().with(Comp1("Nice".to_owned())).with(Comp2(5.0)).with(Comp3(1)).build();
world.create_entity().with(Comp1("Nice".to_owned())).with(Comp3(2)).build();
world.create_entity().with(Comp4(0)).with(Comp2(3.14159265358979)).build();

let serialized = {
let world_serializer = WorldSerializer::<SomeGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("{}", serialized);
serialized
};

{
let mut dispatcher = DispatcherBuilder::new()
.add(RemovalSystem, "removal", &[])
.build();

dispatcher.dispatch(&mut world.res);
world.maintain();
}

{
let world_serializer = WorldSerializer::<SomeGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("before: {}", serialized);
}

{
let entity_list: Vec<_> = {
let entities = world.read_resource::<specs::EntitiesRes>();
entities.join().collect()
};

let world_deserializer = WorldDeserializer::<SomeGroup>::new(&mut world, entity_list.as_slice());
let mut json_deserializer = serde_json::Deserializer::from_str(&serialized);
let _ = world_deserializer.deserialize(&mut json_deserializer);
}

{
let world_serializer = WorldSerializer::<SomeGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("after: {}", serialized);
}

{
println!("locals:");
for local in SomeGroup::local_components() {
println!("{}", local);
}
println!("all:");
for element in SomeGroup::components() {
println!("{}", element);
}
println!("subgroups:");
for subgroup in <SomeGroup as ComponentGroup>::subgroups() {
println!("{}", subgroup);
}
}

fn call_method<T>(s: &str) -> u32 {
println!("Nice {}", s);
42
}

fn call_other<T>(s: &str) -> u32 {
println!("Static {}", s);
3
}

let s = "Something";
call!(component: SomeGroup =>
fn call_method [ ] in [ ] (s)
);
call!(component: SomeGroup =>
fn call_other [ ] in [ ] (s)
);
}

90 changes: 87 additions & 3 deletions examples/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ extern crate shred;
#[macro_use]
extern crate shred_derive;
extern crate specs;
#[macro_use]
extern crate specs_derive;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

fn main() {
use serde::Serialize;
use serde::de::DeserializeSeed;
use serde_json::{Serializer, from_str as json_from_str};
use specs::{Component, DispatcherBuilder, Entities, Join, PackedData, System, VecStorage,
World, WriteStorage};
World, WorldDeserializer, WorldSerializer, WriteStorage};

#[derive(Debug, Serialize, Deserialize)]
struct CompSerialize {
Expand All @@ -22,6 +25,22 @@ fn main() {
type Storage = VecStorage<Self>;
}

#[derive(Debug, Serialize, Deserialize)]
struct CompFloat(f32);
impl Component for CompFloat {
type Storage = VecStorage<CompFloat>;
}

#[derive(ComponentGroup)]
#[allow(dead_code)]
struct SerialGroup {
#[group(serialize)]
comp_serialize: CompSerialize,

#[group(serialize)]
comp_float: CompFloat,
}

#[derive(SystemData)]
struct Data<'a> {
entities: Entities<'a>,
Expand Down Expand Up @@ -65,10 +84,34 @@ fn main() {
}
}

#[derive(SystemData)]
struct RemovalData<'a> {
entities: Entities<'a>,
comp_serial: WriteStorage<'a, CompSerialize>,
comp_float: WriteStorage<'a, CompFloat>,
}

struct RemovalSystem;
impl<'a> System<'a> for RemovalSystem {
type SystemData = RemovalData<'a>;

fn run(&mut self, mut data: RemovalData) {
// Remove all components
for (entity, _) in (&*data.entities, &data.comp_serial.check()).join() {
data.comp_serial.remove(entity);
}
for (entity, _) in (&*data.entities, &data.comp_float.check()).join() {
data.comp_float.remove(entity);
}
}
}

let mut world = World::new();
world.register::<CompSerialize>();
world.register_group::<SerialGroup>();

world.create_entity().build();
world.create_entity()
.with(CompFloat(2.71828182845))
.build();
world.create_entity().build();
world
.create_entity()
Expand All @@ -85,6 +128,7 @@ fn main() {
field: 5,
other: true,
})
.with(CompFloat(3.14159265358979))
.build();
world
.create_entity()
Expand All @@ -100,6 +144,7 @@ fn main() {
field: 0,
other: false,
})
.with(CompFloat(5.0))
.build();

let mut dispatcher = DispatcherBuilder::new()
Expand All @@ -108,4 +153,43 @@ fn main() {

dispatcher.dispatch(&mut world.res);
world.maintain();

let serialized = {
let world_serializer = WorldSerializer::<SerialGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("{}", serialized);
serialized
};

{
let mut dispatcher = DispatcherBuilder::new()
.add(RemovalSystem, "removal", &[])
.build();

dispatcher.dispatch(&mut world.res);
world.maintain();
}

{
let world_serializer = WorldSerializer::<SerialGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("before: {}", serialized);
}

{
let entity_list: Vec<_> = {
let entities = world.read_resource::<specs::EntitiesRes>();
entities.join().collect()
};

let world_deserializer = WorldDeserializer::<SerialGroup>::new(&mut world, entity_list.as_slice());
let mut json_deserializer = serde_json::Deserializer::from_str(&serialized);
let _ = world_deserializer.deserialize(&mut json_deserializer);
}

{
let world_serializer = WorldSerializer::<SerialGroup>::new(&world);
let serialized = serde_json::to_string_pretty(&world_serializer).unwrap();
println!("after: {}", serialized);
}
}
Loading