rework components display

This commit is contained in:
Mikhail 2026-04-14 10:15:44 +08:00
parent a23fbb712e
commit 2c5461fca1
22 changed files with 1434 additions and 576 deletions

View File

@ -45,16 +45,9 @@ namespace DCFApixels.DragonECS
[MetaGroup(EcsUnityConsts.PACK_GROUP, OTHER_GROUP)]
[MetaDescription(AUTHOR, "Template for UnityComponent<T>")]
[MetaID("DragonECS_13DAACF9910155DD27F822442987E0AE")]
[MetaProxy(typeof(UnityComponentTemplate<>.UnityComponentMetaProxy))]
public abstract class UnityComponentTemplate<T> : ComponentTemplateBase<UnityComponent<T>> where T : Component
{
public override string Name
{
get { return typeof(T).Name; }
}
public override MetaGroup Group
{
get { return UnityComponentConsts.BaseGroup; }
}
public sealed override void Apply(short worldID, int entityID)
{
EcsWorld.GetPoolInstance<EcsPool<UnityComponent<T>>>(worldID).TryAddOrGet(entityID) = component;
@ -69,5 +62,11 @@ namespace DCFApixels.DragonECS
}
}
}
protected class UnityComponentMetaProxy : ComponentTemplateMetaProxy
{
public override string Name { get { return typeof(T).GetMeta().Name; } }
public override MetaGroup Group { get { return UnityComponentConsts.BaseGroup; } }
public UnityComponentMetaProxy(Type type) : base(type) { }
}
}
}

View File

@ -186,7 +186,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
return false;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
const float UNITY_HEIGHT_CONSTANT = 18f;
if (property.hasMultipleDifferentValues)

View File

