diff --git a/crates/blenvy/src/components/fake_entity.rs b/crates/blenvy/src/components/fake_entity.rs new file mode 100644 index 0000000..fa80971 --- /dev/null +++ b/crates/blenvy/src/components/fake_entity.rs @@ -0,0 +1,257 @@ +pub(crate) struct Entity { + name: Option, +} + +const _: () = { + use bevy::reflect as bevy_reflect; + + #[allow(unused_mut)] + impl bevy_reflect::GetTypeRegistration for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + Option: bevy_reflect::FromReflect + + bevy_reflect::TypePath + + bevy_reflect::__macro_exports::RegisterForReflection, + { + fn get_type_registration() -> bevy_reflect::TypeRegistration { + let mut registration = bevy_reflect::TypeRegistration::of::(); + registration + .insert::< + bevy_reflect::ReflectFromPtr, + >(bevy_reflect::FromType::::from_type()); + registration.insert::( + bevy_reflect::FromType::::from_type(), + ); + registration + } + #[inline(never)] + fn register_type_dependencies(registry: &mut bevy_reflect::TypeRegistry) { + as bevy_reflect::__macro_exports::RegisterForReflection>::__register( + registry, + ); + } + } + impl bevy_reflect::Typed for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + Option: bevy_reflect::FromReflect + + bevy_reflect::TypePath + + bevy_reflect::__macro_exports::RegisterForReflection, + { + fn type_info() -> &'static bevy_reflect::TypeInfo { + static CELL: bevy_reflect::utility::NonGenericTypeInfoCell = + bevy_reflect::utility::NonGenericTypeInfoCell::new(); + CELL.get_or_set(|| { + bevy_reflect::TypeInfo::Struct( + bevy_reflect::StructInfo::new::(&[ + // TODO: changed here + bevy_reflect::NamedField::new::>("name") + .with_custom_attributes( + bevy_reflect::attributes::CustomAttributes::default(), + ), + ]) + .with_custom_attributes(bevy_reflect::attributes::CustomAttributes::default()), + ) + }) + } + } + impl bevy_reflect::TypePath for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + { + fn type_path() -> &'static str { + "bevy_ecs::entity::Entity" + } + fn short_type_path() -> &'static str { + "Entity" + } + fn type_ident() -> Option<&'static str> { + ::core::option::Option::Some("Entity") + } + fn crate_name() -> Option<&'static str> { + ::core::option::Option::Some("bevy_ecs::entity".split(':').next().unwrap()) + } + fn module_path() -> Option<&'static str> { + ::core::option::Option::Some("bevy_ecs::entity") + } + } + impl bevy_reflect::Struct for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + Option: bevy_reflect::FromReflect + + bevy_reflect::TypePath + + bevy_reflect::__macro_exports::RegisterForReflection, + { + fn field(&self, name: &str) -> ::core::option::Option<&dyn bevy_reflect::Reflect> { + match name { + "name" => ::core::option::Option::Some(&self.name), + _ => ::core::option::Option::None, + } + } + fn field_mut( + &mut self, + name: &str, + ) -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> { + match name { + "name" => ::core::option::Option::Some(&mut self.name), + _ => ::core::option::Option::None, + } + } + fn field_at(&self, index: usize) -> ::core::option::Option<&dyn bevy_reflect::Reflect> { + match index { + 0usize => ::core::option::Option::Some(&self.name), + _ => ::core::option::Option::None, + } + } + fn field_at_mut( + &mut self, + index: usize, + ) -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> { + match index { + 0usize => ::core::option::Option::Some(&mut self.name), + _ => ::core::option::Option::None, + } + } + fn name_at(&self, index: usize) -> ::core::option::Option<&str> { + match index { + 0usize => ::core::option::Option::Some("name"), + _ => ::core::option::Option::None, + } + } + fn field_len(&self) -> usize { + 1usize + } + 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 = ::core::default::Default::default(); + dynamic.set_represented_type(bevy_reflect::Reflect::get_represented_type_info(self)); + dynamic.insert_boxed("name", bevy_reflect::Reflect::clone_value(&self.name)); + dynamic + } + } + impl bevy_reflect::Reflect for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + Option: bevy_reflect::FromReflect + + bevy_reflect::TypePath + + bevy_reflect::__macro_exports::RegisterForReflection, + { + #[inline] + fn get_represented_type_info( + &self, + ) -> ::core::option::Option<&'static bevy_reflect::TypeInfo> { + ::core::option::Option::Some(::type_info()) + } + #[inline] + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + #[inline] + fn as_any(&self) -> &dyn ::core::any::Any { + self + } + #[inline] + fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { + self + } + #[inline] + fn into_reflect( + self: ::std::boxed::Box, + ) -> ::std::boxed::Box { + 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 clone_value(&self) -> ::std::boxed::Box { + ::std::boxed::Box::new(bevy_reflect::Struct::clone_dynamic(self)) + } + #[inline] + fn set( + &mut self, + value: ::std::boxed::Box, + ) -> ::core::result::Result<(), ::std::boxed::Box> { + *self = ::take(value)?; + ::core::result::Result::Ok(()) + } + #[inline] + fn try_apply( + &mut self, + value: &dyn bevy_reflect::Reflect, + ) -> ::core::result::Result<(), bevy_reflect::ApplyError> { + if let bevy_reflect::ReflectRef::Struct(struct_value) = + bevy_reflect::Reflect::reflect_ref(value) + { + for (i, value) in ::core::iter::Iterator::enumerate( + bevy_reflect::Struct::iter_fields(struct_value), + ) { + let name = bevy_reflect::Struct::name_at(struct_value, i).unwrap(); + if let ::core::option::Option::Some(v) = + bevy_reflect::Struct::field_mut(self, name) + { + bevy_reflect::Reflect::try_apply(v, value)?; + } + } + } else { + return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds { + from_kind: bevy_reflect::Reflect::reflect_kind(value), + to_kind: bevy_reflect::ReflectKind::Struct, + }); + } + ::core::result::Result::Ok(()) + } + #[inline] + fn reflect_kind(&self) -> bevy_reflect::ReflectKind { + bevy_reflect::ReflectKind::Struct + } + #[inline] + fn reflect_ref(&self) -> bevy_reflect::ReflectRef { + bevy_reflect::ReflectRef::Struct(self) + } + #[inline] + fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut { + bevy_reflect::ReflectMut::Struct(self) + } + #[inline] + fn reflect_owned(self: ::std::boxed::Box) -> bevy_reflect::ReflectOwned { + bevy_reflect::ReflectOwned::Struct(self) + } + fn reflect_partial_eq( + &self, + value: &dyn bevy_reflect::Reflect, + ) -> ::core::option::Option { + bevy_reflect::struct_partial_eq(self, value) + } + } + impl bevy_reflect::FromReflect for Entity + where + Self: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync, + Option: bevy_reflect::FromReflect + + bevy_reflect::TypePath + + bevy_reflect::__macro_exports::RegisterForReflection, + { + fn from_reflect(reflect: &dyn bevy_reflect::Reflect) -> ::core::option::Option { + if let bevy_reflect::ReflectRef::Struct(__ref_struct) = + bevy_reflect::Reflect::reflect_ref(reflect) + { + ::core::option::Option::Some(Self { + name: (|| { + as bevy_reflect::FromReflect>::from_reflect( + bevy_reflect::Struct::field(__ref_struct, "name")?, + ) + })()?, + }) + } else { + ::core::option::Option::None + } + } + } +}; diff --git a/crates/blenvy/src/components/mod.rs b/crates/blenvy/src/components/mod.rs index 6b42c00..9c499f2 100644 --- a/crates/blenvy/src/components/mod.rs +++ b/crates/blenvy/src/components/mod.rs @@ -7,6 +7,8 @@ pub use ronstring_to_reflect_component::*; pub mod process_gltfs; pub use process_gltfs::*; +mod fake_entity; + pub mod blender_settings; use bevy::{ diff --git a/crates/blenvy/src/components/process_gltfs.rs b/crates/blenvy/src/components/process_gltfs.rs index c7b9edb..d861662 100644 --- a/crates/blenvy/src/components/process_gltfs.rs +++ b/crates/blenvy/src/components/process_gltfs.rs @@ -74,8 +74,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { ); let type_registry: &AppTypeRegistry = world.resource(); - let type_registry = type_registry.read(); - let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry); + let mut type_registry = type_registry.write(); + let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry); // let name = name.unwrap_or(&Name::new("")); let (target_entity, updated_components) = @@ -90,8 +90,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { ); let type_registry: &AppTypeRegistry = world.resource(); - let type_registry = type_registry.read(); - let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry); + let mut type_registry = type_registry.write(); + let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry); let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components); @@ -105,8 +105,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { ); let type_registry: &AppTypeRegistry = world.resource(); - let type_registry = type_registry.read(); - let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry); + let mut type_registry = type_registry.write(); + let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry); let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components); @@ -120,8 +120,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { ); let type_registry: &AppTypeRegistry = world.resource(); - let type_registry = type_registry.read(); - let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry); + let mut type_registry = type_registry.write(); + let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry); let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components); diff --git a/crates/blenvy/src/components/ronstring_to_reflect_component.rs b/crates/blenvy/src/components/ronstring_to_reflect_component.rs index e772d89..ba1a473 100644 --- a/crates/blenvy/src/components/ronstring_to_reflect_component.rs +++ b/crates/blenvy/src/components/ronstring_to_reflect_component.rs @@ -1,15 +1,17 @@ +use std::any::TypeId; + use bevy::log::{debug, warn}; use bevy::reflect::serde::ReflectDeserializer; -use bevy::reflect::{Reflect, TypeRegistration, TypeRegistry}; +use bevy::reflect::{GetTypeRegistration, Reflect, TypeRegistration, TypeRegistry}; use bevy::utils::HashMap; use ron::Value; use serde::de::DeserializeSeed; -use super::capitalize_first_letter; +use super::{capitalize_first_letter, fake_entity}; pub fn ronstring_to_reflect_component( ron_string: &str, - type_registry: &TypeRegistry, + type_registry: &mut TypeRegistry, ) -> Vec<(Box, TypeRegistration)> { let lookup: HashMap = ron::from_str(ron_string).unwrap(); let mut components: Vec<(Box, TypeRegistration)> = Vec::new(); @@ -96,10 +98,16 @@ fn components_string_to_components( fn bevy_components_string_to_components( parsed_value: String, - type_registry: &TypeRegistry, + type_registry: &mut TypeRegistry, components: &mut Vec<(Box, TypeRegistration)>, ) { let lookup: HashMap = ron::from_str(&parsed_value).unwrap(); + + let recovery_entity_type = type_registry + .get(TypeId::of::()) + .cloned(); + type_registry.overwrite_registration(fake_entity::Entity::get_type_registration()); + for (key, value) in lookup.into_iter() { let parsed_value: String = match value.clone() { Value::String(str) => str, @@ -121,10 +129,10 @@ fn bevy_components_string_to_components( let reflect_deserializer = ReflectDeserializer::new(type_registry); let component = reflect_deserializer .deserialize(&mut deserializer) - .unwrap_or_else(|_| { + .unwrap_or_else(|e| { panic!( - "failed to deserialize component {} with value: {:?}", - key, value + "failed to deserialize component '{}' with value '{:?}': {:?}", + key, value, e ) }); @@ -136,4 +144,10 @@ fn bevy_components_string_to_components( warn!("no type registration for {}", key); } } + + if let Some(original_entity) = recovery_entity_type { + type_registry.overwrite_registration(original_entity); + } else { + warn!("There isn't an original type registration for `bevy_ecs::entity::Entity` but it was overwriten. Stuff may break and/or panic. Make sure that you register it!"); + } } diff --git a/examples/relations/art/untitled.blend b/examples/relations/art/untitled.blend index c585df9..2ce2f62 100644 Binary files a/examples/relations/art/untitled.blend and b/examples/relations/art/untitled.blend differ diff --git a/examples/relations/assets/levels/World.glb b/examples/relations/assets/levels/World.glb index 9cf25cb..1609605 100644 Binary files a/examples/relations/assets/levels/World.glb and b/examples/relations/assets/levels/World.glb differ diff --git a/examples/relations/src/main.rs b/examples/relations/src/main.rs index ee083ce..85b0098 100644 --- a/examples/relations/src/main.rs +++ b/examples/relations/src/main.rs @@ -3,7 +3,7 @@ use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlu #[derive(Component, Reflect)] #[reflect(Component)] -pub struct TupleRelations(Entity); +pub struct TupleRelations(Entity); // TODO: Serialization on blender side currently is broken #[derive(Component, Reflect)] #[reflect(Component)] diff --git a/tools/blenvy/add_ons/bevy_components/propGroups/conversions_from_prop_group.py b/tools/blenvy/add_ons/bevy_components/propGroups/conversions_from_prop_group.py index 2541cc4..b3437a1 100644 --- a/tools/blenvy/add_ons/bevy_components/propGroups/conversions_from_prop_group.py +++ b/tools/blenvy/add_ons/bevy_components/propGroups/conversions_from_prop_group.py @@ -26,7 +26,7 @@ conversion_tables = { "bevy_color::linear_rgba::LinearRgba": lambda value: "LinearRgba(red:"+str(value[0])+ ", green:"+str(value[1])+ ", blue:"+str(value[2])+ ", alpha:"+str(value[3])+ ")", "bevy_color::hsva::Hsva": lambda value: "Hsva(hue:"+str(value[0])+ ", saturation:"+str(value[1])+ ", value:"+str(value[2])+ ", alpha:"+str(value[3])+ ")", - "bevy_ecs::entity::Entity": lambda value: 'Entity(name: ' + ('Some("' + str(value.name) + '")') if value is not None else "None" + ')' + "bevy_ecs::entity::Entity": lambda value: 'Entity(name: ' + (('Some("' + str(value.name) + '")') if value is not None else "None") + ')', } #converts the value of a property group(no matter its complexity) into a single custom property value