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 struct ComponentColumn {
|
||||||
pub data: NonNull<u8>,
|
pub data: NonNull<u8>,
|
||||||
|
@ -9,6 +9,7 @@ pub struct ComponentColumn {
|
||||||
pub entry_size: usize,
|
pub entry_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl ComponentColumn {
|
impl ComponentColumn {
|
||||||
/// Creates an invalid component column. Do not attempt to use it.
|
/// Creates an invalid component column. Do not attempt to use it.
|
||||||
pub unsafe fn dangling() -> Self {
|
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.
|
/// Set a component from pointer at an entity index.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
@ -117,46 +105,6 @@ pub struct Archetype {
|
||||||
const DEFAULT_CAPACITY: usize = 32;
|
const DEFAULT_CAPACITY: usize = 32;
|
||||||
|
|
||||||
impl Archetype {
|
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 {
|
pub fn from_bundle_info(new_id: ArchetypeId, bundle_info: Vec<ComponentInfo>) -> Archetype {
|
||||||
let columns = bundle_info.into_iter().map(|i| {
|
let columns = bundle_info.into_iter().map(|i| {
|
||||||
unsafe { ComponentColumn::new(i, DEFAULT_CAPACITY) }
|
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
|
/// Add an entity and its component bundle to the Archetype
|
||||||
///
|
///
|
||||||
/// # Safety:
|
/// # Safety:
|
||||||
|
@ -196,7 +129,7 @@ impl Archetype {
|
||||||
let entity_index = self.entities.len();
|
let entity_index = self.entities.len();
|
||||||
self.entities.push(entity);
|
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();
|
let col = self.columns.iter_mut().find(|c| c.info.type_id == type_id).unwrap();
|
||||||
unsafe { col.set_at(entity_index, data); }
|
unsafe { col.set_at(entity_index, data); }
|
||||||
});
|
});
|
||||||
|
@ -204,7 +137,7 @@ impl Archetype {
|
||||||
ArchetypeEntityId(entity_index as u64)
|
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 {
|
pub(crate) fn is_archetype_for(&self, types: Vec<TypeId>) -> bool {
|
||||||
self.columns.iter().all(|c| types.contains(&c.info.type_id))
|
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 {
|
pub trait Bundle {
|
||||||
// Get a list of type ids that this bundle is storing
|
/// Get a list of type ids that this bundle is storing
|
||||||
fn types(&self) -> Vec<TypeId>;
|
fn type_ids(&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 ComponentInfo's for the components in this bundle
|
||||||
fn info(&self) -> Vec<ComponentInfo>;
|
fn info(&self) -> Vec<ComponentInfo>;
|
||||||
|
|
||||||
/// Take the bundle by calling the closure with pointers to each component, its type and size.
|
/// 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.
|
/// 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,) {
|
impl<C1: Component> Bundle for (C1,) {
|
||||||
fn types(&self) -> Vec<TypeId> {
|
fn type_ids(&self) -> Vec<TypeId> {
|
||||||
vec![self.0.type_id()]
|
vec![self.0.type_id()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,51 +24,50 @@ impl<C1: Component> Bundle for (C1,) {
|
||||||
vec![ComponentInfo::new::<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;
|
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 {
|
macro_rules! impl_bundle_tuple {
|
||||||
( $(($name: ident, $index: tt))+ ) => (
|
( $($name: ident),+ ) => (
|
||||||
|
#[allow(non_snake_case)]
|
||||||
impl<$($name: Component),+> Bundle for ($($name,)+) {
|
impl<$($name: Component),+> Bundle for ($($name,)+) {
|
||||||
fn types(&self) -> Vec<TypeId> {
|
fn type_ids(&self) -> Vec<TypeId> {
|
||||||
vec![$(self.$index.type_id()),+]
|
// 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>> {
|
fn info(&self) -> Vec<ComponentInfo> {
|
||||||
vec![$(Box::new(vec![self.$index])),+]
|
vec![$(ComponentInfo::new::<$name>()),+]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_component_columns(columns: Vec<&Box<dyn ComponentColumn>>) -> Self {
|
fn take(self, mut f: impl FnMut(NonNull<u8>, TypeId, usize)) {
|
||||||
let mut chains = Vec::new();
|
// these names wont follow rust convention, but its a macro so deal with it
|
||||||
|
let ($($name),+) = self;
|
||||||
|
|
||||||
for col in columns.iter() {
|
$(f(NonNull::from(&$name).cast(), TypeId::of::<$name>(), size_of::<$name>());)+
|
||||||
col.
|
|
||||||
}
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} */
|
}
|
||||||
|
|
||||||
// hopefully 16 components in a bundle is enough
|
// hopefully 16 components in a bundle is enough
|
||||||
//impl_bundle_tuple! { (C1, 0) }
|
impl_bundle_tuple! { C1, C2 }
|
||||||
/* impl_bundle_tuple! { (C1, 0) (C2, 1) }
|
impl_bundle_tuple! { C1, C2, C3 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) }
|
impl_bundle_tuple! { C1, C2, C3, C4 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8 }
|
||||||
impl_bundle_tuple! { (C1, 0) (C2, 1) (C3, 2) (C4, 3) (C5, 4) (C6, 5) (C7, 6) (C8, 7) }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14 }
|
||||||
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, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15 }
|
||||||
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, 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() {
|
fn main() {
|
||||||
let mut world = World::new();
|
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 pos = Position2d(836, 348);
|
||||||
let _e = world.spawn((pos,));
|
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 std::{marker::PhantomData, any::TypeId, ptr::NonNull};
|
||||||
|
|
||||||
use crate::component::Component;
|
use super::{Fetch, Query, AsQuery, DefaultQuery};
|
||||||
|
|
||||||
use super::{Fetch, Query, AsQuery, IntoQuery, DefaultQuery};
|
|
||||||
|
|
||||||
pub struct FetchBorrow<'a, T> {
|
pub struct FetchBorrow<'a, T> {
|
||||||
ptr: NonNull<u8>,
|
ptr: NonNull<u8>,
|
||||||
|
@ -16,7 +14,7 @@ where
|
||||||
{
|
{
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
|
|
||||||
fn create_empty() -> Self {
|
fn dangling() -> Self {
|
||||||
FetchBorrow {
|
FetchBorrow {
|
||||||
ptr: NonNull::dangling(),
|
ptr: NonNull::dangling(),
|
||||||
size: 0,
|
size: 0,
|
||||||
|
@ -103,7 +101,7 @@ where
|
||||||
{
|
{
|
||||||
type Item = &'a mut T;
|
type Item = &'a mut T;
|
||||||
|
|
||||||
fn create_empty() -> Self {
|
fn dangling() -> Self {
|
||||||
FetchBorrowMut {
|
FetchBorrowMut {
|
||||||
ptr: NonNull::dangling(),
|
ptr: NonNull::dangling(),
|
||||||
size: 0,
|
size: 0,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{world::Entity, archetype::{Archetype, ArchetypeId}};
|
use crate::{world::Entity, archetype::{Archetype, ArchetypeId}};
|
||||||
|
|
||||||
use super::{Fetch, Query, DefaultQuery, AsQuery};
|
use super::{Fetch, Query};
|
||||||
|
|
||||||
pub struct EntitiesFetch<'a> {
|
pub struct EntitiesFetch<'a> {
|
||||||
entities: &'a [Entity],
|
entities: &'a [Entity],
|
||||||
|
@ -14,7 +14,7 @@ impl<'a> Fetch<'a> for EntitiesFetch<'a> {
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_empty() -> Self {
|
fn dangling() -> Self {
|
||||||
Self {
|
Self {
|
||||||
entities: &[],
|
entities: &[],
|
||||||
}
|
}
|
||||||
|
@ -29,22 +29,14 @@ impl Query for Entities {
|
||||||
type Fetch<'a> = EntitiesFetch<'a>;
|
type Fetch<'a> = EntitiesFetch<'a>;
|
||||||
|
|
||||||
fn can_visit_archetype(&self, archetype: &Archetype) -> bool {
|
fn can_visit_archetype(&self, archetype: &Archetype) -> bool {
|
||||||
|
let _ = archetype; // ignore unused warnings
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn fetch<'a>(&self, arch_id: ArchetypeId, archetype: &'a Archetype) -> Self::Fetch<'a> {
|
unsafe fn fetch<'a>(&self, arch_id: ArchetypeId, archetype: &'a Archetype) -> Self::Fetch<'a> {
|
||||||
|
let _ = arch_id; // ignore unused warnings
|
||||||
EntitiesFetch {
|
EntitiesFetch {
|
||||||
entities: &archetype.entities,
|
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, ArchetypeId}, world::ArchetypeEntityId};
|
||||||
|
|
||||||
use crate::{archetype::{Archetype, ComponentColumn, ArchetypeId}, bundle::Bundle, component::Component, world::{Record, EntityId, ArchetypeEntityId}};
|
|
||||||
|
|
||||||
pub mod view;
|
pub mod view;
|
||||||
pub use view::*;
|
pub use view::*;
|
||||||
|
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use entities::*;
|
pub use entities::*;
|
||||||
|
|
||||||
pub mod borrow;
|
pub mod borrow;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use borrow::*;
|
pub use borrow::*;
|
||||||
|
|
||||||
pub struct QuerySimple<'a> {
|
pub mod tuple;
|
||||||
//entities: Iter<Entity
|
#[allow(unused_imports)]
|
||||||
archetypes: Vec<&'a Archetype>,
|
pub use tuple::*;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A [`Fetch`]er implementation gets data out of an archetype.
|
/// A [`Fetch`]er implementation gets data out of an archetype.
|
||||||
pub trait Fetch<'a> {
|
pub trait Fetch<'a> {
|
||||||
|
@ -93,7 +27,7 @@ pub trait Fetch<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an empty Fetch. DO NOT try to `get_item` on this
|
/// 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;
|
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 {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
ViewIter {
|
ViewIter {
|
||||||
query: self.query,
|
query: self.query,
|
||||||
fetcher: Q::Fetch::create_empty(),
|
fetcher: Q::Fetch::dangling(),
|
||||||
archetypes: self.archetypes,
|
archetypes: self.archetypes,
|
||||||
next_archetype: 0,
|
next_archetype: 0,
|
||||||
component_indices: 0..0,
|
component_indices: 0..0,
|
||||||
|
|
|
@ -13,4 +13,21 @@ impl Vec2 {
|
||||||
y,
|
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::collections::{HashMap, VecDeque};
|
||||||
use std::slice::Iter;
|
|
||||||
|
|
||||||
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)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct EntityId(pub u64);
|
pub struct EntityId(pub u64);
|
||||||
|
@ -60,7 +59,7 @@ impl World {
|
||||||
where
|
where
|
||||||
B: Bundle
|
B: Bundle
|
||||||
{
|
{
|
||||||
let bundle_types = bundle.types();
|
let bundle_types = bundle.type_ids();
|
||||||
let new_entity = self.get_new_entity();
|
let new_entity = self.get_new_entity();
|
||||||
|
|
||||||
// try to find an archetype
|
// try to find an archetype
|
||||||
|
@ -102,30 +101,11 @@ impl World {
|
||||||
new_entity
|
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> {
|
pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> {
|
||||||
let archetypes = self.archetypes.values().collect();
|
let archetypes = self.archetypes.values().collect();
|
||||||
let v = View::new(T::default_query(), archetypes);
|
let v = View::new(T::default_query(), archetypes);
|
||||||
v.into_iter()
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -144,7 +124,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn query_entities() {
|
fn world_view_entities() {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.spawn((Vec2 {
|
world.spawn((Vec2 {
|
||||||
x: 10.0,
|
x: 10.0,
|
||||||
|
|
Loading…
Reference in New Issue