Ver código fonte

Implemented join for fetched resources

master
Bergmann89 5 anos atrás
pai
commit
f6a2f34a3c
10 arquivos alterados com 441 adições e 16 exclusões
  1. +238
    -0
      async-ecs/src/access/join.rs
  2. +2
    -0
      async-ecs/src/access/mod.rs
  3. +1
    -4
      async-ecs/src/dispatcher/task.rs
  4. +1
    -1
      async-ecs/src/lib.rs
  5. +11
    -7
      async-ecs/src/main.rs
  6. +55
    -0
      async-ecs/src/misc/bit_and.rs
  7. +4
    -0
      async-ecs/src/misc/mod.rs
  8. +47
    -0
      async-ecs/src/misc/split.rs
  9. +6
    -2
      async-ecs/src/storage/masked_storage.rs
  10. +76
    -2
      async-ecs/src/storage/storage_wrapper.rs

+ 238
- 0
async-ecs/src/access/join.rs Ver arquivo

@@ -0,0 +1,238 @@
use std::ops::{Deref, DerefMut};

use hibitset::{BitIter, BitSetAll, BitSetLike};
use log::warn;

use crate::{
entity::{Entities, Entity, Index},
misc::BitAnd,
resource::{Ref, RefMut, Resource},
};

use super::{read::Read, write::Write};

pub trait Join {
type Type;
type Value;
type Mask: BitSetLike;

fn open(self) -> (Self::Mask, Self::Value);

fn get(value: &mut Self::Value, index: Index) -> Self::Type;

fn join(self) -> JoinIter<Self>
where
Self: Sized,
{
JoinIter::new(self)
}

fn maybe(self) -> MaybeJoin<Self>
where
Self: Sized,
{
MaybeJoin(self)
}

#[inline]
fn is_unconstrained() -> bool {
false
}
}

pub struct MaybeJoin<J: Join>(pub J);

impl<T> Join for MaybeJoin<T>
where
T: Join,
{
type Mask = BitSetAll;
type Type = Option<<T as Join>::Type>;
type Value = (<T as Join>::Mask, <T as Join>::Value);

fn open(self) -> (Self::Mask, Self::Value) {
let (mask, value) = self.0.open();

(BitSetAll, (mask, value))
}

fn get((mask, value): &mut Self::Value, index: Index) -> Self::Type {
if mask.contains(index) {
Some(<T as Join>::get(value, index))
} else {
None
}
}

fn is_unconstrained() -> bool {
true
}
}

pub struct JoinIter<J: Join> {
keys: BitIter<J::Mask>,
values: J::Value,
}

impl<J: Join> JoinIter<J> {
pub fn new(j: J) -> Self {
if <J as Join>::is_unconstrained() {
warn!(
"`Join` possibly iterating through all indices, you might've made a join with all `MaybeJoin`s, which is unbounded in length."
);
}

let (keys, values) = j.open();

JoinIter {
keys: keys.iter(),
values,
}
}

pub fn get(&mut self, entity: Entity, entities: &Entities) -> Option<J::Type> {
if self.keys.contains(entity.index()) && entities.is_alive(entity) {
Some(J::get(&mut self.values, entity.index()))
} else {
None
}
}
}

impl<J: Join> std::iter::Iterator for JoinIter<J> {
type Item = J::Type;

fn next(&mut self) -> Option<J::Type> {
self.keys.next().map(|idx| J::get(&mut self.values, idx))
}
}

impl<J: Join> Clone for JoinIter<J>
where
J::Mask: Clone,
J::Value: Clone,
{
fn clone(&self) -> Self {
Self {
keys: self.keys.clone(),
values: self.values.clone(),
}
}
}

macro_rules! define_tuple_join {
($($from:ident),*) => {
impl<$($from,)*> Join for ($($from),*,)
where $($from: Join),*,
($(<$from as Join>::Mask,)*): BitAnd,
{
type Type = ($($from::Type),*,);
type Value = ($($from::Value),*,);
type Mask = <($($from::Mask,)*) as BitAnd>::Value;

#[allow(non_snake_case)]
fn open(self) -> (Self::Mask, Self::Value) {
let ($($from,)*) = self;
let ($($from,)*) = ($($from.open(),)*);

(
($($from.0),*,).and(),
($($from.1),*,)
)
}

#[allow(non_snake_case)]
fn get(v: &mut Self::Value, i: Index) -> Self::Type {
let &mut ($(ref mut $from,)*) = v;

($($from::get($from, i),)*)
}

#[inline]
fn is_unconstrained() -> bool {
let mut unconstrained = true;

$( unconstrained = unconstrained && $from::is_unconstrained(); )*

unconstrained
}
}
}
}

