impl script finding using meta id

This commit is contained in:
Mikhail 2024-09-27 22:04:00 +08:00
parent a6bb3799d3
commit 62d71d2a21
15 changed files with 605 additions and 56 deletions

View File

@ -8,6 +8,7 @@ using UnityEditor;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[MetaColor(MetaColor.DragonCyan)] [MetaColor(MetaColor.DragonCyan)]
[MetaID("14AC6B239201C6A60337AF3384D237E7")]
[MetaGroup(EcsUnityConsts.PACK_GROUP, EcsConsts.COMPONENTS_GROUP)] [MetaGroup(EcsUnityConsts.PACK_GROUP, EcsConsts.COMPONENTS_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "This component is automatically added if an entity is connected to one of the EcsEntityConnect. It also contains a reference to the connected EcsEntityConnect.")] [MetaDescription(EcsConsts.AUTHOR, "This component is automatically added if an entity is connected to one of the EcsEntityConnect. It also contains a reference to the connected EcsEntityConnect.")]
public readonly struct GameObjectConnect : IEcsComponent, IEcsComponentLifecycle<GameObjectConnect> public readonly struct GameObjectConnect : IEcsComponent, IEcsComponentLifecycle<GameObjectConnect>

View File

@ -1,5 +1,4 @@
#if UNITY_EDITOR #if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEditor; using UnityEditor;

View File

