From 0965df060ceef9f1448c7e6f8b4127baf16c04e5 Mon Sep 17 00:00:00 2001 From: Dmitry Stepanov Date: Fri, 5 Jun 2026 23:06:29 +0300 Subject: [PATCH] `Reflect::try_compare` draft --- fyrox-core-derive/src/reflect.rs | 14 ++++++++++++++ fyrox-core-derive/src/reflect/args.rs | 3 +++ fyrox-core/src/math/mod.rs | 2 +- fyrox-core/src/pool/handle.rs | 6 ++++++ fyrox-core/src/pool/mod.rs | 6 ++++++ fyrox-core/src/reflect/impls.rs | 2 ++ fyrox-core/src/reflect/macros.rs | 6 ++++++ fyrox-core/src/reflect/mod.rs | 12 +++++++++--- 8 files changed, 47 insertions(+), 4 deletions(-) diff --git a/fyrox-core-derive/src/reflect.rs b/fyrox-core-derive/src/reflect.rs index 066333e78..204f23490 100644 --- a/fyrox-core-derive/src/reflect.rs +++ b/fyrox-core-derive/src/reflect.rs @@ -443,6 +443,18 @@ fn gen_impl( } }; + let try_compare = if ty_args.non_comparable { + quote! { + fn try_compare(&self, _other: &dyn Reflect) -> Option { None } + } + } else { + quote! { + fn try_compare(&self, other: &dyn Reflect) -> Option { + (other as &dyn Any).downcast_ref::().map(|other| other == self) + } + } + }; + let type_uuid_str = ty_args.type_uuid.as_str(); let type_uuid = if ty_args.generics.params.is_empty() { quote! { uuid!(#type_uuid_str) } @@ -494,6 +506,8 @@ fn gen_impl( #try_clone_box + #try_compare + fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) { #metadata_ref } diff --git a/fyrox-core-derive/src/reflect/args.rs b/fyrox-core-derive/src/reflect/args.rs index 45b574e0e..82cff433f 100644 --- a/fyrox-core-derive/src/reflect/args.rs +++ b/fyrox-core-derive/src/reflect/args.rs @@ -63,6 +63,9 @@ pub struct TypeArgs { #[darling(default)] pub non_cloneable: bool, + #[darling(default)] + pub non_comparable: bool, + #[darling(default)] pub clone_fn: Option, diff --git a/fyrox-core/src/math/mod.rs b/fyrox-core/src/math/mod.rs index 15043e05a..cc9bb2aec 100644 --- a/fyrox-core/src/math/mod.rs +++ b/fyrox-core/src/math/mod.rs @@ -37,7 +37,7 @@ use fyrox_core_derive::{impl_reflect, impl_visit}; impl_reflect!( #[reflect(type_uuid = "64ef33b7-d05a-4d8d-b0c7-99bcc919271f")] - pub struct Rect {} + pub struct Rect {} ); impl Visit for Rect diff --git a/fyrox-core/src/pool/handle.rs b/fyrox-core/src/pool/handle.rs index 2206e6963..29bdd96f9 100644 --- a/fyrox-core/src/pool/handle.rs +++ b/fyrox-core/src/pool/handle.rs @@ -207,6 +207,12 @@ impl Reflect for Handle { None } } + + fn try_compare(&self, other: &dyn Reflect) -> Option { + (other as &dyn std::any::Any) + .downcast_ref::() + .map(|other| other == self) + } } impl Copy for Handle {} diff --git a/fyrox-core/src/pool/mod.rs b/fyrox-core/src/pool/mod.rs index 02f259a10..985a966d2 100644 --- a/fyrox-core/src/pool/mod.rs +++ b/fyrox-core/src/pool/mod.rs @@ -170,6 +170,12 @@ where Some(Box::new(self.clone())) } + fn try_compare(&self, other: &dyn Reflect) -> Option { + (other as &dyn std::any::Any) + .downcast_ref::() + .map(|other| other == self) + } + #[inline] fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) { func(&[]) diff --git a/fyrox-core/src/reflect/impls.rs b/fyrox-core/src/reflect/impls.rs index ba8249907..1186e3349 100644 --- a/fyrox-core/src/reflect/impls.rs +++ b/fyrox-core/src/reflect/impls.rs @@ -334,6 +334,8 @@ macro_rules! impl_reflect_inner_mutability { Some(Box::new($clone)) } + + fn fields_ref(&$self, func: &mut dyn FnMut(&[FieldRef])) { let guard = $acquire_lock_guard; func(&[{ diff --git a/fyrox-core/src/reflect/macros.rs b/fyrox-core/src/reflect/macros.rs index cf699784a..c99ace23a 100644 --- a/fyrox-core/src/reflect/macros.rs +++ b/fyrox-core/src/reflect/macros.rs @@ -158,6 +158,12 @@ macro_rules! blank_reflect { Some(Box::new(self.clone())) } + fn try_compare(&self, other: &dyn Reflect) -> Option { + (other as &dyn std::any::Any) + .downcast_ref::() + .map(|other| other == self) + } + fn fields_ref(&self, func: &mut dyn FnMut(&[$crate::reflect::FieldRef])) { func(&[]) } diff --git a/fyrox-core/src/reflect/mod.rs b/fyrox-core/src/reflect/mod.rs index 1b789ba8d..af3c6cf27 100644 --- a/fyrox-core/src/reflect/mod.rs +++ b/fyrox-core/src/reflect/mod.rs @@ -53,6 +53,7 @@ pub mod prelude { TypeInfo, }; pub use crate::uuid::{uuid, Uuid}; + pub use std::any::Any; } #[inline] @@ -175,6 +176,11 @@ pub trait Reflect: Any + Debug { /// [`None`] for non-cloneable objects. fn try_clone_box(&self) -> Option>; + /// Tries to compare this object with some other. The result is `Some(bool)` if the underlying + /// type implements [`PartialEq`] trait, `None` - otherwise or if the type is marked with + /// `#[reflect(non_comparable)]` attribute. + fn try_compare(&self, other: &dyn Reflect) -> Option; + /// Calls the given closure with the reference to a slice that contains description for all /// fields in the object. fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])); @@ -1021,7 +1027,7 @@ mod test { }, } - #[derive(Reflect, Clone, Default, Debug)] + #[derive(Reflect, Clone, Default, Debug, PartialEq)] #[reflect(type_uuid = "97718a85-3901-407e-9347-b684c0047743")] struct Foo { enum_field: InheritableVariable, @@ -1031,13 +1037,13 @@ mod test { hash_map: HashMap, } - #[derive(Reflect, Clone, Default, Debug)] + #[derive(Reflect, Clone, Default, Debug, PartialEq)] #[reflect(type_uuid = "9465ea72-dd27-43f3-8ccf-b634e4b2887f")] struct Item { payload: u32, } - #[derive(Reflect, Clone, Default, Debug)] + #[derive(Reflect, Clone, Default, Debug, PartialEq)] #[reflect(type_uuid = "8fb478ac-e4c4-4762-a43a-451147e6e509")] struct Bar { stuff: String,