@ -12,6 +12,74 @@ namespace DCFApixels.DragonECS.Unity.Editors
internal class WorldQueriesMonitorEditor : ExtendedEditor<WorldQueriesMonitor>
{
private GUIStyle _headerStyle;
private const char _searchPatternSeparator = '/';
public readonly struct SearchPattern
{
private readonly string _pattern;
private readonly char _separator;
public SearchPattern(string pattern, char separator)
{
_pattern = pattern ?? throw new ArgumentNullException(nameof(pattern));
_separator = separator;
}
public Enumerator GetEnumerator() => new Enumerator(_pattern, _separator);
public ref struct Enumerator
{
private readonly string _pattern;
private readonly char _separator;
private int _start;
private int _currentStart;
private int _currentLength;
public Enumerator(string pattern, char separator)
{
_pattern = pattern;
_separator = separator;
_start = 0;
_currentStart = -1;
_currentLength = 0;
}
public ReadOnlySpan<char> Current
{
get
{
if (_currentStart < 0)
throw new InvalidOperationException("Enumeration not started or already finished");
return _pattern.AsSpan(_currentStart, _currentLength);
}
}
public bool MoveNext()
{
if (_pattern == null || _start > _pattern.Length)
return false;
int len = _pattern.Length;
while (_start <= len)
{
int i = _start;
while (i < len && _pattern[i] != _separator)
i++;
int subLen = i - _start;
if (subLen > 0) // возвращаем только непустые подстроки
{
_currentStart = _start;
_currentLength = subLen;
_start = i + 1;
return true;
}
// пустая подстрока — пропускаем разделитель и продолжаем
_start = i + 1;
}
return false;
}
}
}
private void CopyToClipboard()
{
@ -148,21 +216,42 @@ namespace DCFApixels.DragonECS.Unity.Editors
int i = 0;
foreach (var executor in executors)
{
bool cheack(ReadOnlySpan<Type> types, string searchPattern)
bool cheack(ReadOnlySpan<Type> types, ReadOnlySpan<char> searchPatternRaw)
{
foreach (var type in types)
{
if(type.Name.Contains(searchPattern, StringComparison.OrdinalIgnoreCase))
if(type.Name.AsSpan().Contains(searchPatternRaw, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
if (!HasSearchPattern ||
cheack(executor.Mask.GetIncTypes_Debug(), searchPattern) ||
cheack(executor.Mask.GetExcTypes_Debug(), searchPattern) ||
cheack(executor.Mask.GetAnyTypes_Debug(), searchPattern))
bool isDraw = false;
if (HasSearchPattern)
{
int subPuttornsCount = 0;
int checkPassesCount = 0;
foreach (var subPattern in new SearchPattern(searchPattern, _searchPatternSeparator))
{
subPuttornsCount++;
if (cheack(executor.Mask.GetIncTypes_Debug(), subPattern) ||
cheack(executor.Mask.GetExcTypes_Debug(), subPattern) ||
cheack(executor.Mask.GetAnyTypes_Debug(), subPattern))
{
checkPassesCount++;
}
}
isDraw = subPuttornsCount <= checkPassesCount;
}
else
{
isDraw = true;
}
if(isDraw)
{
DrawQueryInfo(executor, i++);
}

View File

@ -29,8 +29,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ (byte)AddParamsFlags.NoImport | 7, "NoImport, Layer, Order, IsUnique" },
{ byte.MaxValue, "NoImport, Layer, Order, IsUnique" },
};
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
//return !property.isExpanded ?
// EditorGUIUtility.singleLineHeight + Spacing :

View File

@ -18,6 +18,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
[CustomPropertyDrawer(typeof(CustomToggleAttribute))]
internal class LeftToggleAttributeDrawer : ExtendedPropertyDrawer<CustomToggleAttribute>
{
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
return OneLineHeight + Spacing;
}
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.Boolean)

View File

@ -426,8 +426,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
using (SetAlpha(0))
{
bool result = GUI.Button(position, string.Empty, EditorStyles.miniButtonMid);
var current = Event.current;
return (GUI.enabled && HitTest(position, current), result);
var currentEvent = Event.current;
return (GUI.enabled && HitTest(position, currentEvent), result);
}
}
public static bool IconHoverScan(Rect position, Event current)
@ -486,11 +486,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
if (current.type == EventType.MouseUp)
{
EditorGUIUtility.PingObject(script);
Event.current.Use();
}
else if (current.type == EventType.MouseDown && current.clickCount >= 2)
{
//UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(); //TODO
AssetDatabase.OpenAsset(script);
Event.current.Use();
}
}
}
@ -715,23 +717,23 @@ namespace DCFApixels.DragonECS.Unity.Editors
return DrawTypeMetaBlockPadding * 2 + contentHeight;
}
public static bool DrawTypeMetaElementBlock(ref Rect rect, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementRootProperty, ITypeMeta meta)
public static (bool skip, float optionsWidth) DrawTypeMetaElementBlock(ref Rect rect, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementRootProperty, ITypeMeta meta)
{
var result = DrawTypeMetaBlock_Internal(ref rect, elementRootProperty, meta, elementIndex, arrayProperty.arraySize);
if (result.HasFlag(DrawTypeMetaBlockResultFlags.CloseButtonClicked))
if (result.flags.HasFlag(DrawTypeMetaBlockResultFlags.CloseButtonClicked))
{
arrayProperty.DeleteArrayElementAtIndex(elementIndex);
}
return result != DrawTypeMetaBlockResultFlags.None;
return (result.flags != DrawTypeMetaBlockResultFlags.None, result.optionsWidth);
}
public static bool DrawTypeMetaBlock(ref Rect rect, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
public static (bool skip, float optionsWidth) DrawTypeMetaBlock(ref Rect rect, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
{
var result = DrawTypeMetaBlock_Internal(ref rect, rootProperty, meta, index, total);
if (result.HasFlag(DrawTypeMetaBlockResultFlags.CloseButtonClicked))
if (result.flags.HasFlag(DrawTypeMetaBlockResultFlags.CloseButtonClicked))
{
rootProperty.ResetValues();
}
return result.HasFlag(DrawTypeMetaBlockResultFlags.DropExpanded);
return (result.flags.HasFlag(DrawTypeMetaBlockResultFlags.DropExpanded), result.optionsWidth);
}
[Flags]
@ -743,12 +745,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
private static DrawTypeMetaBlockResultFlags DrawTypeMetaBlock_Internal(ref Rect rect, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
private static (DrawTypeMetaBlockResultFlags flags, float optionsWidth) DrawTypeMetaBlock_Internal(ref Rect rect, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
{
if (meta == null)
{
EditorGUI.DrawRect(rect, Color.black.SetAlpha(EscEditorConsts.COMPONENT_DRAWER_ALPHA));
return DrawTypeMetaBlockResultFlags.None;
return (DrawTypeMetaBlockResultFlags.None, 0f);
}
//string name = meta.Name;
@ -772,6 +774,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
EditorGUI.DrawRect(rect, panelColor);
float optionsWidth = 0f;
Rect optionRect = rect;
rect = rect.AddPadding(DrawTypeMetaBlockPadding * 2f);
@ -781,38 +784,45 @@ namespace DCFApixels.DragonECS.Unity.Editors
optionRect.xMin = optionRect.xMax - 64;
optionRect.center += Vector2.up * DrawTypeMetaBlockPadding;
DrawTypeMetaBlockResultFlags result = DrawTypeMetaBlockResultFlags.None;
using (CheckChanged())
{
//Canceling isExpanded
bool oldIsExpanded = rootProperty.isExpanded;
if (ClickTest(optionRect))
{
rootProperty.isExpanded = oldIsExpanded;
result |= DrawTypeMetaBlockResultFlags.DropExpanded;
}
//bool oldIsExpanded = rootProperty.isExpanded;
//if (ClickTest(optionRect))
//{
// rootProperty.isExpanded = oldIsExpanded;
// result |= DrawTypeMetaBlockResultFlags.DropExpanded;
//}
//Close button
optionRect.xMin = optionRect.xMax - HeadIconsRect.width;
optionsWidth += optionRect.width;
if (CloseButton(optionRect))
{
result |= DrawTypeMetaBlockResultFlags.CloseButtonClicked;
return result;
return (result, optionsWidth);
}
//Edit script button
if (ScriptsCache.TryGetScriptAsset(meta.FindRootTypeMeta(), out MonoScript script))
{
optionRect = HeadIconsRect.MoveTo(optionRect.center - (Vector2.right * optionRect.width));
optionsWidth += optionRect.width;
ScriptAssetButton(optionRect, script);
}
//Description icon
if (string.IsNullOrEmpty(description) == false)
{
optionRect = HeadIconsRect.MoveTo(optionRect.center - (Vector2.right * optionRect.width));
optionsWidth += optionRect.width;
DescriptionIcon(optionRect, description);
}
}
return result;
return (result, optionsWidth);
}
#endregion
@ -978,11 +988,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
#region Init
private static ReferenceDropDown GetReferenceDropDown(Type[] predicatTypes, Type[] sortedWithOutTypes)
{
if (_predicatTypesMenus.TryGetValue((predicatTypes, sortedWithOutTypes), out ReferenceDropDown menu) == false)
if (_predicatTypesMenus.TryGetValue(new PredicateTypesKey(predicatTypes[0], predicatTypes, sortedWithOutTypes), out ReferenceDropDown menu) == false)
{
menu = new ReferenceDropDown(predicatTypes, sortedWithOutTypes);
menu.OnSelected += SelectComponent;
_predicatTypesMenus.Add((predicatTypes, sortedWithOutTypes), menu);
_predicatTypesMenus.Add(new PredicateTypesKey(predicatTypes[0], predicatTypes, sortedWithOutTypes), menu);
}
return menu;

View File

@ -17,6 +17,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityObject = UnityEngine.Object;
@ -213,21 +214,30 @@ namespace DCFApixels.DragonECS.Unity.Editors
_isStaticInit = true;
OnStaticInit();
}
public void Init()
public void Init(SerializedProperty property)
{
if (IsInit) { return; }
_isInit = true;
OnInit();
OnInit(property);
}
protected virtual void OnStaticInit() { }
protected virtual void OnInit() { }
protected virtual void OnInit(SerializedProperty property) { }
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
StaticInit();
Init(property);
return GetCustomHeight(property, label);
}
protected abstract float GetCustomHeight(SerializedProperty property, GUIContent label);
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
using (EcsGUI.CheckChanged(property.serializedObject))
{
StaticInit();
Init();
Init(property);
DrawCustom(position, property, label);
}
}

View File

@ -86,93 +86,94 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
}
internal class ComponentTemplatesDropDown : MetaObjectsDropDown<ComponentTemplateTypeCache>
{
private ComponentTemplatesDropDown() { }
private bool _isCheckUnique;
private SerializedProperty _arrayProperty;
private SerializedProperty _fieldProperty;
public static Dictionary<PredicateTypesKey, ComponentTemplatesDropDown> _dropDownsCache = new Dictionary<PredicateTypesKey, ComponentTemplatesDropDown>(32);
public static ComponentTemplatesDropDown Get(PredicateTypesKey key)
{
if(_dropDownsCache.TryGetValue(key, out var result) == false)
{
result = new ComponentTemplatesDropDown();
IEnumerable<(ComponentTemplateTypeCache template, ITypeMeta meta)> itemMetaPairs = ComponentTemplateTypeCache.All.ToArray()
.Where(o =>
{
return key.Check(o.Type);
})
.Select(o =>
{
return (o, o.Meta);
});
//TODO оптимизировать или вырезать
itemMetaPairs = itemMetaPairs.OrderBy(o => o.meta.Group.Name);
result.Setup(itemMetaPairs);
_dropDownsCache[key] = result;
}
return result;
}
public void OpenForArray(Rect position, SerializedProperty arrayProperty, bool isCheckUnique)
{
_isCheckUnique = isCheckUnique;
_arrayProperty = arrayProperty;
_fieldProperty = null;
Show(position);
}
public void OpenForField(Rect position, SerializedProperty fieldProperty)
{
_isCheckUnique = false;
_arrayProperty = null;
_fieldProperty = fieldProperty;
Show(position);
}
protected override void ItemSelected(Item item)
{
base.ItemSelected(item);
if (item.Obj == null)
{
_fieldProperty.managedReferenceValue = null;
_fieldProperty.serializedObject.ApplyModifiedProperties();
return;
}
Type componentType = item.Obj.GetType();
var data = item.Obj;
if (_arrayProperty != null && data != null)
{
int index = _arrayProperty.arraySize;
if (_isCheckUnique)
{
if (data.IsUnique)
{
for (int i = 0, iMax = _arrayProperty.arraySize; i < iMax; i++)
{
if (_arrayProperty.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
{
return;
}
}
}
}
_arrayProperty.arraySize += 1;
_fieldProperty = _arrayProperty.GetArrayElementAtIndex(index);
}
if (_fieldProperty != null)
{
_fieldProperty.managedReferenceValue = data.CreateInstance();
_fieldProperty.serializedObject.ApplyModifiedProperties();
}
}
}
//internal class ComponentTemplatesDropDown : MetaObjectsDropDown<ComponentTemplateTypeCache>
//{
// private ComponentTemplatesDropDown() { }
//
// private bool _isCheckUnique;
// private SerializedProperty _arrayProperty;
// private SerializedProperty _fieldProperty;
//
// public static Dictionary<PredicateTypesKey, ComponentTemplatesDropDown> _dropDownsCache = new Dictionary<PredicateTypesKey, ComponentTemplatesDropDown>(32);
// public static ComponentTemplatesDropDown Get(PredicateTypesKey key)
// {
// if(_dropDownsCache.TryGetValue(key, out var result) == false)
// {
// result = new ComponentTemplatesDropDown();
// IEnumerable<(ComponentTemplateTypeCache template, ITypeMeta meta)> itemMetaPairs = ComponentTemplateTypeCache.All.ToArray()
// .Where(o =>
// {
// return key.Check(o.Type);
// })
// .Select(o =>
// {
// return (o, o.Meta);
// });
//
// //TODO оптимизировать или вырезать
// itemMetaPairs = itemMetaPairs.OrderBy(o => o.meta.Group.Name);
// result.Setup(itemMetaPairs);
// _dropDownsCache[key] = result;
// }
// return result;
// }
//
// public void OpenForArray(Rect position, SerializedProperty arrayProperty, bool isCheckUnique)
// {
// _isCheckUnique = isCheckUnique;
// _arrayProperty = arrayProperty;
// _fieldProperty = null;
// Show(position);
// }
// public void OpenForField(Rect position, SerializedProperty fieldProperty)
// {
// _isCheckUnique = false;
// _arrayProperty = null;
// _fieldProperty = fieldProperty;
// Show(position);
// }
//
// protected override void ItemSelected(Item item)
// {
// base.ItemSelected(item);
//
// if (item.Obj == null)
// {
// _fieldProperty.managedReferenceValue = null;
// _fieldProperty.serializedObject.ApplyModifiedProperties();
// return;
// }
//
// Type componentType = item.Obj.GetType();
// var data = item.Obj;
//
// if (_arrayProperty != null && data != null)
// {
// int index = _arrayProperty.arraySize;
// if (_isCheckUnique)
// {
// if (data.IsUnique)
// {
// for (int i = 0, iMax = _arrayProperty.arraySize; i < iMax; i++)
// {
// if (_arrayProperty.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
// {
// return;
// }
// }
// }
// }
// _arrayProperty.arraySize += 1;
// _fieldProperty = _arrayProperty.GetArrayElementAtIndex(index);
// }
//
// if (_fieldProperty != null)
// {
// _fieldProperty.managedReferenceValue = data.CreateInstance();
// _fieldProperty.serializedObject.ApplyModifiedProperties();
// }
// }
//}
internal class RuntimeComponentsDropDown : MetaObjectsDropDown<IEcsPool>
{
public RuntimeComponentsDropDown(IEnumerable<IEcsPool> pools)
@ -215,6 +216,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
private bool _isContainsNull;
public IEnumerable<(T, ITypeMeta)> _itemMetaPairs;
public virtual bool IsStaticList { get { return true; } }
public MetaObjectsDropDown() : base(new AdvancedDropdownState())
{
minimumSize = new Vector2(220f, EditorGUIUtility.singleLineHeight * 20);
@ -225,6 +227,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
_name = name;
_isContainsNull = isContainsNull;
_itemMetaPairs = itemMetaPairs;
if (IsStaticList)
{
_itemMetaPairs = _itemMetaPairs.ToArray();
}
}
protected override AdvancedDropdownItem BuildRoot()
{
@ -235,10 +241,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
root.AddChild(new Item(default, "<NULL>", increment++));
}
Dictionary<Key, Item> dict = new Dictionary<Key, Item>();
var list = _itemMetaPairs.ToArray();
foreach (var pair in _itemMetaPairs)
{
ITypeMeta meta = pair.Item2;

View File

@ -1,117 +1,109 @@
using System;
namespace DCFApixels.DragonECS.Unity.Editors
{
internal interface IReferenceButtonAttribute
{
Type[] PredicateTypes { get; }
bool IsHideButtonIfNotNull { get; }
}
}
#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;
using System;
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ReferenceButtonAttribute), true)]
internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer<IReferenceButtonAttribute>
{
private Type[] _withOutTypes;
protected override void OnInit()
{
Type fieldType = fieldInfo.FieldType;
_withOutTypes = fieldType.TryGetAttribute(out ReferenceButtonWithOutAttribute a) ? a.PredicateTypes : Array.Empty<Type>();
//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))
{
_reflectionCache.InitReferenceButtonCache_Editor(sp);
}
return _reflectionCache;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
Init();
if (property.propertyType == SerializedPropertyType.ManagedReference &&
property.managedReferenceValue != null &&
Cahce(property).HasSerializableData_Editor)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
else
{
return OneLineHeight;
}
}
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
if(property.propertyType != SerializedPropertyType.ManagedReference)
{
GUI.Label(position, label);
return;
}
if (IsArrayElement)
{
label = UnityEditorUtility.GetLabelTemp();
}
Rect selButtnoRect = position;
selButtnoRect.height = OneLineHeight;
DrawSelectionPopupButton(selButtnoRect, property);
if (property.managedReferenceValue != null &&
Cahce(property).HasSerializableData_Editor)
{
EditorGUI.PropertyField(position, property, label, true);
}
else
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.LabelField(position, label);
EditorGUI.EndProperty();
}
}
private void DrawSelectionPopupButton(Rect position, SerializedProperty property)
{
Rect buttonRect = IsArrayElement ? position : position.AddPadding(EditorGUIUtility.labelWidth, 0f, 0f, 0f); ;
EcsGUI.DrawSelectReferenceButton(buttonRect, property, Attribute.PredicateTypes.Length == 0 ? new Type[1] { fieldInfo.FieldType } : Attribute.PredicateTypes, _withOutTypes, Attribute.IsHideButtonIfNotNull);
}
}
}
#endif
//using System;
//
//#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;
// using System;
// using UnityEditor;
// using UnityEngine;
//
// [CustomPropertyDrawer(typeof(ReferenceButtonAttribute), true)]
// internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer<IReferenceButtonAttribute>
// {
// private Type[] _withOutTypes;
//
// protected override void OnInit(SerializedProperty property)
// {
// Type fieldType = fieldInfo.FieldType;
// _withOutTypes = fieldType.TryGetAttribute(out ReferenceButtonWithOutAttribute a) ? a.PredicateTypes : Array.Empty<Type>();
// //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))
// {
// _reflectionCache.InitReferenceButtonCache_Editor(sp);
// }
// return _reflectionCache;
// }
//
// public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
// {
// Init(property);
// if (property.propertyType == SerializedPropertyType.ManagedReference &&
// property.managedReferenceValue != null &&
// Cahce(property).HasSerializableData_Editor)
// {
// return EditorGUI.GetPropertyHeight(property, label, true);
// }
// else
// {
// return OneLineHeight;
// }
// }
//
// protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
// {
// if(property.propertyType != SerializedPropertyType.ManagedReference)
// {
// GUI.Label(position, label);
// return;
// }
// if (IsArrayElement)
// {
// label = UnityEditorUtility.GetLabelTemp();
// }
// Rect selButtnoRect = position;
// selButtnoRect.height = OneLineHeight;
// DrawSelectionPopupButton(selButtnoRect, property);
//
// if (property.managedReferenceValue != null &&
// Cahce(property).HasSerializableData_Editor)
// {
// EditorGUI.PropertyField(position, property, label, true);
// }
// else
// {
// EditorGUI.BeginProperty(position, label, property);
// EditorGUI.LabelField(position, label);
// EditorGUI.EndProperty();
// }
// }
//
// private void DrawSelectionPopupButton(Rect position, SerializedProperty property)
// {
// Rect buttonRect = IsArrayElement ? position : position.AddPadding(EditorGUIUtility.labelWidth, 0f, 0f, 0f); ;
// EcsGUI.DrawSelectReferenceButton(buttonRect, property, Attribute.PredicateTypes.Length == 0 ? new Type[1] { fieldInfo.FieldType } : Attribute.PredicateTypes, _withOutTypes, Attribute.IsHideButtonIfNotNull);
// }
// }
//}
//#endif