@ -254,7 +254,7 @@ namespace DCFApixels.DragonECS.Unity.Docs.Editors
using (EcsGUI.Layout.BeginHorizontal()) using (EcsGUI.Layout.BeginHorizontal())
{ {
GUILayout.TextArea(IsUseCustomNames ? meta.Name : meta.TypeName, EditorStyles.boldLabel, GUILayout.ExpandWidth(false)); GUILayout.TextArea(IsUseCustomNames ? meta.Name : meta.TypeName, EditorStyles.boldLabel, GUILayout.ExpandWidth(false));
if (meta.TryGetSourceType(out System.Type targetType) && UnityEditorUtility.TryGetScriptAsset(targetType, out MonoScript script)) if (meta.TryGetSourceType(out System.Type targetType) && ScriptsCache.TryGetScriptAsset(targetType, out MonoScript script))
{ {
EcsGUI.Layout.ScriptAssetButton(script, GUILayout.Width(19f)); EcsGUI.Layout.ScriptAssetButton(script, GUILayout.Width(19f));
} }

View File

@ -0,0 +1,89 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
internal class MonoScriptsAssetProcessor : AssetPostprocessor
{
private static long _version;
public static long Version { get { return _version; } }
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
{
_removedScriptGuids.Clear();
_newScriptIDs.Clear();
foreach (string str in importedAssets)
{
Debug.Log("Reimported Asset: " + str);
ProcessAssetPath(str);
}
foreach (string str in deletedAssets)
{
Debug.Log("Deleted Asset: " + str);
RemoveAssetPath(str);
}
for (int i = 0; i < movedAssets.Length; i++)
{
Debug.Log("Moved Asset: " + movedAssets[i] + " from: " + movedFromAssetPaths[i]);
RemoveAssetPath(movedFromAssetPaths[i]);
ProcessAssetPath(movedAssets[i]);
}
if (didDomainReload)
{
Debug.Log("Domain has been reloaded");
}
foreach (var item in _removedScriptGuids)
{
Debug.Log(item);
}
foreach (var item in _newScriptIDs)
{
Debug.Log(item);
}
_version = DateTime.Now.Ticks;
}
private static List<string> _removedScriptGuids = new List<string>();
private static List<string> _newScriptIDs = new List<string>();
public static IReadOnlyCollection<string> RemovedScriptPaths
{
get { return _removedScriptGuids; }
}
public static IReadOnlyCollection<string> NewScriptPaths
{
get { return _newScriptIDs; }
}
private static void RemoveAssetPath(string filePath)
{
if (IsScript(filePath) == false) { return; }
Debug.Log("RemoveAssetPath: " + filePath);
_removedScriptGuids.Add(filePath);
}
private static void ProcessAssetPath(string filePath)
{
if (IsScript(filePath) == false) { return; }
Debug.Log("ProcessAssetPath: " + filePath);
var script = AssetDatabase.LoadAssetAtPath<MonoScript>(filePath).text;
_newScriptIDs.Add(filePath);
}
private static bool IsScript(string filePath)
{
int i = filePath.Length - 3;
return filePath[i++] == '.'
&& filePath[i++] == 'c'
&& filePath[i++] == 's';
}
}
}
#endif

View File

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

302
src/Editor/ScriptsCache.cs Normal file
View File

@ -0,0 +1,302 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
[FilePath(EcsUnityConsts.LOCAL_CACHE_FOLDER + "/" + nameof(ScriptsCache) + ".prefs", FilePathAttribute.Location.ProjectFolder)]
internal class ScriptsCache : ScriptableSingleton<ScriptsCache>, ISerializationCallbackReceiver
{
[SerializeField]
private bool _isInit = false;
[SerializeField]
private long _version;
#region [SerializeField]
[SerializeField]
private Pair[] _serializableMetaIDScriptPathPairs;
[Serializable]
private struct Pair
{
public string metaID;
public string scriptPath;
public Pair(string metaID, string scriptPath)
{
this.metaID = metaID;
this.scriptPath = scriptPath;
}
}
#endregion
private static Dictionary<string, string> _metaIDScriptPathPairs = new Dictionary<string, string>();
private static SparseArray<MonoScript> _scriptsAssets = new SparseArray<MonoScript>(256);
#region Init/Update
private void InitUpdate()
{
Init();
if (MonoScriptsAssetProcessor.Version <= _version) { return; }
if (MonoScriptsAssetProcessor.RemovedScriptPaths.Count > 0)
{
uint pathsLength = (uint)MonoScriptsAssetProcessor.RemovedScriptPaths.Count;
string[] paths = new string[pathsLength];
int i = 0;
foreach (var path in MonoScriptsAssetProcessor.RemovedScriptPaths)
{
paths[i++] = path;
}
foreach (var metaIDScriptPathPair in _metaIDScriptPathPairs)
{
for (uint j = 0; j < pathsLength; j++)
{
if (paths[j] == metaIDScriptPathPair.Value)
{
_metaIDScriptPathPairs[metaIDScriptPathPair.Key] = null;
}
}
}
}
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;
Save(true);
}
private void Init()
{
if (_isInit) { return; }
_metaIDScriptPathPairs.Clear();
var scriptGuids = AssetDatabase.FindAssets($"* t:MonoScript");
List<string> metaIDsBuffer = new List<string>();
foreach (var guid in scriptGuids)
{
string scriptPath = AssetDatabase.GUIDToAssetPath(guid);
string script = AssetDatabase.LoadAssetAtPath<MonoScript>(scriptPath).text;
if (scriptPath.EndsWith("MetaIDAttribute.cs") == false)
{
ExtractMetaIDs(script, metaIDsBuffer);
}
foreach (var metaID in metaIDsBuffer)
{
_metaIDScriptPathPairs[metaID] = scriptPath;
}
metaIDsBuffer.Clear();
}
foreach (var pair in _metaIDScriptPathPairs)
{
EcsDebug.PrintPass($"k:{pair.Key} v:{pair.Value}");
}
_isInit = true;
Save(true);
}
public void Reinit()
{
_isInit = false;
InitUpdate();
}
#endregion
#region Get
public static bool TryGetScriptAsset(Type meta, out MonoScript script) { return TryGetScriptAsset(meta.GetMeta(), out script); }
public static bool TryGetScriptAsset(TypeMeta meta, out MonoScript script)
{
int uniqueID = meta.GetHashCode();
if (_scriptsAssets.TryGetValue(uniqueID, out script) == false)
{
script = null;
//Ищем по мета айди совпадения
string metaID = meta.MetaID;
if (string.IsNullOrEmpty(metaID) == false)
{
instance.InitUpdate();
if (_metaIDScriptPathPairs.TryGetValue(metaID, out string assetPath))
{
if (assetPath == null)
{
_metaIDScriptPathPairs.Remove(metaID);
}
else
{
MonoScript textAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(assetPath);
if (textAsset != null)
{
script = textAsset;
}
}
}
}
if (script == null)
{
//Ищем совпадения имет в ассетах
string name = meta.TypeName;
int genericTypeCharIndex = name.IndexOf('<');
if (genericTypeCharIndex >= 0)
{
name = name.Substring(0, genericTypeCharIndex);
}
var guids = AssetDatabase.FindAssets($"{name} t:MonoScript");
for (var i = 0; i < guids.Length; i++)
{
MonoScript textAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(AssetDatabase.GUIDToAssetPath(guids[i]));
if (textAsset != null && textAsset.name == name)
{
script = textAsset;
break;
}
}
}
_scriptsAssets.Add(uniqueID, script);
}
return script != null;
}
#endregion
#region ParseUtils
private static void ExtractMetaIDs(string script, List<string> outputList)
{
const string PATTERN = "MetaID";
int lastIndex = 0;
while (true)
{
int index = script.IndexOf(PATTERN, lastIndex) + PATTERN.Length;
if (index < lastIndex || index < PATTERN.Length) { break; }
lastIndex = index;
for (int i = index; i < script.Length; i++)
{
char chr = script[i];
if (char.IsWhiteSpace(chr) == false)
{
if (chr != '(')
{
index = -1;
}
break;
}
}
if (index < 0) { continue; }
int startIndex = -1, endIndex = -1;
bool isVerbal = false;
for (int i = index; i < script.Length; i++)
{
char chr = script[i];
if (chr == '@')
{
isVerbal = true;
if (script.Length <= ++i) { break; }
chr = script[i];
}
if (chr == '"')
{
if (script.Length <= ++i) { break; }
startIndex = i;
break;
}
}
if (startIndex < 0) { continue; }
for (int i = startIndex; i < script.Length; i++)
{
char chr = script[i];
if (chr == '\\')
{
if (script.Length <= ++i) { break; }
continue;
}
if (chr == '"')
{
if (isVerbal)
{
if (script.Length <= ++i) { break; }
if (script[i] != '"')
{
endIndex = i - 2;
break;
}
}
else
{
endIndex = --i;
break;
}
}
}
if (endIndex < startIndex) { continue; }
string substring = script.Substring(startIndex, endIndex - startIndex + 1);
if (isVerbal)
{
outputList.Add(substring.Replace("\"\"", "\""));
}
else
{
outputList.Add(Regex.Unescape(substring));
}
}
}
private static bool IsScript(string filePath)
{
int i = filePath.Length - 3;
return filePath[i++] == '.'
&& filePath[i++] == 'c'
&& filePath[i++] == 's';
}
#endregion
#region ISerializationCallbackReceiver
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
_serializableMetaIDScriptPathPairs = new Pair[_metaIDScriptPathPairs.Count];
int i = 0;
foreach (var item in _metaIDScriptPathPairs)
{
_serializableMetaIDScriptPathPairs[i++] = new Pair(item.Key, item.Value);
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (_serializableMetaIDScriptPathPairs == null) { return; }
foreach (var item in _serializableMetaIDScriptPathPairs)
{
if (string.IsNullOrEmpty(item.scriptPath))
{
_metaIDScriptPathPairs.Add(item.metaID, item.scriptPath);
}
}
}
#endregion
}
}
#endif

