diff --git a/lyra-ecs/src/component_info.rs b/lyra-ecs/src/component_info.rs index 476d530..179e24c 100644 --- a/lyra-ecs/src/component_info.rs +++ b/lyra-ecs/src/component_info.rs @@ -49,16 +49,42 @@ impl Into for u128 { } } -impl From for DynTypeId { +impl Into for TypeId { + fn into(self) -> DynTypeId { + DynTypeId::Rust(self) + } +} + +/* impl From for DynTypeId { fn from(value: TypeId) -> Self { DynTypeId::Rust(value) } -} +} */ impl DynTypeId { pub fn of() -> Self { Self::Rust(TypeId::of::()) } + + pub fn is(&self) -> bool { + match self { + DynTypeId::Rust(tyid) => tyid.clone() == TypeId::of::(), + DynTypeId::Unknown(_) => false, + } + } + + pub fn is_id>(&self, id: I) -> bool { + let id = id.into(); + *self == id + } + + /// Force self into a rust TypeId, will panic if this type is not a Rust type. + pub fn as_rust(&self) -> TypeId { + match self { + DynTypeId::Rust(t) => t.clone(), + DynTypeId::Unknown(_) => panic!("This type is unknown to rust, cannot construct a TypeId from it!"), + } + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -71,7 +97,7 @@ pub struct ComponentInfo { impl ComponentInfo { pub fn new() -> Self { Self { - type_id: DynTypeId::from(TypeId::of::()), + type_id: TypeId::of::().into(), //name: type_name::().to_string(), layout: MemoryLayout::from(Layout::new::()), } diff --git a/lyra-ecs/src/query/dynamic/mod.rs b/lyra-ecs/src/query/dynamic/mod.rs index 3ba11a3..65d7f3c 100644 --- a/lyra-ecs/src/query/dynamic/mod.rs +++ b/lyra-ecs/src/query/dynamic/mod.rs @@ -11,6 +11,12 @@ pub struct DynamicType { pub ptr: NonNull, } +impl DynamicType { + pub fn is(&self) -> bool { + self.info.type_id.is::() + } +} + /// A struct that fetches some dynamic type. /// /// Currently it can only fetch from archetypes, later it will be able to fetch dynamic diff --git a/lyra-ecs/src/query/dynamic/view.rs b/lyra-ecs/src/query/dynamic/view.rs index 2ef7b96..6a314c4 100644 --- a/lyra-ecs/src/query/dynamic/view.rs +++ b/lyra-ecs/src/query/dynamic/view.rs @@ -42,7 +42,7 @@ impl<'a> IntoIterator for DynamicView<'a> { } pub struct DynamicViewIter<'a> { - world: &'a World, + pub world: &'a World, queries: Vec, fetchers: Vec>, archetypes: Vec<&'a Archetype>, diff --git a/lyra-ecs/src/resource.rs b/lyra-ecs/src/resource.rs index 71097f3..54551b4 100644 --- a/lyra-ecs/src/resource.rs +++ b/lyra-ecs/src/resource.rs @@ -1,79 +1,58 @@ -use std::{any::TypeId, alloc::Layout, cell::{RefCell, Ref, RefMut}, ptr::NonNull, alloc}; +use std::{any::{TypeId, Any}, alloc::Layout, cell::{RefCell, Ref, RefMut}, ptr::NonNull, alloc}; /// Shorthand for `Send + Sync + 'static`, so it never needs to be implemented manually. pub trait ResourceObject: Send + Sync + 'static {} impl ResourceObject for T {} /// A type erased storage for a Resource. -/// -/// A pointer instead of a generic is used since Rust may have no idea of the type of the data. pub struct ResourceData { - data: RefCell>, + data: Box>, type_id: TypeId, - layout: Layout, } impl ResourceData { - pub fn new(data: T) -> Self { - let layout = Layout::new::(); - let data = NonNull::from(&data).cast(); - - let ptr = unsafe { - if let Some(ptr) = NonNull::new(alloc::alloc(layout)) { - std::ptr::copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), layout.size()); - ptr - } else { - alloc::handle_alloc_error(layout) - } - }; + pub fn new(data: T) -> Self { Self { - data: RefCell::new(ptr), + data: Box::new(RefCell::new(data)), type_id: TypeId::of::(), - layout, } } - /// Returns a boolean indicating whether or not T is of the same type that is inside this Resource + /// Returns a boolean indicating whether or not `T`` is of the same type of the Resource pub fn is(&self) -> bool { self.type_id == TypeId::of::() } /// Borrow the data inside of the resource. /// - /// # Safety + /// # Panics /// - /// If the type of T is not the same as the expected type, it will panic. + /// * If the data is already borrowed mutably, this will panic. + /// * If the type of `T` is not the same as the resource type. pub fn get<'a, T: 'static>(&'a self) -> Ref<'a, T> { - assert!(TypeId::of::() == self.type_id); - - let data = self.data.borrow(); - Ref::map(data, |ptr| unsafe { &*ptr.cast().as_ptr() }) + Ref::map(self.data.borrow(), |a| a.downcast_ref().unwrap()) } /// Mutably borrow the data inside of the resource. /// /// # Panics /// - /// * If the type of T is not the same as the expected type, it will panic. /// * If the data is already borrowed mutably, this will panic. + /// * If the type of `T` is not the same as the resource type. pub fn get_mut<'a, T: 'static>(&'a self) -> RefMut<'a, T> { - assert!(TypeId::of::() == self.type_id); - - let data = self.data.borrow_mut(); - RefMut::map(data, |ptr| unsafe { &mut *ptr.cast().as_ptr() }) + RefMut::map(self.data.borrow_mut(), |a| a.downcast_mut().unwrap()) } /// Borrow the data inside of the resource. /// - /// # Safety + /// # Panics /// - /// If the type of T is not the same as the expected type, it will panic. + /// * If the type of `T` is not the same as the resource type. pub fn try_get<'a, T: 'static>(&'a self) -> Option> { - assert!(TypeId::of::() == self.type_id); self.data.try_borrow() - .map(|r| Ref::map(r, |ptr| unsafe { &*ptr.cast().as_ptr() })) + .map(|r| Ref::map(r, |a| a.downcast_ref().unwrap())) .ok() } @@ -81,13 +60,10 @@ impl ResourceData { /// /// # Panics /// - /// * If the type of T is not the same as the expected type, it will panic. - /// * If the data is already borrowed mutably, this will panic. + /// * If the type of `T` is not the same as the resource type. pub fn try_get_mut<'a, T: 'static>(&'a self) -> Option> { - assert!(TypeId::of::() == self.type_id); - self.data.try_borrow_mut() - .map(|r| RefMut::map(r, |ptr| unsafe { &mut *ptr.cast().as_ptr() })) + .map(|r| RefMut::map(r, |a| a.downcast_mut().unwrap())) .ok() } } \ No newline at end of file