2023-12-30 23:55:05 +00:00
|
|
|
#![feature(trait_upcasting)]
|
|
|
|
|
|
|
|
use std::{any::TypeId, any::Any, cell::{Ref, RefMut}};
|
|
|
|
|
2024-01-06 20:52:12 +00:00
|
|
|
use lyra_ecs::{world::World, DynamicBundle, Component, Entity, ComponentInfo};
|
2023-12-30 23:55:05 +00:00
|
|
|
|
|
|
|
extern crate self as lyra_reflect;
|
|
|
|
|
2024-01-12 19:08:46 +00:00
|
|
|
pub use lyra_reflect_derive::*;
|
|
|
|
|
2023-12-30 23:55:05 +00:00
|
|
|
#[allow(unused_imports)]
|
|
|
|
pub(crate) mod lyra_engine {
|
|
|
|
pub(crate) mod reflect {
|
|
|
|
pub use super::super::*;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod reflected_struct;
|
|
|
|
pub use reflected_struct::*;
|
|
|
|
|
|
|
|
pub mod reflected_enum;
|
|
|
|
pub use reflected_enum::*;
|
|
|
|
|
|
|
|
pub mod reflected_tuple;
|
|
|
|
pub use reflected_tuple::*;
|
|
|
|
|
|
|
|
pub mod reflected_array;
|
|
|
|
pub use reflected_array::*;
|
|
|
|
|
|
|
|
pub mod reflected_list;
|
|
|
|
pub use reflected_list::*;
|
|
|
|
|
|
|
|
pub mod dynamic_tuple;
|
|
|
|
pub use dynamic_tuple::*;
|
|
|
|
|
|
|
|
pub mod reflected_field;
|
|
|
|
pub use reflected_field::*;
|
|
|
|
|
|
|
|
pub mod util;
|
|
|
|
pub mod field;
|
|
|
|
pub use field::*;
|
|
|
|
pub mod method;
|
|
|
|
pub use method::*;
|
|
|
|
pub mod registry;
|
|
|
|
pub use registry::*;
|
|
|
|
|
2024-01-12 19:08:46 +00:00
|
|
|
pub mod impls;
|
2023-12-30 23:55:05 +00:00
|
|
|
|
|
|
|
pub trait Reflect: Any {
|
|
|
|
fn name(&self) -> String;
|
|
|
|
fn type_id(&self) -> TypeId;
|
|
|
|
|
|
|
|
fn as_any(&self) -> &dyn Any;
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
|
|
|
|
|
|
|
/// Apply a value to this object.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// The method panics if
|
|
|
|
/// * the type of `val` is not the same type as `self`
|
|
|
|
fn apply(&mut self, val: &dyn Reflect);
|
|
|
|
|
|
|
|
/// Clone self into a [`Box<dyn Reflect>`]
|
|
|
|
fn clone_inner(&self) -> Box<dyn Reflect>;
|
|
|
|
|
|
|
|
/// Returns a reflected reference of the value of `self`
|
|
|
|
fn reflect_ref(&self) -> ReflectRef;
|
|
|
|
|
|
|
|
/// Returns a reflected mutable reference of the value of `self`
|
|
|
|
fn reflect_mut(&mut self) -> ReflectMut;
|
|
|
|
|
|
|
|
fn reflect_val(&self) -> &dyn Reflect;
|
|
|
|
|
|
|
|
fn reflect_val_mut(&mut self) -> &mut dyn Reflect;
|
|
|
|
|
|
|
|
/// Returns a boolean indicating if this reflected object is `other_typeid`
|
|
|
|
///
|
|
|
|
/// I can't use a generic here because this trait needs to be object safe
|
|
|
|
fn is(&self, other_typeid: TypeId) -> bool {
|
|
|
|
TypeId::of::<Self>() == other_typeid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ReflectRef<'a> {
|
|
|
|
Struct(&'a dyn Struct),
|
|
|
|
Enum(&'a dyn Enum),
|
|
|
|
Tuple(&'a dyn Tuple),
|
|
|
|
Array(&'a dyn Array),
|
|
|
|
List(&'a dyn List),
|
|
|
|
Value(&'a dyn Reflect),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ReflectRef<'a> {
|
|
|
|
/// Gets the reflected reference as a struct.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// * If `self` is not a `Struct` variant, this will panic
|
|
|
|
pub fn as_struct(&self) -> &dyn Struct {
|
|
|
|
match self {
|
|
|
|
ReflectRef::Struct(s) => *s,
|
|
|
|
_ => panic!("`self` is not a struct variant!"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ReflectMut<'a> {
|
|
|
|
Struct(&'a mut dyn Struct),
|
|
|
|
Enum(&'a mut dyn Enum),
|
|
|
|
Tuple(&'a mut dyn Tuple),
|
|
|
|
Array(&'a mut dyn Array),
|
|
|
|
List(&'a mut dyn List),
|
|
|
|
Value(&'a mut dyn Reflect),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ReflectMut<'a> {
|
|
|
|
/// Retrieves self as a [`ReflectRef`].
|
|
|
|
pub fn as_ref(&self) -> ReflectRef {
|
|
|
|
match self {
|
|
|
|
ReflectMut::Struct(v) => ReflectRef::Struct(*v),
|
|
|
|
ReflectMut::Enum(v) => ReflectRef::Enum(*v),
|
|
|
|
ReflectMut::Tuple(v) => ReflectRef::Tuple(*v),
|
|
|
|
ReflectMut::Array(v) => ReflectRef::Array(*v),
|
|
|
|
ReflectMut::List(v) => ReflectRef::List(*v),
|
|
|
|
ReflectMut::Value(v) => ReflectRef::Value(*v),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the reflected reference as a struct.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// * If `self` is not a `Struct` variant, this will panic
|
|
|
|
pub fn as_struct(&self) -> &dyn Struct {
|
|
|
|
match self {
|
|
|
|
ReflectMut::Struct(s) => *s,
|
|
|
|
_ => panic!("`self` is not a struct variant!"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the reflected reference mutable as a struct.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// * If `self` is not a `Struct` variant, this will panic
|
|
|
|
pub fn as_struct_mut(&mut self) -> &mut dyn Struct {
|
|
|
|
match self {
|
|
|
|
ReflectMut::Struct(s) => *s,
|
|
|
|
_ => panic!("`self` is not a struct variant!"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ReflectEither<'a> {
|
|
|
|
Ref(ReflectRef<'a>),
|
|
|
|
Mut(ReflectMut<'a>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ReflectEither<'a> {
|
|
|
|
/// Converts `self` into a [`ReflectRef`]. Both variants can be retrieved as a reference.
|
|
|
|
/* pub fn into_ref(self) -> ReflectRef<'a> {
|
|
|
|
match self {
|
|
|
|
Self::Ref(v) => v,
|
|
|
|
Self::Mut(v) => v.as_ref()
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
|
|
|
|
/// Attempts to get `self` as a [`ReflectMut`].
|
|
|
|
///
|
|
|
|
/// If `self` is a `Ref`, `None` will be returned
|
|
|
|
pub fn try_into_mut(self) -> Option<ReflectMut<'a>> {
|
|
|
|
match self {
|
|
|
|
Self::Mut(v) => Some(v),
|
|
|
|
Self::Ref(_) => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pub fn as_ref(&self) -> &ReflectRef<'a> {
|
|
|
|
match self {
|
|
|
|
Self::Ref(v) => v,
|
|
|
|
Self::Mut(v) => &v.as_ref()
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
|
|
|
|
pub fn is_mut(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
ReflectEither::Ref(_) => false,
|
|
|
|
ReflectEither::Mut(_) => true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-06 20:52:12 +00:00
|
|
|
#[allow(dead_code)]
|
2023-12-30 23:55:05 +00:00
|
|
|
pub struct Value {
|
|
|
|
inner: Box<dyn Reflect>,
|
|
|
|
type_id: TypeId,
|
|
|
|
ref_type_id: TypeId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Value {
|
|
|
|
pub fn new<T: Reflect>(val: T) -> Self {
|
|
|
|
Self {
|
|
|
|
inner: Box::new(val),
|
|
|
|
type_id: TypeId::of::<T>(),
|
|
|
|
ref_type_id: TypeId::of::<&T>(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove the stored object from Value
|
|
|
|
pub fn take<T: Reflect>(self) -> Option<T> {
|
|
|
|
(self.inner as Box<dyn Any>).downcast::<T>().ok().map(|v| *v)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get<T: Reflect>(&self) -> Option<&T> {
|
|
|
|
self.inner.as_any().downcast_ref::<T>()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_mut<T: Reflect>(&mut self) -> Option<&mut T> {
|
|
|
|
self.inner.as_any_mut().downcast_mut::<T>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait IntoValue {
|
|
|
|
fn into_value(self) -> Value;
|
|
|
|
fn type_id() -> TypeId;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Reflect> IntoValue for T {
|
|
|
|
fn into_value(self) -> Value {
|
|
|
|
Value::new(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn type_id() -> TypeId {
|
|
|
|
TypeId::of::<T>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FromType<T> {
|
|
|
|
fn from_type() -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ReflectedComponent {
|
|
|
|
pub type_id: TypeId,
|
|
|
|
pub info: ComponentInfo,
|
|
|
|
//value: Value,
|
|
|
|
//from_world:
|
|
|
|
|
|
|
|
//from_world: for<'a> fn (world: &'a mut World) -> Box<dyn Reflect>,
|
|
|
|
/// Inserts component into entity in the world
|
|
|
|
fn_insert: for<'a> fn (world: &'a mut World, entity: Entity, component: &dyn Reflect),
|
|
|
|
/// Inserts component into a bundle
|
|
|
|
fn_bundle_insert: for<'a> fn (dynamic_bundle: &'a mut DynamicBundle, component: &dyn Reflect),
|
|
|
|
fn_reflect: for<'a> fn (world: &'a World, entity: Entity) -> Option<Ref<'a, dyn Reflect>>,
|
|
|
|
fn_reflect_mut: for<'a> fn (world: &'a mut World, entity: Entity) -> Option<RefMut<'a, dyn Reflect>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ReflectedComponent {
|
|
|
|
/// Insert the reflected component into an entity.
|
|
|
|
pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
|
|
|
(self.fn_insert)(world, entity, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert this component into a DynamicBundle
|
|
|
|
pub fn bundle_insert(&self, dynamic_bundle: &mut DynamicBundle, component: &dyn Reflect) {
|
|
|
|
(self.fn_bundle_insert)(dynamic_bundle, component)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieves a reflected component from an entity.
|
|
|
|
pub fn reflect<'a>(&'a self, world: &'a World, entity: Entity) -> Option<Ref<'a, dyn Reflect>> {
|
|
|
|
(self.fn_reflect)(world, entity)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieves a reflected component from an entity.
|
|
|
|
pub fn reflect_mut<'a>(&'a mut self, world: &'a mut World, entity: Entity) -> Option<RefMut<'a, dyn Reflect>> {
|
|
|
|
(self.fn_reflect_mut)(world, entity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: Component + Reflect + Default> FromType<C> for ReflectedComponent {
|
|
|
|
fn from_type() -> Self {
|
|
|
|
ReflectedComponent {
|
|
|
|
type_id: TypeId::of::<C>(),
|
|
|
|
info: ComponentInfo::new::<C>(),
|
|
|
|
fn_insert: |world: &mut World, entity: Entity, component: &dyn Reflect| {
|
|
|
|
let mut c = C::default();
|
|
|
|
c.apply(component);
|
|
|
|
world.insert(entity, (c,));
|
|
|
|
},
|
|
|
|
fn_bundle_insert: |bundle: &mut DynamicBundle, component: &dyn Reflect| {
|
|
|
|
let mut c = C::default();
|
|
|
|
c.apply(component);
|
|
|
|
bundle.push(c);
|
|
|
|
},
|
|
|
|
fn_reflect: |world: &World, entity: Entity| {
|
|
|
|
world.view_one::<&C>(entity)
|
|
|
|
.get().map(|c| c as Ref<dyn Reflect>)
|
|
|
|
},
|
|
|
|
fn_reflect_mut: |world: &mut World, entity: Entity| {
|
|
|
|
world.view_one::<&mut C>(entity)
|
|
|
|
.get().map(|c| c as RefMut<dyn Reflect>)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|