Skip to content

Commit

Permalink
Merge #575
Browse files Browse the repository at this point in the history
575: Cleanup the whole crate r=torkleyy a=torkleyy

<!-- Before creating a PR, please make sure you read the contribution guidelines. -->
<!-- Feel free to delete points if they don't make sense for this PR. -->
<!-- You can tick boxes by putting an "x" inside the braces, or by clicking them once the comment is published. -->

<!-- Please use "Fixes #nr" and "Related #nr", respectively. -->

## Checklist

* [x] I've added tests for all code changes and additions (where applicable)
* [x] I've added a demonstration of the new feature to one or more examples
* [x] I've updated the book to reflect my changes
* [x] Usage of new public items is shown in the API docs

## API changes

No direct API changes.

## Issues

Fixes #568



Co-authored-by: Thomas Schaller <[email protected]>
  • Loading branch information
bors[bot] and torkleyy committed Apr 18, 2019
2 parents d977f19 + 4fa25e6 commit 7bd3a76
Show file tree
Hide file tree
Showing 45 changed files with 668 additions and 511 deletions.
15 changes: 9 additions & 6 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
same_line_attributes = false
reorder_imports = true
reorder_import_names = true
reorder_imports_in_group = true
binop_separator = "Back"
#imports_indent = "Block"
hard_tabs = false
merge_imports = true
reorder_impl_items = true
use_field_init_shorthand = true
use_try_shorthand = true
format_doc_comments = true
wrap_comments = true
edition = "2018"
version = "Two"
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: rust

rust:
- nightly
- 1.32.0
- 1.34.0
- stable

cache:
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories = ["concurrency", "game-engines"]
license = "MIT/Apache-2.0"
authors = ["slide-rs hackers"]
exclude = ["bors.toml", ".travis.yml"]
edition = "2018"

# the `storage_cmp` and `storage_sparse` benches are called from `benches_main`
autobenches = false
Expand All @@ -27,9 +28,9 @@ fnv = "1.0"
hibitset = { version = "0.5.3", default-features = false }
log = "0.4"
mopa = "0.2"
shred = { git="https://github.com/slide-rs/shred", branch = "master", default-features = false }
shred = { version = "0.8.0", default-features = false }
shrev = "1.0.0"
shred-derive = "0.5.0"
shred-derive = "0.6.0"
tuple_utils = "0.3"
rayon = { version = "1.0.0", optional = true }
nonzero_signed = "1.0.1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Unlike most other ECS libraries out there, it provides
other and you can use barriers to force several stages in system execution
* high performance for real-world applications

Minimum Rust version: 1.28
Minimum Rust version: 1.34

## [Link to the book][book]

Expand Down
6 changes: 4 additions & 2 deletions benches/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ extern crate test;
use cgmath::Vector2;
use rand::thread_rng;
use shred::RunningTime;
use specs::prelude::*;
use specs::storage::{HashMapStorage, NullStorage};
use specs::{
prelude::*,
storage::{HashMapStorage, NullStorage},
};
use test::Bencher;

type Vec2 = Vector2<f32>;
Expand Down
3 changes: 1 addition & 2 deletions benches/storage_cmp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use criterion::{Bencher, Criterion};
use specs::prelude::*;
use specs::storage;
use specs::{prelude::*, storage};

use super::black_box;

