Dynamically typed bundles and archetypes
This commit is contained in:
parent
e867aaeadb
commit
a1ca2789ce
|
@ -311,9 +311,11 @@ impl Archetype {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{alloc::Layout, ptr::NonNull};
|
||||
|
||||
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;
|
||||
|
||||
|
@ -486,4 +488,31 @@ mod tests {
|
|||
let comp = unsafe { col.get::<Vec2>(1) };
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -70,4 +70,48 @@ 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 }
|
||||
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}};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct MemoryLayout {
|
||||
pub size: usize,
|
||||
pub alignment: usize
|
||||
|
@ -61,7 +61,7 @@ impl DynTypeId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ComponentInfo {
|
||||
pub type_id: DynTypeId,
|
||||
pub name: String,
|
||||
|
|
Loading…
Reference in New Issue