#![feature(trait_upcasting)] use std::{any::TypeId, any::Any, cell::{Ref, RefMut}}; use lyra_ecs::{world::World, DynamicBundle, Component, Entity, ComponentInfo}; extern crate self as lyra_reflect; pub use lyra_reflect_derive::*; #[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::*; pub mod impls; 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`] fn clone_inner(&self) -> Box; /// 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::() == 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> { 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, } } } #[allow(dead_code)] pub struct Value { inner: Box, type_id: TypeId, ref_type_id: TypeId, } impl Value { pub fn new(val: T) -> Self { Self { inner: Box::new(val), type_id: TypeId::of::(), ref_type_id: TypeId::of::<&T>(), } } /// Remove the stored object from Value pub fn take(self) -> Option { (self.inner as Box).downcast::().ok().map(|v| *v) } pub fn get(&self) -> Option<&T> { self.inner.as_any().downcast_ref::() } pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.as_any_mut().downcast_mut::() } } pub trait IntoValue { fn into_value(self) -> Value; fn type_id() -> TypeId; } impl IntoValue for T { fn into_value(self) -> Value { Value::new(self) } fn type_id() -> TypeId { TypeId::of::() } } pub trait FromType { 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, /// 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>, fn_reflect_mut: for<'a> fn (world: &'a mut World, entity: Entity) -> Option>, } 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> { (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> { (self.fn_reflect_mut)(world, entity) } } impl FromType for ReflectedComponent { fn from_type() -> Self { ReflectedComponent { type_id: TypeId::of::(), info: ComponentInfo::new::(), 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) }, fn_reflect_mut: |world: &mut World, entity: Entity| { world.view_one::<&mut C>(entity) .get().map(|c| c as RefMut) }, } } }