View File

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

View File

@ -526,7 +526,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
public static bool DrawTypeMetaElementBlock(ref Rect position, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementProperty, ITypeMeta meta) public static bool DrawTypeMetaElementBlock(ref Rect position, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementProperty, ITypeMeta meta)
{ {
var result = DrawTypeMetaBlock_Internal(ref position, elementProperty, meta); var result = DrawTypeMetaBlock_Internal(ref position, elementProperty, meta, elementIndex, arrayProperty.arraySize);
if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked)) if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked))
{ {
arrayProperty.DeleteArrayElementAtIndex(elementIndex); arrayProperty.DeleteArrayElementAtIndex(elementIndex);
@ -549,7 +549,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
Drop = 1 << 0, Drop = 1 << 0,
CloseButtonClicked = 1 << 1, CloseButtonClicked = 1 << 1,
} }
private static DrawTypeMetaBlockResult DrawTypeMetaBlock_Internal(ref Rect position, SerializedProperty property, ITypeMeta meta) private static DrawTypeMetaBlockResult DrawTypeMetaBlock_Internal(ref Rect position, SerializedProperty property, ITypeMeta meta, int index = -1, int total = -1)
{ {
Color alphaPanelColor; Color alphaPanelColor;
if (meta == null) if (meta == null)
@ -561,18 +561,26 @@ namespace DCFApixels.DragonECS.Unity.Editors
return DrawTypeMetaBlockResult.None; return DrawTypeMetaBlockResult.None;
} }
var counter = property.Copy();
int positionCountr = int.MaxValue;
int depth = -1;
while (counter.NextVisibleDepth(false, ref depth))
{
positionCountr--;
}
string name = meta.Name; string name = meta.Name;
string description = meta.Description.Text; string description = meta.Description.Text;
alphaPanelColor = SelectPanelColor(meta, positionCountr, -1).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); int positionCountr;
if (index < 0)
{
positionCountr = int.MaxValue;
var counter = property.Copy();
int depth = -1;
while (counter.NextVisibleDepth(false, ref depth))
{
positionCountr--;
}
}
else
{
positionCountr = index;
}
alphaPanelColor = SelectPanelColor(meta, positionCountr, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA; alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None; DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None;
@ -605,7 +613,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
return result; return result;
} }
//Edit script button //Edit script button
if (UnityEditorUtility.TryGetScriptAsset(meta.Type, out MonoScript script)) if (ScriptsCache.TryGetScriptAsset(meta.FindRootTypeMeta(), out MonoScript script))
{ {
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
ScriptAssetButton(optionButton, script); ScriptAssetButton(optionButton, script);
@ -1136,7 +1144,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
return; return;
} }
//Edit script button //Edit script button
if (UnityEditorUtility.TryGetScriptAsset(componentType, out MonoScript script)) if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script))
{ {
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
EcsGUI.ScriptAssetButton(optionButton, script); EcsGUI.ScriptAssetButton(optionButton, script);

View File

@ -43,6 +43,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
get { return UserSettingsPrefs.instance.IsShowHidden; } get { return UserSettingsPrefs.instance.IsShowHidden; }
set { UserSettingsPrefs.instance.IsShowHidden = value; } set { UserSettingsPrefs.instance.IsShowHidden = value; }
} }
private static ComponentColorMode ComponentColorMode
{
get { return UserSettingsPrefs.instance.ComponentColorMode; }
set { UserSettingsPrefs.instance.ComponentColorMode = value; }
}
protected bool IsMultipleTargets => targets.Length > 1; protected bool IsMultipleTargets => targets.Length > 1;
protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsStaticInit { get { return _isStaticInit; } }
@ -152,6 +158,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
get { return UserSettingsPrefs.instance.IsShowHidden; } get { return UserSettingsPrefs.instance.IsShowHidden; }
set { UserSettingsPrefs.instance.IsShowHidden = value; } set { UserSettingsPrefs.instance.IsShowHidden = value; }
} }
private static ComponentColorMode ComponentColorMode
{
get { return UserSettingsPrefs.instance.ComponentColorMode; }
set { UserSettingsPrefs.instance.ComponentColorMode = value; }
}
protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsStaticInit { get { return _isStaticInit; } }
protected virtual bool IsInit { get { return _isInit; } } protected virtual bool IsInit { get { return _isInit; } }
protected void StaticInit() protected void StaticInit()

