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 {
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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