Skip to content

Commit

Permalink
Merge pull request #218 from Anders429/0.9.0
Browse files Browse the repository at this point in the history
0.9.0
  • Loading branch information
Anders429 authored Apr 22, 2023
2 parents b9fdc53 + 5165f84 commit ec18ed4
Show file tree
Hide file tree
Showing 86 changed files with 2,314 additions and 4,896 deletions.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

## Unreleased

## 0.9.0 - 2023-04-22
### Changed
- `resource::ContainsViews` now only requires a single generic parameter for indices.
- `World::view_resources()` now only requires a single generic parameter for indices.
- `registry::ContainsEntity` now only requires a single generic parameter for indices.
- `World::insert()` now only requires a single generic parameter for indices.
- `registry::ContainsEntities` now only requires a single generic parameter for indices.
- `World::extend()` now only requires a single generic parameter for indices.
- `World::insert()` no longer requires `E` to implement `Entity`.
- `World::extend()` no longer requires `E` to implement `Entities`.
- `World::query()` and `World::par_query()` both no longer require `V` and `F` to implement `Filter`.
- `registry::ContainsQuery` now only requires a single generic parameter for indices.
- `registry::ContainsParQuery` now only requires a single generic parameter for indices.
- `registry::ContainsViews` now only requires a single generic parameter for indices.
- `World::query()` now only requires a single parameter for query indices.
- `Entry::query()` now only requires a single parameter for query indices.
- `World::run_system()` now only requires a single parameter for query indices.
- `World::run_par_system()` now only requires a single parameter for query indices.
- `World::run_schedule()` now only requires a single parameter for query indices.
- `query::view::Disjoint` now only requires a single parameter for indices.
- `System::run()` now takes the results iterator as a generic parameter `I` to simplify the interface.
- `ParSystem::run()` now takes the results parallel iterator as a generic parameter `I` to simplify the interface.
- `System` and `ParSystem` both no longer require `Filter` and `Views` to implement `Filter`.
- `result::Iter` no longer requires `V` and `F` to implement `Filter`.
- `Entry::query()` no longer requires `V` and `F` to implement `Filter`.
- `system::schedule::Schedule` now only requires a single parameter for indices.
- `World::run_system()` now only requires a single parameter for schedule indices.
### Fixed
- `Schedule`s can now no longer access non-`Sync` components and resources.
- Multiple calls to `Entry::add()` or `Entry::remove()` that change the shape of the entity now no longer accesses the wrong internal entity row, preventing potential undefined behavior.

