ecs: create DynamicViewOne
CI / build (push) Failing after 11m20s
Details
CI / build (push) Failing after 11m20s
Details
This commit is contained in:
parent
256025849e
commit
60c139f9b2
|
@ -12,6 +12,13 @@ pub struct Entity {
|
|||
}
|
||||
|
||||
impl Entity {
|
||||
pub fn new(id: EntityId, gen: u64) -> Self {
|
||||
Self {
|
||||
id,
|
||||
generation: gen,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> EntityId {
|
||||
self.id
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::{World, ComponentColumn, ComponentInfo};
|
|||
mod view;
|
||||
pub use view::*;
|
||||
|
||||
mod view_one;
|
||||
pub use view_one::*;
|
||||
|
||||
use super::Fetch;
|
||||
|
||||
/// Data that rust does not know the type of
|
||||
|
|
|
@ -57,11 +57,17 @@ pub struct 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<_>>();
|
||||
|
||||
loop {
|
||||
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![];
|
||||
|
||||
for fetcher in self.fetchers.iter_mut() {
|
||||
|
@ -78,11 +84,7 @@ impl DynamicViewStateIter {
|
|||
continue;
|
||||
}
|
||||
|
||||
let arch = archetypes.get(self.next_archetype-1).unwrap();
|
||||
return Some(DynamicViewItem {
|
||||
row: fetch_res,
|
||||
entity: arch.entity_at_index(ArchetypeEntityId(entity_index)).unwrap()
|
||||
})
|
||||
return Some((entity, fetch_res));
|
||||
} else {
|
||||
if self.next_archetype >= archetypes.len() {
|
||||
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
|
||||
/// Rust doesn't actually need to know the types of what its iterating over.
|
||||
impl<'a> IntoIterator for DynamicView<'a> {
|
||||
type Item = DynamicViewItem;
|
||||
type Item = (Entity, Vec<DynamicType>);
|
||||
|
||||
type IntoIter = DynamicViewIter<'a>;
|
||||
|
||||
|
@ -160,7 +162,7 @@ pub struct DynamicViewIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for DynamicViewIter<'a> {
|
||||
type Item = DynamicViewItem;
|
||||
type Item = (Entity, Vec<DynamicType>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next(&self.world)
|
||||
|
@ -193,8 +195,8 @@ mod tests {
|
|||
view.push(query);
|
||||
|
||||
let mut view_iter = view.into_iter();
|
||||
while let Some(view_row) = view_iter.next(&world) {
|
||||
assert_eq!(view_row.row.len(), 1);
|
||||
while let Some((_e, view_row)) = view_iter.next(&world) {
|
||||
assert_eq!(view_row.len(), 1);
|
||||
|
||||
let mut row_iter = view_row.row.iter();
|
||||
|
||||
|
@ -222,8 +224,8 @@ mod tests {
|
|||
let mut view = DynamicView::new(&world);
|
||||
view.push(query);
|
||||
|
||||
for view_row in view.into_iter() {
|
||||
assert_eq!(view_row.row.len(), 1);
|
||||
for (_e, view_row) in view.into_iter() {
|
||||
assert_eq!(view_row.len(), 1);
|
||||
|
||||
let mut row_iter = view_row.row.iter();
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue