diff --git a/src/DebugUtils/Editor/SettingsEditor.cs b/src/DebugUtils/Editor/SettingsEditor.cs index e50c171..22b7045 100644 --- a/src/DebugUtils/Editor/SettingsEditor.cs +++ b/src/DebugUtils/Editor/SettingsEditor.cs @@ -78,9 +78,9 @@ namespace DCFApixels.DragonECS.Unity.Editors rect = GUILayoutUtility.GetLastRect(); rect.xMin += 9f; GUI.Label(rect, "Scripting Define Symbols", EditorStyles.whiteLargeLabel); - + InitDefines(); - + EditorGUI.BeginChangeCheck(); foreach (var symbol in _defineSymbols) { diff --git a/src/DebugUtils/UnityDebugService.cs b/src/DebugUtils/UnityDebugService.cs index e0b6f96..15a8bca 100644 --- a/src/DebugUtils/UnityDebugService.cs +++ b/src/DebugUtils/UnityDebugService.cs @@ -26,6 +26,7 @@ namespace DCFApixels.DragonECS } public static void Activate() { + if (Instance.GetType() == typeof(UnityDebugService)) { return; } Set(); } diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index c4f6cbd..aa91f42 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -418,19 +418,29 @@ namespace DCFApixels.DragonECS.Unity.Editors { var current = Event.current; var hover = IconHoverScan(position, current); - using (new ColorScope(new Color(1f, 1f, 1f, hover ? 1f : 0.8f))) + if (GUI.enabled) { - DrawIcon(position, Icons.Instance.FileIcon, hover ? 1f : 2f, "One click - Ping File. Double click - Edit Script"); - } - if (hover) - { - if (current.type == EventType.MouseUp) + using (SetColor(1f, 1f, 1f, hover ? 1f : 0.8f)) { - EditorGUIUtility.PingObject(script); + DrawIcon(position, Icons.Instance.FileIcon, hover ? 1f : 2f, "One click - Ping File. Double click - Edit Script"); } - else if (current.type == EventType.MouseDown && current.clickCount >= 2) + if (hover) { - AssetDatabase.OpenAsset(script); + if (current.type == EventType.MouseUp) + { + EditorGUIUtility.PingObject(script); + } + else if (current.type == EventType.MouseDown && current.clickCount >= 2) + { + AssetDatabase.OpenAsset(script); + } + } + } + else + { + using (SetColor(0.85f, 0.85f, 0.85f, 0.7f)) + { + DrawIcon(position, Icons.Instance.FileIcon, 2f, "One click - Ping File. Double click - Edit Script"); } } } diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs index 8b29d2d..8d33618 100644 --- a/src/Internal/Editor/UnityEditorUtility.cs +++ b/src/Internal/Editor/UnityEditorUtility.cs @@ -1,10 +1,8 @@ -using DCFApixels.DragonECS.Unity.Internal; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; -using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Editors { @@ -101,6 +99,7 @@ namespace DCFApixels.DragonECS.Unity.Editors #if UNITY_EDITOR namespace DCFApixels.DragonECS.Unity.Editors { + using DCFApixels.DragonECS.Unity.Internal; using UnityEditor; using Assembly = System.Reflection.Assembly; @@ -109,12 +108,17 @@ namespace DCFApixels.DragonECS.Unity.Editors { static UnityEditorUtility() { + const int PREWARMUP_LIST_SIZE = 64; EcsWorld.ResetStaticState(); + UnityDebugService.Activate(); _integrationAssembly = typeof(UnityEditorUtility).Assembly; - List serializableTypes = new List(); - List entityEditorBlockDrawers = new List(); + List serializableTypes = new List(PREWARMUP_LIST_SIZE); + List typeWithMetaIDMetas = new List(PREWARMUP_LIST_SIZE); + List serializableTypeWithMetaIDMetas = new List(PREWARMUP_LIST_SIZE); + List entityEditorBlockDrawers = new List(PREWARMUP_LIST_SIZE); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { //var targetTypes = assembly.GetTypes().Where(type => @@ -124,29 +128,75 @@ namespace DCFApixels.DragonECS.Unity.Editors foreach (var type in assembly.GetTypes()) { - if ((type.IsGenericType || type.IsAbstract || type.IsInterface) == false && - typeof(EntityEditorBlockDrawer).IsAssignableFrom(type)) + bool hasMetaID = false; + if (TypeMeta.TryGetCustomMeta(type, out TypeMeta meta) && meta.IsHasMetaID()) { - var drawer = (EntityEditorBlockDrawer)Activator.CreateInstance(type); - entityEditorBlockDrawers.Add(drawer); + typeWithMetaIDMetas.Add(meta); + hasMetaID = true; + } + + if (type.IsConcreteType()) + { + if (typeof(EntityEditorBlockDrawer).IsAssignableFrom(type)) + { + var drawer = (EntityEditorBlockDrawer)Activator.CreateInstance(type); + entityEditorBlockDrawers.Add(drawer); + } + + if (type.IsUnityObject() == false && type.GetConstructor(Type.EmptyTypes) != null) + { + serializableTypes.Add(type); + if (hasMetaID) + { + serializableTypeWithMetaIDMetas.Add(meta); + } + } + } + } + } + _serializableTypes = serializableTypes.ToArray(); + _typeWithMetaIDMetas = typeWithMetaIDMetas.ToArray(); + _serializableTypeWithMetaIDMetas = serializableTypeWithMetaIDMetas.ToArray(); + _entityEditorBlockDrawers = entityEditorBlockDrawers.ToArray(); + + _metaIDCollisions = MetaID.FindMetaIDCollisions(_typeWithMetaIDMetas); + IsHasAnyMetaIDCollision = _metaIDCollisions.IsHasAnyCollision; + if (_metaIDCollisions.IsHasAnyCollision) + { + StringBuilder log = new StringBuilder(); + log.Append("MetaID identifier collisions detected. Some functions that use MetaID were disabled until the collisions were fixed. List of collisions:\r\n"); + + { + int i = 0; + foreach (var collision in _metaIDCollisions) + { + i++; + log.Append('├'); + log.Append($"ID: {collision.MetaID}\r\n"); + int j = 0; + foreach (var meta in collision) + { + j++; + log.Append('│'); + + + if (j == collision.Count) + { + log.Append('└'); + } + else + { + log.Append('├'); + } + + log.Append($"Type: {meta.TypeName}\r\n"); + } } } - var targetTypes = assembly.GetTypes().Where(type => - (type.IsGenericType || type.IsAbstract || type.IsInterface) == false && - type.IsSubclassOf(typeof(UnityObject)) == false && - type.GetConstructor(Type.EmptyTypes) != null); - - serializableTypes.AddRange(targetTypes); + Debug.LogError(log.ToString()); } - _serializableTypes = serializableTypes.ToArray(); - _entityEditorBlockDrawers = entityEditorBlockDrawers.ToArray(); - _serializableTypeWithMetaIDMetas = serializableTypes - .Where(TypeMeta.IsHasMetaID) - .Select(type => type.ToMeta()) - .ToArray(); - - foreach (var item in _serializableTypeWithMetaIDMetas) + foreach (var item in _typeWithMetaIDMetas) { _metaIDTypePairs[item.MetaID] = item.Type; } @@ -160,8 +210,12 @@ namespace DCFApixels.DragonECS.Unity.Editors internal static readonly Assembly _integrationAssembly; internal static readonly Type[] _serializableTypes; - internal static readonly EntityEditorBlockDrawer[] _entityEditorBlockDrawers; + internal static readonly TypeMeta[] _typeWithMetaIDMetas; internal static readonly TypeMeta[] _serializableTypeWithMetaIDMetas; + internal static readonly EntityEditorBlockDrawer[] _entityEditorBlockDrawers; + + internal static readonly MetaID.CollisionList _metaIDCollisions; + public static readonly bool IsHasAnyMetaIDCollision; private static readonly Dictionary _metaIDTypePairs = new Dictionary(); public static bool TryGetTypeForMetaID(string metaID, out Type type) diff --git a/src/Internal/ReflectionExtensions.cs b/src/Internal/ReflectionExtensions.cs index 074469d..c321bdf 100644 --- a/src/Internal/ReflectionExtensions.cs +++ b/src/Internal/ReflectionExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Reflection; using System.Runtime.CompilerServices; +using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Internal { @@ -18,6 +19,20 @@ namespace DCFApixels.DragonECS.Unity.Internal { return self.GetCustomAttribute() != null; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsConcreteType(this Type self) + { + if (self.IsGenericType || self.IsAbstract || self.IsInterface) + { + return false; + } + return self.IsValueType || self.IsClass; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsUnityObject(this Type self) + { + return self.IsSubclassOf(typeof(UnityObject)); + } } } #endif diff --git a/src/Internal/ScriptsCache.cs b/src/Internal/ScriptsCache.cs index 9319f78..151749d 100644 --- a/src/Internal/ScriptsCache.cs +++ b/src/Internal/ScriptsCache.cs @@ -33,55 +33,89 @@ namespace DCFApixels.DragonECS.Unity.Editors } #endregion private static Dictionary _metaIDScriptPathPairs = new Dictionary(); + public static IReadOnlyDictionary MetaIDScriptPathPairs + { + get + { + instance.InitUpdate(); + return _metaIDScriptPathPairs; + } + } private static SparseArray _scriptsAssets = new SparseArray(256); + public static void Reinit() + { + instance._isInit = false; + _metaIDScriptPathPairs.Clear(); + instance.InitUpdate(); + } + #region Init/Update + private static object _lock = new object(); private void InitUpdate() { Init(); - if (MonoScriptsAssetProcessor.Version <= _version) { return; } - - if (MonoScriptsAssetProcessor.RemovedScriptPaths.Count > 0) + lock (_lock) { - uint pathsLength = (uint)MonoScriptsAssetProcessor.RemovedScriptPaths.Count; - string[] paths = new string[pathsLength]; - int i = 0; - foreach (var path in MonoScriptsAssetProcessor.RemovedScriptPaths) + if (MonoScriptsAssetProcessor.Version <= _version) { return; } + + if (MonoScriptsAssetProcessor.RemovedScriptPaths.Count > 0) { - paths[i++] = path; - } - foreach (var metaIDScriptPathPair in _metaIDScriptPathPairs) - { - for (uint j = 0; j < pathsLength; j++) + List removedKeys = new List(); + uint pathsLength = (uint)MonoScriptsAssetProcessor.RemovedScriptPaths.Count; + string[] paths = new string[pathsLength]; + int i = 0; + foreach (var path in MonoScriptsAssetProcessor.RemovedScriptPaths) { - if (paths[j] == metaIDScriptPathPair.Value) + paths[i++] = path; + } + foreach (var metaIDScriptPathPair in _metaIDScriptPathPairs) + { + for (uint j = 0; j < pathsLength; j++) { - _metaIDScriptPathPairs[metaIDScriptPathPair.Key] = null; + if (paths[j] == metaIDScriptPathPair.Value) + { + removedKeys.Add(metaIDScriptPathPair.Key); + } + } + } + + foreach (var key in removedKeys) + { + _metaIDScriptPathPairs.Remove(key); + } + } + + if (MonoScriptsAssetProcessor.NewScriptPaths.Count > 0) + { + List metaIDs = new List(); + foreach (var assetPath in MonoScriptsAssetProcessor.NewScriptPaths) + { + ExtractMetaIDs(AssetDatabase.LoadAssetAtPath(assetPath).text, metaIDs); + foreach (var metaID in metaIDs) + { + _metaIDScriptPathPairs[metaID] = assetPath; } } } - } - List metaIDs = new List(); - foreach (var assetPath in MonoScriptsAssetProcessor.NewScriptPaths) - { - ExtractMetaIDs(AssetDatabase.LoadAssetAtPath(assetPath).text, metaIDs); - foreach (var metaID in metaIDs) - { - _metaIDScriptPathPairs[metaID] = assetPath; - } - } - _version = MonoScriptsAssetProcessor.Version; + _version = MonoScriptsAssetProcessor.Version; - Save(true); + Save(true); + } } private void Init() { if (_isInit && _metaIDScriptPathPairs.Count > 0) { return; } + if (_metaIDScriptPathPairs == null) + { + _metaIDScriptPathPairs = new Dictionary(); + } + _metaIDScriptPathPairs.Clear(); var scriptGuids = AssetDatabase.FindAssets($"* t:MonoScript"); @@ -113,44 +147,44 @@ namespace DCFApixels.DragonECS.Unity.Editors Save(true); } - public void Reinit() - { - _isInit = false; - InitUpdate(); - } #endregion #region Get public static bool TryGetScriptAsset(TypeMeta meta, out MonoScript script) { - int uniqueID = meta.GetHashCode(); + int metaUniqueID = meta.GetHashCode(); - if (_scriptsAssets.TryGetValue(uniqueID, out script) == false) + if (_scriptsAssets.TryGetValue(metaUniqueID, out script) == false) { script = null; //Ищем по мета айди совпадения - string metaID = meta.MetaID; - if (string.IsNullOrEmpty(metaID) == false) + if (UnityEditorUtility.IsHasAnyMetaIDCollision == false) { - instance.InitUpdate(); - if (_metaIDScriptPathPairs.TryGetValue(metaID, out string assetPath)) + if (meta.IsHasMetaID()) { - if (assetPath == null) + instance.InitUpdate(); + + string metaID = meta.MetaID; + if (_metaIDScriptPathPairs.TryGetValue(metaID, out string assetPath)) { - _metaIDScriptPathPairs.Remove(metaID); - } - else - { - MonoScript textAsset = AssetDatabase.LoadAssetAtPath(assetPath); - if (textAsset != null) + if (assetPath == null) { - script = textAsset; + _metaIDScriptPathPairs.Remove(metaID); + } + else + { + MonoScript textAsset = AssetDatabase.LoadAssetAtPath(assetPath); + if (textAsset != null) + { + script = textAsset; + } } } } } + if (script == null) { //Ищем совпадения имен в ассетах @@ -170,7 +204,7 @@ namespace DCFApixels.DragonECS.Unity.Editors if (assetPath.IndexOf("Packages/com.unity.") == 0) { - if(skippedCount == 0) + if (skippedCount == 0) { skipped = new string[guids.Length]; } @@ -185,7 +219,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } } - if(script == null) + if (script == null) { foreach (var assetPath in new ReadOnlySpan(skipped, 0, skippedCount)) { @@ -199,7 +233,9 @@ namespace DCFApixels.DragonECS.Unity.Editors } } - _scriptsAssets.Add(uniqueID, script); + + + _scriptsAssets.Add(metaUniqueID, script); } return script != null; } diff --git a/src/Tools/DeepDebugger.meta b/src/Tools/DeepDebugger.meta new file mode 100644 index 0000000..4e969fc --- /dev/null +++ b/src/Tools/DeepDebugger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da6b7ba7fc0a44a4f8228f10ef5abcd1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Tools/DeepDebugger/Editors.meta b/src/Tools/DeepDebugger/Editors.meta new file mode 100644 index 0000000..5dc3fff --- /dev/null +++ b/src/Tools/DeepDebugger/Editors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 620c5dc67428c21428ff4bd9c92ed631 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs b/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs new file mode 100644 index 0000000..0611cda --- /dev/null +++ b/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs @@ -0,0 +1,47 @@ +#if UNITY_EDITOR +using DCFApixels.DragonECS.Unity.Internal; +using UnityEditor; +using UnityEngine; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + internal class DeepDebuggerWindow : EditorWindow + { + public const string TITLE = "DeepDebuggerWindow"; + +#if DRAGONECS_DEEP_DEBUG + [MenuItem("Tools/" + EcsConsts.FRAMEWORK_NAME + "/" + TITLE)] + static void Open() + { + var wnd = GetWindow(); + wnd.titleContent = new GUIContent(TITLE); + wnd.minSize = new Vector2(100f, 120f); + wnd.Show(); + } +#endif + + private Vector2 pos; + private void OnGUI() + { + var dicst = ScriptsCache.MetaIDScriptPathPairs; + + pos = GUILayout.BeginScrollView(pos); + + if (GUILayout.Button("Reset")) + { + ScriptsCache.Reinit(); + } + + foreach (var (metaID, scriptPath) in dicst) + { + GUILayout.Label("", GUILayout.ExpandWidth(true)); + Rect rect = GUILayoutUtility.GetLastRect(); + var (leftRect, rightRect) = rect.HorizontalSliceLerp(0.5f); + GUI.Label(leftRect, metaID); + GUI.Label(rightRect, scriptPath); + } + GUILayout.EndScrollView(); + } + } +} +#endif diff --git a/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs.meta b/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs.meta new file mode 100644 index 0000000..855daa6 --- /dev/null +++ b/src/Tools/DeepDebugger/Editors/DeepDebuggerWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66e2240e9dd52204daec6a089888e7be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Tools/DragonDocs/DragonDocs.cs b/src/Tools/DragonDocs/DragonDocs.cs index cc37c01..1795f05 100644 --- a/src/Tools/DragonDocs/DragonDocs.cs +++ b/src/Tools/DragonDocs/DragonDocs.cs @@ -42,7 +42,7 @@ namespace DCFApixels.DragonECS.Unity.Docs { foreach (var type in assembly.GetTypes()) { - if (TypeMeta.IsHasMeta(type)) + if (TypeMeta.IsHasCustomMeta(type)) { result.Add(type); }