diff --git a/src/Consts.cs b/src/Consts.cs index aef5ffa..d029ca0 100644 --- a/src/Consts.cs +++ b/src/Consts.cs @@ -7,4 +7,14 @@ public const string DEBUG_LAYER = EcsConsts.NAME_SPACE + "Unity." + nameof(DEBUG_LAYER); } + + public class EcsUnityDefines + { + public const bool DISABLE_SERIALIZE_REFERENCE_RECOVERY = +#if DISABLE_SERIALIZE_REFERENCE_RECOVERY + true; +#else + false; +#endif + } } diff --git a/src/Utils/Reference.cs b/src/Utils/Reference.cs index b2f42ad..57d59a8 100644 --- a/src/Utils/Reference.cs +++ b/src/Utils/Reference.cs @@ -1,15 +1,43 @@ -using System.Runtime.CompilerServices; +//#define DISABLE_SERIALIZE_REFERENCE_RECOVERY +using System; +using System.Runtime.CompilerServices; using UnityEngine; +#if UNITY_EDITOR && !DISABLE_SERIALIZE_REFERENCE_RECOVERY +using DCFApixels.DragonECS.Unity.Internal; +using System.Collections.Generic; +using UnityEditor; +#endif + namespace DCFApixels.DragonECS { - [System.Serializable] +#if UNITY_EDITOR && !DISABLE_SERIALIZE_REFERENCE_RECOVERY + [InitializeOnLoad] + internal static class ReferenceUtility + { + static ReferenceUtility() + { + _recompileAfterInitializationScope = true; + EditorApplication.update += BeforeCompilation; + + } + private static void BeforeCompilation() + { + _recompileAfterInitializationScope = false; + EditorApplication.update -= BeforeCompilation; + } + + internal static bool _recompileAfterInitializationScope = false; + } +#endif + + [Serializable] public struct Reference -#if UNITY_EDITOR +#if UNITY_EDITOR && !DISABLE_SERIALIZE_REFERENCE_RECOVERY : ISerializationCallbackReceiver #endif { -#if UNITY_EDITOR +#if UNITY_EDITOR && !DISABLE_SERIALIZE_REFERENCE_RECOVERY [SerializeReference] private T _value; [SerializeField] @@ -21,41 +49,69 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] set { _value = value; } } -#else +#else + [SerializeField] public T Value; #endif + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return Value == null; } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator T(Reference a) { return a.Value; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Reference(T a) { return new Reference() { Value = a }; } + +#if UNITY_EDITOR && !DISABLE_SERIALIZE_REFERENCE_RECOVERY + private static Dictionary _metaIDTypePairs; -#if UNITY_EDITOR - private static System.Collections.Generic.Dictionary _metaIDTypePairs; private static void InitRecoverCache() { - if (_metaIDTypePairs == null) { return; } - _metaIDTypePairs = new System.Collections.Generic.Dictionary(); + if (_metaIDTypePairs != null) { return; } + _metaIDTypePairs = new Dictionary(); + + List types = new List(); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (var type in assembly.GetTypes()) + { + if (type.TryGetAttribute(out MetaIDAttribute atr)) + { + _metaIDTypePairs.Add(atr.ID, type); + } + } + } } private static T TryRecoverReference(string metaID) { InitRecoverCache(); - if (_metaIDTypePairs.TryGetValue(metaID, out System.Type type)) + if (_metaIDTypePairs.TryGetValue(metaID, out Type type)) { - return (T)System.Activator.CreateInstance(type); + return (T)Activator.CreateInstance(type); } return default; } + + void ISerializationCallbackReceiver.OnAfterDeserialize() { - if (_value == null) + if (_value == null && ReferenceUtility._recompileAfterInitializationScope && string.IsNullOrEmpty(_json) == false) { int indexof = _json.IndexOf(','); _value = TryRecoverReference(_json.Substring(0, indexof)); if (_value == null) { return; } JsonUtility.FromJsonOverwrite(_json.Substring(indexof + 1), _value); - _json = null; } + _json = null; } void ISerializationCallbackReceiver.OnBeforeSerialize() { - _json = $"{_value.GetMeta().MetaID},{JsonUtility.ToJson(_value)}"; + if (_value != null && EditorApplication.isPlaying == false) + { + _json = $"{_value.GetMeta().MetaID},{JsonUtility.ToJson(_value)}"; + } } #endif } -} +} \ No newline at end of file