define_tuple_join! { A }
define_tuple_join! { A, B }
define_tuple_join! { A, B, C }
define_tuple_join! { A, B, C, D }
define_tuple_join! { A, B, C, D, E }
define_tuple_join! { A, B, C, D, E, F }
define_tuple_join! { A, B, C, D, E, F, G }
define_tuple_join! { A, B, C, D, E, F, G, H }
define_tuple_join! { A, B, C, D, E, F, G, H, I }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O }
define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P }

macro_rules! define_mutable_join {
($ty:ty) => {
impl<'a, 'b, T> Join for &'a mut $ty
where
&'a mut T: Join,
T: Resource,
{
type Type = <&'a mut T as Join>::Type;
type Value = <&'a mut T as Join>::Value;
type Mask = <&'a mut T as Join>::Mask;

fn open(self) -> (Self::Mask, Self::Value) {
self.deref_mut().open()
}

fn get(v: &mut Self::Value, i: Index) -> Self::Type {
<&'a mut T as Join>::get(v, i)
}

#[inline]
fn is_unconstrained() -> bool {
<&'a mut T as Join>::is_unconstrained()
}
}
};
}

define_mutable_join!(Write<'b, T>);
define_mutable_join!(RefMut<'b, T>);

macro_rules! define_immutable_join {
($ty:ty) => {
impl<'a, 'b, T> Join for &'a $ty
where
&'a T: Join,
T: Resource,
{
type Type = <&'a T as Join>::Type;
type Value = <&'a T as Join>::Value;
type Mask = <&'a T as Join>::Mask;

fn open(self) -> (Self::Mask, Self::Value) {
self.deref().open()
}

fn get(v: &mut Self::Value, i: Index) -> Self::Type {
<&'a T as Join>::get(v, i)
}

#[inline]
fn is_unconstrained() -> bool {
<&'a T as Join>::is_unconstrained()
}
}
};
}

define_immutable_join!(Read<'b, T>);
define_immutable_join!(Ref<'b, T>);

+ 2
- 0
async-ecs/src/access/mod.rs Ver arquivo

@@ -1,10 +1,12 @@
pub mod accessor; pub mod accessor;
pub mod join;
pub mod read; pub mod read;
pub mod read_storage; pub mod read_storage;
pub mod write; pub mod write;
pub mod write_storage; pub mod write_storage;


pub use accessor::{Accessor, AccessorCow, AccessorType, StaticAccessor}; pub use accessor::{Accessor, AccessorCow, AccessorType, StaticAccessor};
pub use join::Join;
pub use read::Read; pub use read::Read;
pub use read_storage::ReadStorage; pub use read_storage::ReadStorage;
pub use write::Write; pub use write::Write;


+ 1
- 4
async-ecs/src/dispatcher/task.rs Ver arquivo

@@ -11,13 +11,12 @@ pub async fn execute(
) { ) {
info!("System started: {}", &name); info!("System started: {}", &name);


run(&name, dispatchable, sender, receivers, world).await;
run(dispatchable, sender, receivers, world).await;


info!("System finished: {}", &name); info!("System finished: {}", &name);
} }


async fn run( async fn run(
name: &str,
mut dispatchable: BoxedDispatchable, mut dispatchable: BoxedDispatchable,
sender: Sender, sender: Sender,
mut receivers: Vec<Receiver>, mut receivers: Vec<Receiver>,
@@ -31,8 +30,6 @@ async fn run(
} }
} }


info!("Run system: {}", &name);

let world = world.borrow(); let world = world.borrow();
let world = world.as_ref().unwrap(); let world = world.as_ref().unwrap();




+ 1
- 1
async-ecs/src/lib.rs Ver arquivo

@@ -11,7 +11,7 @@ pub mod storage;
pub mod system; pub mod system;
pub mod world; pub mod world;


pub use access::{ReadStorage, WriteStorage};
pub use access::{Join, ReadStorage, WriteStorage};
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;
pub use resource::Resources; pub use resource::Resources;
pub use storage::VecStorage; pub use storage::VecStorage;


+ 11
- 7
async-ecs/src/main.rs Ver arquivo

@@ -2,7 +2,7 @@ use std::io::Error as IoError;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};


use async_ecs::{ use async_ecs::{
dispatcher::Error as DispatcherError, Dispatcher, ReadStorage, System, VecStorage, World,
dispatcher::Error as DispatcherError, Dispatcher, Join, ReadStorage, System, VecStorage, World,
WriteStorage, WriteStorage,
}; };
use async_ecs_derive::Component; use async_ecs_derive::Component;
@@ -137,9 +137,11 @@ impl Acceleration {
impl<'a> System<'a> for Move { impl<'a> System<'a> for Move {
type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>); type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>);


fn run(&mut self, (position, velocity): Self::SystemData) {
let _position = position;
let _velocity = velocity;
fn run(&mut self, (mut position, velocity): Self::SystemData) {
for (position, velocity) in (&mut position, &velocity).join() {
position.x += velocity.x;
position.y += velocity.y;
}


/* /*
use specs::{prelude::ParallelIterator, ParJoin}; use specs::{prelude::ParallelIterator, ParJoin};
@@ -157,9 +159,11 @@ impl<'a> System<'a> for Move {
impl<'a> System<'a> for Accelerate { impl<'a> System<'a> for Accelerate {
type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>); type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>);


fn run(&mut self, (velocity, acceleration): Self::SystemData) {
let _velocity = velocity;
let _acceleration = acceleration;
fn run(&mut self, (mut velocity, acceleration): Self::SystemData) {
for (velocity, acceleration) in (&mut velocity, &acceleration).join() {
velocity.x += acceleration.x;
velocity.y += acceleration.y;
}


/* /*
use specs::{prelude::ParallelIterator, ParJoin}; use specs::{prelude::ParallelIterator, ParJoin};


+ 55
- 0
async-ecs/src/misc/bit_and.rs Ver arquivo

@@ -0,0 +1,55 @@
use hibitset::{BitSetAnd, BitSetLike};

use crate::misc::Split;

pub trait BitAnd {
type Value: BitSetLike;

fn and(self) -> Self::Value;
}

impl<A> BitAnd for (A,)
where
A: BitSetLike,
{
type Value = A;

fn and(self) -> Self::Value {
self.0
}
}

macro_rules! bitset_and {
($($from:ident),*) => {
impl<$($from),*> BitAnd for ($($from),*)
where $($from: BitSetLike),*
{
type Value = BitSetAnd<
<<Self as Split>::Left as BitAnd>::Value,
<<Self as Split>::Right as BitAnd>::Value
>;

fn and(self) -> Self::Value {
let (l, r) = self.split();

BitSetAnd(l.and(), r.and())
}
}
}
}

bitset_and! { A, B }
bitset_and! { A, B, C }
bitset_and! { A, B, C, D }
bitset_and! { A, B, C, D, E }
bitset_and! { A, B, C, D, E, F }
bitset_and! { A, B, C, D, E, F, G }
bitset_and! { A, B, C, D, E, F, G, H }
bitset_and! { A, B, C, D, E, F, G, H, I }
bitset_and! { A, B, C, D, E, F, G, H, I, J }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K, L }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K, L, M }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K, L, M, N }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O }
bitset_and! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P }

+ 4
- 0
async-ecs/src/misc/mod.rs Ver arquivo

@@ -1,3 +1,7 @@
pub mod bit_and;
pub mod split;
pub mod try_default; pub mod try_default;


pub use bit_and::BitAnd;
pub use split::Split;
pub use try_default::TryDefault; pub use try_default::TryDefault;

+ 47
- 0
async-ecs/src/misc/split.rs Ver arquivo

@@ -0,0 +1,47 @@
pub trait Split {
type Left;
type Right;

fn split(self) -> (Self::Left, Self::Right);
}

macro_rules! for_each_prefix (
($m:ident, [$(($acc:tt),)*], []) => {
$m!($($acc,)*);
};
($m:ident, [$(($acc:tt),)*], [($arg0:tt), $(($arg:tt),)*]) => {
$m!($($acc,)*);
for_each_prefix!($m, [$(($acc),)* ($arg0),], [$(($arg),)*]);
};
);

macro_rules! split_impl (
($(($a:ident, $b:ident),)*) => (
impl<$($a,)* $($b,)*> Split for ($($a,)* $($b,)*) {
type Left = ($($a,)*);
type Right = ($($b,)*);
#[allow(non_snake_case)]
fn split(self) -> (Self::Left, Self::Right) {
match self {
($($a,)* $($b,)*) => (($($a,)*), ($($b,)*))
}
}
}
impl<$($a,)* $($b,)* TLast> Split for ($($a,)* $($b,)* TLast,) {
type Left = ($($a,)*);
type Right = ($($b,)* TLast,);
#[allow(non_snake_case)]
fn split(self) -> (Self::Left, Self::Right) {
match self {
($($a,)* $($b,)* t_last,) => (($($a,)*), ($($b,)* t_last,))
}
}
}
);
);

for_each_prefix! {
split_impl,
[],
[((T0, T1)), ((T2, T3)), ((T4, T5)), ((T6, T7)), ((T8, T9)), ((T10, T11)), ((T12, T13)), ((T14, T15)),]
}

+ 6
- 2
async-ecs/src/storage/masked_storage.rs Ver arquivo

@@ -5,8 +5,8 @@ use hibitset::BitSet;
use crate::{component::Component, entity::Entity, storage::Storage}; use crate::{component::Component, entity::Entity, storage::Storage};


pub struct MaskedStorage<T: Component> { pub struct MaskedStorage<T: Component> {
mask: BitSet,
inner: T::Storage,
pub(crate) mask: BitSet,
pub(crate) inner: T::Storage,
} }


impl<T: Component> MaskedStorage<T> { impl<T: Component> MaskedStorage<T> {
@@ -17,6 +17,10 @@ impl<T: Component> MaskedStorage<T> {
} }
} }


pub fn open_mut(&mut self) -> (&BitSet, &mut T::Storage) {
(&self.mask, &mut self.inner)
}

pub fn insert(&mut self, entity: Entity, mut component: T) -> Option<T> { pub fn insert(&mut self, entity: Entity, mut component: T) -> Option<T> {
let index = entity.index(); let index = entity.index();




+ 76
- 2
async-ecs/src/storage/storage_wrapper.rs Ver arquivo

@@ -1,20 +1,27 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::DerefMut;
use std::ops::{Deref, DerefMut, Not};

use hibitset::{BitSet, BitSetNot};


use crate::{ use crate::{
access::Join,
component::Component, component::Component,
entity::{Entities, Entity},
entity::{Entities, Entity, Index},
error::Error, error::Error,
resource::Ref, resource::Ref,
storage::MaskedStorage, storage::MaskedStorage,
}; };


use super::Storage;

pub struct StorageWrapper<'a, T, D> { pub struct StorageWrapper<'a, T, D> {
data: D, data: D,
entities: Ref<'a, Entities>, entities: Ref<'a, Entities>,
phantom: PhantomData<T>, phantom: PhantomData<T>,
} }


pub struct AntiStorage<'a>(pub &'a BitSet);

impl<'a, T, D> StorageWrapper<'a, T, D> { impl<'a, T, D> StorageWrapper<'a, T, D> {
pub fn new(data: D, entities: Ref<'a, Entities>) -> Self { pub fn new(data: D, entities: Ref<'a, Entities>) -> Self {
Self { Self {
@@ -37,4 +44,71 @@ where


Ok(self.data.insert(entity, component)) Ok(self.data.insert(entity, component))
} }

pub fn not(&self) -> AntiStorage<'_> {
AntiStorage(&self.data.mask)
}
}

impl<'a, 'e, T, D> Not for &'a StorageWrapper<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
{
type Output = AntiStorage<'a>;

fn not(self) -> Self::Output {
AntiStorage(&self.data.mask)
}
}

impl<'a, 'e, T, D> Join for &'a StorageWrapper<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
{
type Mask = &'a BitSet;
type Type = &'a T;
type Value = &'a T::Storage;

fn open(self) -> (Self::Mask, Self::Value) {
(&self.data.mask, &self.data.inner)
}

fn get(v: &mut Self::Value, i: Index) -> &'a T {
v.get(i)
}
}

impl<'a, 'e, T, D> Join for &'a mut StorageWrapper<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
type Mask = &'a BitSet;
type Type = &'a mut T;
type Value = &'a mut T::Storage;

fn open(self) -> (Self::Mask, Self::Value) {
self.data.open_mut()
}

fn get(v: &mut Self::Value, i: Index) -> &'a mut T {
// HACK
let value: *mut Self::Value = v as *mut Self::Value;

unsafe { (*value).get_mut(i) }
}
}

impl<'a> Join for AntiStorage<'a> {
type Mask = BitSetNot<&'a BitSet>;
type Type = ();
type Value = ();

fn open(self) -> (Self::Mask, ()) {
(BitSetNot(self.0), ())
}

fn get(_: &mut (), _: Index) {}
} }

Carregando…
Cancelar
Salvar