View File

@ -105,10 +105,6 @@ namespace DCFApixels.DragonECS.Unity.Internal
}
return _memberwiseCloneMethdo.Invoke(obj, null);
}
internal static object Clone_Reflection<T>(this T obj)
{
return Clone_Reflection((object)obj);
}
}
internal partial class UnityReflectionCache

View File

@ -1,24 +1,30 @@
using System;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Internal
{
internal readonly struct PredicateTypesKey : IEquatable<PredicateTypesKey>
{
public readonly Type[] Types;
public readonly Type TargetType;
public readonly Type[] AllowTypes;
public readonly Type[] WithoutTypes;
public PredicateTypesKey(Type[] types) : this(types, Type.EmptyTypes) { }
public PredicateTypesKey(Type[] types, Type[] withoutTypes)
public PredicateTypesKey(Type signleType) : this(signleType, new Type[] { signleType } , Type.EmptyTypes) { }
public PredicateTypesKey(Type targetType, Type[] types) : this(targetType, types, Type.EmptyTypes) { }
public PredicateTypesKey(Type targetType, Type[] types, Type[] withoutTypes)
{
Types = types;
if(targetType == null)
{
Throw.ArgumentNullException();
}
TargetType = targetType;
AllowTypes = types;
WithoutTypes = withoutTypes;
}
public bool Check(Type type)
{
bool isAssignable = false;
foreach (Type predicateTypes in Types)
bool isAssignable = AllowTypes.Length == 0;
foreach (Type allowType in AllowTypes)
{
if (predicateTypes.IsAssignableFrom(type))
if (allowType.IsAssignableFrom(type))
{
isAssignable = true;
break;
@ -37,15 +43,20 @@ namespace DCFApixels.DragonECS.Unity.Internal
}
}
return isAssignable;
return isAssignable && TargetType.IsAssignableFrom(type);
}
public bool Equals(PredicateTypesKey other)
{
if (Types.Length != other.Types.Length) { return false; }
if (AllowTypes.Length != other.AllowTypes.Length) { return false; }
if (WithoutTypes.Length != other.WithoutTypes.Length) { return false; }
for (int i = 0; i < Types.Length; i++)
if (TargetType != other.TargetType)
{
if (Types[i] != other.Types[i])
return false;
}
for (int i = 0; i < AllowTypes.Length; i++)
{
if (AllowTypes[i] != other.AllowTypes[i])
{
return false;
}
@ -65,8 +76,7 @@ namespace DCFApixels.DragonECS.Unity.Internal
}
public override int GetHashCode()
{
return HashCode.Combine(Types, WithoutTypes);
return HashCode.Combine(TargetType, AllowTypes, WithoutTypes);
}
public static implicit operator PredicateTypesKey((Type[], Type[]) types) { return new PredicateTypesKey(types.Item1, types.Item2); }
}
}

View File

@ -8,6 +8,10 @@ namespace DCFApixels.DragonECS.Unity.Internal
{
throw new ArgumentOutOfRangeException();
}
internal static void ArgumentNullException()
{
throw new ArgumentNullException();
}
internal static void Argument(string message)
{
throw new ArgumentException(message);

View File

@ -12,7 +12,10 @@ namespace DCFApixels.DragonECS
public struct ComponentTemplateProperty : IEquatable<ComponentTemplateProperty>
{
[SerializeReference]
[ReferenceDropDown]
[TypeMetaBlock]
private ITemplateNode _template;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ComponentTemplateProperty(ITemplateNode template)
{
@ -28,7 +31,7 @@ namespace DCFApixels.DragonECS
public Type Type
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _template is IComponentTemplate tml ? tml.Type : _template.GetType(); }
get { return _template is IComponentTemplate tml ? tml.ComponentType : _template.GetType(); }
}
public bool IsNull
{
@ -83,12 +86,19 @@ namespace DCFApixels.DragonECS
public readonly struct Null { }
}
public sealed class ComponentTemplateFieldAttribute : PropertyAttribute, IReferenceButtonAttribute
public sealed class ComponentTemplateFieldAttribute : PropertyAttribute, IReferenceDropDownAttribute
{
public Type[] PredicateTypes;
Type[] IReferenceButtonAttribute.PredicateTypes { get { return PredicateTypes; } }
bool IReferenceButtonAttribute.IsHideButtonIfNotNull { get { return true; } }
public ComponentTemplateFieldAttribute() { }
public readonly bool IsHideButtonIfNotNull = true;
Type[] IReferenceDropDownAttribute.PredicateTypes { get { return PredicateTypes; } }
bool IReferenceDropDownAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
public ComponentTemplateFieldAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { }
public ComponentTemplateFieldAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { }
public ComponentTemplateFieldAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes)
{
IsHideButtonIfNotNull = isHideButtonIfNotNull;
PredicateTypes = predicateTypes;
Array.Sort(predicateTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal));
}
}
public sealed class ComponentTemplateAttribute : PropertyAttribute { }
}

