fix functionality of using MetaID

This commit is contained in:
DCFApixels 2025-03-20 10:34:20 +08:00
parent f05767a795
commit 75be984bdc
11 changed files with 274 additions and 84 deletions

View File

@ -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)
{

View File

@ -26,6 +26,7 @@ namespace DCFApixels.DragonECS
}
public static void Activate()
{
if (Instance.GetType() == typeof(UnityDebugService)) { return; }
Set<UnityDebugService>();
}

View File

@ -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");
}
}
}

View File

@ -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<Type> serializableTypes = new List<Type>();
List<EntityEditorBlockDrawer> entityEditorBlockDrawers = new List<EntityEditorBlockDrawer>();
List<Type> serializableTypes = new List<Type>(PREWARMUP_LIST_SIZE);
List<TypeMeta> typeWithMetaIDMetas = new List<TypeMeta>(PREWARMUP_LIST_SIZE);
List<TypeMeta> serializableTypeWithMetaIDMetas = new List<TypeMeta>(PREWARMUP_LIST_SIZE);
List<EntityEditorBlockDrawer> entityEditorBlockDrawers = new List<EntityEditorBlockDrawer>(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<string, Type> _metaIDTypePairs = new Dictionary<string, Type>();
public static bool TryGetTypeForMetaID(string metaID, out Type type)

View File

@ -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<T>() != 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

View File

@ -33,55 +33,89 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
#endregion
private static Dictionary<string, string> _metaIDScriptPathPairs = new Dictionary<string, string>();
public static IReadOnlyDictionary<string, string> MetaIDScriptPathPairs
{
get
{
instance.InitUpdate();
return _metaIDScriptPathPairs;
}
}
private static SparseArray<MonoScript> _scriptsAssets = new SparseArray<MonoScript>(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<string> removedKeys = new List<string>();
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<string> metaIDs = new List<string>();
foreach (var assetPath in MonoScriptsAssetProcessor.NewScriptPaths)
{
ExtractMetaIDs(AssetDatabase.LoadAssetAtPath<MonoScript>(assetPath).text, metaIDs);
foreach (var metaID in metaIDs)
{
_metaIDScriptPathPairs[metaID] = assetPath;
}
}
}
}
List<string> metaIDs = new List<string>();
foreach (var assetPath in MonoScriptsAssetProcessor.NewScriptPaths)
{
ExtractMetaIDs(AssetDatabase.LoadAssetAtPath<MonoScript>(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<string, string>();
}
_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<MonoScript>(assetPath);
if (textAsset != null)
if (assetPath == null)
{
script = textAsset;
_metaIDScriptPathPairs.Remove(metaID);
}
else
{
MonoScript textAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(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<string>(skipped, 0, skippedCount))
{
@ -199,7 +233,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
_scriptsAssets.Add(uniqueID, script);
_scriptsAssets.Add(metaUniqueID, script);
}
return script != null;
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da6b7ba7fc0a44a4f8228f10ef5abcd1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 620c5dc67428c21428ff4bd9c92ed631
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<DeepDebuggerWindow>();
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

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66e2240e9dd52204daec6a089888e7be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}