ecs: create DynamicViewOne
CI / build (push) Failing after 11m20s Details

This commit is contained in:
SeanOMik 2024-09-02 19:29:37 -04:00
parent 256025849e
commit 60c139f9b2
5 changed files with 148 additions and 13 deletions

View File

@ -12,6 +12,13 @@ pub struct Entity {
} }
impl Entity { impl Entity {
pub fn new(id: EntityId, gen: u64) -> Self {
Self {
id,
generation: gen,
}
}
pub fn id(&self) -> EntityId { pub fn id(&self) -> EntityId {
self.id self.id
} }

View File

@ -5,6 +5,9 @@ use crate::{World, ComponentColumn, ComponentInfo};
mod view; mod view;
pub use view::*; pub use view::*;
mod view_one;
pub use view_one::*;
use super::Fetch; use super::Fetch;
/// Data that rust does not know the type of /// Data that rust does not know the type of

View File

@ -57,11 +57,17 @@ pub struct DynamicViewStateIter {
} }
impl DynamicViewStateIter { impl DynamicViewStateIter {
pub fn next(&mut self, world: &World) -> Option<DynamicViewItem> { pub fn next(&mut self, world: &World) -> Option<(Entity, Vec<DynamicType>)> {
let archetypes = world.archetypes.values().collect::<Vec<_>>(); let archetypes = world.archetypes.values().collect::<Vec<_>>();
loop { loop {
if let Some(entity_index) = self.component_indices.next() { if let Some(entity_index) = self.component_indices.next() {
let entity = {
let arch_id = self.next_archetype - 1;
let arch = unsafe { archetypes.get_unchecked(arch_id) };
arch.entity_at_index(ArchetypeEntityId(entity_index)).unwrap()
};
let mut fetch_res = vec![]; let mut fetch_res = vec![];
for fetcher in self.fetchers.iter_mut() { for fetcher in self.fetchers.iter_mut() {
@ -78,11 +84,7 @@ impl DynamicViewStateIter {
continue; continue;
} }
let arch = archetypes.get(self.next_archetype-1).unwrap(); return Some((entity, fetch_res));
return Some(DynamicViewItem {
row: fetch_res,
entity: arch.entity_at_index(ArchetypeEntityId(entity_index)).unwrap()
})
} else { } else {
if self.next_archetype >= archetypes.len() { if self.next_archetype >= archetypes.len() {
return None; // ran out of archetypes to go through return None; // ran out of archetypes to go through
@ -138,7 +140,7 @@ impl<'a> DynamicView<'a> {
/// This works great for a embedding with a scripting language (*cough* *cough* WASM) since /// This works great for a embedding with a scripting language (*cough* *cough* WASM) since
/// Rust doesn't actually need to know the types of what its iterating over. /// Rust doesn't actually need to know the types of what its iterating over.
impl<'a> IntoIterator for DynamicView<'a> { impl<'a> IntoIterator for DynamicView<'a> {
type Item = DynamicViewItem; type Item = (Entity, Vec<DynamicType>);
type IntoIter = DynamicViewIter<'a>; type IntoIter = DynamicViewIter<'a>;
@ -160,7 +162,7 @@ pub struct DynamicViewIter<'a> {
} }
impl<'a> Iterator for DynamicViewIter<'a> { impl<'a> Iterator for DynamicViewIter<'a> {
type Item = DynamicViewItem; type Item = (Entity, Vec<DynamicType>);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.inner.next(&self.world) self.inner.next(&self.world)
@ -193,8 +195,8 @@ mod tests {
view.push(query); view.push(query);
let mut view_iter = view.into_iter(); let mut view_iter = view.into_iter();
while let Some(view_row) = view_iter.next(&world) { while let Some((_e, view_row)) = view_iter.next(&world) {
assert_eq!(view_row.row.len(), 1); assert_eq!(view_row.len(), 1);
let mut row_iter = view_row.row.iter(); let mut row_iter = view_row.row.iter();
@ -222,8 +224,8 @@ mod tests {
let mut view = DynamicView::new(&world); let mut view = DynamicView::new(&world);
view.push(query); view.push(query);
for view_row in view.into_iter() { for (_e, view_row) in view.into_iter() {
assert_eq!(view_row.row.len(), 1); assert_eq!(view_row.len(), 1);
let mut row_iter = view_row.row.iter(); let mut row_iter = view_row.row.iter();

View File

@ -0,0 +1,123 @@
use crate::{query::Fetch, Entity, World};
use super::{DynamicType, FetchDynamicTypeUnsafe, QueryDynamicType};
/// A view of dynamic types (types that are not known to Rust).
///
/// This view gives you the ability to iterate over types that are unknown to Rust, which we call
/// dynamic types. This is great for embedding with a scripting language (*cough* *cough* WASM)
/// since Rust doesn't actually need to know the types of what its iterating over.
pub struct DynamicViewOne<'a> {
world: &'a World,
pub entity: Entity,
pub queries: Vec<QueryDynamicType>
}
impl<'a> DynamicViewOne<'a> {
pub fn new(world: &'a World, entity: Entity) -> Self {
Self {
world,
entity,
queries: vec![],
}
}
/// Create a new [`DynamicViewOne`] with queries.
pub fn new_with(world: &'a World, entity: Entity, queries: Vec<QueryDynamicType>) -> Self {
Self {
world,
entity,
queries
}
}
pub fn get(self) -> Option<Vec<DynamicType>> {
let arch = self.world.entity_archetype(self.entity)?;
let aid = arch.entity_indexes().get(&self.entity)?;
// get all fetchers for the queries
let mut fetchers: Vec<FetchDynamicTypeUnsafe> = self.queries.iter()
.map(|q| unsafe { q.fetch(self.world, arch.id(), arch) } )
.collect();
let mut fetch_res = vec![];
for fetcher in fetchers.iter_mut() {
if !fetcher.can_visit_item(*aid) {
return None;
} else {
let i = unsafe { fetcher.get_item(*aid) };
fetch_res.push(i);
}
}
if fetch_res.is_empty() {
None
} else {
Some(fetch_res)
}
}
}
#[cfg(test)]
mod tests {
use std::{alloc::Layout, ptr::NonNull};
use crate::{World, ComponentInfo, DynTypeId, DynamicBundle, query::dynamic::QueryDynamicType};
use super::DynamicViewOne;
#[test]
fn single_dynamic_view_one_state() {
let comp_layout = Layout::new::<u32>();
let comp_info = ComponentInfo::new_unknown(Some("u32".to_string()), DynTypeId::Unknown(100), comp_layout);
let mut dynamic_bundle = DynamicBundle::default();
let comp = 50u32;
let ptr = NonNull::from(&comp).cast::<u8>();
dynamic_bundle.push_unknown(ptr, comp_info.clone());
let mut world = World::new();
let e = world.spawn(dynamic_bundle);
let query = QueryDynamicType::from_info(comp_info);
let view = DynamicViewOne::new_with(&world, e, vec![query]);
let view_row = view.get()
.expect("failed to get entity row");
assert_eq!(view_row.len(), 1);
let mut row_iter = view_row.iter();
let dynamic_type = row_iter.next().unwrap();
let component_data = unsafe { dynamic_type.ptr.cast::<u32>().as_ref() };
assert_eq!(*component_data, 50);
}
#[test]
fn single_dynamic_view_one() {
let comp_layout = Layout::new::<u32>();
let comp_info = ComponentInfo::new_unknown(Some("u32".to_string()), DynTypeId::Unknown(100), comp_layout);
let mut dynamic_bundle = DynamicBundle::default();
let comp = 50u32;
let ptr = NonNull::from(&comp).cast::<u8>();
dynamic_bundle.push_unknown(ptr, comp_info.clone());
let mut world = World::new();
let e = world.spawn(dynamic_bundle);
let query = QueryDynamicType::from_info(comp_info);
let view = DynamicViewOne::new_with(&world, e, vec![query]);
let view_row = view.get()
.expect("failed to get entity row");
assert_eq!(view_row.len(), 1);
let mut row_iter = view_row.iter();
let dynamic_type = row_iter.next().unwrap();
let component_data = unsafe { dynamic_type.ptr.cast::<u32>().as_ref() };
assert_eq!(*component_data, 50);
}
}

@ -1 +1 @@
Subproject commit a761f4094bc18190285b4687ec804161fea874b6 Subproject commit 54c9926a04cdef657289fd67730c0b85d1bdda3e