diff --git a/src/system.rs b/src/system.rs index d59e3fc..7903e11 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,4 +1,6 @@ +use std::alloc::{Layout, handle_alloc_error}; use std::ffi::c_void; +use std::slice::from_raw_parts; use crate::cache::WorldInfoCache; use crate::*; @@ -45,6 +47,7 @@ pub struct SystemBuilder<'w> { // we need to keep these in memory until after build name_temp: String, expr_temp: String, + set_context: bool, next_term_index: usize, } @@ -78,9 +81,32 @@ impl<'w> SystemBuilder<'w> { name_temp: "".to_owned(), expr_temp: "".to_owned(), next_term_index: 0, + set_context: false, } } + pub fn context(mut self, value:T) -> Self { + assert!(!self.set_context); + let layout = Layout::new::(); + unsafe { + let ptr = std::alloc::alloc(layout); + if ptr.is_null() { + handle_alloc_error(layout); + } + *(ptr as *mut T) = value; + self.desc.ctx = ptr.cast::(); + }; + self.set_context = true; + self + } + + pub fn context_ptr(mut self, ptr: *mut c_void) -> Self { + assert!(!self.set_context); + self.desc.ctx = ptr; + self.set_context = true; + self + } + pub fn named(mut self, name: &str) -> Self { self.name_temp = name.to_owned(); self @@ -297,6 +323,13 @@ impl Iter { Self::get_field::(self, index) } + pub unsafe fn get_context<'a, T>(&'a self) -> &'a T { + let context = (*self.it).ctx.cast::() + .as_ref() + .unwrap(); + &context + } + fn get_field(&self, index: i32) -> Column { // validate that types match. could avoid this in Release builds perhaps to get max perf let field_id = unsafe { ecs_field_id(self.it, index) }; @@ -358,6 +391,12 @@ impl Iter { ColumnDynamic::new(array, count, size, is_shared) } + + #[inline] + pub fn raw_fields<'a>(&'a self) -> &'a [ecs_term_t] { + let terms = unsafe { (*self.it).terms }; + unsafe { from_raw_parts(terms, self.field_count() as usize) } + } } pub type SystemCallback = unsafe extern "C" fn(*mut ecs_iter_t); @@ -432,11 +471,6 @@ impl ColumnDynamic { ColumnDynamic { array, count, element_size, is_shared } } - #[inline] - pub fn count(&self) -> usize { - self.count - } - pub fn element_size(&self) -> usize { self.element_size }