use std::{any::{Any, TypeId}, ptr::NonNull}; use lyra_ecs::{AtomicRef, AtomicRefMut, ResourceObject, World}; use crate::{Reflect, FromType}; #[derive(Clone)] pub struct ReflectedResource { pub type_id: TypeId, fn_reflect: for<'a> fn (world: &'a World) -> Option>, fn_reflect_mut: for<'a> fn (world: &'a mut World) -> Option>, fn_reflect_ptr: fn (world: &mut World) -> Option>, fn_refl_insert: fn (world: &mut World, this: Box), } impl ReflectedResource { /// Retrieves the reflected resource from the world. pub fn reflect<'a>(&self, world: &'a World) -> Option> { (self.fn_reflect)(world) } /// Retrieves a mutable reflected resource from the world. pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option> { (self.fn_reflect_mut)(world) } pub fn reflect_ptr(&self, world: &mut World) -> Option> { (self.fn_reflect_ptr)(world) } /// Insert the resource into the world. pub fn insert(&self, world: &mut World, this: Box) { (self.fn_refl_insert)(world, this) } } impl FromType for ReflectedResource { fn from_type() -> Self { Self { type_id: TypeId::of::(), fn_reflect: |world: &World| { world.get_resource::() .map(|r| { // TODO: figure out change tracking for reflected resource let r = r.get_inner(); AtomicRef::map(r, |r| r as &dyn Reflect) }) }, fn_reflect_mut: |world: &mut World| { world.get_resource_mut::() .map(|r| { // TODO: figure out change tracking for reflected resource let r = r.get_inner(); AtomicRefMut::map(r, |r| r as &mut dyn Reflect) }) }, fn_reflect_ptr: |world: &mut World| unsafe { world.get_resource_ptr::() .map(|ptr| ptr.cast::()) }, fn_refl_insert: |world: &mut World, this: Box| { let res = this as Box; let res = res.downcast::() .expect("Provided a non-matching type to ReflectedResource insert method!"); let res = *res; world.add_resource(res); } } } }