Reflect::fields_info_mut + optimizations

- allows iterating over fields while be able to mutate them
- reduced FieldInfoRef/Mut size even more to just a pointer+fat pointer
This commit is contained in:
Dmitry Stepanov
2025-03-13 20:52:28 +03:00
parent ecd10b91cc
commit c171b68830
26 changed files with 411 additions and 175 deletions
+2 -2
View File
@@ -1110,8 +1110,8 @@ impl TrackList {
let mut descriptors = Vec::new();
if let Some(node) = graph.try_get(node) {
node.as_reflect(&mut |node| {
descriptors = object_to_property_tree("", node, &mut |field: &FieldInfo| {
let type_id = field.reflect_value.type_id();
descriptors = object_to_property_tree("", node, &mut |field: &FieldInfoRef| {
let type_id = field.value.field_value_as_reflect().type_id();
type_id != TypeId::of::<TextureBytes>()
// Vertex buffer cannot be animated (mainly because it contains untyped data).
&& type_id != TypeId::of::<VertexBuffer>()
@@ -183,7 +183,7 @@ pub struct TexturePropertyEditorDefinition {
}
impl TexturePropertyEditorDefinition {
fn value(&self, field_info: &FieldInfo) -> Result<Option<TextureResource>, InspectorError> {
fn value(&self, field_info: &FieldInfoRef) -> Result<Option<TextureResource>, InspectorError> {
if self.untyped {
let value = field_info.cast_value::<Option<UntypedResource>>()?;
let casted = value.as_ref().and_then(|r| r.try_cast::<Texture>());
+2 -2
View File
@@ -170,7 +170,7 @@ pub fn object_to_property_tree<F>(
filter: &mut F,
) -> Vec<PropertyDescriptor>
where
F: FnMut(&FieldInfo) -> bool,
F: FnMut(&FieldInfoRef) -> bool,
{
let mut descriptors = Vec::new();
@@ -180,7 +180,7 @@ where
continue;
}
let field_ref = field_info.reflect_value;
let field_ref = field_info.value.field_value_as_reflect();
let path = if parent_path.is_empty() {
field_info.name.to_owned()
+73 -8
View File
@@ -90,7 +90,7 @@ macro_rules! define_two_args_node {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[
{
static METADATA: FieldMetadata = FieldMetadata {
@@ -107,10 +107,9 @@ macro_rules! define_two_args_node {
doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &*self.lhs,
reflect_value: &*self.lhs,
}
},
{
@@ -127,15 +126,59 @@ macro_rules! define_two_args_node {
precision: None,doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &*self.rhs,
reflect_value: &*self.rhs,
}
},
])
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Lhs",
display_name: "Lhs",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut *self.lhs,
}
},
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Rhs",
display_name: "Rhs",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut *self.rhs,
}
},
])
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
@@ -262,7 +305,7 @@ impl<T: EntityId> Reflect for NotNode<T> {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[{
static METADATA: FieldMetadata = FieldMetadata {
name: "Lhs",
@@ -278,10 +321,32 @@ impl<T: EntityId> Reflect for NotNode<T> {
doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &*self.lhs,
reflect_value: &*self.lhs,
}
}])
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [{
static METADATA: FieldMetadata = FieldMetadata {
name: "Lhs",
display_name: "Lhs",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut *self.lhs,
}
}])
}
+50 -15
View File
@@ -41,6 +41,7 @@ pub fn impl_reflect(ty_args: &args::TypeArgs) -> TokenStream2 {
quote!(func(&mut [])),
None,
quote!(func(&[])),
quote!(func(&mut [])),
);
}
@@ -59,6 +60,7 @@ pub fn gen_fields_metadata_body(
props: &[Property],
field_getters: &[TokenStream2],
field_args: &ast::Fields<args::FieldArgs>,
is_mut: bool,
) -> TokenStream2 {
let props = field_args
.fields
@@ -67,7 +69,7 @@ pub fn gen_fields_metadata_body(
.filter(|(_i, f)| !f.hidden)
.zip(props.iter().zip(field_getters))
.map(|((i, field), (prop, field_getter))| {
self::quote_field_prop(&prop.value, i, field_getter, field)
self::quote_field_prop(&prop.value, i, field_getter, field, is_mut)
});
quote! {
@@ -81,6 +83,7 @@ fn quote_field_prop(
nth_field: usize,
field_getter: &TokenStream2,
field: &args::FieldArgs,
is_mut: bool,
) -> TokenStream2 {
let field_ident = match &field.ident {
Some(ident) => quote!(#ident),
@@ -126,6 +129,12 @@ fn quote_field_prop(
let description = field.description.clone().unwrap_or_default();
let variant = if is_mut {
quote! { FieldInfoMut }
} else {
quote! { FieldInfoRef }
};
quote! {
{
static METADATA: FieldMetadata = FieldMetadata {
@@ -142,10 +151,9 @@ fn quote_field_prop(
description: #description,
};
FieldInfo {
#variant {
metadata: &METADATA,
value: #field_getter,
reflect_value: #field_getter,
}
}
}
@@ -168,7 +176,8 @@ fn impl_reflect_struct(ty_args: &args::TypeArgs, field_args: &args::Fields) -> T
let fields = fields.collect::<Vec<_>>();
let field_muts = field_muts.collect::<Vec<_>>();
let metadata = gen_fields_metadata_body(&props, &fields, field_args);
let metadata_ref = gen_fields_metadata_body(&props, &fields, field_args, false);
let metadata_mut = gen_fields_metadata_body(&props, &field_muts, field_args, true);
let field_body = quote! {
match name {
@@ -213,7 +222,10 @@ fn impl_reflect_struct(ty_args: &args::TypeArgs, field_args: &args::Fields) -> T
fields_mut_body,
set_field_body,
quote! {
func(&[#metadata])
func(&[#metadata_ref])
},
quote! {
func(&mut [#metadata_mut])
},
)
}
@@ -266,7 +278,8 @@ fn struct_set_field_body(ty_args: &args::TypeArgs) -> Option<TokenStream2> {
fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs]) -> TokenStream2 {
let mut fields_list = Vec::new();
let mut fields_list_mut = Vec::new();
let mut fields_info = Vec::new();
let mut fields_info_ref = Vec::new();
let mut fields_info_mut = Vec::new();
let (fields, field_muts): (Vec<_>, Vec<_>) = variant_args
.iter()
.map(|v| {
@@ -299,7 +312,8 @@ fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs
let fields = fields.collect::<Vec<_>>();
let field_muts = field_muts.collect::<Vec<_>>();
let metadata = gen_fields_metadata_body(&props, &fields, &v.fields);
let metadata_ref = gen_fields_metadata_body(&props, &fields, &v.fields, false);
let metadata_mut = gen_fields_metadata_body(&props, &field_muts, &v.fields, true);
let fields_list_raw = quote! {
#(
@@ -339,8 +353,12 @@ fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs
#matcher => func(&mut [ #fields_mut_list_raw ]),
});
fields_info.push(quote! {
#matcher => func(&[#metadata]),
fields_info_ref.push(quote! {
#matcher => func(&[#metadata_ref]),
});
fields_info_mut.push(quote! {
#matcher => func(&mut [#metadata_mut]),
});
(fields, field_muts)
@@ -356,6 +374,7 @@ fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs
quote!(func(&mut [])),
None,
quote!(func(&[])),
quote!(func(&mut [])),
)
} else {
let field_body = quote! {
@@ -394,15 +413,24 @@ fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs
}
};
let fields_metadata_body = quote! {
let fields_metadata_ref_body = quote! {
match self {
#(
#fields_info
#fields_info_ref
)*
_ => func(&[])
}
};
let fields_metadata_mut_body = quote! {
match self {
#(
#fields_info_mut
)*
_ => func(&mut [])
}
};
self::gen_impl(
ty_args,
field_body,
@@ -410,11 +438,13 @@ fn impl_reflect_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs
fields_body,
fields_mut_body,
None,
fields_metadata_body,
fields_metadata_ref_body,
fields_metadata_mut_body,
)
}
}
#[allow(clippy::too_many_arguments)]
fn gen_impl(
ty_args: &args::TypeArgs,
field: TokenStream2,
@@ -422,7 +452,8 @@ fn gen_impl(
fields: TokenStream2,
fields_mut: TokenStream2,
set_field: Option<TokenStream2>,
metadata: TokenStream2,
metadata_ref: TokenStream2,
metadata_mut: TokenStream2,
) -> TokenStream2 {
let ty_ident = &ty_args.ident;
let generics = ty_args.impl_generics();
@@ -486,8 +517,12 @@ fn gen_impl(
#assembly_name
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
#metadata
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
#metadata_ref
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
#metadata_mut
}
fn into_any(self: Box<Self>) -> Box<dyn ::core::any::Any> {
+11 -37
View File
@@ -368,15 +368,13 @@ fn inspect_default() {
};
let expected = vec![
FieldInfo {
FieldInfoRef {
metadata: &the_field_metadata,
value: &data.the_field,
reflect_value: &data.the_field,
},
FieldInfo {
FieldInfoRef {
metadata: &another_field_metadata,
value: &data.another_field,
reflect_value: &data.another_field,
},
];
@@ -419,12 +417,11 @@ fn inspect_attributes() {
};
let expected = vec![
FieldInfo {
FieldInfoRef {
metadata: &x_metadata,
value: &data.x,
reflect_value: &data.x,
},
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "y",
display_name: "Y",
@@ -439,7 +436,6 @@ fn inspect_attributes() {
doc: "",
},
value: &data.y,
reflect_value: &data.y,
},
];
@@ -457,23 +453,21 @@ fn inspect_struct() {
assert_eq!(
fields_info,
vec![
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "0",
display_name: "0",
..default_prop_metadata()
},
value: &x.0,
reflect_value: &x.0,
},
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "1",
display_name: "1",
..default_prop_metadata()
},
value: &x.1,
reflect_value: &x.1,
},
]
)
@@ -510,7 +504,7 @@ fn inspect_enum() {
assert_eq!(
fields_info,
vec![
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "Named@x",
display_name: "X",
@@ -520,12 +514,8 @@ fn inspect_enum() {
Data::Named { ref x, .. } => x,
_ => unreachable!(),
},
reflect_value: match data {
Data::Named { ref x, .. } => x,
_ => unreachable!(),
},
},
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "Named@y",
display_name: "Y",
@@ -535,12 +525,8 @@ fn inspect_enum() {
Data::Named { ref y, .. } => y,
_ => unreachable!(),
},
reflect_value: match data {
Data::Named { ref y, .. } => y,
_ => unreachable!(),
},
},
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "Named@z",
display_name: "Z",
@@ -550,10 +536,6 @@ fn inspect_enum() {
Data::Named { ref z, .. } => z,
_ => unreachable!(),
},
reflect_value: match data {
Data::Named { ref z, .. } => z,
_ => unreachable!(),
},
},
]
)
@@ -565,7 +547,7 @@ fn inspect_enum() {
assert_eq!(
fields_info,
vec![
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "Tuple@0",
display_name: "0",
@@ -575,12 +557,8 @@ fn inspect_enum() {
Data::Tuple(ref f0, ref _f1) => f0,
_ => unreachable!(),
},
reflect_value: match data {
Data::Tuple(ref f0, ref _f1) => f0,
_ => unreachable!(),
},
},
FieldInfo {
FieldInfoRef {
metadata: &FieldMetadata {
name: "Tuple@1",
display_name: "1",
@@ -590,10 +568,6 @@ fn inspect_enum() {
Data::Tuple(ref _f0, ref f1) => f1,
_ => unreachable!(),
},
reflect_value: match data {
Data::Tuple(ref _f0, ref f1) => f1,
_ => unreachable!(),
},
},
]
)
+50 -34
View File
@@ -83,6 +83,34 @@ impl<T: Reflect> ReflectHandle for Handle<T> {
}
}
static INDEX_METADATA: FieldMetadata = FieldMetadata {
name: "Index",
display_name: "Index",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
static GENERATION_METADATA: FieldMetadata = FieldMetadata {
name: "Generation",
display_name: "Generation",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
impl<T: Reflect> Reflect for Handle<T> {
fn source_path() -> &'static str {
file!()
@@ -115,47 +143,35 @@ impl<T: Reflect> Reflect for Handle<T> {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Index",
display_name: "Index",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfo {
metadata: &METADATA,
FieldInfoRef {
metadata: &INDEX_METADATA,
value: &self.index,
reflect_value: &self.index,
}
},
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Generation",
display_name: "Generation",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfo {
metadata: &METADATA,
FieldInfoRef {
metadata: &GENERATION_METADATA,
value: &self.generation,
reflect_value: &self.generation,
}
},
])
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [
{
FieldInfoMut {
metadata: &INDEX_METADATA,
value: &mut self.index,
}
},
{
FieldInfoMut {
metadata: &GENERATION_METADATA,
value: &mut self.generation,
}
},
])
+6 -1
View File
@@ -126,10 +126,15 @@ where
}
#[inline]
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[])
}
#[inline]
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [])
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
+92 -27
View File
@@ -33,21 +33,39 @@ use std::{
pub mod prelude {
pub use super::{
FieldInfo, FieldMetadata, FieldValue, Reflect, ReflectArray, ReflectHashMap,
ReflectInheritableVariable, ReflectList, ResolvePath, SetFieldByPathError,
FieldInfoMut, FieldInfoRef, FieldMetadata, FieldValue, Reflect, ReflectArray,
ReflectHashMap, ReflectInheritableVariable, ReflectList, ResolvePath, SetFieldByPathError,
};
}
/// A value of a field..
pub trait FieldValue: Any + 'static {
/// Casts `self` to a `&dyn Any`
fn as_any(&self) -> &dyn Any;
fn field_value_as_any_ref(&self) -> &dyn Any;
/// Casts `self` to a `&mut dyn Any`
fn field_value_as_any_mut(&mut self) -> &mut dyn Any;
fn field_value_as_reflect(&self) -> &dyn Reflect;
fn field_value_as_reflect_mut(&mut self) -> &mut dyn Reflect;
fn type_name(&self) -> &'static str;
}
impl<T: 'static> FieldValue for T {
fn as_any(&self) -> &dyn Any {
impl<T: Reflect> FieldValue for T {
fn field_value_as_any_ref(&self) -> &dyn Any {
self
}
fn field_value_as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn field_value_as_reflect(&self) -> &dyn Reflect {
self
}
fn field_value_as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
@@ -110,7 +128,7 @@ pub struct FieldMetadata<'s> {
pub precision: Option<usize>,
}
pub struct FieldInfo<'a, 'b> {
pub struct FieldInfoRef<'a, 'b> {
/// A reference to field's metadata.
pub metadata: &'a FieldMetadata<'b>,
@@ -118,12 +136,9 @@ pub struct FieldInfo<'a, 'b> {
/// means that while `field/fields/field_mut/fields_mut` might return a reference to other value,
/// than the actual field, the `value` is guaranteed to be a reference to the real value.
pub value: &'a dyn FieldValue,
/// A reference to the value casted to `Reflect`.
pub reflect_value: &'a dyn Reflect,
}
impl<'b> Deref for FieldInfo<'_, 'b> {
impl<'b> Deref for FieldInfoRef<'_, 'b> {
type Target = FieldMetadata<'b>;
fn deref(&self) -> &Self::Target {
@@ -131,10 +146,10 @@ impl<'b> Deref for FieldInfo<'_, 'b> {
}
}
impl FieldInfo<'_, '_> {
impl FieldInfoRef<'_, '_> {
/// Tries to cast a value to a given type.
pub fn cast_value<T: 'static>(&self) -> Result<&T, CastError> {
match self.value.as_any().downcast_ref::<T>() {
match self.value.field_value_as_any_ref().downcast_ref::<T>() {
Some(value) => Ok(value),
None => Err(CastError::TypeMismatch {
property_name: self.metadata.name.to_string(),
@@ -145,7 +160,7 @@ impl FieldInfo<'_, '_> {
}
}
impl fmt::Debug for FieldInfo<'_, '_> {
impl fmt::Debug for FieldInfoRef<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FieldInfo")
.field("metadata", &self.metadata)
@@ -154,7 +169,43 @@ impl fmt::Debug for FieldInfo<'_, '_> {
}
}
impl PartialEq<Self> for FieldInfo<'_, '_> {
impl PartialEq<Self> for FieldInfoRef<'_, '_> {
fn eq(&self, other: &Self) -> bool {
let value_ptr_a = self.value as *const _ as *const ();
let value_ptr_b = other.value as *const _ as *const ();
std::ptr::eq(value_ptr_a, value_ptr_b)
}
}
pub struct FieldInfoMut<'a, 'b> {
/// A reference to field's metadata.
pub metadata: &'a FieldMetadata<'b>,
/// An reference to the actual value of the property. This is "non-mangled" reference, which
/// means that while `field/fields/field_mut/fields_mut` might return a reference to other value,
/// than the actual field, the `value` is guaranteed to be a reference to the real value.
pub value: &'a mut dyn FieldValue,
}
impl<'b> Deref for FieldInfoMut<'_, 'b> {
type Target = FieldMetadata<'b>;
fn deref(&self) -> &Self::Target {
self.metadata
}
}
impl fmt::Debug for FieldInfoMut<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FieldInfo")
.field("metadata", &self.metadata)
.field("value", &format_args!("{:?}", self.value as *const _))
.finish()
}
}
impl PartialEq<Self> for FieldInfoMut<'_, '_> {
fn eq(&self, other: &Self) -> bool {
let value_ptr_a = self.value as *const _ as *const ();
let value_ptr_b = other.value as *const _ as *const ();
@@ -212,7 +263,9 @@ pub trait Reflect: ReflectBase {
fn doc(&self) -> &'static str;
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo]));
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef]));
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut]));
fn into_any(self: Box<Self>) -> Box<dyn Any>;
@@ -850,7 +903,7 @@ impl dyn Reflect {
pub fn enumerate_fields_recursively<F>(&self, func: &mut F, ignored_types: &[TypeId])
where
F: FnMut(&str, Option<&FieldInfo>, &dyn Reflect),
F: FnMut(&str, Option<&FieldInfoRef>, &dyn Reflect),
{
self.enumerate_fields_recursively_internal("", None, func, ignored_types)
}
@@ -858,11 +911,11 @@ impl dyn Reflect {
fn enumerate_fields_recursively_internal<F>(
&self,
path: &str,
field_info: Option<&FieldInfo>,
field_info: Option<&FieldInfoRef>,
func: &mut F,
ignored_types: &[TypeId],
) where
F: FnMut(&str, Option<&FieldInfo>, &dyn Reflect),
F: FnMut(&str, Option<&FieldInfoRef>, &dyn Reflect),
{
if ignored_types.contains(&self.type_id()) {
return;
@@ -961,12 +1014,15 @@ impl dyn Reflect {
&compound_path
};
field.reflect_value.enumerate_fields_recursively_internal(
field_path,
Some(field),
func,
ignored_types,
);
field
.value
.field_value_as_reflect()
.enumerate_fields_recursively_internal(
field_path,
Some(field),
func,
ignored_types,
);
}
})
}
@@ -1165,10 +1221,15 @@ macro_rules! blank_reflect {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[])
}
#[inline]
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [])
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
@@ -1236,10 +1297,14 @@ macro_rules! delegate_reflect {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.deref().fields_info(func)
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.deref_mut().fields_info_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
(*self).into_any()
}
@@ -1301,7 +1366,7 @@ macro_rules! newtype_reflect {
self.0.doc()
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.0.fields_info(func)
}
+6 -1
View File
@@ -330,11 +330,16 @@ macro_rules! impl_reflect_inner_mutability {
env!("CARGO_PKG_NAME")
}
fn fields_info(&$self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&$self, func: &mut dyn FnMut(&[FieldInfoRef])) {
let guard = $acquire_lock_guard;
guard.fields_info(func)
}
fn fields_info_mut(&mut $self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
let mut guard = $acquire_lock_guard;
guard.fields_info_mut(func)
}
fn into_any($self: Box<Self>) -> Box<dyn Any> {
let inner = $into_inner;
Box::new(inner)
+6 -1
View File
@@ -404,10 +404,15 @@ where
}
#[inline]
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.value.fields_info(func)
}
#[inline]
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.value.fields_info_mut(func)
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Box::new(self.value).into_any()
+5 -1
View File
@@ -1539,10 +1539,14 @@ mod test {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.0.deref().fields_info(func)
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.0.deref_mut().fields_info_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Reflect::into_any(self.0)
}
+5 -1
View File
@@ -557,10 +557,14 @@ impl Reflect for Node {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.0.deref().fields_info(func)
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.0.deref_mut().fields_info_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Reflect::into_any(self.0)
}
+66 -7
View File
@@ -95,7 +95,7 @@ impl Reflect for Limb {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
func(&[
{
static METADATA: FieldMetadata = FieldMetadata {
@@ -111,10 +111,9 @@ impl Reflect for Limb {
precision: None,
doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &self.bone,
reflect_value: &self.bone,
}
},
{
@@ -131,10 +130,9 @@ impl Reflect for Limb {
precision: None,
doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &self.physical_bone,
reflect_value: &self.physical_bone,
}
},
{
@@ -151,10 +149,71 @@ impl Reflect for Limb {
precision: None,
doc: "",
};
FieldInfo {
FieldInfoRef {
metadata: &METADATA,
value: &self.children,
reflect_value: &self.children,
}
},
])
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
func(&mut [
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Bone",
display_name: "Bone",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut self.bone,
}
},
{
static METADATA: FieldMetadata = FieldMetadata {
name: "PhysicalBone",
display_name: "Physical Bone",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut self.physical_bone,
}
},
{
static METADATA: FieldMetadata = FieldMetadata {
name: "Children",
display_name: "Children",
description: "",
tag: "",
read_only: false,
immutable_collection: false,
min_value: None,
max_value: None,
step: None,
precision: None,
doc: "",
};
FieldInfoMut {
metadata: &METADATA,
value: &mut self.children,
}
},
])
+7 -2
View File
@@ -27,7 +27,7 @@ use crate::{
core::{
log::Log,
pool::Handle,
reflect::{FieldInfo, Reflect, ReflectArray, ReflectList},
reflect::{FieldInfoRef, Reflect, ReflectArray, ReflectList},
type_traits::ComponentProvider,
uuid::Uuid,
visitor::{Visit, VisitResult, Visitor},
@@ -39,6 +39,7 @@ use crate::{
plugin::{Plugin, PluginContainer},
scene::{base::NodeScriptMessage, node::Node, Scene},
};
use fyrox_core::reflect::FieldInfoMut;
use std::{
any::{Any, TypeId},
fmt::{Debug, Formatter},
@@ -695,10 +696,14 @@ impl Reflect for Script {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.instance.fields_info(func)
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.instance.fields_info_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self.instance.into_any()
}
+1 -1
View File
@@ -869,7 +869,7 @@ mod test {
use fyrox_core::uuid::{uuid, Uuid};
use fyrox_core::{
reflect::{FieldInfo, Reflect},
reflect::prelude::*,
visitor::{Visit, VisitResult, Visitor},
TypeUuidProvider,
};
+1 -1
View File
@@ -208,7 +208,7 @@ impl ResourceState {
#[cfg(test)]
mod test {
use fyrox_core::{
reflect::{FieldInfo, Reflect},
reflect::{FieldInfoRef, Reflect},
TypeUuidProvider,
};
use std::error::Error;
+4 -6
View File
@@ -120,7 +120,7 @@ fn create_items<'a, 'b, T, I>(
iter: I,
environment: Option<Arc<dyn InspectorEnvironment>>,
definition_container: Arc<PropertyEditorDefinitionContainer>,
property_info: &FieldInfo<'a, 'b>,
property_info: &FieldInfoRef<'a, 'b>,
ctx: &mut BuildContext,
sync_flag: u64,
layer_index: usize,
@@ -153,10 +153,9 @@ where
doc: property_info.doc,
};
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &metadata,
value: item,
reflect_value: item,
};
let editor =
@@ -248,7 +247,7 @@ where
pub fn build(
self,
ctx: &mut BuildContext,
property_info: &FieldInfo<'a, '_>,
property_info: &FieldInfoRef<'a, '_>,
sync_flag: u64,
name_column_width: f32,
) -> Result<Handle<UiNode>, InspectorError> {
@@ -413,10 +412,9 @@ where
doc: property_info.doc,
};
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &metadata,
value: obj,
reflect_value: obj,
};
if let Some(message) =
+4 -6
View File
@@ -231,7 +231,7 @@ fn create_items<'a, 'b, T, I>(
iter: I,
environment: Option<Arc<dyn InspectorEnvironment>>,
definition_container: Arc<PropertyEditorDefinitionContainer>,
property_info: &FieldInfo<'a, 'b>,
property_info: &FieldInfoRef<'a, 'b>,
ctx: &mut BuildContext,
sync_flag: u64,
layer_index: usize,
@@ -251,7 +251,7 @@ where
let name = format!("{}[{index}]", property_info.name);
let display_name = format!("{}[{index}]", property_info.display_name);
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: &name,
display_name: &display_name,
@@ -266,7 +266,6 @@ where
doc: property_info.doc,
},
value: item,
reflect_value: item,
};
let editor =
@@ -384,7 +383,7 @@ where
pub fn build(
self,
ctx: &mut BuildContext,
property_info: &FieldInfo<'a, '_>,
property_info: &FieldInfoRef<'a, '_>,
sync_flag: u64,
name_column_width: f32,
) -> Result<Handle<UiNode>, InspectorError> {
@@ -581,7 +580,7 @@ where
let name = format!("{}[{index}]", property_info.name);
let display_name = format!("{}[{index}]", property_info.display_name);
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: &name,
display_name: &display_name,
@@ -596,7 +595,6 @@ where
doc: property_info.doc,
},
value: obj,
reflect_value: obj,
};
if let Some(message) =
+2 -4
View File
@@ -233,7 +233,7 @@ where
let value = property_info.cast_value::<InheritableVariable<T>>()?;
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -248,7 +248,6 @@ where
doc: property_info.doc,
},
value: &**value,
reflect_value: &**value,
};
let instance =
@@ -324,7 +323,7 @@ where
let value = property_info.cast_value::<InheritableVariable<T>>()?;
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -339,7 +338,6 @@ where
doc: property_info.doc,
},
value: &**value,
reflect_value: &**value,
};
return definition
@@ -44,7 +44,7 @@ use std::{
/// A general-purpose property editor definition that creates
/// a nested inspector within an [Expander](crate::expander::Expander) widget to allow the user
/// to edited properties of type T.
/// The expander is labeled with [FieldInfo::display_name].
/// The expander is labeled with [FieldInfoRef::display_name].
/// The layer_index for the inner inspector is increased by 1.
pub struct InspectablePropertyEditorDefinition<T>
where
+2 -2
View File
@@ -152,7 +152,7 @@ pub struct PropertyEditorBuildContext<'a, 'b, 'c, 'd> {
/// General context for widget building to be used for creating the editor.
pub build_context: &'a mut BuildContext<'c>,
/// The FieldInfo of the property to edit, extracted from the object we are inspecting by reflection.
pub property_info: &'b FieldInfo<'b, 'd>,
pub property_info: &'b FieldInfoRef<'b, 'd>,
/// Untyped reference to the environment that the Inspector is being used in.
/// This will often be
/// [fyroxed_base::inspector::EditorEnvironment](https://docs.rs/fyroxed_base/latest/fyroxed_base/inspector/struct.EditorEnvironment.html)
@@ -197,7 +197,7 @@ pub struct PropertyEditorMessageContext<'a, 'b, 'c> {
/// [UiMessage::flags] set to `sync_flag`.
pub ui: &'b mut UserInterface,
/// The FieldInfo of the property to edit, extracted from the object we are inspecting by reflection.
pub property_info: &'a FieldInfo<'a, 'c>,
pub property_info: &'a FieldInfoRef<'a, 'c>,
/// The list of the Inspectors property editors.
/// This allows one property editor to make use of other property editors.
pub definition_container: Arc<PropertyEditorDefinitionContainer>,
+2 -4
View File
@@ -85,7 +85,7 @@ where
let value = property_info.cast_value::<RefCell<T>>()?.borrow();
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -100,7 +100,6 @@ where
doc: property_info.doc,
},
value: &*value,
reflect_value: &*value,
};
definition
@@ -134,7 +133,7 @@ where
let value = ctx.property_info.cast_value::<RefCell<T>>()?.borrow();
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -149,7 +148,6 @@ where
doc: property_info.doc,
},
value: &*value,
reflect_value: &*value,
};
return definition
+2 -4
View File
@@ -225,7 +225,7 @@ where
{
let property_info = ctx.property_info;
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -240,7 +240,6 @@ where
doc: property_info.doc,
},
value: &**value,
reflect_value: &**value,
};
let instance =
@@ -303,7 +302,7 @@ where
let value = property_info.cast_value::<StyledProperty<T>>()?;
let proxy_property_info = FieldInfo {
let proxy_property_info = FieldInfoRef {
metadata: &FieldMetadata {
name: property_info.name,
display_name: property_info.display_name,
@@ -318,7 +317,6 @@ where
doc: property_info.doc,
},
value: &**value,
reflect_value: &**value,
};
return definition
+5 -5
View File
@@ -534,11 +534,11 @@ impl From<CastError> for InspectorError {
/// Stores the association between a field in an object and an editor widget in an [Inspector].
#[derive(Clone, Debug)]
pub struct ContextEntry {
/// The name of the field being edited, as found in [FieldInfo::name].
/// The name of the field being edited, as found in [FieldInfoRef::name].
pub property_name: String,
/// The name of the field being edited, as found in [FieldInfo::display_name].
/// The name of the field being edited, as found in [FieldInfoRef::display_name].
pub property_display_name: String,
/// The name of the field being edited, as found in [FieldInfo::tag].
/// The name of the field being edited, as found in [FieldInfoRef::tag].
pub property_tag: String,
/// The type of the property being edited, as found in [PropertyEditorDefinition::value_type_id](editors::PropertyEditorDefinition::value_type_id).
pub property_value_type_id: TypeId,
@@ -856,7 +856,7 @@ impl InspectorContext {
let mut editors = Vec::new();
object.fields_info(&mut |fields_info| {
for (i, (field_text, info)) in fields_text.iter().zip(fields_info.iter()).enumerate() {
if !filter.pass(info.reflect_value) {
if !filter.pass(info.value.field_value_as_reflect()) {
continue;
}
@@ -1022,7 +1022,7 @@ impl InspectorContext {
object.fields_info(&mut |fields_info| {
for info in fields_info {
if !filter.pass(info.reflect_value) {
if !filter.pass(info.value.field_value_as_reflect()) {
continue;
}
+5 -1
View File
@@ -307,10 +307,14 @@ impl Reflect for UiNode {
env!("CARGO_PKG_NAME")
}
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfoRef])) {
self.0.deref().fields_info(func)
}
fn fields_info_mut(&mut self, func: &mut dyn FnMut(&mut [FieldInfoMut])) {
self.0.deref_mut().fields_info_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Reflect::into_any(self.0)
}