Create simple function systems
This commit is contained in:
parent
7f17a97ef7
commit
9c6c32199d
|
@ -30,7 +30,6 @@
|
||||||
"args": [
|
"args": [
|
||||||
"test",
|
"test",
|
||||||
"--no-run",
|
"--no-run",
|
||||||
"--bin=lyra-ecs",
|
|
||||||
"--package=lyra-ecs",
|
"--package=lyra-ecs",
|
||||||
"query::resource::tests::query",
|
"query::resource::tests::query",
|
||||||
"--",
|
"--",
|
||||||
|
@ -39,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "lyra-ecs",
|
"name": "lyra-ecs",
|
||||||
"kind": "bin"
|
"kind": "lib"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"args": [],
|
"args": [],
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.75"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -29,6 +35,7 @@ checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
name = "lyra-ecs"
|
name = "lyra-ecs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.75"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.8.5" # used for tests
|
rand = "0.8.5" # used for tests
|
||||||
|
|
|
@ -21,5 +21,14 @@ pub use component_info::*;
|
||||||
mod resource;
|
mod resource;
|
||||||
pub use resource::*;
|
pub use resource::*;
|
||||||
|
|
||||||
|
mod system;
|
||||||
|
pub use system::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum Access {
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ use std::{marker::PhantomData, any::TypeId, ptr::NonNull, cell::{Ref, RefCell, R
|
||||||
|
|
||||||
use crate::{world::World, ComponentColumn};
|
use crate::{world::World, ComponentColumn};
|
||||||
|
|
||||||
use super::{Fetch, Query, AsQuery, DefaultQuery};
|
use super::{Fetch, Query, AsQuery};
|
||||||
|
|
||||||
/// Fetcher for borrowing components from archetypes.
|
/// Fetcher for borrowing components from archetypes.
|
||||||
pub struct FetchBorrow<'a, T> {
|
pub struct FetchBorrow<'a, T> {
|
||||||
|
@ -45,6 +45,14 @@ pub struct QueryBorrow<T> {
|
||||||
_phantom: PhantomData<T>
|
_phantom: PhantomData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for QueryBorrow<T> {}
|
||||||
|
|
||||||
|
impl<T> Clone for QueryBorrow<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: 'static> QueryBorrow<T> {
|
impl<T: 'static> QueryBorrow<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -62,6 +70,10 @@ where
|
||||||
|
|
||||||
type Fetch<'a> = FetchBorrow<'a, T>;
|
type Fetch<'a> = FetchBorrow<'a, T>;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
QueryBorrow::<T>::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||||
archetype.columns.iter().any(|c| c.info.type_id == self.type_id)
|
archetype.columns.iter().any(|c| c.info.type_id == self.type_id)
|
||||||
}
|
}
|
||||||
|
@ -82,22 +94,10 @@ impl<T: 'static> AsQuery for QueryBorrow<T> {
|
||||||
type Query = Self;
|
type Query = Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> DefaultQuery for QueryBorrow<T> {
|
|
||||||
fn default_query() -> Self {
|
|
||||||
QueryBorrow::<T>::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static> AsQuery for &T {
|
impl<T: 'static> AsQuery for &T {
|
||||||
type Query = QueryBorrow<T>;
|
type Query = QueryBorrow<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> DefaultQuery for &T {
|
|
||||||
fn default_query() -> QueryBorrow<T> {
|
|
||||||
QueryBorrow::<T>::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A fetcher for mutably borrowing components from archetypes.
|
/// A fetcher for mutably borrowing components from archetypes.
|
||||||
pub struct FetchBorrowMut<'a, T> {
|
pub struct FetchBorrowMut<'a, T> {
|
||||||
col: &'a ComponentColumn,
|
col: &'a ComponentColumn,
|
||||||
|
@ -139,6 +139,14 @@ pub struct QueryBorrowMut<T> {
|
||||||
_phantom: PhantomData<T>
|
_phantom: PhantomData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for QueryBorrowMut<T> {}
|
||||||
|
|
||||||
|
impl<T> Clone for QueryBorrowMut<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: 'static> QueryBorrowMut<T> {
|
impl<T: 'static> QueryBorrowMut<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -156,6 +164,10 @@ where
|
||||||
|
|
||||||
type Fetch<'a> = FetchBorrowMut<'a, T>;
|
type Fetch<'a> = FetchBorrowMut<'a, T>;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
QueryBorrowMut::<T>::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||||
archetype.columns.iter().any(|c| c.info.type_id == self.type_id)
|
archetype.columns.iter().any(|c| c.info.type_id == self.type_id)
|
||||||
}
|
}
|
||||||
|
@ -176,22 +188,10 @@ impl<T: 'static> AsQuery for QueryBorrowMut<T> {
|
||||||
type Query = Self;
|
type Query = Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> DefaultQuery for QueryBorrowMut<T> {
|
|
||||||
fn default_query() -> Self {
|
|
||||||
QueryBorrowMut::<T>::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static> AsQuery for &mut T {
|
impl<T: 'static> AsQuery for &mut T {
|
||||||
type Query = QueryBorrowMut<T>;
|
type Query = QueryBorrowMut<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> DefaultQuery for &mut T {
|
|
||||||
fn default_query() -> QueryBorrowMut<T> {
|
|
||||||
QueryBorrowMut::<T>::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{any::TypeId, mem::size_of, marker::PhantomData};
|
use std::{any::TypeId, mem::size_of, marker::PhantomData};
|
||||||
|
|
|
@ -21,6 +21,7 @@ impl<'a> Fetch<'a> for EntitiesFetch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct Entities;
|
pub struct Entities;
|
||||||
|
|
||||||
impl Query for Entities {
|
impl Query for Entities {
|
||||||
|
@ -28,6 +29,10 @@ impl Query for Entities {
|
||||||
|
|
||||||
type Fetch<'a> = EntitiesFetch;
|
type Fetch<'a> = EntitiesFetch;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
Entities
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &Archetype) -> bool {
|
||||||
let _ = archetype; // ignore unused warnings
|
let _ = archetype; // ignore unused warnings
|
||||||
true
|
true
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub trait Fetch<'a> {
|
||||||
unsafe fn get_item(&mut self, entity: ArchetypeEntityId) -> Self::Item;
|
unsafe fn get_item(&mut self, entity: ArchetypeEntityId) -> Self::Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Query {
|
pub trait Query: Copy {
|
||||||
/// The item that this query yields
|
/// The item that this query yields
|
||||||
type Item<'a>: 'a;
|
type Item<'a>: 'a;
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ pub trait Query {
|
||||||
/// [`View`] uses this to determine if it should continue to iterate this Query.
|
/// [`View`] uses this to determine if it should continue to iterate this Query.
|
||||||
const ALWAYS_FETCHES: bool = false;
|
const ALWAYS_FETCHES: bool = false;
|
||||||
|
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
/// Returns true if the archetype should be visited or skipped.
|
/// Returns true if the archetype should be visited or skipped.
|
||||||
fn can_visit_archetype(&self, archetype: &Archetype) -> bool;
|
fn can_visit_archetype(&self, archetype: &Archetype) -> bool;
|
||||||
|
|
||||||
|
@ -74,10 +76,6 @@ pub trait IntoQuery {
|
||||||
fn into_query(self) -> Self;
|
fn into_query(self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DefaultQuery: AsQuery {
|
|
||||||
fn default_query() -> Self::Query;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{world::World, archetype::Archetype, tests::Vec2};
|
use crate::{world::World, archetype::Archetype, tests::Vec2};
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{marker::PhantomData, any::TypeId, ptr::NonNull, cell::Ref};
|
||||||
|
|
||||||
use crate::{world::World, resource::ResourceObject};
|
use crate::{world::World, resource::ResourceObject};
|
||||||
|
|
||||||
use super::{Query, Fetch, AsQuery, DefaultQuery};
|
use super::{Query, Fetch, AsQuery};
|
||||||
|
|
||||||
pub struct FetchResource<'a, T> {
|
pub struct FetchResource<'a, T> {
|
||||||
world: Option<&'a World>,
|
world: Option<&'a World>,
|
||||||
|
@ -34,19 +34,33 @@ impl<'a, T: 'a + 'static> Fetch<'a> for FetchResource<'a, T> {
|
||||||
///
|
///
|
||||||
/// Resources are stored in an archetype with the id of [`world::RESOURCE_ARCHETYPE_ID`]. There is only one instance of a type of resource.
|
/// Resources are stored in an archetype with the id of [`world::RESOURCE_ARCHETYPE_ID`]. There is only one instance of a type of resource.
|
||||||
/// The resources are stored in that archetype in the first entity in the column.
|
/// The resources are stored in that archetype in the first entity in the column.
|
||||||
pub struct QueryResource<T> {
|
pub struct QueryResource<T: ResourceObject> {
|
||||||
_phantom: PhantomData<T>
|
_phantom: PhantomData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: ResourceObject> Copy for QueryResource<T> {}
|
||||||
|
|
||||||
|
impl<T: ResourceObject> Clone for QueryResource<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Resource<T> = QueryResource<T>;
|
pub type Resource<T> = QueryResource<T>;
|
||||||
|
|
||||||
impl<T: 'static> Query for QueryResource<T> {
|
impl<T: ResourceObject + 'static> Query for QueryResource<T> {
|
||||||
type Item<'a> = Ref<'a, T>;
|
type Item<'a> = Ref<'a, T>;
|
||||||
|
|
||||||
type Fetch<'a> = FetchResource<'a, T>;
|
type Fetch<'a> = FetchResource<'a, T>;
|
||||||
|
|
||||||
const ALWAYS_FETCHES: bool = true;
|
const ALWAYS_FETCHES: bool = true;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
QueryResource::<T> {
|
||||||
|
_phantom: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, _archetype: &crate::archetype::Archetype) -> bool {
|
fn can_visit_archetype(&self, _archetype: &crate::archetype::Archetype) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -66,14 +80,6 @@ impl<T: 'static> Query for QueryResource<T> {
|
||||||
impl<R: ResourceObject> AsQuery for QueryResource<R> {
|
impl<R: ResourceObject> AsQuery for QueryResource<R> {
|
||||||
type Query = QueryResource<R>;
|
type Query = QueryResource<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: ResourceObject> DefaultQuery for QueryResource<R> {
|
|
||||||
fn default_query() -> Self::Query {
|
|
||||||
QueryResource::<R> {
|
|
||||||
_phantom: PhantomData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{world::World, tests::{Vec2, Vec3}};
|
use crate::{world::World, tests::{Vec2, Vec3}};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::world::World;
|
use crate::world::World;
|
||||||
|
|
||||||
use super::{Query, Fetch, AsQuery, DefaultQuery};
|
use super::{Query, Fetch, AsQuery};
|
||||||
|
|
||||||
// Technically all of these implementations for a 2-sized tuple
|
// Technically all of these implementations for a 2-sized tuple
|
||||||
// can be implemented by the macro near the end of the file, but
|
// can be implemented by the macro near the end of the file, but
|
||||||
|
@ -37,6 +37,10 @@ where
|
||||||
|
|
||||||
type Fetch<'a> = (Q1::Fetch<'a>, Q2::Fetch<'a>);
|
type Fetch<'a> = (Q1::Fetch<'a>, Q2::Fetch<'a>);
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
(Q1::new(), Q2::new())
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||||
let (q1, q2) = self;
|
let (q1, q2) = self;
|
||||||
q1.can_visit_archetype(archetype) && q2.can_visit_archetype(archetype)
|
q1.can_visit_archetype(archetype) && q2.can_visit_archetype(archetype)
|
||||||
|
@ -56,16 +60,6 @@ where
|
||||||
type Query = (Q1::Query, Q2::Query);
|
type Query = (Q1::Query, Q2::Query);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Q1, Q2> DefaultQuery for (Q1, Q2)
|
|
||||||
where
|
|
||||||
Q1: DefaultQuery,
|
|
||||||
Q2: DefaultQuery,
|
|
||||||
{
|
|
||||||
fn default_query() -> (Q1::Query, Q2::Query) {
|
|
||||||
( Q1::default_query(), Q2::default_query() )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_bundle_tuple {
|
macro_rules! impl_bundle_tuple {
|
||||||
( $($name: ident),+ ) => (
|
( $($name: ident),+ ) => (
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -95,6 +89,10 @@ macro_rules! impl_bundle_tuple {
|
||||||
type Item<'a> = ($($name::Item<'a>,)+);
|
type Item<'a> = ($($name::Item<'a>,)+);
|
||||||
type Fetch<'a> = ($($name::Fetch<'a>,)+);
|
type Fetch<'a> = ($($name::Fetch<'a>,)+);
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
( $($name::new(),)+ )
|
||||||
|
}
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||||
let ( $($name,)+ ) = self;
|
let ( $($name,)+ ) = self;
|
||||||
|
|
||||||
|
@ -112,12 +110,6 @@ macro_rules! impl_bundle_tuple {
|
||||||
impl<$($name: AsQuery),+> AsQuery for ($($name,)+) {
|
impl<$($name: AsQuery),+> AsQuery for ($($name,)+) {
|
||||||
type Query = ($($name::Query,)+);
|
type Query = ($($name::Query,)+);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($name: DefaultQuery),+> DefaultQuery for ($($name,)+) {
|
|
||||||
fn default_query() -> ($($name::Query,)+) {
|
|
||||||
( $($name::default_query(),)+ )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
use std::{ptr::NonNull, marker::PhantomData};
|
||||||
|
|
||||||
|
use crate::{world::World, View, Query, Access};
|
||||||
|
|
||||||
|
/// A system that does not mutate the world
|
||||||
|
pub trait System {
|
||||||
|
fn world_access(&self) -> Access;
|
||||||
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for converting something into a system.
|
||||||
|
pub trait IntoSystem<T> {
|
||||||
|
type System: System;
|
||||||
|
|
||||||
|
fn into_system(self) -> Self::System;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait FnArg {
|
||||||
|
type Arg<'a>;
|
||||||
|
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
|
unsafe fn get<'a>(&mut self, world: &'a World) -> Self::Arg<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FnSystem<F, Args> {
|
||||||
|
inner: F,//for<'a> fn(Args) -> anyhow::Result<()>
|
||||||
|
//args: Args,
|
||||||
|
_p: PhantomData<Args>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* impl<'a, F, Q> System for FnSystem<F, Q>
|
||||||
|
where
|
||||||
|
Q: FnArg,
|
||||||
|
F: Fn(Q::Arg<'a>,) -> anyhow::Result<()>, */
|
||||||
|
|
||||||
|
|
||||||
|
impl<F, A> System for FnSystem<F, A>
|
||||||
|
where
|
||||||
|
A: FnArg,
|
||||||
|
F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>,
|
||||||
|
{
|
||||||
|
fn world_access(&self) -> Access {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
||||||
|
let world = unsafe { world.as_ref() };
|
||||||
|
|
||||||
|
let mut a = A::new();
|
||||||
|
|
||||||
|
let a = unsafe { a.get(world) };
|
||||||
|
|
||||||
|
(self.inner)(a)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* impl<F, A> IntoSystem<A> for F
|
||||||
|
where
|
||||||
|
A: FnArg,
|
||||||
|
F: for<'a> Fn(A::Arg<'a>) -> anyhow::Result<()>,
|
||||||
|
{
|
||||||
|
type System = FnSystem<F, A>;
|
||||||
|
|
||||||
|
fn into_system(self) -> Self::System {
|
||||||
|
FnSystem {
|
||||||
|
_p: PhantomData,
|
||||||
|
inner: self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* impl<F, Q> IntoSystem<Q> for F
|
||||||
|
where
|
||||||
|
Q: Query,
|
||||||
|
F: for<'a> Fn(<FnArgStorage<Q> as FnArg>::Arg<'a>) -> anyhow::Result<()>,
|
||||||
|
{
|
||||||
|
type System = FnSystem<F, FnArgStorage<Q>>;
|
||||||
|
|
||||||
|
fn into_system(self) -> Self::System {
|
||||||
|
FnSystem {
|
||||||
|
_p: PhantomData,
|
||||||
|
inner: self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
impl<F, Q> IntoSystem<Q> for F
|
||||||
|
where
|
||||||
|
Q: Query,
|
||||||
|
F: for<'a> FnMut(<FnArgStorage<Q> as FnArg>::Arg<'a>) -> anyhow::Result<()>,
|
||||||
|
{
|
||||||
|
type System = FnSystem<F, FnArgStorage<Q>>;
|
||||||
|
|
||||||
|
fn into_system(self) -> Self::System {
|
||||||
|
FnSystem {
|
||||||
|
_p: PhantomData,
|
||||||
|
inner: self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FnArgStorage<Q: Query> {
|
||||||
|
query: Q,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Query> FnArg for FnArgStorage<Q> {
|
||||||
|
type Arg<'b> = View<'b, Q>;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
FnArgStorage {
|
||||||
|
query: Q::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get<'b>(&mut self, world: &'b World) -> Self::Arg<'b> {
|
||||||
|
let arch = world.archetypes.values().collect();
|
||||||
|
let v = View::new(world, self.query, arch);
|
||||||
|
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{ptr::NonNull, sync::atomic::{AtomicU8, Ordering}, rc::Rc, ops::Add};
|
||||||
|
|
||||||
|
use crate::{tests::Vec2, View, QueryBorrow, world::World};
|
||||||
|
use super::{System, IntoSystem};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_system() {
|
||||||
|
let mut world = World::new();
|
||||||
|
world.spawn((Vec2::rand(),));
|
||||||
|
world.spawn((Vec2::rand(),));
|
||||||
|
world.spawn((Vec2::rand(),));
|
||||||
|
world.spawn((Vec2::rand(),));
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
let test_system = |view: View<QueryBorrow<Vec2>>| -> anyhow::Result<()> {
|
||||||
|
for v in view.into_iter() {
|
||||||
|
println!("Got v at: {:?}", v);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
test_system.into_system().execute(NonNull::from(&world)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(count, 4);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{collections::{HashMap, VecDeque}, any::TypeId, cell::{Ref, RefMut}};
|
use std::{collections::{HashMap, VecDeque}, any::TypeId, cell::{Ref, RefMut}};
|
||||||
|
|
||||||
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View, DefaultQuery}, resource::ResourceData};
|
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View}, resource::ResourceData, Query, AsQuery};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct EntityId(pub u64);
|
pub struct EntityId(pub u64);
|
||||||
|
@ -115,9 +115,9 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> {
|
pub fn view<'a, T: 'static + Component + AsQuery>(&'a self) -> ViewIter<'a, T::Query> {
|
||||||
let archetypes = self.archetypes.values().collect();
|
let archetypes = self.archetypes.values().collect();
|
||||||
let v = View::new(self, T::default_query(), archetypes);
|
let v = View::new(self, T::Query::new(), archetypes);
|
||||||
v.into_iter()
|
v.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue