From dc0aae1c67a3451961e5c7193a73e662d30cec60 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:55:10 +0800 Subject: [PATCH] fixes --- src/Internal/Editor/EcsGUI.cs | 15 +++ src/Internal/Editor/ExtendedEditor.cs | 6 -- src/Internal/Editor/MetaObjectsDropDown.cs | 2 +- .../ReferenceButtonAttributeDrawer.cs | 46 ++++++++-- src/Internal/ReflectionExtensions.cs | 92 ++++++++++++++++++- 5 files changed, 145 insertions(+), 16 deletions(-) diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index 58da319..c4a05bd 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -855,6 +855,21 @@ namespace DCFApixels.DragonECS.Unity.Editors } return result; } + internal static bool HasSerializableData(this SerializedProperty property) + { + var propsCounter = property.Copy(); + int lastDepth = propsCounter.depth; + bool next = propsCounter.Next(true) && lastDepth < propsCounter.depth; + while (next) + { + if(propsCounter.propertyType != SerializedPropertyType.Generic) + { + return true; + } + next = propsCounter.Next(true) && lastDepth < propsCounter.depth; + } + return false; + } #endregion #region SelectPanelColor diff --git a/src/Internal/Editor/ExtendedEditor.cs b/src/Internal/Editor/ExtendedEditor.cs index 6880c6d..d4f267d 100644 --- a/src/Internal/Editor/ExtendedEditor.cs +++ b/src/Internal/Editor/ExtendedEditor.cs @@ -222,20 +222,14 @@ namespace DCFApixels.DragonECS.Unity.Editors protected virtual void OnStaticInit() { } protected virtual void OnInit() { } - //private Stopwatch _stopwatch = new Stopwatch(); - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - //_stopwatch.Restart(); using (EcsGUI.CheckChanged(property.serializedObject)) { StaticInit(); Init(); DrawCustom(position, property, label); } - //_stopwatch.Stop(); - //var result = _stopwatch.Elapsed; - //UnityEngine.Debug.Log($"{result.Minutes}:{result.Seconds}:{result.Milliseconds}"); } protected abstract void DrawCustom(Rect position, SerializedProperty property, GUIContent label); } diff --git a/src/Internal/Editor/MetaObjectsDropDown.cs b/src/Internal/Editor/MetaObjectsDropDown.cs index 2841098..afe5f8a 100644 --- a/src/Internal/Editor/MetaObjectsDropDown.cs +++ b/src/Internal/Editor/MetaObjectsDropDown.cs @@ -99,7 +99,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } else { - meta = dummy.Type.GetMeta(); + meta = dummy.Type.ToMeta(); } return (dummy, meta); }); diff --git a/src/Internal/ReferenceButtonAttributeDrawer.cs b/src/Internal/ReferenceButtonAttributeDrawer.cs index 6bdb4a3..014ed18 100644 --- a/src/Internal/ReferenceButtonAttributeDrawer.cs +++ b/src/Internal/ReferenceButtonAttributeDrawer.cs @@ -10,6 +10,26 @@ namespace DCFApixels.DragonECS.Unity.Editors } #if UNITY_EDITOR +namespace DCFApixels.DragonECS.Unity.Internal +{ + using DCFApixels.DragonECS.Unity.Editors; + using UnityEditor; + internal partial class UnityReflectionCache + { + public bool IsReferenceButtonCacheInit_Editor; + public bool InitReferenceButtonCache_Editor(SerializedProperty sp) + { + if (IsReferenceButtonCacheInit_Editor) { return false; } + + HasSerializableData_Editor = sp.HasSerializableData(); + + IsReferenceButtonCacheInit_Editor = true; + return true; + } + public bool HasSerializableData_Editor; + } +} + namespace DCFApixels.DragonECS.Unity.Editors { using DCFApixels.DragonECS.Unity.Internal; @@ -26,19 +46,30 @@ namespace DCFApixels.DragonECS.Unity.Editors { Type fieldType = fieldInfo.FieldType; _withOutTypes = fieldType.TryGetAttribute(out ReferenceButtonWithOutAttribute a) ? a.PredicateTypes : Array.Empty(); - if (fieldType.IsGenericType) + //if (fieldType.IsGenericType) + //{ + // if (fieldType.IsGenericTypeDefinition == false) + // { + // fieldType = fieldType.GetGenericTypeDefinition(); + // } + //} + } + + private UnityReflectionCache _reflectionCache; + private UnityReflectionCache Cahce(SerializedProperty sp) + { + if (UnityReflectionCache.InitLocal(sp.managedReferenceValue.GetType(), ref _reflectionCache)) { - if (fieldType.IsGenericTypeDefinition == false) - { - fieldType = fieldType.GetGenericTypeDefinition(); - } + _reflectionCache.InitReferenceButtonCache_Editor(sp); } + return _reflectionCache; } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { Init(); - if (property.managedReferenceValue != null) + if (property.managedReferenceValue != null && + Cahce(property).HasSerializableData_Editor) { return EditorGUI.GetPropertyHeight(property, label, true); } @@ -58,7 +89,8 @@ namespace DCFApixels.DragonECS.Unity.Editors selButtnoRect.height = OneLineHeight; DrawSelectionPopupButton(selButtnoRect, property); - if (property.managedReferenceValue != null) + if (property.managedReferenceValue != null && + Cahce(property).HasSerializableData_Editor) { EditorGUI.PropertyField(position, property, label, true); } diff --git a/src/Internal/ReflectionExtensions.cs b/src/Internal/ReflectionExtensions.cs index 177d7ee..cffa79e 100644 --- a/src/Internal/ReflectionExtensions.cs +++ b/src/Internal/ReflectionExtensions.cs @@ -1,7 +1,9 @@ #if UNITY_EDITOR using System; +using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; +using UnityEngine; using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Internal @@ -33,20 +35,106 @@ namespace DCFApixels.DragonECS.Unity.Internal { return self.IsSubclassOf(typeof(UnityObject)); } + public static bool HasUnitySerializableFields(this Type self) + { + var fields = self.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + if (fields.Length <= 0) + { + return false; + } + foreach (var field in fields) + { + if (field.IsUnitySerializableField() && + (field.FieldType.IsUnitySerializableLeafType() || + HasUnitySerializableFields(field.FieldType))) + { + return true; + } + } + return false; + } + public static bool IsUnitySerializableField(this FieldInfo self) + { + if ((self.IsPublic || self.HasAttribute()) && self.FieldType.IsUnitySerializableType()) + { + return true; + } + { + if (self.HasAttribute()) + { + return true; + } + return false; + } + } + public static bool IsUnitySerializableLeafType(this Type self) + { + if (self.IsPrimitive) + { + return true; + } + if (self.IsEnum) + { + return true; + } + if (self == typeof(string)) + { + return true; + } + return false; + } + public static bool IsUnitySerializableType(this Type self) + { + if (self.IsAbstract) + { + return false; + } + if (self.IsUnitySerializableLeafType()) + { + return true; + } + return self.HasAttribute(); + } - private static MethodInfo memberwiseCloneMethdo = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); + private static MethodInfo _memberwiseCloneMethdo = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); internal static object Clone_Reflection(this object obj) { if (obj is ICloneable cloneable) { return cloneable.Clone(); } - return memberwiseCloneMethdo.Invoke(obj, null); + return _memberwiseCloneMethdo.Invoke(obj, null); } internal static object Clone_Reflection(this T obj) { return Clone_Reflection((object)obj); } } + + internal partial class UnityReflectionCache + { + private static readonly Dictionary _cache = new Dictionary(); + public static bool InitLocal(Type type, ref UnityReflectionCache localCache) + { + if (localCache != null && localCache.Type == type) { return false; } + localCache = Get(type); + return true; + } + public static UnityReflectionCache Get(Type type) + { + if(_cache.TryGetValue(type, out var result) == false) + { + result = new UnityReflectionCache(type); + _cache.Add(type, result); + } + return result; + } + + public readonly Type Type; + public UnityReflectionCache(Type type) + { + Type = type; + } + } } #endif