View File

@ -9,200 +9,222 @@ namespace DCFApixels.DragonECS.Unity.Editors
[CustomPropertyDrawer(typeof(ComponentTemplateProperty), true)]
internal class ComponentTemplatePropertyDrawer : ExtendedPropertyDrawer
{
private ComponentTemplateReferenceDrawer _drawer = new ComponentTemplateReferenceDrawer(new PredicateTypesKey(new Type[] { typeof(ITemplateNode) }));
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
//private EcsDragonFieldDrawer _drawer = new EcsDragonFieldDrawer(new PredicateTypesKey(typeof(ITemplateNode)));
//protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
//{
// property.Next(true);
// _drawer.StaticInit();
// _drawer.Init(property);
// return _drawer.GetPropertyHeight(property, label);
//}
//protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
//{
// var root = property.Copy();
// property.Next(true);
// _drawer.StaticInit();
// _drawer.Init(property);
// _drawer.Draw(position, root, property, label);
//}
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
property.Next(true);
_drawer.StaticInit();
_drawer.Init();
return _drawer.GetPropertyHeight(property, label);
return EditorGUI.GetPropertyHeight(property, label);
}
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
var root = property.Copy();
property.Next(true);
_drawer.StaticInit();
_drawer.Init();
_drawer.Draw(position, root, property, label);
EditorGUI.PropertyField(position, property, label);
}
}
[CustomPropertyDrawer(typeof(ComponentTemplateFieldAttribute), true)]
internal class ComponentTemplateReferenceDrawer : ExtendedPropertyDrawer<ComponentTemplateFieldAttribute>
{
private const float DamagedComponentHeight = 18f * 2f;
private ComponentTemplatesDropDown _componentDropDown;
private PredicateTypesKey? _predicateOverride;
#region Properties
private float Padding => Spacing;
protected override bool IsInit => _componentDropDown != null;
#endregion
public ComponentTemplateReferenceDrawer() { }
public ComponentTemplateReferenceDrawer(PredicateTypesKey key)
{
_predicateOverride = key;
}
#region Init
protected override void OnInit()
{
PredicateTypesKey key;
if(_predicateOverride == null)
{
Type[] withOutTypes = Type.EmptyTypes;
if (fieldInfo != null)
{
withOutTypes = fieldInfo.TryGetAttribute(out ReferenceButtonWithOutAttribute a) ? a.PredicateTypes : Array.Empty<Type>();
}
if (Attribute != null)
{
var types = Attribute.PredicateTypes;
if(types == null || types.Length == 0)
{
types = new Type[] { typeof(ITemplateNode) };
}
key = new PredicateTypesKey(types, withOutTypes);
}
else
{
key = new PredicateTypesKey(new Type[] { typeof(object) }, withOutTypes);
}
_predicateOverride = key;
}
_componentDropDown = ComponentTemplatesDropDown.Get(_predicateOverride.Value);
_componentDropDown.OnSelected += SelectComponent;
}
[ThreadStatic]
private static SerializedProperty currentProperty;
private static void SelectComponent(ComponentTemplatesDropDown.Item item)
{
//EcsGUI.Changed = true;
object inst = item.Obj.CreateInstance();
currentProperty.managedReferenceValue = inst;
currentProperty.isExpanded = false;
currentProperty.serializedObject.ApplyModifiedProperties();
}
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
//#region No SerializeReference
//if (property.propertyType != SerializedPropertyType.ManagedReference)
//[CustomPropertyDrawer(typeof(ComponentTemplateFieldAttribute), true)]
//internal class ComponentTemplateFieldDrawer : ExtendedPropertyDrawer<ComponentTemplateFieldAttribute>
//{
// return EditorGUI.GetPropertyHeight(property, label);
//}
//#endregion
if (isSerializeReference)
{
var instance = property.managedReferenceValue;
IComponentTemplate template = instance as IComponentTemplate;
if (instance == null)
{
return EditorGUIUtility.singleLineHeight + Padding * 2f;
}
try
{
if (instance is ComponentTemplateBase customTemplate)
{
property = property.FindPropertyRelative("component");
}
}
catch
{
property = null;
}
if (property == null)
{
return DamagedComponentHeight;
}
}
int propCount = EcsGUI.GetChildPropertiesCount(property);
return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f;
}
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
Draw(position, property, property, label);
}
public void Draw(Rect rect, SerializedProperty rootProperty, SerializedProperty property, GUIContent label)
{
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
//#region No SerializeReference
//if (isSerializeReference == false)
//{
// EditorGUI.PropertyField(position, property, label, true);
// private const float DamagedComponentHeight = 18f * 2f;
// private ComponentTemplatesDropDown _componentDropDown;
// private PredicateTypesKey? _predicateOverride;
//
// #region Properties
// private float Padding => Spacing;
// protected override bool IsInit => _componentDropDown != null;
// #endregion
//
// public ComponentTemplateFieldDrawer() { }
// public ComponentTemplateFieldDrawer(PredicateTypesKey key)
// {
// _predicateOverride = key;
// }
//
// #region Init
// protected override void OnInit(SerializedProperty property)
// {
// PredicateTypesKey key;
// if(_predicateOverride == null)
// {
// Type[] withOutTypes = Type.EmptyTypes;
// if (fieldInfo != null)
// {
// withOutTypes = fieldInfo.TryGetAttribute(out ReferenceButtonWithOutAttribute a) ? a.PredicateTypes : Array.Empty<Type>();
// }
// if (Attribute != null)
// {
// var types = Attribute.PredicateTypes;
// if(types == null || types.Length == 0)
// {
// types = new Type[] { typeof(ITemplateNode) };
// }
// key = new PredicateTypesKey(typeof(ITemplateNode), types, withOutTypes);
// }
// else
// {
// key = new PredicateTypesKey(typeof(object), withOutTypes);
// }
// _predicateOverride = key;
// }
// _componentDropDown = ComponentTemplatesDropDown.Get(_predicateOverride.Value);
// _componentDropDown.OnSelected += SelectComponent;
// }
//
// [ThreadStatic]
// private static SerializedProperty currentProperty;
// private static void SelectComponent(ComponentTemplatesDropDown.Item item)
// {
// //EcsGUI.Changed = true;
// object inst = item.Obj.CreateInstance();
// currentProperty.managedReferenceValue = inst;
// currentProperty.isExpanded = false;
// currentProperty.serializedObject.ApplyModifiedProperties();
// }
// #endregion
//
// public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
// {
// bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
// //#region No SerializeReference
// //if (property.propertyType != SerializedPropertyType.ManagedReference)
// //{
// // return EditorGUI.GetPropertyHeight(property, label);
// //}
// //#endregion
//
// if (isSerializeReference)
// {
// var instance = property.managedReferenceValue;
// IComponentTemplate template = instance as IComponentTemplate;
// if (instance == null)
// {
// return EditorGUIUtility.singleLineHeight + Padding * 2f;
// }
//
// try
// {
// if (instance is ComponentTemplateBase customTemplate)
// {
// property = property.FindPropertyRelative("component");
// }
// }
// catch
// {
// property = null;
// }
// if (property == null)
// {
// return DamagedComponentHeight;
// }
// }
//
// int propCount = EcsGUI.GetChildPropertiesCount(property);
//
// return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f;
// }
//
// protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
// {
// Draw(position, property, property, label);
// }
// public void Draw(Rect rect, SerializedProperty rootProperty, SerializedProperty property, GUIContent label)
// {
// bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
// //#region No SerializeReference
// //if (isSerializeReference == false)
// //{
// // EditorGUI.PropertyField(position, property, label, true);
// // return;
// //}
// //#endregion
//
// ITypeMeta meta = null;
// SerializedProperty componentProp = property;
// if (isSerializeReference)
// {
// var template = property.managedReferenceValue;
// if (template == null)
// {
// DrawSelectionPopup(rect, property, label);
// return;
// }
//
// IComponentTemplate componentTemplate = template as IComponentTemplate;
// if (componentProp.managedReferenceValue is ComponentTemplateBase customTemplate)
// {
// componentProp = property.FindPropertyRelative("component");
// }
// if (componentProp == null)
// {
// DrawDamagedComponent(rect, "Damaged component template.");
// return;
// }
//
// meta = template as ITypeMeta;
// if (meta == null)
// {
// if (componentTemplate != null)
// {
// meta = componentTemplate.ComponentType.GetMeta();
// }
// else
// {
// meta = template.GetMeta();
// }
// }
// }
// else
// {
// meta = fieldInfo.FieldType.GetMeta();
// }
//
//
// if (EcsGUI.DrawTypeMetaBlock(ref rect, rootProperty, meta).skip)
// {
// return;
// }
//
// label.text = 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 DrawSelectionPopup(Rect position, SerializedProperty property, GUIContent label)
// {
// EditorGUI.LabelField(position, label);
// Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f);
// if (GUI.Button(buttonRect, "Select"))
// {
// currentProperty = property;
// _componentDropDown.Show(buttonRect);
// }
// }
// private void DrawDamagedComponent(Rect position, string message)
// {
// EditorGUI.HelpBox(position, message, MessageType.Warning);
// }
//}
//#endregion
ITypeMeta meta = null;
SerializedProperty componentProp = property;
if (isSerializeReference)
{
var instance = property.managedReferenceValue;
if (instance == null)
{
DrawSelectionPopup(rect, property, label);
return;
}
IComponentTemplate template = instance as IComponentTemplate;
if (componentProp.managedReferenceValue is ComponentTemplateBase customTemplate)
{
componentProp = property.FindPropertyRelative("component");
}
if (componentProp == null)
{
DrawDamagedComponent(rect, "Damaged component template.");
return;
}
meta = template is ITypeMeta metaOverride ? metaOverride : _predicateOverride.Value.Types[0].GetMeta();
}
else
{
meta = fieldInfo.FieldType.GetMeta();
}
if (EcsGUI.DrawTypeMetaBlock(ref rect, rootProperty, meta))
{
return;
}
label.text = 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 DrawSelectionPopup(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.LabelField(position, label);
Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f);
if (GUI.Button(buttonRect, "Select"))
{
currentProperty = property;
_componentDropDown.Show(buttonRect);
}
}
private void DrawDamagedComponent(Rect position, string message)
{
EditorGUI.HelpBox(position, message, MessageType.Warning);
}
}
}
#endif