## 0.8.2 - 2023-04-02
### Fixed
- `Entry::query()` now requires a less-strict lifetime.
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "brood"
version = "0.8.2"
version = "0.9.0"
authors = ["Anders Evensen"]
edition = "2021"
rust-version = "1.65.0"
Expand All @@ -27,7 +27,7 @@ serde = {version = "1.0.148", default-features = false, features = ["alloc"], op
[dev-dependencies]
claims = "0.7.1"
rustversion = "1.0.9"
serde_assert = "0.2.0"
serde_assert = "0.4.0"
serde_derive = "1.0.148"
trybuild = "1.0.72"

Expand Down
35 changes: 20 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Note that entities stored in `world` above can be made up of any subset of the `
To operate on the entities stored in a `World`, a `System` must be used. `System`s are defined to operate on any entities containing a specified set of components, reading and modifying those components. An example system could be defined and run as follows:

``` rust
use brood::{query::{filter, result, Views}, registry::ContainsQuery, system::System};
use brood::{query::{filter, result, Views}, registry, system::System};

struct UpdatePosition;

Expand All @@ -85,11 +85,12 @@ impl System for UpdatePosition {
type ResourceViews: Views!();
type EntryViews: Views!();

fn run<'a, R, S, FI, VI, P, I, Q, EP, EI, EQ>(
fn run<'a, R, S, I, E>(
&mut self,
query_results: Result<R, S, result::Iter<'a, R, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>, Self::ResourceViews<'a>, Self::EntryViews<'a>, (EP, EI, EQ)>,
query_results: Result<R, S, I, Self::ResourceViews<'a>, Self::EntryViews<'a>, E>,
) where
R: ContainsQuery<Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>,
R: registry::Registry,
I: Iterator<Item = Self::Views<'a>>,
{
for result!(position, velocity) in query_results.iter {
position.x += velocity.x;
Expand Down Expand Up @@ -160,7 +161,8 @@ Note that there are two modes for serialization, depending on whether the serial
To parallelize system operations on entities (commonly referred to as inner-parallelism), a `ParSystem` can be used instead of a standard `System`. This will allow the `ParSystem`'s operations to be spread across multiple CPUs. For example, a `ParSystem` can be defined as follows:

``` rust
use brood::{entity, query::{filter, result, Views}, Registry, registry::ContainsParQuery, World, system::ParSystem};
use brood::{entity, query::{filter, result, Views}, Registry, registry, World, system::ParSystem};
use rayon::iter::ParallelIterator;

struct Position {
x: f32,
Expand Down Expand Up @@ -195,11 +197,12 @@ impl ParSystem for UpdatePosition {
type ResourceViews: Views!();
type EntryViews: Views!();

fn run<'a, R, S, FI, VI, P, I, Q, EP, EI, EQ>(
fn run<'a, R, S, I, E>(
&mut self,
query_results: Result<R, S, result::ParIter<'a, R, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>, Self::ResourceViews<'a>, Self::EntryViews<'a>, (EP, EI, EQ)>,
query_results: Result<R, S, I, Self::ResourceViews<'a>, Self::EntryViews<'a>, E>,
) where
R: ContainsParQuery<'a, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>,
R: registry::Registry,
I: ParallelIterator<Item = Self::Views<'a>>,
{
query_results.iter.for_each(|result!(position, velocity)| {
position.x += velocity.x;
Expand All @@ -219,7 +222,7 @@ Multiple `System`s and `ParSystem`s can be run in parallel as well by defining a
Define and run a `Schedule` that contains multiple `System`s as follows:

``` rust
use brood::{entity, query::{filter, result, Views}, Registry, registry::ContainsQuery, World, system::{schedule, schedule::task, System}};
use brood::{entity, query::{filter, result, Views}, Registry, registry, World, system::{schedule, schedule::task, System}};

struct Position {
x: f32,
Expand Down Expand Up @@ -256,11 +259,12 @@ impl System for UpdatePosition {
type ResourceViews: Views!();
type EntryViews: Views!();

fn run<'a, R, S, FI, VI, P, I, Q, EP, EI, EQ>(
fn run<'a, R, S, I, E>(
&mut self,
query_results: Result<R, S, result::Iter<'a, R, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>, Self::ResourceViews<'a>, Self::EntryViews<'a>, (EP, EI, EQ)>,
query_results: Result<R, S, I, Self::ResourceViews<'a>, Self::EntryViews<'a>, E>,
) where
R: ContainsQuery<'a, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>,
R: registry::Registry,
I: Iterator<Item = Self::Views<'a>>,
{
for result!(position, velocity) in query_results.iter {
position.x += velocity.x;
Expand All @@ -277,11 +281,12 @@ impl System for UpdateIsMoving {
type ResourceViews: Views!();
type EntryViews: Views!();

fn run<'a, R, S, FI, VI, P, I, Q, EP, EI, EQ>(
fn run<'a, R, S, I, E>(
&mut self,
query_results: Result<R, S, result::ParIter<'a, R, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>, Self::ResourceViews<'a>, Self::EntryViews<'a>, (EP, EI, EQ)>,
query_results: Result<R, S, I, Self::ResourceViews<'a>, Self::EntryViews<'a>, E>,
) where
R: ContainsQuery<'a, Self::Filter, FI, Self::Views<'a>, VI, P, I, Q>,
R: registry::Registry,
I: Iterator<Item = Self::Views<'a>>,
{
for result!(velocity, is_moving) in query_results.iter {
is_moving.0 = velocity.x != 0.0 || velocity.y != 0.0;
Expand Down
20 changes: 1 addition & 19 deletions src/archetype/impl_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,6 @@ mod tests {
let mut deserializer = Deserializer::builder()
.tokens(tokens)
.is_human_readable(false)
.self_describing(false)
.build();
assert_ok_eq!(
Archetype::<Registry>::deserialize(&mut deserializer),
Expand Down Expand Up @@ -986,7 +985,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1062,7 +1060,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1089,7 +1086,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1163,7 +1159,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1189,7 +1184,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1211,7 +1205,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1235,7 +1228,6 @@ mod tests {
Token::TupleEnd,
]))
.is_human_readable(false)
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1320,10 +1312,7 @@ mod tests {
Token::TupleEnd,
])
);
let mut deserializer = Deserializer::builder()
.tokens(tokens)
.self_describing(false)
.build();
let mut deserializer = Deserializer::builder().tokens(tokens).build();
assert_ok_eq!(
Archetype::<Registry>::deserialize(&mut deserializer),
archetype
Expand All @@ -1350,7 +1339,6 @@ mod tests {
Token::TupleEnd,
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1398,7 +1386,6 @@ mod tests {
Token::TupleEnd,
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1432,7 +1419,6 @@ mod tests {
Token::TupleEnd,
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand Down Expand Up @@ -1482,7 +1468,6 @@ mod tests {
Token::TupleEnd,
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1507,7 +1492,6 @@ mod tests {
Token::Tuple { len: 0 },
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1528,7 +1512,6 @@ mod tests {
Token::TupleEnd,
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand All @@ -1551,7 +1534,6 @@ mod tests {
Token::U64(3),
Token::TupleEnd,
]))
.self_describing(false)
.build();

assert_err_eq!(
Expand Down
58 changes: 26 additions & 32 deletions src/archetype/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ use crate::{
},
Entity,
},
query::view::{
Views,
ViewsSealed,
query::{
view,
view::ViewsSealed,
},
registry,
registry::{
Expand Down Expand Up @@ -238,18 +238,18 @@ where

/// # Safety
/// Each component viewed by `V` must also be identified by this archetype's `Identifier`.
pub(crate) unsafe fn view<'a, V, P, I, Q>(
pub(crate) unsafe fn view<'a, Views, Indices>(
&mut self,
) -> <<<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable as ContainsViewsOuter<
) -> <<<R as ContainsViewsSealed<'a, Views, Indices>>::Viewable as ContainsViewsOuter<
'a,
V,
P,
I,
Q,
Views,
<R as ContainsViewsSealed<'a, Views, Indices>>::Containments,
<R as ContainsViewsSealed<'a, Views, Indices>>::Indices,
<R as ContainsViewsSealed<'a, Views, Indices>>::ReshapeIndices,
>>::Canonical as ViewsSealed<'a>>::Results
where
V: Views<'a>,
R: ContainsViews<'a, V, P, I, Q>,
Views: view::Views<'a>,
R: ContainsViews<'a, Views, Indices>,
{
// SAFETY: `self.components` contains the raw parts for `Vec<C>`s of size `self.length`
// for each component `C` identified in `self.identifier` in the canonical order defined by
Expand All @@ -258,7 +258,7 @@ where
// `self.entity_identifiers` also contains the raw parts for a valid
// `Vec<entity::Identifier>` of size `self.length`.
unsafe {
<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable::view(
<R as ContainsViewsSealed<'a, Views, Indices>>::Viewable::view(
&self.components,
self.entity_identifiers,
self.length,
Expand Down Expand Up @@ -309,19 +309,19 @@ where
/// Each component viewed by `V` must also be identified by this archetype's `Identifier`.
///
/// The index `index` must be a valid index into this archetype.
pub(crate) unsafe fn view_row_unchecked<'a, V, P, I, Q>(
pub(crate) unsafe fn view_row_unchecked<'a, Views, Indices>(
&mut self,
index: usize,
) -> <<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable as ContainsViewsOuter<
) -> <<R as ContainsViewsSealed<'a, Views, Indices>>::Viewable as ContainsViewsOuter<
'a,
V,
P,
I,
Q,
Views,
<R as ContainsViewsSealed<'a, Views, Indices>>::Containments,
<R as ContainsViewsSealed<'a, Views, Indices>>::Indices,
<R as ContainsViewsSealed<'a, Views, Indices>>::ReshapeIndices,
>>::Canonical
where
V: Views<'a>,
R: ContainsViews<'a, V, P, I, Q>,
Views: view::Views<'a>,
R: ContainsViews<'a, Views, Indices>,
{
// SAFETY: `self.components` contains the raw parts for `Vec<C>`s of size `self.length`
// for each component `C` identified in `self.identifier` in the canonical order defined by
Expand All @@ -334,7 +334,7 @@ where
// this archetype, and therefore within the bounds of each column and the entity
// identifiers of this archetype.
unsafe {
<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable::view_one(
<R as ContainsViewsSealed<'a, Views, Indices>>::Viewable::view_one(
index,
&self.components,
self.entity_identifiers,
Expand All @@ -346,19 +346,13 @@ where

/// # Safety
/// The index `index` must be a valid index into this archetype.
pub(crate) unsafe fn view_row_maybe_uninit_unchecked<'a, V, P, I, Q>(
pub(crate) unsafe fn view_row_maybe_uninit_unchecked<'a, Views, Indices>(
&mut self,
index: usize,
) -> <<<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable as ContainsViewsOuter<
'a,
V,
P,
I,
Q,
>>::Canonical as ViewsSealed<'a>>::MaybeUninit
) -> Views::MaybeUninit
where
V: Views<'a>,
R: ContainsViews<'a, V, P, I, Q>,
Views: view::Views<'a>,
R: ContainsViews<'a, Views, Indices>,
{
// SAFETY: `self.components` contains the raw parts for `Vec<C>`s of size `self.length`
// for each component `C` identified in `self.identifier` in the canonical order defined by
Expand All @@ -371,7 +365,7 @@ where
// this archetype, and therefore within the bounds of each column and the entity
// identifiers of this archetype.
unsafe {
<R as ContainsViewsSealed<'a, V, P, I, Q>>::Viewable::view_one_maybe_uninit(
<R as ContainsViewsSealed<'a, Views, Indices>>::Viewable::view_one_maybe_uninit(
index,
&self.components,
self.entity_identifiers,
Expand Down
Loading

0 comments on commit ec18ed4

Please sign in to comment.