View File

@ -66,6 +66,7 @@ namespace DCFApixels.DragonECS.Unity.Internal
} }
public static void DebugRect_Editor(params Rect[] rects) public static void DebugRect_Editor(params Rect[] rects)
{ {
#if UNITY_EDITOR
uint colorState = NextXorShiftState(3136587146); uint colorState = NextXorShiftState(3136587146);
foreach (var rect in rects) foreach (var rect in rects)
{ {
@ -75,6 +76,7 @@ namespace DCFApixels.DragonECS.Unity.Internal
GUI.Box(rect, "", EditorStyles.selectionRect); GUI.Box(rect, "", EditorStyles.selectionRect);
EditorGUI.DrawRect(rect, color); EditorGUI.DrawRect(rect, color);
} }
#endif
} }
#endregion #endregion

View File

@ -99,7 +99,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
_reorderableRecordsList.onRemoveCallback += OnReorderableListRemove; _reorderableRecordsList.onRemoveCallback += OnReorderableListRemove;
_reorderableRecordsList.drawElementCallback += OnReorderableListDrawEmptyElement; _reorderableRecordsList.drawElementCallback += OnReorderableListDrawEmptyElement;
_reorderableRecordsList.drawElementBackgroundCallback += OnReorderableRecordsListDrawElement; _reorderableRecordsList.drawElementBackgroundCallback += OnReorderableRecordsListDrawElement;
_reorderableRecordsList.drawNoneElementCallback += OnReorderableRecordsListDrawNoneElement; _reorderableRecordsList.drawNoneElementCallback += OnReorderableListDrawNoneElement;
_reorderableRecordsList.elementHeightCallback += OnReorderableRecordsListElementHeight; _reorderableRecordsList.elementHeightCallback += OnReorderableRecordsListElementHeight;
_reorderableRecordsList.onReorderCallback += OnReorderableListReorder; _reorderableRecordsList.onReorderCallback += OnReorderableListReorder;
_reorderableRecordsList.showDefaultBackground = false; _reorderableRecordsList.showDefaultBackground = false;
@ -110,19 +110,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
_systemsDropDown = new SystemsDropDown(); _systemsDropDown = new SystemsDropDown();
} }
private void OnReorderableRecordsListDrawNoneElement(Rect rect) #region _reorderableList
{ private void OnReorderableListDrawNoneElement(Rect rect) { }
}
private void OnReorderableListDrawEmptyElement(Rect rect, int index, bool isActive, bool isFocused) { } private void OnReorderableListDrawEmptyElement(Rect rect, int index, bool isActive, bool isFocused) { }
private void OnReorderableListReorder(ReorderableList list) private void OnReorderableListReorder(ReorderableList list)
{ {
EcsGUI.Changed = true; EcsGUI.Changed = true;
} }
#region _reorderableList
private void OnReorderableListRemove(ReorderableList list) private void OnReorderableListRemove(ReorderableList list)
{ {
if (list.selectedIndices.Count <= 0) if (list.selectedIndices.Count <= 0)
@ -163,15 +157,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
#region _reorderableRecordsList #region _reorderableRecordsList
private void OnReorderableRecordsListDrawElement(Rect rect, int index, bool isActive, bool isFocused) private void OnReorderableRecordsListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{ {
if (index < 0) { return; } if (index < 0 || Event.current.type == EventType.Used) { return; }
rect = rect.AddPadding(OneLineHeight + Spacing, Spacing * 2f, Spacing, Spacing); rect = rect.AddPadding(OneLineHeight + Spacing, Spacing * 2f, Spacing, Spacing);
using (EcsGUI.CheckChanged()) using (EcsGUI.CheckChanged())
{ {
if (Event.current.type == EventType.Used)
{
return;
}
//EcsDebug.PrintPass(index);
SerializedProperty prop = _recordsProp.GetArrayElementAtIndex(index); SerializedProperty prop = _recordsProp.GetArrayElementAtIndex(index);
var targetProp = prop.FindPropertyRelative(nameof(EcsPipelineTemplateSO.Record.target)); var targetProp = prop.FindPropertyRelative(nameof(EcsPipelineTemplateSO.Record.target));

View File

@ -177,7 +177,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
return; return;
} }
//Edit script button //Edit script button
if (UnityEditorUtility.TryGetScriptAsset(componentType, out MonoScript script)) if (ScriptsCache.TryGetScriptAsset(meta.FindRootTypeMeta(), out MonoScript script))
{ {
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
EcsGUI.ScriptAssetButton(optionButton, script); EcsGUI.ScriptAssetButton(optionButton, script);

View File

@ -3,6 +3,7 @@ using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Reflection; using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEditorInternal;
using UnityEngine; using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
@ -13,18 +14,140 @@ namespace DCFApixels.DragonECS.Unity.Editors
private ComponentDropDown _componentDropDown; private ComponentDropDown _componentDropDown;
private static ComponentColorMode AutoColorMode private SerializedProperty _componentsProp;
{ private ReorderableList _reorderableComponentsList;
get { return UserSettingsPrefs.instance.ComponentColorMode; }
set { UserSettingsPrefs.instance.ComponentColorMode = value; }
}
#region Init #region Init
protected override bool IsInit => _componentDropDown != null; protected override bool IsInit => _componentDropDown != null;
protected override void OnInit() protected override void OnInit()
{ {
_componentDropDown = new ComponentDropDown(); _componentDropDown = new ComponentDropDown();
_componentsProp = serializedObject.FindProperty(Target.ComponentsPropertyName);
_reorderableComponentsList = new ReorderableList(serializedObject, _componentsProp, true, false, false, false);
_reorderableComponentsList.onAddCallback += OnReorderableComponentsListAdd;
_reorderableComponentsList.onRemoveCallback += OnReorderableListRemove;
_reorderableComponentsList.drawElementCallback += OnReorderableListDrawEmptyElement;
_reorderableComponentsList.drawElementBackgroundCallback += OnReorderableComponentsListDrawElement;
_reorderableComponentsList.drawNoneElementCallback += OnReorderableComponentsListDrawNoneElement;
_reorderableComponentsList.elementHeightCallback += OnReorderableComponentsListElementHeight;
_reorderableComponentsList.onReorderCallback += OnReorderableListReorder;
_reorderableComponentsList.showDefaultBackground = false;
_reorderableComponentsList.footerHeight = 0f;
_reorderableComponentsList.headerHeight = 0f;
_reorderableComponentsList.elementHeight = 0f;
} }
#region ReorderableComponentsList
private void OnReorderableComponentsListDrawNoneElement(Rect rect) { }
private void OnReorderableListDrawEmptyElement(Rect rect, int index, bool isActive, bool isFocused) { }
private void OnReorderableListReorder(ReorderableList list)
{
EcsGUI.Changed = true;
}
private SerializedProperty GetTargetProperty(SerializedProperty prop)
{
IComponentTemplate template = prop.managedReferenceValue as IComponentTemplate;
if (template == null || prop.managedReferenceValue == null)
{
//DrawDamagedComponent_Replaced(componentRefProp, index);
return prop;
}
SerializedProperty componentProperty = prop;
try
{
if (componentProperty.managedReferenceValue is ComponentTemplateBase customTemplate)
{
componentProperty = prop.FindPropertyRelative("component");
}
if (componentProperty == null)
{
throw new NullReferenceException();
}
}
catch (Exception e)
{
Debug.LogException(e, serializedObject.targetObject);
//DrawDamagedComponent(index, "Damaged component template.");
return prop;
}
return componentProperty;
}
private float OnReorderableComponentsListElementHeight(int index)
{
var componentProperty = GetTargetProperty(_componentsProp.GetArrayElementAtIndex(index));
float result = EditorGUI.GetPropertyHeight(componentProperty);
return EcsGUI.GetTypeMetaBlockHeight(result) + Spacing * 2f;
}
private void OnReorderableComponentsListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
if (index < 0 || Event.current.type == EventType.Used) { return; }
rect = rect.AddPadding(OneLineHeight + Spacing, Spacing * 2f, Spacing, Spacing);
using (EcsGUI.CheckChanged())
{
SerializedProperty prop = _componentsProp.GetArrayElementAtIndex(index);
IComponentTemplate template = prop.managedReferenceValue as IComponentTemplate;
if (template == null || prop.managedReferenceValue == null)
{
DrawDamagedComponent_Replaced(prop, index);
return;
}
var componentProp = GetTargetProperty(prop);
ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta();
if (EcsGUI.DrawTypeMetaElementBlock(ref rect, _componentsProp, index, componentProp, meta))
{
return;
}
GUIContent label = UnityEditorUtility.GetLabel(meta.Name);
if (componentProp.propertyType == SerializedPropertyType.Generic)
{
EditorGUI.PropertyField(rect, componentProp, label, true);
}
else
{
EditorGUI.PropertyField(rect.AddPadding(0, 20f, 0, 0), componentProp, label, true);
}
}
}
private void OnReorderableComponentsListAdd(ReorderableList list)
{
list.serializedProperty.arraySize += 1;
list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1).ResetValues();
EcsGUI.Changed = true;
}
private void OnReorderableListRemove(ReorderableList list)
{
if (list.selectedIndices.Count <= 0)
{
if (list.serializedProperty.arraySize > 0)
{
list.serializedProperty.DeleteArrayElementAtIndex(list.serializedProperty.arraySize - 1);
}
return;
}
for (int i = list.selectedIndices.Count - 1; i >= 0; i--)
{
list.serializedProperty.DeleteArrayElementAtIndex(list.selectedIndices[i]);
}
EcsGUI.Changed = true;
}
#endregion
#endregion #endregion
#region Add/Remove #region Add/Remove
@ -40,23 +163,24 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
#endregion #endregion
protected void Draw(ITemplateInternal target) protected override void DrawCustom()
{ {
Init(); Init();
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
if (componentsProp == null) if (_componentsProp == null)
{ {
return; return;
} }
using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)))
{ {
DrawTop(target, componentsProp); DrawTop(Target, _componentsProp);
GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true)); _reorderableComponentsList.DoLayoutList();
for (int i = componentsProp.arraySize - 1; i >= 0; i--) //GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true));
{ //for (int i = _componentsProp.arraySize - 1; i >= 0; i--)
DrawComponentData(componentsProp.GetArrayElementAtIndex(i), componentsProp.arraySize, i); //{
} // DrawComponentData(_componentsProp.GetArrayElementAtIndex(i), _componentsProp.arraySize, i);
//}
} }
} }
private void DrawTop(ITemplateInternal target, SerializedProperty componentsProp) private void DrawTop(ITemplateInternal target, SerializedProperty componentsProp)
@ -69,7 +193,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
break; break;
case EcsGUI.AddClearButton.Clear: case EcsGUI.AddClearButton.Clear:
Init(); Init();
serializedObject.FindProperty(target.ComponentsPropertyName).ClearArray(); componentsProp.ClearArray();
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
break; break;
} }
@ -151,7 +275,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
componentProperty.isExpanded = !componentProperty.isExpanded; componentProperty.isExpanded = !componentProperty.isExpanded;
} }
//Edit script button //Edit script button
if (UnityEditorUtility.TryGetScriptAsset(componentType, out MonoScript script)) if (ScriptsCache.TryGetScriptAsset(meta.FindRootTypeMeta(), out MonoScript script))
{ {
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
EcsGUI.ScriptAssetButton(optionButton, script); EcsGUI.ScriptAssetButton(optionButton, script);
@ -222,18 +346,18 @@ namespace DCFApixels.DragonECS.Unity.Editors
[CustomEditor(typeof(ScriptableEntityTemplate), true)] [CustomEditor(typeof(ScriptableEntityTemplate), true)]
internal class EntityTemplatePresetEditor : EntityTemplateEditorBase<ScriptableEntityTemplate> internal class EntityTemplatePresetEditor : EntityTemplateEditorBase<ScriptableEntityTemplate>
{ {
protected override void DrawCustom() //protected override void DrawCustom()
{ //{
Draw(Target); // Draw(Target);
} //}
} }
[CustomEditor(typeof(MonoEntityTemplate), true)] [CustomEditor(typeof(MonoEntityTemplate), true)]
internal class EntityTemplateEditor : EntityTemplateEditorBase<MonoEntityTemplate> internal class EntityTemplateEditor : EntityTemplateEditorBase<MonoEntityTemplate>
{ {
protected override void DrawCustom() //protected override void DrawCustom()
{ //{
Draw(Target); // Draw(Target);
} //}
} }
} }
#endif #endif