View File

@ -10,13 +10,14 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
internal abstract class EntityTemplateEditorBase : ExtendedEditor
{
private ComponentTemplatesDropDown _componentDropDown;
private DragonFieldDropDown _componentDropDown;
private SerializedProperty _componentsProp;
private SerializedProperty _componentTemplatesProp;
private SerializedProperty _templatesProp;
private ReorderableList _reorderableComponentsList;
private int _reorderableComponentsListLastCount;
private static readonly Type[] _predicateTypes = new Type[] { typeof(ITemplateNode) };
private static readonly Type[] _predicateTypes = new Type[] { typeof(IComponentTemplate), typeof(IEcsComponentMember) };
protected abstract bool IsSO { get; }
@ -24,11 +25,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected override bool IsInit { get { return _componentDropDown != null; } }
protected override void OnInit()
{
_componentDropDown = ComponentTemplatesDropDown.Get(new PredicateTypesKey(_predicateTypes, Type.EmptyTypes));
_componentDropDown = DragonFieldDropDown.Get(new PredicateTypesKey(typeof(ITemplateNode), _predicateTypes, Type.EmptyTypes));
_componentsProp = serializedObject.FindProperty("_componentTemplates");
_componentTemplatesProp = serializedObject.FindProperty("_componentTemplates");
_templatesProp = serializedObject.FindProperty("_templates");
_reorderableComponentsList = new ReorderableList(serializedObject, _componentsProp, true, false, false, false);
_reorderableComponentsList = new ReorderableList(serializedObject, _componentTemplatesProp, true, false, false, false);
_reorderableComponentsList.onAddCallback += OnReorderableComponentsListAdd;
_reorderableComponentsList.onRemoveCallback += OnReorderableListRemove;
_reorderableComponentsList.drawElementCallback += OnReorderableListDrawEmptyElement;
@ -73,48 +75,67 @@ namespace DCFApixels.DragonECS.Unity.Editors
private float OnReorderableComponentsListElementHeight(int index)
{
var componentProperty = GetTargetProperty(_componentsProp.GetArrayElementAtIndex(index));
float result = EditorGUI.GetPropertyHeight(componentProperty);
return EcsGUI.GetTypeMetaBlockHeight(result) + Spacing * 2f;
SerializedProperty prop = _componentTemplatesProp.GetArrayElementAtIndex(index);
GUIContent label = UnityEditorUtility.GetLabelTemp();
return EditorGUI.GetPropertyHeight(prop, label) + Spacing * 2f;
//var componentProperty = GetTargetProperty(_componentTemplatesProp.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; }
SerializedProperty prop = _componentTemplatesProp.GetArrayElementAtIndex(index);
GUIContent label = UnityEditorUtility.GetLabelTemp();
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);
EditorGUI.PropertyField(rect, prop, UnityEditorUtility.GetLabel(prop.displayName), true);
EditorGUI.PropertyField(rect, prop, label);
return;
}
var componentProp = GetTargetProperty(prop);
ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.GetMeta();
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);
}
}
//if (index < 0 || Event.current.type == EventType.Used) { return; }
//rect = rect.AddPadding(OneLineHeight + Spacing, Spacing * 2f, Spacing, Spacing);
//using (EcsGUI.CheckChanged())
//{
// SerializedProperty prop = _componentTemplatesProp.GetArrayElementAtIndex(index);
//
// var template = prop.managedReferenceValue;
// if (template == null)
// {
// //DrawDamagedComponent_Replaced(prop, index);
// EditorGUI.PropertyField(rect, prop, UnityEditorUtility.GetLabel(prop.displayName), true);
// return;
// }
// IComponentTemplate componentTemplate = template as IComponentTemplate;
// var componentProp = GetTargetProperty(prop);
//
// ITypeMeta meta = template as ITypeMeta;
// if(meta == null)
// {
// if (componentTemplate != null)
// {
// meta = componentTemplate.ComponentType.GetMeta();
// }
// else
// {
// meta = template.GetMeta();
// }
// }
//
// if (EcsGUI.DrawTypeMetaElementBlock(ref rect, _componentTemplatesProp, index, componentProp, meta).skip)
// {
// 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)
@ -147,6 +168,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
Init();
if (IsSO)
{
EcsGUI.Layout.ManuallySerializeButton(targets);
@ -186,21 +209,32 @@ namespace DCFApixels.DragonECS.Unity.Editors
SerializedProperty iterator = serializedObject.GetIterator();
iterator.NextVisible(true);
using (EcsGUI.Disable)
{
EditorGUILayout.PropertyField(iterator, true);
}
while (iterator.NextVisible(false))
{
if (_componentsProp != null && iterator.name == _componentsProp.name)
if ((_componentTemplatesProp != null && iterator.name == _componentTemplatesProp.name) ||
(_templatesProp != null && iterator.name == _templatesProp.name))
{
using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetTransperentBlackBackgrounStyle()))
{
DrawTop(_componentsProp);
_reorderableComponentsList.DoLayoutList();
}
}
else
{
EditorGUILayout.PropertyField(iterator, true);
}
}
if (_templatesProp != null)
{
EditorGUILayout.PropertyField(_templatesProp, true);
}
using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetTransperentBlackBackgrounStyle()))
{
DrawTop(_componentTemplatesProp);
_reorderableComponentsList.DoLayoutList();
}
}
private void DrawTop(SerializedProperty componentsProp)
{

View File

@ -4,6 +4,7 @@
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using UnityEngine;
@ -14,7 +15,7 @@ namespace DCFApixels.DragonECS
public interface IComponentTemplate : ITemplateNode
{
#region Properties
Type Type { get; }
Type ComponentType { get; }
bool IsUnique { get; }
#endregion
@ -33,16 +34,11 @@ namespace DCFApixels.DragonECS
}
[Serializable]
public abstract class ComponentTemplateBase : IComponentTemplate, ITypeMeta
[MetaProxy(typeof(ComponentTemplateMetaProxy))]
public abstract class ComponentTemplateBase : IComponentTemplate
{
#region Properties
public abstract Type Type { get; }
public virtual ITypeMeta BaseMeta { get { return null; } }
public virtual string Name { get { return string.Empty; } }
public virtual MetaColor Color { get { return new MetaColor(MetaColor.Black); } }
public virtual MetaGroup Group { get { return MetaGroup.Empty; } }
public virtual MetaDescription Description { get { return MetaDescription.Empty; } }
public virtual IReadOnlyList<string> Tags { get { return Array.Empty<string>(); } }
public abstract Type ComponentType { get; }
public virtual bool IsUnique { get { return true; } }
#endregion
@ -54,67 +50,136 @@ namespace DCFApixels.DragonECS
public abstract void Apply(short worldID, int entityID);
#endregion
protected class ComponentTemplateMetaProxy : MetaProxy
{
protected static TypeMeta Meta;
public override string Name { get { return Meta?.Name; } }
public override MetaColor? Color { get { return Meta?.Color; } }
public override MetaGroup Group { get { return Meta?.Group; } }
public override MetaDescription Description { get { return Meta?.Description; } }
public override IEnumerable<string> Tags { get { return Meta?.Tags; } }
public ComponentTemplateMetaProxy(Type type) : base(type)
{
if (type.IsGenericType && type.ContainsGenericParameters == false)
{
var g = type.GetGenericArguments();
if (g.Length == 1)
{
Meta = g[0].GetMeta();
}
}
}
}
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public abstract class ComponentTemplateBase<T> : ComponentTemplateBase, ICloneable
where T : struct
{
protected static readonly TypeMeta Meta = EcsDebugUtility.GetTypeMeta<T>();
private static bool _defaultValueTypeInit = false;
private static T _defaultValueType;
protected static T DefaultValueType
private static bool _defaultValueInit = false;
private static bool _hasDefaultValue = false;
private static T _defaultValue;
private static ICloneable _defaultValueCloneable;
private static CloneMethod _defaultValueCloneMethod;
private enum CloneMethod
{
get
Set,
Clone_Reflection,
ICloneable,
}
protected static void InitStatic()
{
if (_defaultValueTypeInit == false)
if (_defaultValueInit == false)
{
_hasDefaultValue = false;
Type type = typeof(T);
if (type.IsValueType)
{
FieldInfo field;
field = type.GetField("Default", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == type)
{
_defaultValueType = (T)field.GetValue(null);
_defaultValue = (T)field.GetValue(null);
_hasDefaultValue = true;
}
if(_hasDefaultValue == false)
{
field = type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == type)
{
_defaultValueType = (T)field.GetValue(null);
_defaultValue = (T)field.GetValue(null);
_hasDefaultValue = true;
}
}
_defaultValueTypeInit = true;
if (_defaultValue == null)
{
_hasDefaultValue = false;
}
return _defaultValueType;
if (_hasDefaultValue)
{
_defaultValueCloneable = _defaultValue as ICloneable;
_defaultValueCloneMethod = CloneMethod.Set;
if (type.IsValueType == false)
{
_defaultValueCloneMethod = CloneMethod.Clone_Reflection;
}
if (_defaultValueCloneable != null)
{
_defaultValueCloneMethod = CloneMethod.ICloneable;
}
}
_defaultValueInit = true;
}
}
protected virtual T DefaultComponent
{
get
{
if (_hasDefaultValue)
{
return CloneComponent(_defaultValue);
}
return default;
}
}
[SerializeField]
protected T component = DefaultValueType;
protected T component;
[SerializeField]
[HideInInspector]
private byte _offset; // Avoids the error "Cannot get managed reference index with out bounds offset"
#region Properties
public sealed override ITypeMeta BaseMeta { get { return Meta; } }
public sealed override Type Type { get { return typeof(T); } }
public override string Name { get { return Meta.Name; } }
public override MetaColor Color { get { return Meta.Color; } }
public override MetaGroup Group { get { return Meta.Group; } }
public override MetaDescription Description { get { return Meta.Description; } }
public override IReadOnlyList<string> Tags { get { return Meta.Tags; } }
#endregion
public ComponentTemplateBase()
{
InitStatic();
component = DefaultComponent;
}
public sealed override Type ComponentType { get { return typeof(T); } }
#region Methods
public sealed override object GetRaw() { return component; }
public sealed override void SetRaw(object raw) { component = (T)raw; }
protected virtual T CloneComponent() { return component; }
protected virtual T CloneComponent(T component)
{
switch (_defaultValueCloneMethod)
{
case CloneMethod.Set:
return component;
case CloneMethod.Clone_Reflection:
return (T)component.Clone_Reflection();
case CloneMethod.ICloneable:
return (T)_defaultValueCloneable.Clone();
}
return default;
}
object ICloneable.Clone()
{
ComponentTemplateBase<T> templateClone = (ComponentTemplateBase<T>)MemberwiseClone();
templateClone.component = CloneComponent();
templateClone.component = CloneComponent(component);
return templateClone;
}
#endregion
@ -174,9 +239,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
get
{
if (_meta == null)
{
{
_meta = ComponentType.GetMeta();
}
}
return _meta;
}
}
@ -194,7 +261,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
field = Type.GetField("Default", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type)
{
_defaultValueDummy = field.GetValue(null);
_defaultValueDummy = field.GetValue(null).Clone_Reflection();
}
if(_defaultValueDummy == null)
@ -202,7 +269,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
field = Type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type)
{
_defaultValueDummy = field.GetValue(null);
_defaultValueDummy = field.GetValue(null).Clone_Reflection();
}
}
}
@ -216,15 +283,17 @@ namespace DCFApixels.DragonECS.Unity.Editors
Type = type;
IsUnique = false;
if (typeof(IComponentTemplate).IsAssignableFrom(type))
if (type.GetInterfaces().Contains(typeof(ITypeMeta)))
{
var metaOverride = (ITypeMeta)Activator.CreateInstance(type);
_meta = metaOverride;
}
if (type.GetInterfaces().Contains(typeof(IComponentTemplate)))
{
var ct = (IComponentTemplate)Activator.CreateInstance(type);
IsUnique = ct.IsUnique;
ComponentType = ct.Type;
if (ct is ITypeMeta metaOverride)
{
_meta = metaOverride;
}
ComponentType = ct.ComponentType;
}
else
{

View File

@ -2,6 +2,7 @@
#undef DEBUG
#endif
using DCFApixels.DragonECS.Unity;
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
@ -24,8 +25,10 @@ namespace DCFApixels.DragonECS
public class MonoEntityTemplate : MonoEntityTemplateBase, ITemplateNode
{
[SerializeReference]
[ReferenceButton(true, typeof(ITemplateNode))]
[ReferenceDropDown(true)]
[TypeMetaBlock]
[FormerlySerializedAs("_components")]
[ArrayElement]
private ITemplateNode[] _componentTemplates;
#region Methods

View File

@ -25,7 +25,7 @@ namespace DCFApixels.DragonECS
[SerializeField]
private ScriptableEntityTemplateBase[] _templates;
[SerializeReference]
[ReferenceButton(true, typeof(ITemplateNode))]
[ReferenceDropDown(true)]
[FormerlySerializedAs("_components")]
private ITemplateNode[] _componentTemplates;

View File

@ -119,7 +119,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
bool isNull = targetProp.managedReferenceValue == null;
ITypeMeta meta = isNull ? null : targetProp.managedReferenceValue.GetMeta();
if (EcsGUI.DrawTypeMetaElementBlock(ref rect, _recordsProp, index, prop, meta))
if (EcsGUI.DrawTypeMetaElementBlock(ref rect, _recordsProp, index, prop, meta).skip)
{
return;
}

View File

@ -41,7 +41,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
float result = 0f;
if (IsArrayElement == false)

View File

@ -103,8 +103,8 @@ namespace DCFApixels.DragonECS.Unity
public struct Record
{
[SerializeReference]
[ReferenceButton(true, typeof(IEcsModule), typeof(IEcsProcess))]
[ReferenceButtonWithOut(typeof(IEcsRunner))]
[ReferenceDropDown(true, typeof(IEcsModule), typeof(IEcsProcess))]
[ReferenceDropDownWithout(typeof(IEcsRunner))]
[ArrayElement]
public object target;// нельзя менять поярдок полей, иначе это поломает отрисовку в инспекторе изза применения property.Next(bool);
public AddParams parameters;

View File

@ -2,35 +2,637 @@
#undef DEBUG
#endif
using DCFApixels.DragonECS.Unity.Editors;
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS
{
public sealed class ReferenceButtonAttribute : PropertyAttribute, IReferenceButtonAttribute
internal interface IReferenceDropDownAttribute
{
public readonly Type[] PredicateTypes;
Type[] PredicateTypes { get; }
bool IsHideButtonIfNotNull { get; }
}
//public sealed class ReferenceButtonAttribute : PropertyAttribute, IReferenceDropDownAttribute
//{
// public readonly Type[] PredicateTypes;
// public readonly bool IsHideButtonIfNotNull;
// Type[] IReferenceDropDownAttribute.PredicateTypes { get { return PredicateTypes; } }
// bool IReferenceDropDownAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
// public ReferenceButtonAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { }
// public ReferenceButtonAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { }
// public ReferenceButtonAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes)
// {
// IsHideButtonIfNotNull = isHideButtonIfNotNull;
// PredicateTypes = predicateTypes;
// Array.Sort(predicateTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal));
// }
//}
//public sealed class ReferenceButtonWithOutAttribute : Attribute
//{
// public readonly Type[] PredicateTypes;
// [Obsolete("With empty parameters, this attribute makes no sense.", true)]
// public ReferenceButtonWithOutAttribute() : this(Array.Empty<Type>()) { }
// public ReferenceButtonWithOutAttribute(params Type[] predicateTypes)
// {
// PredicateTypes = predicateTypes;
// Array.Sort(predicateTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal));
// }
//}
public sealed class ReferenceDropDownAttribute : PropertyAttribute, IReferenceDropDownAttribute
{
public readonly Type[] AllowTypes;
public readonly bool IsHideButtonIfNotNull;
Type[] IReferenceButtonAttribute.PredicateTypes { get { return PredicateTypes; } }
bool IReferenceButtonAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
public ReferenceButtonAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { }
public ReferenceButtonAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { }
public ReferenceButtonAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes)
Type[] IReferenceDropDownAttribute.PredicateTypes { get { return AllowTypes; } }
bool IReferenceDropDownAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
public ReferenceDropDownAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { }
public ReferenceDropDownAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { }
public ReferenceDropDownAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes)
{
IsHideButtonIfNotNull = isHideButtonIfNotNull;
PredicateTypes = predicateTypes;
AllowTypes = predicateTypes;
Array.Sort(predicateTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal));
}
}
public sealed class ReferenceButtonWithOutAttribute : Attribute
public sealed class ReferenceDropDownWithoutAttribute : Attribute
{
public readonly Type[] PredicateTypes;
[Obsolete("With empty parameters, this attribute makes no sense.", true)]
public ReferenceButtonWithOutAttribute() : this(Array.Empty<Type>()) { }
public ReferenceButtonWithOutAttribute(params Type[] predicateTypes)
public ReferenceDropDownWithoutAttribute() : this(Array.Empty<Type>()) { }
public ReferenceDropDownWithoutAttribute(params Type[] predicateTypes)
{
PredicateTypes = predicateTypes;
Array.Sort(predicateTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal));
}
}
public sealed class TypeMetaBlockAttribute : PropertyAttribute { }
}
#if UNITY_EDITOR
namespace DCFApixels.DragonECS.Unity.Editors
{
[CustomPropertyDrawer(typeof(ReferenceDropDownAttribute), true)]
[CustomPropertyDrawer(typeof(TypeMetaBlockAttribute), true)]
internal class EcsDragonFieldDrawer : ExtendedPropertyDrawer
{
private const float DamagedComponentHeight = 18f * 2f;
private DragonFieldDropDown _dropDown;
private PredicateTypesKey? _predicateOverride;
private ReferenceDropDownAttribute ReferenceDropDownAttribute;
private ReferenceDropDownWithoutAttribute ReferenceDropDownWithoutAttribute;
private TypeMetaBlockAttribute TypeMetaBlockAttribute;
private bool _isInit = false;
private bool _hasSerializableData;
[ThreadStatic]
private static int _skips = 0;
private bool CheckSkip()
{
if (_skips > 0)
{
_skips--;
return true;
}
int count = 0;
if (ReferenceDropDownAttribute != null) { count++; }
if (TypeMetaBlockAttribute != null) { count++; }
_skips = count - 1;
return false;
}
#region Properties
private float Padding => Spacing;
protected override bool IsInit => _isInit;
private bool IsDrawDropDown => ReferenceDropDownAttribute != null;
private bool IsDrawMetaBlock => TypeMetaBlockAttribute != null;
#endregion
public EcsDragonFieldDrawer() { }
public EcsDragonFieldDrawer(PredicateTypesKey key)
{
_predicateOverride = key;
}
#region Init
protected override void OnInit(SerializedProperty property)
{
PredicateTypesKey key;
_hasSerializableData = true;
if (fieldInfo != null)
{
if (property.propertyType == SerializedPropertyType.ManagedReference)
{
_hasSerializableData = property.HasSerializableData();
}
foreach (var atrRaw in Attributes)
{
switch (atrRaw)
{
case ReferenceDropDownAttribute atr: ReferenceDropDownAttribute = atr; break;
case ReferenceDropDownWithoutAttribute atr: ReferenceDropDownWithoutAttribute = atr; break;
case TypeMetaBlockAttribute atr: TypeMetaBlockAttribute = atr; break;
}
}
}
if (_predicateOverride == null && fieldInfo != null)
{
var targetType = fieldInfo.FieldType;
if (ReferenceDropDownAttribute != null)
{
Type[] withOutTypes = ReferenceDropDownWithoutAttribute != null ? ReferenceDropDownWithoutAttribute.PredicateTypes : Type.EmptyTypes;
bool allAssignableTypes = targetType != typeof(ITemplateNode);
var types = ReferenceDropDownAttribute.AllowTypes;
if (types == null || types.Length == 0)
{
if (allAssignableTypes)
{
types = new Type[] { targetType };
}
else
{
types = new Type[] { typeof(IComponentTemplate), typeof(IEcsComponentMember) };
}
}
key = new PredicateTypesKey(targetType, types, withOutTypes);
}
else
{
key = new PredicateTypesKey(targetType, new Type[] { targetType });
}
_predicateOverride = key;
}
if (IsDrawDropDown)
{
_dropDown = DragonFieldDropDown.Get(_predicateOverride.Value);
_dropDown.OnSelected += SelectComponent;
}
_isInit = true;
}
[ThreadStatic]
private static SerializedProperty currentProperty;
private static void SelectComponent(DragonFieldDropDown.Item item)
{
//EcsGUI.Changed = true;
if (item.Obj == null)
{
currentProperty.managedReferenceValue = null;
}
else
{
currentProperty.managedReferenceValue = item.Obj.CreateInstance();
currentProperty.isExpanded = false;
}
currentProperty.serializedObject.ApplyModifiedProperties();
EcsGUI.DelayedChanged = true;
}
#endregion
protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{
if (CheckSkip()) { return EditorGUI.GetPropertyHeight(property, label); }
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
SerializedProperty componentProp = property;
if (isSerializeReference)
{
var instance = property.managedReferenceValue;
if (instance == null)
{
float result = EditorGUIUtility.singleLineHeight;
if (IsDrawMetaBlock)
{
result += Padding * 2f;
}
return result;
}
try
{
if (instance is ComponentTemplateBase customTemplate)
{
componentProp = property.FindPropertyRelative("component");
}
}
catch
{
componentProp = property;
}
if (componentProp == null)
{
return DamagedComponentHeight;
}
}
{
float result = EditorGUIUtility.singleLineHeight;
if (_hasSerializableData)
{
result = EditorGUI.GetPropertyHeight(componentProp, label);
}
if (IsDrawMetaBlock)
{
result += Padding * 4f;
}
return result;
}
}
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
Draw(position, property, property, label);
}
public void Draw(Rect rect, SerializedProperty rootProperty, SerializedProperty property, GUIContent label)
{
if (CheckSkip()) { EditorGUI.PropertyField(rect, property, label, true); return; }
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
var e = Event.current;
ITypeMeta meta = null;
SerializedProperty componentProp = property;
bool isDrawProperty = true;
bool isDrawDropDown = IsDrawDropDown && isSerializeReference;
if (isSerializeReference)
{
var template = property.managedReferenceValue;
if (template is ComponentTemplateBase)
{
componentProp = property.FindPropertyRelative("component");
}
if (componentProp == null)
{
DrawDamagedComponent(rect, "Damaged component template.");
return;
}
if (template == null)
{
isDrawProperty = false;
}
//meta = template as ITypeMeta;
if (meta == null)
{
if (template is IComponentTemplate componentTemplate)
{
meta = componentTemplate.ComponentType.GetMeta();
}
else
{
meta = template.GetMeta();
}
}
if (isDrawDropDown && template != null && ReferenceDropDownAttribute.IsHideButtonIfNotNull)
{
isDrawDropDown = false;
}
}
else
{
meta = fieldInfo.FieldType.GetMeta();
}
float selectionButtonRightOffset = 0f;
if (isDrawProperty)
{
if (IsDrawMetaBlock)
{
ref var r = ref rect;
var (skip, optionsWidth) = EcsGUI.DrawTypeMetaBlock(ref r, rootProperty, meta);
selectionButtonRightOffset = optionsWidth;
if (skip)
{
return;
}
}
}
if (isDrawProperty)
{
if (IsArrayElement)
{
label.text = meta.Name;
}
var fieldRect = rect;
if (property != componentProp &&
componentProp.propertyType != SerializedPropertyType.Generic &&
componentProp.propertyType != SerializedPropertyType.ManagedReference)
{
fieldRect.xMax -= selectionButtonRightOffset;
isDrawDropDown = false;
}
var et = e.type;
if (_hasSerializableData)
{
EditorGUI.PropertyField(fieldRect, componentProp, label, true);
}
else
{
EditorGUI.LabelField(rect, label);
}
var labelRect = rect;
labelRect.width = EditorGUIUtility.labelWidth;
labelRect.xMin -= 20f;
if (e.type == EventType.Used && EcsGUI.HitTest(labelRect, e) == false)
{
e.type = et;
}
}
else
{
EditorGUI.LabelField(rect, label);
}
if (isDrawDropDown)
{
rect.xMax -= selectionButtonRightOffset;
DrawSelectionDropDown(rect, property, label);
}
}
private void DrawSelectionDropDown(Rect rect, SerializedProperty property, GUIContent label)
{
if (rect.width < 0) { return; }
var position = IsArrayElement ? rect : rect.AddPadding(EditorGUIUtility.labelWidth, 0f, 0f, 0f);
position.height = OneLineHeight;
bool isHideButtonIfNotNull = ReferenceDropDownAttribute.IsHideButtonIfNotNull;
object obj = property.hasMultipleDifferentValues ? null : property.managedReferenceValue;
string text = obj == null ? "Select..." : obj.GetMeta().Name;
if (!isHideButtonIfNotNull || obj == null)
{
if (GUI.Button(position, text, EditorStyles.layerMaskField))
{
currentProperty = property;
_dropDown.OpenForField(position, property);
}
}
else
{
GUI.Label(position, text);
}
}
private void DrawDamagedComponent(Rect position, string message)
{
EditorGUI.HelpBox(position, message, MessageType.Warning);
}
}
internal class DragonFieldDropDown : MetaObjectsDropDown<DragonFieldCahce>
{
private DragonFieldDropDown() { }
private bool _isCheckUnique;
private SerializedProperty _arrayProperty;
private SerializedProperty _fieldProperty;
public static Dictionary<PredicateTypesKey, DragonFieldDropDown> _dropDownsCache = new Dictionary<PredicateTypesKey, DragonFieldDropDown>(32);
public static DragonFieldDropDown Get(PredicateTypesKey key)
{
if (_dropDownsCache.TryGetValue(key, out var result) == false)
{
result = new DragonFieldDropDown();
IEnumerable<(DragonFieldCahce template, ITypeMeta meta)> itemMetaPairs = DragonFieldCahce.All.ToArray()
.Where(o =>
{
return key.Check(o.Type);
})
.Select(o =>
{
return (o, (ITypeMeta)o.Meta);
});
//TODO оптимизировать или вырезать
itemMetaPairs = itemMetaPairs.OrderBy(o => o.meta.Group.Name);
result.Setup(itemMetaPairs);
_dropDownsCache[key] = result;
}
return result;
}
public void OpenForArray(Rect position, SerializedProperty arrayProperty, bool isCheckUnique)
{
_isCheckUnique = isCheckUnique;
_arrayProperty = arrayProperty;
_fieldProperty = null;
Show(position);
}
public void OpenForField(Rect position, SerializedProperty fieldProperty)
{
_isCheckUnique = false;
_arrayProperty = null;
_fieldProperty = fieldProperty;
Show(position);
}
protected override void ItemSelected(Item item)
{
if (item.Obj == null)
{
_fieldProperty.managedReferenceValue = null;
_fieldProperty.serializedObject.ApplyModifiedProperties();
return;
}
Type componentType = item.Obj.GetType();
var data = item.Obj;
if (_arrayProperty != null && data != null)
{
int index = _arrayProperty.arraySize;
if (_isCheckUnique)
{
if (data.IsUnique)
{
for (int i = 0, iMax = _arrayProperty.arraySize; i < iMax; i++)
{
if (_arrayProperty.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
{
return;
}
}
}
}
_arrayProperty.arraySize += 1;
_fieldProperty = _arrayProperty.GetArrayElementAtIndex(index);
}
if (_fieldProperty != null)
{
_fieldProperty.managedReferenceValue = data.CreateInstance();
_fieldProperty.serializedObject.ApplyModifiedProperties();
}
//Event.current.Use();
}
}
internal class DragonFieldCahce
{
private static DragonFieldCahce[] _all;
internal static IReadOnlyList<DragonFieldCahce> All
{
get { return _all; }
}
static DragonFieldCahce() { StaticInit(); }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void StaticInit()
{
List<DragonFieldCahce> list = new List<DragonFieldCahce>(UnityEditorUtility._serializableTypes.Length);
foreach (var type in UnityEditorUtility._serializableTypes)
{
DragonFieldCahce element = new DragonFieldCahce(type);
list.Add(element);
}
_all = list.ToArray();
}
public readonly Type Type;
public readonly Type ComponentType;
public readonly bool IsUnique;
private TypeMeta _meta;
public TypeMeta Meta
{
get
{
if (_meta == null)
{
{
_meta = Type.GetMeta();
}
}
return _meta;
}
}
private bool _defaultValueTypeInit = false;
private object _defaultValueDummy;
public object DefaultValue
{
get
{
if (_defaultValueTypeInit == false)
{
if (Type.IsValueType)
{
FieldInfo field;
field = Type.GetField("Default", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type)
{
_defaultValueDummy = field.GetValue(null).Clone_Reflection();
}
if (_defaultValueDummy == null)
{
field = Type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type)
{
_defaultValueDummy = field.GetValue(null).Clone_Reflection();
}
}
}
_defaultValueTypeInit = true;
}
return _defaultValueDummy;
}
}
public DragonFieldCahce(Type type)
{
Type = type;
IsUnique = false;
if (type.GetInterfaces().Contains(typeof(IComponentTemplate)))
{
var ct = (IComponentTemplate)Activator.CreateInstance(type);
IsUnique = ct.IsUnique;
ComponentType = ct.ComponentType;
}
else
{
ComponentType = Type;
}
}
public object CreateInstance()
{
if (DefaultValue != null)
{
return DefaultValue.Clone_Reflection();
}
return Activator.CreateInstance(Type);
}
public override string ToString()
{
return Type.ToString();
}
}
}
#endif