Resource and ResourceMut pointers

This commit is contained in:
Carter Anderson 2020-04-29 16:32:19 -07:00
parent 45a710fe6a
commit 2d3903299b
6 changed files with 410 additions and 153 deletions

View file

@ -1,10 +1,8 @@
use legion::{
filter::EntityFilter,
prelude::{
into_resource_for_each_system, into_resource_system, IntoQuery, ResourceSet, Resources,
Resources,
Runnable, Schedulable, World,
},
query::{DefaultFilter, View},
};
pub enum System {
Schedulable(Box<dyn Schedulable>),
@ -32,24 +30,3 @@ where
System::ThreadLocalFn(Box::new(system))
}
}
impl System {
pub fn resource_for_each<'a, Q, F, R, X>(name: &'static str, system: F) -> Self
where
Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
F: FnMut(&mut X, Q) + Send + Sync + 'static,
R: EntityFilter + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static,
{
into_resource_for_each_system(name, system).into()
}
pub fn resource<'a, F, X>(name: &'static str, system: F) -> Self
where
F: FnMut(&mut X) + Send + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static,
{
into_resource_system(name, system).into()
}
}

View file

@ -9,6 +9,7 @@ mod system_fn_types;
pub use bit_set;
pub use system::*;
pub use system_fn::*;
pub use system_fn_types::{ResourceMut, Resource};
pub mod prelude {
pub use crate::{
@ -17,11 +18,12 @@ pub mod prelude {
into_resource_system,
// aliased preparedread and preparedwrite used by system_fn
resource::{
PreparedRead as Resource, PreparedWrite as ResourceMut, ResourceSet, Resources,
ResourceSet, Resources,
},
schedule::{Executor, Runnable, Schedulable, Schedule},
IntoSystem,
System,
SystemBuilder,
Resource, ResourceMut,
};
}

View file

@ -630,7 +630,7 @@ pub struct SubWorld {
}
impl SubWorld {
unsafe fn new(
pub(super) unsafe fn new(
world: &World,
access: &Access<ComponentTypeId>,
archetypes: &ArchetypeAccess,

View file

@ -1,7 +1,7 @@
use crate::{
resource::{PreparedRead, Resource, ResourceSet, ResourceTypeId},
resource::{ResourceSet, ResourceTypeId},
schedule::{ArchetypeAccess, Schedulable},
Access, System, SystemAccess, SystemFnWrapper, SystemQuery,
Access, SystemAccess, SystemQuery, system_fn_types::{FuncSystem, FuncSystemFnWrapper},
};
use bit_set::BitSet;
use fxhash::FxHashMap;
@ -20,9 +20,9 @@ pub fn into_resource_for_each_system<'a, Q, F, R, X>(
where
Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
F: FnMut(&mut X, Q) + Send + Sync + 'static,
F: FnMut(X, Q) + Send + Sync + 'static,
R: EntityFilter + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static,
X: ResourceSet<PreparedResources = X> + 'static + Clone,
{
let mut resource_access: Access<ResourceTypeId> = Access::default();
resource_access.reads.extend(X::read_types().iter());
@ -32,19 +32,19 @@ where
component_access.reads.extend(Q::read_types().iter());
component_access.writes.extend(Q::write_types().iter());
let run_fn = SystemFnWrapper(
let run_fn = FuncSystemFnWrapper(
move |_,
world,
resources: &mut X,
resources: X,
query: &mut SystemQuery<Q, <Q as DefaultFilter>::Filter>| {
for components in query.iter_mut(world) {
system(resources, components);
system(resources.clone(), components);
}
},
PhantomData,
);
Box::new(System {
Box::new(FuncSystem {
name: name.into(),
queries: AtomicRefCell::new(Q::query()),
access: SystemAccess {
@ -61,7 +61,7 @@ where
pub fn into_resource_system<'a, F, X>(name: &'static str, mut system: F) -> Box<dyn Schedulable>
where
F: FnMut(&mut X) + Send + Sync + 'static,
F: FnMut(X) + Send + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static,
{
let mut resource_access: Access<ResourceTypeId> = Access::default();
@ -69,14 +69,14 @@ where
resource_access.writes.extend(X::write_types().iter());
let component_access: Access<ComponentTypeId> = Access::default();
let run_fn = SystemFnWrapper(
move |_, _, resources: &mut X, _| {
let run_fn = FuncSystemFnWrapper(
move |_, _, resources: X, _| {
system(resources);
},
PhantomData,
);
Box::new(System {
Box::new(FuncSystem {
name: name.into(),
queries: AtomicRefCell::new(()),
access: SystemAccess {
@ -98,72 +98,17 @@ where
fn into_system(self, name: &'static str) -> Box<dyn Schedulable>;
}
// impl<F, X: Resource + Send + Sync + 'static, A: Component, B: Component> IntoSystem<(X,), (A, B)> for F
// where
// F: for<'a> FnMut(&X, Ref<'a, A>, Ref<'a, B>) + Send + Sync + 'static,
// {
// fn into_system(mut self, name: &'static str) -> Box<dyn Schedulable> {
// let mut resource_access: Access<ResourceTypeId> = Access::default();
// resource_access
// .reads
// .extend(<PreparedRead<X>>::read_types().iter());
// resource_access
// .writes
// .extend(<PreparedRead<X>>::write_types().iter());
// let mut component_access: Access<ComponentTypeId> = Access::default();
// component_access
// .reads
// .extend(<(Ref<A>, Ref<B>) as View>::read_types().iter());
// component_access
// .writes
// .extend(<(Ref<A>, Ref<B>) as View>::write_types().iter());
// let run_fn = SystemFnWrapper(
// move |_,
// world,
// x: &mut PreparedRead<X>,
// query: &mut SystemQuery<
// (Ref<A>, Ref<B>),
// EntityFilterTuple<
// And<(ComponentFilter<A>, ComponentFilter<B>)>,
// And<(Passthrough, Passthrough)>,
// And<(Passthrough, Passthrough)>,
// >,
// >| {
// for (a, b) in query.iter_mut(world) {
// self(&*x, a, b);
// }
// },
// PhantomData,
// );
// Box::new(System {
// name: name.into(),
// queries: AtomicRefCell::new(<(Ref<A>, Ref<B>)>::query()),
// access: SystemAccess {
// resources: resource_access,
// components: component_access,
// tags: Access::default(),
// },
// archetypes: ArchetypeAccess::Some(BitSet::default()),
// _resources: PhantomData::<PreparedRead<X>>,
// command_buffer: FxHashMap::default(),
// run_fn: AtomicRefCell::new(run_fn),
// })
// }
// }
impl<
'a,
F,
X: Resource + Send + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static + Clone,
A: for<'b> View<'b> + DefaultFilter<Filter = AF> + ViewElement,
AF: EntityFilter + Sync + 'static,
B: for<'b> View<'b> + DefaultFilter<Filter = BF> + ViewElement,
BF: EntityFilter + Sync + 'static,
> IntoSystem<'a, (X,), (A, B)> for F
where
F: FnMut(&X, A, B) + Send + Sync + 'static,
F: FnMut(X, A, B) + Send + Sync + 'static,
<A as View<'a>>::Iter: Iterator<Item = A>,
<B as View<'a>>::Iter: Iterator<Item = B>,
{
@ -171,10 +116,10 @@ where
let mut resource_access: Access<ResourceTypeId> = Access::default();
resource_access
.reads
.extend(<PreparedRead<X>>::read_types().iter());
.extend(<X>::read_types().iter());
resource_access
.writes
.extend(<PreparedRead<X>>::write_types().iter());
.extend(<X>::write_types().iter());
let mut component_access: Access<ComponentTypeId> = Access::default();
component_access
.reads
@ -183,10 +128,10 @@ where
.writes
.extend(<(A, B) as View>::write_types().iter());
let run_fn = SystemFnWrapper(
let run_fn = FuncSystemFnWrapper(
move |_,
world,
x: &mut PreparedRead<X>,
x: X::PreparedResources,
query: &mut SystemQuery<
(A, B),
EntityFilterTuple<
@ -205,13 +150,13 @@ where
>,
>| {
for (a, b) in query.iter_mut(world) {
self(&*x, a, b);
self(x.clone(), a, b);
}
},
PhantomData,
);
Box::new(System {
Box::new(FuncSystem {
name: name.into(),
queries: AtomicRefCell::new(<(A, B)>::query()),
access: SystemAccess {
@ -220,7 +165,7 @@ where
tags: Access::default(),
},
archetypes: ArchetypeAccess::Some(BitSet::default()),
_resources: PhantomData::<PreparedRead<X>>,
_resources: PhantomData::<X::PreparedResources>,
command_buffer: FxHashMap::default(),
run_fn: AtomicRefCell::new(run_fn),
})
@ -242,10 +187,10 @@ macro_rules! impl_system {
let resource_access: Access<ResourceTypeId> = Access::default();
let component_access: Access<ComponentTypeId> = component_access!(($($view),+));
let run_fn = SystemFnWrapper(
let run_fn = FuncSystemFnWrapper(
move |_,
world,
_: &mut (),
_: (),
query: &mut system_query!($($view, $filter),+)
,
| {
@ -256,7 +201,7 @@ macro_rules! impl_system {
PhantomData,
);
Box::new(System {
Box::new(FuncSystem {
name: name.into(),
queries: AtomicRefCell::new(query!($($view),+)),
access: SystemAccess {
@ -357,7 +302,7 @@ mod tests {
use crate::{
into_resource_for_each_system,
resource::{PreparedRead, PreparedWrite, Resources},
IntoSystem,
IntoSystem, system_fn_types::{ResourceMut, Resource},
};
use legion_core::{
borrow::{Ref, RefMut},
@ -375,30 +320,53 @@ mod tests {
#[test]
fn test_into_system() {
// fn read_system(a: &A, x: Ref<X>, y: Ref<Y>) {
// println!("{} {} {}", a.0, x.0, y.0);
// }
// fn read_system(x: Ref<X>) {
// println!("{}", x.0);
// }
fn read_system(x: Ref<X>, y: Ref<Y>, mut z: RefMut<A>) {
z.0 += 1;
println!("{} {} {}", x.0, y.0, z.0);
}
let mut world = World::new();
let mut resources = Resources::default();
resources.insert(A(0));
world.insert((), vec![(X(1), Y(1)), (X(2), Y(2))]);
let mut system = read_system.into_system("hi");
// fn single_read_system(x: Ref<X>) {
// println!("{}", x.0);
// }
// let mut system = single_read_system.into_system("hi");
// system.run(&mut world, &mut resources);
// fn read_write_system(x: Ref<X>, y: Ref<Y>, mut z: RefMut<A>) {
// z.0 += 1;
// println!("{} {} {}", x.0, y.0, z.0);
// }
// (
// {
// |x: Resource<A>, y: Ref<Y>, mut z: RefMut<A>| {
// z.0 += 1;
// println!("{} {} {}", x.0, y.0, z.0);
// }}).into_system("bleh");
// let mut system = read_write_system.into_system("read_write");
// system.run(&mut world, &mut resources);
// fn resource_system(a: Resource<A>, x: Ref<X>, y: Ref<Y>) {
// println!("{} {} {}", a.0, x.0, y.0);
// }
// let mut system = resource_system.into_system("hi");
// system.run(&mut world, &mut resources);
fn resource_system_mut(mut a: ResourceMut<A>, x: Ref<X>, y: Ref<Y>) {
let hi = &mut a;
a.0 += 1;
println!("{} {} {}", a.0, x.0, y.0);
}
let mut system = resource_system_mut.into_system("hi");
system.run(&mut world, &mut resources);
}
#[test]
fn test_system_fn() {
fn read_write_system(_: &mut (), (_x, mut y): (Ref<X>, RefMut<Y>)) { y.0 += 1; }
fn read_write_system(_: (), (_x, mut y): (Ref<X>, RefMut<Y>)) { y.0 += 1; }
let mut world = World::new();
let mut resources = Resources::default();
@ -410,34 +378,34 @@ mod tests {
#[test]
fn test_resource_system_fn() {
fn my_system(
(a, b): &mut (PreparedWrite<A>, PreparedRead<B>),
(x, mut y): (Ref<X>, RefMut<Y>),
) {
assert_eq!(**b, B(1));
// assert_eq!(**b, B(0));
if a.0 == 0 {
assert_eq!(*x, X(2));
assert_eq!(*y, Y(3));
} else if a.0 == 1 {
assert_eq!(*x, X(4));
assert_eq!(*y, Y(5));
y.0 += 1;
assert_eq!(*y, Y(6));
} else {
panic!("unexpected value");
}
// fn my_system(
// (a,): (Resource<A>,),
// (x, mut y): (Ref<X>, RefMut<Y>),
// ) {
// assert_eq!(*a, A(1));
// // assert_eq!(**b, B(0));
// if a.0 == 0 {
// assert_eq!(*x, X(2));
// assert_eq!(*y, Y(3));
// } else if a.0 == 1 {
// assert_eq!(*x, X(4));
// assert_eq!(*y, Y(5));
// y.0 += 1;
// assert_eq!(*y, Y(6));
// } else {
// panic!("unexpected value");
// }
a.0 += 1;
}
// // a.0 += 1;
// }
let mut world = World::new();
let mut resources = Resources::default();
// let mut world = World::new();
// let mut resources = Resources::default();
resources.insert(A(0));
resources.insert(B(1));
world.insert((), vec![(X(2), Y(3)), (X(4), Y(5))]);
let mut my_system = into_resource_for_each_system("read_resources", my_system);
my_system.run(&mut world, &mut resources);
// resources.insert(A(0));
// resources.insert(B(1));
// world.insert((), vec![(X(2), Y(3)), (X(4), Y(5))]);
// let mut my_system = into_resource_for_each_system("read_resources", my_system);
// my_system.run(&mut world, &mut resources);
}
}

View file

@ -1,9 +1,186 @@
use crate::resource::{
PreparedRead, PreparedWrite, Resource, ResourceSet, ResourceTypeId, Resources,
};
use std::ops::{Deref, DerefMut};
use crate::{schedule::{ArchetypeAccess, Runnable}, resource::{
PreparedRead, PreparedWrite, ResourceSet, ResourceTypeId, Resources, self
}, QuerySet, SystemId, SubWorld, SystemAccess};
use std::{marker::PhantomData, ops::{Deref, DerefMut}, hash::{Hasher, Hash}};
use legion_core::{world::{World, WorldId}, storage::ComponentTypeId, borrow::{AtomicRefCell, RefMut}, command::CommandBuffer};
use tracing::{debug, span, info, Level};
use fxhash::FxHashMap;
#[derive(Debug)]
pub struct Resource<'a, T: 'a> {
#[allow(dead_code)]
// held for drop impl
_marker: PhantomData<&'a ()>,
value: *const T,
}
impl<T: Resource> ResourceSet for PreparedRead<T> {
unsafe impl<'a, T: resource::Resource> Send for Resource<'a, T> {}
unsafe impl<'a, T: resource::Resource> Sync for Resource<'a, T> {}
impl<'a, T: 'a> Clone for Resource<'a, T> {
#[inline(always)]
fn clone(&self) -> Self { Resource::new(self.value) }
}
impl<'a, T: 'a> Resource<'a, T> {
#[inline(always)]
fn new(resource: *const T) -> Self { Self { value: resource, _marker: PhantomData::default()} }
#[inline(always)]
pub fn map<K: 'a, F: FnMut(&T) -> &K>(&self, mut f: F) -> Resource<'a, K> {
Resource::new(f(&self))
}
}
impl<'a, T: 'a> Deref for Resource<'a, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target { unsafe { &*self.value } }
}
impl<'a, T: 'a> AsRef<T> for Resource<'a, T> {
#[inline(always)]
fn as_ref(&self) -> &T { unsafe { &*self.value } }
}
impl<'a, T: 'a> std::borrow::Borrow<T> for Resource<'a, T> {
#[inline(always)]
fn borrow(&self) -> &T { unsafe { &*self.value } }
}
impl<'a, T> PartialEq for Resource<'a, T>
where
T: 'a + PartialEq,
{
fn eq(&self, other: &Self) -> bool { self.value == other.value }
}
impl<'a, T> Eq for Resource<'a, T> where T: 'a + Eq {}
impl<'a, T> PartialOrd for Resource<'a, T>
where
T: 'a + PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl<'a, T> Ord for Resource<'a, T>
where
T: 'a + Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.value.cmp(&other.value) }
}
impl<'a, T> Hash for Resource<'a, T>
where
T: 'a + Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) { self.value.hash(state); }
}
impl<'a, T: resource::Resource> ResourceSet for Resource<'a, T> {
type PreparedResources = Resource<'a, T>;
unsafe fn fetch_unchecked(resources: &Resources) -> Self::PreparedResources {
let resource = resources
.get::<T>()
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
Resource::new(resource.deref() as *const T)
}
fn read_types() -> Vec<ResourceTypeId> { vec![ResourceTypeId::of::<T>()] }
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
#[derive(Debug)]
pub struct ResourceMut<'a, T: 'a> {
// held for drop impl
_marker: PhantomData<&'a mut ()>,
value: *mut T,
}
unsafe impl<'a, T: resource::Resource> Send for ResourceMut<'a, T> {}
unsafe impl<'a, T: resource::Resource> Sync for ResourceMut<'a, T> {}
impl<'a, T: 'a> Clone for ResourceMut<'a, T> {
#[inline(always)]
fn clone(&self) -> Self { ResourceMut::new(self.value) }
}
impl<'a, T: 'a> ResourceMut<'a, T> {
#[inline(always)]
fn new(resource: *mut T) -> Self { Self { value: resource, _marker: PhantomData::default()} }
#[inline(always)]
pub fn map_into<K: 'a, F: FnMut(&mut T) -> K>(mut self, mut f: F) -> ResourceMut<'a, K> {
ResourceMut::new(&mut f(&mut self))
}
}
impl<'a, T: 'a> Deref for ResourceMut<'a, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target { unsafe { &*self.value } }
}
impl<'a, T: 'a> DerefMut for ResourceMut<'a, T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *self.value } }
}
impl<'a, T: 'a> AsRef<T> for ResourceMut<'a, T> {
#[inline(always)]
fn as_ref(&self) -> &T { unsafe { &*self.value } }
}
impl<'a, T: 'a> std::borrow::Borrow<T> for ResourceMut<'a, T> {
#[inline(always)]
fn borrow(&self) -> &T { unsafe { &*self.value } }
}
impl<'a, T> PartialEq for ResourceMut<'a, T>
where
T: 'a + PartialEq,
{
fn eq(&self, other: &Self) -> bool { self.value == other.value }
}
impl<'a, T> Eq for ResourceMut<'a, T> where T: 'a + Eq {}
impl<'a, T> PartialOrd for ResourceMut<'a, T>
where
T: 'a + PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl<'a, T> Ord for ResourceMut<'a, T>
where
T: 'a + Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.value.cmp(&other.value) }
}
impl<'a, T> Hash for ResourceMut<'a, T>
where
T: 'a + Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) { self.value.hash(state); }
}
impl<'a, T: resource::Resource> ResourceSet for ResourceMut<'a, T> {
type PreparedResources = ResourceMut<'a, T>;
unsafe fn fetch_unchecked(resources: &Resources) -> Self::PreparedResources {
let mut resource = resources
.get_mut::<T>()
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
ResourceMut::new(resource.deref_mut() as *mut T)
}
fn read_types() -> Vec<ResourceTypeId> { vec![ResourceTypeId::of::<T>()] }
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
impl<T: resource::Resource> ResourceSet for PreparedRead<T> {
type PreparedResources = PreparedRead<T>;
unsafe fn fetch_unchecked(resources: &Resources) -> Self::PreparedResources {
@ -16,7 +193,7 @@ impl<T: Resource> ResourceSet for PreparedRead<T> {
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
impl<T: Resource> ResourceSet for PreparedWrite<T> {
impl<T: resource::Resource> ResourceSet for PreparedWrite<T> {
type PreparedResources = PreparedWrite<T>;
unsafe fn fetch_unchecked(resources: &Resources) -> Self::PreparedResources {
@ -28,3 +205,135 @@ impl<T: Resource> ResourceSet for PreparedWrite<T> {
fn read_types() -> Vec<ResourceTypeId> { Vec::new() }
fn write_types() -> Vec<ResourceTypeId> { vec![ResourceTypeId::of::<T>()] }
}
/// The concrete type which contains the system closure provided by the user. This struct should
/// not be instantiated directly, and instead should be created using `SystemBuilder`.
///
/// Implements `Schedulable` which is consumable by the `StageExecutor`, executing the closure.
///
/// Also handles caching of archetype information in a `BitSet`, as well as maintaining the provided
/// information about what queries this system will run and, as a result, its data access.
///
/// Queries are stored generically within this struct, and the `SystemQuery` types are generated
/// on each `run` call, wrapping the world and providing the set to the user in their closure.
pub struct FuncSystem<R, Q, F>
where
R: ResourceSet,
Q: QuerySet,
F: FuncSystemFn<
Resources = <R as ResourceSet>::PreparedResources,
Queries = <Q as QuerySet>::Queries,
>,
{
pub name: SystemId,
pub _resources: PhantomData<R>,
pub queries: AtomicRefCell<Q>,
pub run_fn: AtomicRefCell<F>,
pub archetypes: ArchetypeAccess,
// These are stored statically instead of always iterated and created from the
// query types, which would make allocations every single request
pub access: SystemAccess,
// We pre-allocate a command buffer for ourself. Writes are self-draining so we never have to rellocate.
pub command_buffer: FxHashMap<WorldId, AtomicRefCell<CommandBuffer>>,
}
impl<R, Q, F> Runnable for FuncSystem<R, Q, F>
where
R: ResourceSet,
Q: QuerySet,
F: FuncSystemFn<
Resources = <R as ResourceSet>::PreparedResources,
Queries = <Q as QuerySet>::Queries,
>,
{
fn name(&self) -> &SystemId { &self.name }
fn reads(&self) -> (&[ResourceTypeId], &[ComponentTypeId]) {
(&self.access.resources.reads, &self.access.components.reads)
}
fn writes(&self) -> (&[ResourceTypeId], &[ComponentTypeId]) {
(
&self.access.resources.writes,
&self.access.components.writes,
)
}
fn prepare(&mut self, world: &World) {
if let ArchetypeAccess::Some(bitset) = &mut self.archetypes {
self.queries.get_mut().filter_archetypes(world, bitset);
}
}
fn accesses_archetypes(&self) -> &ArchetypeAccess { &self.archetypes }
fn command_buffer_mut(&self, world: WorldId) -> Option<RefMut<CommandBuffer>> {
self.command_buffer.get(&world).map(|cmd| cmd.get_mut())
}
unsafe fn run_unsafe(&mut self, world: &World, resources: &Resources) {
let span = span!(Level::INFO, "System", system = %self.name);
let _guard = span.enter();
debug!("Initializing");
let resources = R::fetch_unchecked(resources);
let mut queries = self.queries.get_mut();
let mut prepared_queries = queries.prepare();
let mut world_shim = SubWorld::new(world, &self.access.components, &self.archetypes);
let cmd = self
.command_buffer
.entry(world.id())
.or_insert_with(|| AtomicRefCell::new(CommandBuffer::new(world)));
info!("Running");
let mut borrow = self.run_fn.get_mut();
borrow.deref_mut().run(
&mut cmd.get_mut(),
&mut world_shim,
resources,
&mut prepared_queries,
);
}
}
/// Supertrait used for defining systems. All wrapper objects for systems implement this trait.
///
/// This trait will generally not be used by users.
pub trait FuncSystemFn {
type Resources;
type Queries;
fn run(
&mut self,
commands: &mut CommandBuffer,
world: &mut SubWorld,
resources: Self::Resources,
queries: &mut Self::Queries,
);
}
pub struct FuncSystemFnWrapper<
R,
Q,
F: FnMut(&mut CommandBuffer, &mut SubWorld, R, &mut Q) + 'static,
>(pub F, pub PhantomData<(R, Q)>);
impl<F, R, Q> FuncSystemFn for FuncSystemFnWrapper<R, Q, F>
where
F: FnMut(&mut CommandBuffer, &mut SubWorld, R, &mut Q) + 'static,
{
type Resources = R;
type Queries = Q;
fn run(
&mut self,
commands: &mut CommandBuffer,
world: &mut SubWorld,
resources: Self::Resources,
queries: &mut Self::Queries,
) {
(self.0)(commands, world, resources, queries);
}
}

View file

@ -54,10 +54,11 @@ pub use legion::{
systems::{
bit_set::BitSet,
resource::{
PreparedRead as Resource, PreparedWrite as ResourceMut, ResourceSet, Resources,
ResourceSet, Resources,
},
schedule::{Executor, Runnable, Schedulable, Schedule},
IntoSystem, SubWorld, SystemBuilder,
Resource, ResourceMut,
},
world::{Universe, World},
};