Skip to content

Instantly share code, notes, and snippets.

@paul-hansen
Created July 27, 2023 07:21
Show Gist options
  • Save paul-hansen/c47f6af05732c0c03230fad5027f55e4 to your computer and use it in GitHub Desktop.
Save paul-hansen/c47f6af05732c0c03230fad5027f55e4 to your computer and use it in GitHub Desktop.
Use type_name for TypePath in Bevy 0.11
use bevy::prelude::*;
use bevy::reflect::utility::GenericTypePathCell;
use bevy::reflect::{TypePath, TypeRegistry, Typed};
use std::any::Any;
use std::marker::PhantomData;
struct Foo<T> {
_marker: PhantomData<T>,
}
#[allow(unused_mut)]
impl<T> bevy::reflect::GetTypeRegistration for Foo<T>
where
PhantomData<T>: Any + Send + Sync,
{
fn get_type_registration() -> bevy::reflect::TypeRegistration {
let mut registration = bevy::reflect::TypeRegistration::of::<Self>();
registration
.insert::<bevy::reflect::ReflectFromPtr>(bevy::reflect::FromType::<Self>::from_type());
registration.insert::<ReflectFromReflect>(bevy::reflect::FromType::<Self>::from_type());
let ignored_indices = ::core::iter::IntoIterator::into_iter([]);
registration.insert::<bevy::reflect::serde::SerializationData>(
bevy::reflect::serde::SerializationData::new(ignored_indices),
);
registration
}
}
impl<T> Typed for Foo<T>
where
PhantomData<T>: Any + Send + Sync,
{
fn type_info() -> &'static bevy::reflect::TypeInfo {
static CELL: bevy::reflect::utility::GenericTypeInfoCell =
bevy::reflect::utility::GenericTypeInfoCell::new();
CELL.get_or_insert::<Self, _>(|| {
let fields = [];
let info = bevy::reflect::StructInfo::new::<Self>("Foo", &fields);
bevy::reflect::TypeInfo::Struct(info)
})
}
}
impl<T> bevy::reflect::Reflect for Foo<T>
where
PhantomData<T>: Any + Send + Sync,
{
#[inline]
fn type_name(&self) -> &str {
core::any::type_name::<Self>()
}
#[inline]
fn get_represented_type_info(&self) -> Option<&'static bevy::reflect::TypeInfo> {
Some(<Self as Typed>::type_info())
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn bevy::reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy::reflect::Reflect {
self
}
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy::reflect::Reflect {
self
}
#[inline]
fn apply(&mut self, value: &dyn bevy::reflect::Reflect) {
if let bevy::reflect::ReflectRef::Struct(struct_value) = Reflect::reflect_ref(value) {
for (i, value) in Iterator::enumerate(Struct::iter_fields(struct_value)) {
let name = Struct::name_at(struct_value, i).unwrap();
if let Some(v) = Struct::field_mut(self, name) {
v.apply(value)
}
}
} else {
{
panic!("Attempted to apply non-struct type to struct type.");
};
}
}
#[inline]
fn set(
&mut self,
value: Box<dyn bevy::reflect::Reflect>,
) -> Result<(), Box<dyn bevy::reflect::Reflect>> {
*self = <dyn bevy::reflect::Reflect>::take(value)?;
Ok(())
}
fn reflect_ref(&self) -> bevy::reflect::ReflectRef {
bevy::reflect::ReflectRef::Struct(self)
}
fn reflect_mut(&mut self) -> bevy::reflect::ReflectMut {
bevy::reflect::ReflectMut::Struct(self)
}
fn reflect_owned(self: Box<Self>) -> bevy::reflect::ReflectOwned {
bevy::reflect::ReflectOwned::Struct(self)
}
#[inline]
fn clone_value(&self) -> Box<dyn bevy::reflect::Reflect> {
Box::new(Struct::clone_dynamic(self))
}
fn reflect_partial_eq(&self, value: &dyn bevy::reflect::Reflect) -> Option<bool> {
bevy::reflect::struct_partial_eq(self, value)
}
}
impl<T> Struct for Foo<T>
where
PhantomData<T>: Any + Send + Sync,
{
fn field(&self, _name: &str) -> Option<&dyn bevy::reflect::Reflect> {
None
}
fn field_mut(&mut self, _name: &str) -> Option<&mut dyn bevy::reflect::Reflect> {
None
}
fn field_at(&self, _index: usize) -> Option<&dyn bevy::reflect::Reflect> {
None
}
fn field_at_mut(&mut self, _index: usize) -> Option<&mut dyn bevy::reflect::Reflect> {
None
}
fn name_at(&self, _index: usize) -> Option<&str> {
None
}
fn field_len(&self) -> usize {
0usize
}
fn iter_fields(&self) -> bevy::reflect::FieldIter {
bevy::reflect::FieldIter::new(self)
}
fn clone_dynamic(&self) -> bevy::reflect::DynamicStruct {
let mut dynamic: bevy::reflect::DynamicStruct = Default::default();
dynamic.set_represented_type(bevy::reflect::Reflect::get_represented_type_info(self));
dynamic
}
}
impl<T> bevy::reflect::FromReflect for Foo<T>
where
PhantomData<T>: Any + Send + Sync + Default,
{
fn from_reflect(reflect: &dyn bevy::reflect::Reflect) -> Option<Self> {
if let bevy::reflect::ReflectRef::Struct(__ref_struct) = Reflect::reflect_ref(reflect) {
Some(Self {
_marker: Default::default(),
})
} else {
None
}
}
}
struct NotTypePath;
impl<T: 'static> TypePath for Foo<T> {
fn type_path() -> &'static str {
std::any::type_name::<Self>()
}
fn short_type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| bevy::utils::get_short_name(std::any::type_name::<Self>()))
}
fn type_ident() -> Option<&'static str> {
Some("Foo")
}
fn crate_name() -> Option<&'static str> {
Some("my_crate")
}
fn module_path() -> Option<&'static str> {
Some("my_crate::foo")
}
}
fn main() {
// Can use `TypePath`
let _ = <Foo<NotTypePath> as TypePath>::type_path();
// Can register the type
let registry = TypeRegistry::default();
registry.internal.write().register::<Foo<NotTypePath>>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment