Dynamically typed bundles and archetypes
This commit is contained in:
parent
e867aaeadb
commit
a1ca2789ce
|
@ -311,9 +311,11 @@ impl Archetype {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::{alloc::Layout, ptr::NonNull};
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::{tests::{Vec2, Vec3}, world::{Entity, EntityId}, bundle::{Bundle, self}};
|
use crate::{tests::{Vec2, Vec3}, world::{Entity, EntityId}, bundle::{Bundle, self}, ComponentInfo, MemoryLayout, DynTypeId, DynamicBundle};
|
||||||
|
|
||||||
use super::Archetype;
|
use super::Archetype;
|
||||||
|
|
||||||
|
@ -486,4 +488,31 @@ mod tests {
|
||||||
let comp = unsafe { col.get::<Vec2>(1) };
|
let comp = unsafe { col.get::<Vec2>(1) };
|
||||||
assert_eq!(comp.clone(), bundles[2]);
|
assert_eq!(comp.clone(), bundles[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This test simulates an archetype that stores types that rust does not know about.
|
||||||
|
#[test]
|
||||||
|
fn dynamic_archetype() {
|
||||||
|
let layout = MemoryLayout::from(Layout::new::<u32>());
|
||||||
|
let info = ComponentInfo::new_unknown(DynTypeId::Unknown(100), "u32", layout);
|
||||||
|
let infos = vec![info.clone()];
|
||||||
|
|
||||||
|
let mut a = Archetype::from_bundle_info(super::ArchetypeId(0), infos);
|
||||||
|
|
||||||
|
let mut dynamic_bundle = DynamicBundle::default();
|
||||||
|
let comp = 50u32;
|
||||||
|
let ptr = NonNull::from(&comp).cast::<u8>();
|
||||||
|
dynamic_bundle.push_unknown(ptr, info.clone());
|
||||||
|
|
||||||
|
a.add_entity(
|
||||||
|
Entity {
|
||||||
|
id: EntityId(0),
|
||||||
|
generation: 0
|
||||||
|
}, dynamic_bundle
|
||||||
|
);
|
||||||
|
|
||||||
|
let col = a.columns.iter().next().unwrap();
|
||||||
|
let ptr = col.borrow_ptr();
|
||||||
|
assert_eq!(unsafe { *ptr.cast::<u32>().as_ref() }, comp);
|
||||||
|
assert_eq!(col.info, info);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -71,3 +71,47 @@ 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 }
|
||||||
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 }
|
||||||
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16 }
|
impl_bundle_tuple! { C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16 }
|
||||||
|
|
||||||
|
/// A bundle of components
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DynamicBundle {
|
||||||
|
bundle: Vec<(NonNull<u8>, ComponentInfo)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicBundle {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Push a type known to rust to this bundle
|
||||||
|
pub fn push<C>(&mut self, comp: C)
|
||||||
|
where
|
||||||
|
C: Component
|
||||||
|
{
|
||||||
|
let info = ComponentInfo::new::<C>();
|
||||||
|
let data = NonNull::from(&comp).cast::<u8>();
|
||||||
|
|
||||||
|
self.bundle.push((data, info));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Push an unknown type to the bundle
|
||||||
|
pub fn push_unknown(&mut self, data: NonNull<u8>, info: ComponentInfo) {
|
||||||
|
self.bundle.push((data, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bundle for DynamicBundle {
|
||||||
|
fn type_ids(&self) -> Vec<DynTypeId> {
|
||||||
|
self.bundle.iter().map(|b| b.1.type_id).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn info(&self) -> Vec<ComponentInfo> {
|
||||||
|
self.bundle.iter().map(|b| b.1.clone()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take(self, mut f: impl FnMut(NonNull<u8>, DynTypeId, usize)) {
|
||||||
|
for (data, info) in self.bundle.iter() {
|
||||||
|
f(data.clone(), info.type_id, info.layout.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{any::{TypeId, type_name}, alloc::{Layout, LayoutError}};
|
use std::{any::{TypeId, type_name}, alloc::{Layout, LayoutError}};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct MemoryLayout {
|
pub struct MemoryLayout {
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
pub alignment: usize
|
pub alignment: usize
|
||||||
|
@ -61,7 +61,7 @@ impl DynTypeId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct ComponentInfo {
|
pub struct ComponentInfo {
|
||||||
pub type_id: DynTypeId,
|
pub type_id: DynTypeId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
Loading…
Reference in New Issue