Expand Down
6 changes: 4 additions & 2 deletions benches/storage_sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ macro_rules! setup {
macro_rules! gap {
($storage:ident, $name:ident => $sparsity:expr) => {
mod $name {
use super::{
super::{black_box, Bencher, Criterion},
setup, CompBool, CompInt,
};
use specs::prelude::*;
use super::super::{black_box, Bencher, Criterion};
use super::{setup, CompBool, CompInt};

fn insert(bencher: &mut Bencher) {
let (world, entities) = setup(true, false, $sparsity);
Expand Down
3 changes: 1 addition & 2 deletions benches/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ extern crate specs;
extern crate test;

use criterion::{Bencher, Criterion};
use specs::prelude::*;
use specs::storage::HashMapStorage;
use specs::{prelude::*, storage::HashMapStorage};

#[derive(Clone, Debug)]
struct CompInt(i32);
Expand Down
3 changes: 1 addition & 2 deletions examples/cluster_bomb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use rand::prelude::*;

use rayon::iter::ParallelIterator;

use specs::prelude::*;
use specs::{storage::HashMapStorage, WorldExt};
use specs::{prelude::*, storage::HashMapStorage, WorldExt};

const TAU: f32 = 2. * std::f32::consts::PI;

Expand Down
19 changes: 10 additions & 9 deletions examples/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ extern crate shred;
extern crate shred_derive;
extern crate specs;

use specs::prelude::*;
use specs::storage::HashMapStorage;
use specs::WorldExt;
use shred::ResourceId;
use specs::{prelude::*, storage::HashMapStorage, WorldExt};
// -- Components --
// A component exists for 0..n
// entities.
Expand Down Expand Up @@ -193,9 +192,10 @@ impl<'a> System<'a> for AddIntToFloat {

fn run(&mut self, (comp_int, comp_float): Self::SystemData) {
// This system demonstrates the use of `.maybe()`.
// As the name implies, it doesn't filter any entities; it yields an `Option<CompInt>`.
// So the `join` will yield all entities that have a `CompFloat`, just returning a
// `CompInt` if the entity happens to have one.
// As the name implies, it doesn't filter any entities; it yields an
// `Option<CompInt>`. So the `join` will yield all entities that have a
// `CompFloat`, just returning a `CompInt` if the entity happens to have
// one.
for (f, i) in (&comp_float, comp_int.maybe()).join() {
let sum = f.0 + i.map(|i| i.0 as f32).unwrap_or(0.0);
println!("Result: sum = {}", sum);
Expand Down Expand Up @@ -233,11 +233,12 @@ fn main() {
.with(AddIntToFloat, "add_float_int", &[])
.build();

// setup() will setup all Systems we added, registering all resources and components that
// they will try to read from and write to
// setup() will setup all Systems we added, registering all resources and
// components that they will try to read from and write to
dispatcher.setup(&mut w);

// create_entity() of World provides with an EntityBuilder to add components to an Entity
// create_entity() of World provides with an EntityBuilder to add components to
// an Entity
w.create_entity()
.with(CompInt(4))
.with(CompBool(false))
Expand Down
23 changes: 14 additions & 9 deletions examples/ordered_track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ impl<'a> System<'a> for SysA {
.channel()
.read(self.reader_id.as_mut().expect("ReaderId not found"));

// These events are received in the same order they were operated on in the last frame.
// However, be careful. Just because you received a `Modified/Inserted` event does not mean that the
// entity at that index has a component. To get the current state of the entity, you should replay the
// events in order to see the final result of the component. Partial iteration over the events might lead
// to weird bugs and issues.
// These events are received in the same order they were operated on in the last
// frame. However, be careful. Just because you received a
// `Modified/Inserted` event does not mean that the entity at that index
// has a component. To get the current state of the entity, you should replay
// the events in order to see the final result of the component. Partial
// iteration over the events might lead to weird bugs and issues.
for event in events {
match event {
ComponentEvent::Modified(id) => {
Expand All @@ -58,7 +59,10 @@ impl<'a> System<'a> for SysA {
self.cache.insert(*id, (entity, component.0));
println!("{:?} had {:?} inserted", entity, component.0);
} else {
println!("{:?} had a component inserted, but was removed before the next update.", entity);
println!(
"{:?} had a component inserted, but was removed before the next update.",
entity
);
}
}
ComponentEvent::Removed(id) => {
Expand Down Expand Up @@ -102,9 +106,10 @@ fn main() {
{
let mut tracked = world.write_storage::<TrackedComponent>();

// Note that any removal after a modification won't be seen in the next frame, instead you
// will find no component or if a new component was inserted right after it was inserted then
// then you will find the new inserted component rather than the modified one from earlier.
// Note that any removal after a modification won't be seen in the next frame,
// instead you will find no component or if a new component was inserted
// right after it was inserted then then you will find the new inserted
// component rather than the modified one from earlier.
tracked.get_mut(e3).unwrap().0 = 20;
tracked.remove(e3);
tracked.insert(e3, TrackedComponent(10)).unwrap();
Expand Down
103 changes: 62 additions & 41 deletions examples/saveload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ extern crate specs;

use std::fmt;

use specs::error::NoError;
use specs::prelude::*;
use specs::saveload::{
DeserializeComponents, MarkedBuilder, SerializeComponents, U64Marker, U64MarkerAllocator,
use specs::{
error::NoError,
prelude::*,
saveload::{
DeserializeComponents, MarkedBuilder, SerializeComponents, U64Marker, U64MarkerAllocator,
},
};

// This is an example of how the serialized data of two entities might look on disk.
// This is an example of how the serialized data of two entities might look on
// disk.
//
// When serializing entities, they are written in an array of tuples, each tuple representing one entity.
// The entity's marker and components are written as fields into these tuples, knowing nothing about the original entity's id.
// When serializing entities, they are written in an array of tuples, each tuple
// representing one entity. The entity's marker and components are written as
// fields into these tuples, knowing nothing about the original entity's id.
const ENTITIES: &str = "
[
(
Expand Down Expand Up @@ -59,16 +63,19 @@ impl Component for Mass {
type Storage = VecStorage<Self>;
}

// It is necessary to supply the `(De)SerializeComponents`-trait with an error type that implements the `Display`-trait.
// In this case we want to be able to return different errors, and we are going to use a `.ron`-file to store our data.
// Therefore we use a custom enum, which can display both the `NoError`and `ron::ser::Error` type.
// This enum could be extended to incorporate for example `std::io::Error` and more.
// It is necessary to supply the `(De)SerializeComponents`-trait with an error
// type that implements the `Display`-trait. In this case we want to be able to
// return different errors, and we are going to use a `.ron`-file to store our
// data. Therefore we use a custom enum, which can display both the `NoError`and
// `ron::ser::Error` type. This enum could be extended to incorporate for
// example `std::io::Error` and more.
#[derive(Debug)]
enum Combined {
Ron(ron::ser::Error),
}

// Implementing the required `Display`-trait, by matching the `Combined` enum, allowing different error types to be displayed.
// Implementing the required `Display`-trait, by matching the `Combined` enum,
// allowing different error types to be displayed.
impl fmt::Display for Combined {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Expand All @@ -77,7 +84,8 @@ impl fmt::Display for Combined {
}
}

// This returns the `ron::ser:Error` in form of the `Combined` enum, which can then be matched and displayed accordingly.
// This returns the `ron::ser:Error` in form of the `Combined` enum, which can
// then be matched and displayed accordingly.
impl From<ron::ser::Error> for Combined {
fn from(x: ron::ser::Error) -> Self {
Combined::Ron(x)
Expand All @@ -94,15 +102,16 @@ impl From<NoError> for Combined {
fn main() {
let mut world = World::new();

// Since in this example no system uses these resources, they have to be registered manually.
// This is typically not required.
// Since in this example no system uses these resources, they have to be
// registered manually. This is typically not required.
world.register::<Pos>();
world.register::<Mass>();
world.register::<U64Marker>();

// Adds a predefined marker allocator to the world, as a resource.
// This predifined marker uses a `HashMap<u64, Entity>` to keep track of all entities that should be (de)serializable,
// as well as which ids are already in use.
// This predifined marker uses a `HashMap<u64, Entity>` to keep track of all
// entities that should be (de)serializable, as well as which ids are
// already in use.
world.add_resource(U64MarkerAllocator::new());

world
Expand Down Expand Up @@ -130,8 +139,8 @@ fn main() {
struct Serialize;

impl<'a> System<'a> for Serialize {
// This SystemData contains the entity-resource, as well as all components that shall be serialized,
// plus the marker component storage.
// This SystemData contains the entity-resource, as well as all components that
// shall be serialized, plus the marker component storage.
type SystemData = (
Entities<'a>,
ReadStorage<'a, Pos>,
Expand All @@ -140,20 +149,26 @@ fn main() {
);

fn run(&mut self, (ents, pos, mass, markers): Self::SystemData) {
// First we need a serializer for the format of choice, in this case the `.ron`-format.
// First we need a serializer for the format of choice, in this case the
// `.ron`-format.
let mut ser = ron::ser::Serializer::new(Some(Default::default()), true);

// For serialization we use the [`SerializeComponents`](struct.SerializeComponents.html)-trait's `serialize` function.
// It takes two generic parameters:
// * An unbound type -> `NoError` (However, the serialize function expects it to be bound by the `Display`-trait)
// * A type implementing the `Marker`-trait -> [U64Marker](struct.U64Marker.html) (a convenient, predefined marker)
// For serialization we use the
// [`SerializeComponents`](struct.SerializeComponents.html)-trait's `serialize`
// function. It takes two generic parameters:
// * An unbound type -> `NoError` (However, the serialize function expects it to
// be bound by the `Display`-trait)
// * A type implementing the `Marker`-trait ->
// [U64Marker](struct.U64Marker.html) (a convenient, predefined marker)
//
// The first parameter resembles the `.join()` syntax from other specs-systems,
// every component that should be serialized has to be put inside a tuple.
//
// The second and third parameters are just the entity-storage and marker-storage, which get `.join()`ed internally.
// The second and third parameters are just the entity-storage and
// marker-storage, which get `.join()`ed internally.
//
// Lastly, we provide a mutable reference to the serializer of choice, which has to have the `serde::ser::Serializer`-trait implemented.
// Lastly, we provide a mutable reference to the serializer of choice, which has
// to have the `serde::ser::Serializer`-trait implemented.
SerializeComponents::<NoError, U64Marker>::serialize(
&(&pos, &mass),
&ents,
Expand All @@ -164,14 +179,14 @@ fn main() {
// TODO: Specs should return an error which combines serialization
// and component errors.

// At this point, `ser` could be used to write its contents to a file, which is not done here.
// Instead we print the content of this pseudo-file.
// At this point, `ser` could be used to write its contents to a file, which is
// not done here. Instead we print the content of this pseudo-file.
println!("{}", ser.into_output_string());
}
}

// Running the system results in a print to the standard output channel, in `.ron`-format,
// showing how the serialized dummy entities look like.
// Running the system results in a print to the standard output channel, in
// `.ron`-format, showing how the serialized dummy entities look like.
Serialize.run_now(&world);

// -----------------
Expand All @@ -180,8 +195,9 @@ fn main() {
struct Deserialize;

impl<'a> System<'a> for Deserialize {
// This requires all the component storages our serialized entities have, mutably,
// plus a `MarkerAllocator` resource to write the deserialized ids into, so that we can later serialize again.
// This requires all the component storages our serialized entities have,
// mutably, plus a `MarkerAllocator` resource to write the deserialized
// ids into, so that we can later serialize again.
type SystemData = (
Entities<'a>,
Write<'a, U64MarkerAllocator>,
Expand All @@ -191,18 +207,21 @@ fn main() {
);

fn run(&mut self, (ent, mut alloc, pos, mass, mut markers): Self::SystemData) {
// The `const ENTITIES: &str` at the top of this file was formatted according to the `.ron`-specs,
// therefore we need a `.ron`-deserializer.
// Others can be used, as long as they implement the `serde::de::Deserializer`-trait.
// The `const ENTITIES: &str` at the top of this file was formatted according to
// the `.ron`-specs, therefore we need a `.ron`-deserializer.
// Others can be used, as long as they implement the
// `serde::de::Deserializer`-trait.
use ron::de::Deserializer;

// Typical file operations are omitted in this example, since we do not have a seperate file, but a `const &str`.
// We use a convencience function of the `ron`-crate: `from_str`, to convert our data form the top of the file.
// Typical file operations are omitted in this example, since we do not have a
// seperate file, but a `const &str`. We use a convencience function
// of the `ron`-crate: `from_str`, to convert our data form the top of the file.
if let Ok(mut de) = Deserializer::from_str(ENTITIES) {
// Again, we need to pass in a type implementing the `Display`-trait,
// as well as a type implementing the `Marker`-trait.
// However, from the function parameter `&mut markers`, which refers to the `U64Marker`-storage,
// the necessary type of marker can be inferred, hence the `, _>´.
// However, from the function parameter `&mut markers`, which refers to the
// `U64Marker`-storage, the necessary type of marker can be
// inferred, hence the `, _>´.
DeserializeComponents::<Combined, _>::deserialize(
&mut (pos, mass),
&ent,
Expand All @@ -215,10 +234,12 @@ fn main() {
}
}

// If we run this system now, the `ENTITIES: &str` is going to be deserialized, and two entities are created.
// If we run this system now, the `ENTITIES: &str` is going to be deserialized,
// and two entities are created.
Deserialize.run_now(&world);

// Printing the `Pos`-component storage entries to show the result of deserializing.
// Printing the `Pos`-component storage entries to show the result of
// deserializing.
println!(
"{:#?}",
(&world.read_storage::<Pos>()).join().collect::<Vec<_>>()
Expand Down
Loading

0 comments on commit 7bd3a76

Please sign in to comment.