View File

@ -67,7 +67,7 @@ namespace DCFApixels.DragonECS
savedRecords[i] = default; savedRecords[i] = default;
} }
} }
if(recordSingle != null) if (recordSingle != null)
{ {
string metaid = recordSingle.GetMeta().MetaID; string metaid = recordSingle.GetMeta().MetaID;
list.singleRecord = new SavedRecord(-1, metaid, JsonUtility.ToJson(recordSingle)); list.singleRecord = new SavedRecord(-1, metaid, JsonUtility.ToJson(recordSingle));
@ -126,6 +126,7 @@ namespace DCFApixels.DragonECS
public class MonoEntityTemplate : MonoEntityTemplateBase, ITemplateInternal public class MonoEntityTemplate : MonoEntityTemplateBase, ITemplateInternal
{ {
[SerializeReference] [SerializeReference]
[ReferenceButton(typeof(IComponentTemplate))]
private IComponentTemplate[] _components; private IComponentTemplate[] _components;
#region Properties #region Properties

View File

@ -24,6 +24,7 @@ namespace DCFApixels.DragonECS
public class ScriptableEntityTemplate : ScriptableEntityTemplateBase, ITemplateInternal public class ScriptableEntityTemplate : ScriptableEntityTemplateBase, ITemplateInternal
{ {
[SerializeReference] [SerializeReference]
[ReferenceButton(typeof(IComponentTemplate))]
private IComponentTemplate[] _components; private IComponentTemplate[] _components;
#region Properties #region Properties