88 lines
3.2 KiB
Rust
88 lines
3.2 KiB
Rust
use std::{any::{Any, TypeId}, ptr::NonNull};
|
|
|
|
use lyra_ecs::{AtomicRef, AtomicRefMut, ResourceObject, Tick, World};
|
|
|
|
use crate::{Reflect, FromType};
|
|
|
|
#[derive(Clone)]
|
|
pub struct ReflectedResource {
|
|
pub type_id: TypeId,
|
|
|
|
fn_reflect: for<'a> fn (world: &'a World) -> Option<AtomicRef<'a, dyn Reflect>>,
|
|
fn_reflect_tick: for<'a> fn (world: &'a World) -> Option<Tick>,
|
|
fn_reflect_is_changed: fn (world: &World) -> Option<bool>,
|
|
fn_reflect_mut: for<'a> fn (world: &'a mut World) -> Option<AtomicRefMut<'a, dyn Reflect>>,
|
|
fn_reflect_ptr: fn (world: &mut World) -> Option<NonNull<u8>>,
|
|
fn_refl_insert: fn (world: &mut World, this: Box<dyn Reflect>),
|
|
}
|
|
|
|
impl ReflectedResource {
|
|
/// Retrieves the reflected resource from the world.
|
|
pub fn reflect<'a>(&self, world: &'a World) -> Option<AtomicRef<'a, dyn Reflect>> {
|
|
(self.fn_reflect)(world)
|
|
}
|
|
|
|
pub fn reflect_tick(&self, world: &World) -> Option<Tick> {
|
|
(self.fn_reflect_tick)(world)
|
|
}
|
|
|
|
pub fn reflect_is_changed(&self, world: &World) -> Option<bool> {
|
|
(self.fn_reflect_is_changed)(world)
|
|
}
|
|
|
|
/// Retrieves a mutable reflected resource from the world.
|
|
pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option<AtomicRefMut<'a, dyn Reflect>> {
|
|
(self.fn_reflect_mut)(world)
|
|
}
|
|
|
|
pub fn reflect_ptr(&self, world: &mut World) -> Option<NonNull<u8>> {
|
|
(self.fn_reflect_ptr)(world)
|
|
}
|
|
|
|
/// Insert the resource into the world.
|
|
pub fn insert(&self, world: &mut World, this: Box<dyn Reflect>) {
|
|
(self.fn_refl_insert)(world, this)
|
|
}
|
|
}
|
|
|
|
impl<T: ResourceObject + Reflect> FromType<T> for ReflectedResource {
|
|
fn from_type() -> Self {
|
|
Self {
|
|
type_id: TypeId::of::<T>(),
|
|
fn_reflect: |world: &World| {
|
|
world.get_resource::<T>()
|
|
.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_tick: |world: &World| {
|
|
world.get_resource_tick::<T>()
|
|
},
|
|
fn_reflect_is_changed: |world: &World| {
|
|
world.get_resource::<T>()
|
|
.map(|r| r.changed())
|
|
},
|
|
fn_reflect_mut: |world: &mut World| {
|
|
world.get_resource_mut::<T>()
|
|
.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::<T>()
|
|
.map(|ptr| ptr.cast::<u8>())
|
|
},
|
|
fn_refl_insert: |world: &mut World, this: Box<dyn Reflect>| {
|
|
let res = this as Box<dyn Any>;
|
|
let res = res.downcast::<T>()
|
|
.expect("Provided a non-matching type to ReflectedResource insert method!");
|
|
let res = *res;
|
|
world.add_resource(res);
|
|
}
|
|
}
|
|
}
|
|
} |