Implement query for tuples of query types
This commit is contained in:
parent
2e53156b0d
commit
2c718231ed
|
@ -1,6 +1,6 @@
|
|||
use std::{any::{Any, TypeId, type_name}, ptr::{NonNull, self}, alloc::{self, Layout, alloc}, mem::size_of};
|
||||
use std::{any::TypeId, ptr::{NonNull, self}, alloc::{self, Layout, alloc}};
|
||||
|
||||
use crate::{world::{Entity, ArchetypeEntityId}, bundle::Bundle, component::Component, component_info::ComponentInfo};
|
||||
use crate::{world::{Entity, ArchetypeEntityId}, bundle::Bundle, component_info::ComponentInfo};
|
||||
|
||||
pub struct ComponentColumn {
|
||||
pub data: NonNull<u8>,
|
||||
|
@ -9,6 +9,7 @@ pub struct ComponentColumn {
|
|||
pub entry_size: usize,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl ComponentColumn {
|
||||
/// Creates an invalid component column. Do not attempt to use it.
|
||||
pub unsafe fn dangling() -> Self {
|
||||
|
@ -45,19 +46,6 @@ impl ComponentColumn {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates an empty column of the same type
|
||||
pub unsafe fn create_empty(&self, capacity: usize) -> Self {
|
||||
let data = ComponentColumn::alloc(self.info.layout, capacity);
|
||||
|
||||
let size = self.info.layout.size();
|
||||
Self {
|
||||
data,
|
||||
capacity,
|
||||
info: self.info.clone(),
|
||||
entry_size: size,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a component from pointer at an entity index.
|
||||
///
|
||||
/// # Safety
|
||||
|
@ -117,46 +105,6 @@ pub struct Archetype {
|
|||
const DEFAULT_CAPACITY: usize = 32;
|
||||
|
||||
impl Archetype {
|
||||
/// Create a new archetype from another archetype and add a column
|
||||
pub fn new_archetype_add<T: Component>(new_id: ArchetypeId, archetype: &Archetype) -> Archetype {
|
||||
let mut columns: Vec<_> = archetype
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| unsafe { c.create_empty(DEFAULT_CAPACITY) })
|
||||
.collect();
|
||||
|
||||
// Make sure a column for the new component does not exist
|
||||
assert_ne!(true, columns.iter().any(|c| c.info.type_id == TypeId::of::<T>()) );
|
||||
columns.push(unsafe { ComponentColumn::new(ComponentInfo::new::<T>(), DEFAULT_CAPACITY) });
|
||||
|
||||
Archetype {
|
||||
id: new_id,
|
||||
entities: Vec::new(),
|
||||
columns,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new archetype from another archetype and remove a column
|
||||
pub fn new_archetype_remove<T: Component>(new_id: ArchetypeId, archetype: &Archetype) -> Archetype {
|
||||
let mut columns: Vec<_> = archetype
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| unsafe { c.create_empty(DEFAULT_CAPACITY) })
|
||||
.collect();
|
||||
|
||||
let idx = columns
|
||||
.iter()
|
||||
.position(|column| column.info.type_id == TypeId::of::<T>())
|
||||
.unwrap();
|
||||
columns.remove(idx);
|
||||
|
||||
Archetype {
|
||||
id: new_id,
|
||||
entities: Vec::new(),
|
||||
columns,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bundle_info(new_id: ArchetypeId, bundle_info: Vec<ComponentInfo>) -> Archetype {
|
||||
let columns = bundle_info.into_iter().map(|i| {
|
||||
unsafe { ComponentColumn::new(i, DEFAULT_CAPACITY) }
|
||||
|
@ -169,21 +117,6 @@ impl Archetype {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_component_mut<T: Component>(&mut self, entity: ArchetypeEntityId) -> Option<&mut T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn get_entity_component<T: Component>(&self, entity: ArchetypeEntityId) -> Option<&T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
|
||||
self.columns.iter().find(|c| c.info.type_id == type_id)
|
||||
.map(|c| unsafe { c.get(entity.0 as usize) })
|
||||
}
|
||||
|
||||
pub fn get_component_column<T: Component>(&self) -> Option<&Vec<T>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Add an entity and its component bundle to the Archetype
|
||||
///
|
||||
/// # Safety:
|
||||
|
@ -196,7 +129,7 @@ impl Archetype {
|
|||
let entity_index = self.entities.len();
|
||||
self.entities.push(entity);
|
||||
|
||||
bundle.takefn(|data, type_id, size| {
|
||||
bundle.take(|data, type_id, _size| {
|
||||
let col = self.columns.iter_mut().find(|c| c.info.type_id == type_id).unwrap();
|
||||
unsafe { col.set_at(entity_index, data); }
|
||||
});
|
||||
|
@ -204,7 +137,7 @@ impl Archetype {
|
|||
ArchetypeEntityId(entity_index as u64)
|
||||
}
|
||||
|
||||
/// returns a boolean indicating whether this archetype can store the TypeIds given
|
||||
/// Returns a boolean indicating whether this archetype can store the TypeIds given
|
||||
pub(crate) fn is_archetype_for(&self, types: Vec<TypeId>) -> bool {
|
||||
self.columns.iter().all(|c| types.contains(&c.info.type_id))
|
||||
}
|
||||
|
|
|
@ -1,27 +1,22 @@
|
|||
use std::{any::{TypeId, Any}, cell::Ref, ptr::NonNull, mem::size_of};
|
||||
use std::{any::{TypeId, Any}, ptr::NonNull, mem::size_of};
|
||||
|
||||
use crate::{archetype::{ComponentColumn, Archetype}, component::Component, component_info::ComponentInfo};
|
||||
use crate::{component::Component, component_info::ComponentInfo};
|
||||
|
||||
pub trait Bundle {
|
||||
// Get a list of type ids that this bundle is storing
|
||||
fn types(&self) -> Vec<TypeId>;
|
||||
/// Take components into a list.
|
||||
/// The return value could be seen as a list of a list of components, but that inner list
|
||||
/// only contains a single value to make it easier to add it to an archetype.
|
||||
//fn take_components(self) -> Vec<Box<dyn ComponentColumn>>;
|
||||
|
||||
//fn from_component_columns(columns: Vec<&Box<dyn ComponentColumn>>) -> Self;
|
||||
//fn from_archetype(archetype: &Archetype) -> Self;
|
||||
/// Get a list of type ids that this bundle is storing
|
||||
fn type_ids(&self) -> Vec<TypeId>;
|
||||
|
||||
/// Get ComponentInfo's for the components in this bundle
|
||||
fn info(&self) -> Vec<ComponentInfo>;
|
||||
|
||||
/// Take the bundle by calling the closure with pointers to each component, its type and size.
|
||||
/// The closure is expected to take ownership of the pointer.
|
||||
fn takefn(self, cb: impl FnMut(NonNull<u8>, TypeId, usize));
|
||||
fn take(self, f: impl FnMut(NonNull<u8>, TypeId, usize));
|
||||
}
|
||||
|
||||
// The macro below can implement this for us, but this is here for development
|
||||
impl<C1: Component> Bundle for (C1,) {
|
||||
fn types(&self) -> Vec<TypeId> {
|
||||
fn type_ids(&self) -> Vec<TypeId> {
|
||||
vec![self.0.type_id()]
|
||||
}
|
||||
|
||||
|
@ -29,51 +24,50 @@ impl<C1: Component> Bundle for (C1,) {
|
|||
vec![ComponentInfo::new::<C1>()]
|
||||
}
|
||||
|
||||
fn takefn(self, mut cb: impl FnMut(NonNull<u8>, TypeId, usize)) {
|
||||
fn take(self, mut f: impl FnMut(NonNull<u8>, TypeId, usize)) {
|
||||
let (c1, ) = self;
|
||||
|
||||
cb(NonNull::from(&c1).cast(), TypeId::of::<C1>(), size_of::<C1>());
|
||||
f(NonNull::from(&c1).cast(), TypeId::of::<C1>(), size_of::<C1>());
|
||||
}
|
||||
}
|
||||
|
||||
/* macro_rules! impl_bundle_tuple {
|
||||
( $(($name: ident, $index: tt))+ ) => (
|
||||
macro_rules! impl_bundle_tuple {
|
||||
( $($name: ident),+ ) => (
|
||||
#[allow(non_snake_case)]
|
||||
impl<$($name: Component),+> Bundle for ($($name,)+) {
|
||||
fn types(&self) -> Vec<TypeId> {
|
||||
vec![$(self.$index.type_id()),+]
|
||||
fn type_ids(&self) -> Vec<TypeId> {
|
||||
// these names wont follow rust convention, but its a macro so deal with it
|
||||
let ($($name),+) = self;
|
||||
vec![$($name.type_id()),+]
|
||||
}
|
||||
|
||||
fn take_components(self) -> Vec<Box<dyn ComponentColumn>> {
|
||||
vec![$(Box::new(vec![self.$index])),+]
|
||||
fn info(&self) -> Vec<ComponentInfo> {
|
||||
vec![$(ComponentInfo::new::<$name>()),+]
|
||||
}
|
||||
|
||||
fn from_component_columns(columns: Vec<&Box<dyn ComponentColumn>>) -> Self {
|
||||
let mut chains = Vec::new();
|
||||
fn take(self, mut f: impl FnMut(NonNull<u8>, TypeId, usize)) {
|
||||
// these names wont follow rust convention, but its a macro so deal with it
|
||||
let ($($name),+) = self;
|
||||
|
||||
for col in columns.iter() {
|
||||
col.
|
||||
}
|
||||
|
||||
todo!()
|
||||
$(f(NonNull::from(&$name).cast(), TypeId::of::<$name>(), size_of::<$name>());)+
|
||||
}
|
||||
}
|
||||
);
|
||||
} */
|
||||
}
|
||||
|
||||
// hopefully 16 components in a bundle is enough
|
||||
//impl_bundle_tuple! { (C1, 0) }
|
||||
/* impl_bundle_tuple! { (C1, 0) (C2, 1) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) (C11, 10) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) (C11, 10) (C12, 11) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) (C11, 10) (C12, 11) (C13, 12) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) (C11, 10) (C12, 11) (C13, 12) (C14, 13) }
|
||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) (C9, 8) (C10, 9) (C11, 10) (C12, 11) (C13, 12) (C14, 13) (C15, 14) }
|
||||
*/
|
||||
impl_bundle_tuple! { C1, C2 }
|
||||
impl_bundle_tuple! { C1, C2, C3 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15 }
|
||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16 }
|
|
@ -16,25 +16,7 @@ pub struct Position2d(i32, i32);
|
|||
|
||||
fn main() {
|
||||
let mut world = World::new();
|
||||
|
||||
let pos = Position2d(50, 50);
|
||||
let e = world.spawn((pos,));
|
||||
|
||||
if let Some(pos) = world.get_component::<Position2d>(e) {
|
||||
println!("Got Position2d: {:?}", pos);
|
||||
} else {
|
||||
println!("no component found :(");
|
||||
}
|
||||
|
||||
let pos = Position2d(836, 348);
|
||||
let _e = world.spawn((pos,));
|
||||
|
||||
println!("\nstart of querying!\n");
|
||||
|
||||
let mut q = world.query_better();
|
||||
q.with_component::<Position2d>();
|
||||
|
||||
for pos in q.run::<Position2d>() {
|
||||
println!("Queried Position2d: {:?}", pos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use std::{marker::PhantomData, any::TypeId, ptr::NonNull};
|
||||
|
||||
use crate::component::Component;
|
||||
|
||||
use super::{Fetch, Query, AsQuery, IntoQuery, DefaultQuery};
|
||||
use super::{Fetch, Query, AsQuery, DefaultQuery};
|
||||
|
||||
pub struct FetchBorrow<'a, T> {
|
||||
ptr: NonNull<u8>,
|
||||
|
@ -16,7 +14,7 @@ where
|
|||
{
|
||||
type Item = &'a T;
|
||||
|
||||
fn create_empty() -> Self {
|
||||
fn dangling() -> Self {
|
||||
FetchBorrow {
|
||||
ptr: NonNull::dangling(),
|
||||
size: 0,
|
||||
|
@ -103,7 +101,7 @@ where
|
|||
{
|
||||
type Item = &'a mut T;
|
||||
|
||||
fn create_empty() -> Self {
|
||||
fn dangling() -> Self {
|
||||
FetchBorrowMut {
|
||||
ptr: NonNull::dangling(),
|
||||
size: 0,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{world::Entity, archetype::{Archetype, ArchetypeId}};
|
||||
|
||||
use super::{Fetch, Query, DefaultQuery, AsQuery};
|
||||
use super::{Fetch, Query};
|
||||
|
||||
pub struct EntitiesFetch<'a> {
|
||||
entities: &'a [Entity],
|
||||
|
@ -14,7 +14,7 @@ impl<'a> Fetch<'a> for EntitiesFetch<'a> {
|
|||
e
|
||||
}
|
||||
|
||||
fn create_empty() -> Self {
|
||||
fn dangling() -> Self {
|
||||
Self {
|
||||
entities: &[],
|
||||
}
|
||||
|
@ -29,22 +29,14 @@ impl Query for Entities {
|
|||
type Fetch<'a> = EntitiesFetch<'a>;
|
||||
|
||||
fn can_visit_archetype(&self, archetype: &Archetype) -> bool {
|
||||
let _ = archetype; // ignore unused warnings
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn fetch<'a>(&self, arch_id: ArchetypeId, archetype: &'a Archetype) -> Self::Fetch<'a> {
|
||||
let _ = arch_id; // ignore unused warnings
|
||||
EntitiesFetch {
|
||||
entities: &archetype.entities,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* impl AsQuery for Entities {
|
||||
type Query = Entities;
|
||||
}
|
||||
|
||||
impl DefaultQuery for Entities {
|
||||
fn default_query() -> Self {
|
||||
Entities
|
||||
}
|
||||
} */
|
||||
}
|
|
@ -1,85 +1,19 @@
|
|||
use std::{any::{TypeId, Any}, cell::RefCell, rc::Rc, collections::{HashMap, VecDeque}, io::Read, slice::Iter, ops::Range};
|
||||
|
||||
use crate::{archetype::{Archetype, ComponentColumn, ArchetypeId}, bundle::Bundle, component::Component, world::{Record, EntityId, ArchetypeEntityId}};
|
||||
use crate::{archetype::{Archetype, ArchetypeId}, world::ArchetypeEntityId};
|
||||
|
||||
pub mod view;
|
||||
pub use view::*;
|
||||
|
||||
pub mod entities;
|
||||
#[allow(unused_imports)]
|
||||
pub use entities::*;
|
||||
|
||||
pub mod borrow;
|
||||
#[allow(unused_imports)]
|
||||
pub use borrow::*;
|
||||
|
||||
pub struct QuerySimple<'a> {
|
||||
//entities: Iter<Entity
|
||||
archetypes: Vec<&'a Archetype>,
|
||||
type_ids: Vec<TypeId>,
|
||||
}
|
||||
|
||||
impl<'a> QuerySimple<'a> {
|
||||
pub fn new(archetypes: Vec<&'a Archetype>) -> Self {
|
||||
Self {
|
||||
archetypes,
|
||||
type_ids: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_component<T: Any>(&mut self) {
|
||||
let type_id = TypeId::of::<T>();
|
||||
self.type_ids.push(type_id);
|
||||
}
|
||||
|
||||
pub fn run<C1: Component>(&self) -> impl Iterator<Item = &C1>
|
||||
{
|
||||
//let mut columns = Vec::new();
|
||||
|
||||
/* for type_id in self.type_ids.iter() {
|
||||
for arch in self.archetypes.iter() {
|
||||
if let Some(col) = arch.columns
|
||||
.iter().find(|c| c.component_type_id() == type_id.clone()) {
|
||||
|
||||
columns.push(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut entities: Vec<&C1> = columns.iter().map(|bx| bx.as_any().downcast_ref::<C1>()
|
||||
.expect("Failure to downcast component column"))
|
||||
.collect(); */
|
||||
|
||||
let entities = self.archetypes
|
||||
.iter()
|
||||
.filter_map(|a| a.get_component_column::<C1>())
|
||||
.flatten();
|
||||
|
||||
|
||||
/* let columns = self.type_ids
|
||||
.iter()
|
||||
.map(|type_id| {
|
||||
let a = self.archetypes
|
||||
.iter()
|
||||
.filter_map(|arch| {
|
||||
arch.columns
|
||||
.iter()
|
||||
.find(|c| c.component_type_id() == type_id.clone())
|
||||
});
|
||||
}); */
|
||||
|
||||
/* self.type_ids
|
||||
.iter()
|
||||
.map(|type_id| {
|
||||
self.archetypes
|
||||
.iter()
|
||||
.map(|arch| {
|
||||
arch.get_component_column_typeid(type_id.clone())
|
||||
})
|
||||
}); */
|
||||
|
||||
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
pub mod tuple;
|
||||
#[allow(unused_imports)]
|
||||
pub use tuple::*;
|
||||
|
||||
/// A [`Fetch`]er implementation gets data out of an archetype.
|
||||
pub trait Fetch<'a> {
|
||||
|
@ -93,7 +27,7 @@ pub trait Fetch<'a> {
|
|||
}
|
||||
|
||||
/// Creates an empty Fetch. DO NOT try to `get_item` on this
|
||||
fn create_empty() -> Self;
|
||||
fn dangling() -> Self;
|
||||
|
||||
unsafe fn get_item(&mut self, entity: ArchetypeEntityId) -> Self::Item;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
use super::{Query, Fetch, AsQuery, DefaultQuery};
|
||||
|
||||
// Technically all of these implementations for a 2-sized tuple
|
||||
// can be implemented by the macro near the end of the file, but
|
||||
// these are left here for development.
|
||||
|
||||
impl<'a, F1, F2> Fetch<'a> for (F1, F2)
|
||||
where
|
||||
F1: Fetch<'a>,
|
||||
F2: Fetch<'a>,
|
||||
{
|
||||
type Item = (F1::Item, F2::Item);
|
||||
|
||||
fn dangling() -> Self {
|
||||
(F1::dangling(), F2::dangling())
|
||||
}
|
||||
|
||||
fn can_visit_item(&mut self, entity: crate::world::ArchetypeEntityId) -> bool {
|
||||
let (f1, f2) = self;
|
||||
f1.can_visit_item(entity) && f2.can_visit_item(entity)
|
||||
}
|
||||
|
||||
unsafe fn get_item(&mut self, entity: crate::world::ArchetypeEntityId) -> Self::Item {
|
||||
let (f1, f2) = self;
|
||||
( f1.get_item(entity), f2.get_item(entity) )
|
||||
}
|
||||
}
|
||||
|
||||
impl<Q1, Q2> Query for (Q1, Q2)
|
||||
where
|
||||
Q1: Query,
|
||||
Q2: Query,
|
||||
{
|
||||
type Item<'a> = (Q1::Item<'a>, Q2::Item<'a>);
|
||||
|
||||
type Fetch<'a> = (Q1::Fetch<'a>, Q2::Fetch<'a>);
|
||||
|
||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||
let (q1, q2) = self;
|
||||
q1.can_visit_archetype(archetype) && q2.can_visit_archetype(archetype)
|
||||
}
|
||||
|
||||
unsafe fn fetch<'a>(&self, arch_id: crate::archetype::ArchetypeId, archetype: &'a crate::archetype::Archetype) -> Self::Fetch<'a> {
|
||||
let (q1, q2) = self;
|
||||
( q1.fetch(arch_id, archetype), q2.fetch(arch_id, archetype) )
|
||||
}
|
||||
}
|
||||
|
||||
impl<Q1, Q2> AsQuery for (Q1, Q2)
|
||||
where
|
||||
Q1: AsQuery,
|
||||
Q2: AsQuery,
|
||||
{
|
||||
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 {
|
||||
( $($name: ident),+ ) => (
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $($name: Fetch<'a>),+> Fetch<'a> for ($($name,)+) {
|
||||
type Item = ($($name::Item,)+);
|
||||
|
||||
fn dangling() -> Self {
|
||||
( $($name::dangling(),)+ )
|
||||
}
|
||||
|
||||
fn can_visit_item(&mut self, entity: crate::world::ArchetypeEntityId) -> bool {
|
||||
let ( $($name,)+ ) = self;
|
||||
|
||||
// this is the only way I could figure out how to do an 'and'
|
||||
let bools = vec![$($name.can_visit_item(entity),)+];
|
||||
bools.iter().all(|b| *b)
|
||||
}
|
||||
|
||||
unsafe fn get_item(&mut self, entity: crate::world::ArchetypeEntityId) -> Self::Item {
|
||||
let ( $($name,)+ ) = self;
|
||||
( $($name.get_item(entity),)+ )
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<$($name: Query),+> Query for ($($name,)+) {
|
||||
type Item<'a> = ($($name::Item<'a>,)+);
|
||||
type Fetch<'a> = ($($name::Fetch<'a>,)+);
|
||||
|
||||
fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool {
|
||||
let ( $($name,)+ ) = self;
|
||||
|
||||
// this is the only way I could figure out how to do an 'and'
|
||||
let bools = vec![$($name.can_visit_archetype(archetype),)+];
|
||||
bools.iter().all(|b| *b)
|
||||
}
|
||||
|
||||
unsafe fn fetch<'a>(&self, arch_id: crate::archetype::ArchetypeId, archetype: &'a crate::archetype::Archetype) -> Self::Fetch<'a> {
|
||||
let ( $($name,)+ ) = self;
|
||||
( $($name.fetch(arch_id, archetype),)+ )
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($name: AsQuery),+> AsQuery for ($($name,)+) {
|
||||
type Query = ($($name::Query,)+);
|
||||
}
|
||||
|
||||
impl<$($name: DefaultQuery),+> DefaultQuery for ($($name,)+) {
|
||||
fn default_query() -> ($($name::Query,)+) {
|
||||
( $($name::default_query(),)+ )
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Hopefully up to 16 queries in a SINGLE view is enough
|
||||
impl_bundle_tuple! { Q1, Q2, Q3 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15 }
|
||||
impl_bundle_tuple! { Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, Q16 }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{world::World, tests::{Vec2, Vec3}};
|
||||
|
||||
#[test]
|
||||
fn tuple_queries() {
|
||||
let mut world = World::new();
|
||||
|
||||
let comps = &[
|
||||
(
|
||||
Vec2 {
|
||||
x: 10.0,
|
||||
y: 15.0,
|
||||
},
|
||||
Vec3 {
|
||||
x: 83.0,
|
||||
y: 38.0,
|
||||
z: 98.0,
|
||||
}
|
||||
),
|
||||
(
|
||||
Vec2 {
|
||||
x: 152.0,
|
||||
y: 3585.0,
|
||||
},
|
||||
Vec3 {
|
||||
x: 43.0,
|
||||
y: 29.0,
|
||||
z: 30.0,
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
world.spawn(comps[0]);
|
||||
world.spawn(comps[1]);
|
||||
|
||||
for (pos2, pos3) in world.view::<(&Vec2, &Vec3)>() {
|
||||
println!("Entity at {:?} and {:?}", pos2, pos3);
|
||||
assert!(comps.contains(&( pos2.clone(), pos3.clone() )));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ where
|
|||
fn into_iter(self) -> Self::IntoIter {
|
||||
ViewIter {
|
||||
query: self.query,
|
||||
fetcher: Q::Fetch::create_empty(),
|
||||
fetcher: Q::Fetch::dangling(),
|
||||
archetypes: self.archetypes,
|
||||
next_archetype: 0,
|
||||
component_indices: 0..0,
|
||||
|
|
|
@ -13,4 +13,21 @@ impl Vec2 {
|
|||
y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
|
||||
pub struct Vec3 {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
impl Vec3 {
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
z
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use std::{collections::{HashMap, VecDeque}, any::{Any, TypeId}};
|
||||
use std::slice::Iter;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{QuerySimple, ViewIter, IntoQuery, View, AsQuery, DefaultQuery}};
|
||||
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View, DefaultQuery}};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct EntityId(pub u64);
|
||||
|
@ -60,7 +59,7 @@ impl World {
|
|||
where
|
||||
B: Bundle
|
||||
{
|
||||
let bundle_types = bundle.types();
|
||||
let bundle_types = bundle.type_ids();
|
||||
let new_entity = self.get_new_entity();
|
||||
|
||||
// try to find an archetype
|
||||
|
@ -102,30 +101,11 @@ impl World {
|
|||
new_entity
|
||||
}
|
||||
|
||||
pub fn get_component<T: Component>(&self, entity: Entity) -> Option<&T> {
|
||||
let record = self.entity_index.get(&entity.id)?;
|
||||
let archetype = self.archetypes.get(&record.id)?;
|
||||
|
||||
archetype.get_entity_component(record.index)
|
||||
}
|
||||
|
||||
pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> {
|
||||
let archetypes = self.archetypes.values().collect();
|
||||
let v = View::new(T::default_query(), archetypes);
|
||||
v.into_iter()
|
||||
}
|
||||
|
||||
pub fn query_better(&self) -> QuerySimple {
|
||||
let archetypes = self.archetypes.values().collect();
|
||||
QuerySimple::new(archetypes)
|
||||
}
|
||||
|
||||
/* pub fn query_m<B: Bundle>(&self) -> impl Iterator<Item = &T> {
|
||||
self.archetypes
|
||||
.iter()
|
||||
.filter_map(|(_, a)| a.get_component_column::<T>())
|
||||
.flatten()
|
||||
} */
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -144,7 +124,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn query_entities() {
|
||||
fn world_view_entities() {
|
||||
let mut world = World::new();
|
||||
world.spawn((Vec2 {
|
||||
x: 10.0,
|
||||
|
|
Loading…
Reference in New Issue