mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2026-04-22 04:35:55 +08:00
rework components display
This commit is contained in:
parent
a23fbb712e
commit
2c5461fca1
@ -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) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -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++);
|
||||
}
|
||||
|
||||
@ -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 :
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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); }
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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 { }
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
[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)
|
||||
//{
|
||||
// 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 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);
|
||||
EditorGUI.PropertyField(position, property, label);
|
||||
}
|
||||
}
|
||||
//[CustomPropertyDrawer(typeof(ComponentTemplateFieldAttribute), true)]
|
||||
//internal class ComponentTemplateFieldDrawer : 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 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);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
#endif
|
||||
@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
EditorGUI.PropertyField(rect, prop, label);
|
||||
return;
|
||||
//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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
{
|
||||
Set,
|
||||
Clone_Reflection,
|
||||
ICloneable,
|
||||
}
|
||||
protected static void InitStatic()
|
||||
{
|
||||
if (_defaultValueInit == false)
|
||||
{
|
||||
_hasDefaultValue = false;
|
||||
Type type = typeof(T);
|
||||
FieldInfo field;
|
||||
field = type.GetField("Default", BindingFlags.Static | BindingFlags.Public);
|
||||
if (field != null && field.FieldType == type)
|
||||
{
|
||||
_defaultValue = (T)field.GetValue(null);
|
||||
_hasDefaultValue = true;
|
||||
}
|
||||
if(_hasDefaultValue == false)
|
||||
{
|
||||
field = type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
|
||||
if (field != null && field.FieldType == type)
|
||||
{
|
||||
_defaultValue = (T)field.GetValue(null);
|
||||
_hasDefaultValue = true;
|
||||
}
|
||||
}
|
||||
if (_defaultValue == null)
|
||||
{
|
||||
_hasDefaultValue = false;
|
||||
}
|
||||
|
||||
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 (_defaultValueTypeInit == false)
|
||||
if (_hasDefaultValue)
|
||||
{
|
||||
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);
|
||||
}
|
||||
field = type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
|
||||
if (field != null && field.FieldType == type)
|
||||
{
|
||||
_defaultValueType = (T)field.GetValue(null);
|
||||
}
|
||||
}
|
||||
_defaultValueTypeInit = true;
|
||||
return CloneComponent(_defaultValue);
|
||||
}
|
||||
return _defaultValueType;
|
||||
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
|
||||
@ -175,7 +240,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
if (_meta == null)
|
||||
{
|
||||
_meta = ComponentType.GetMeta();
|
||||
{
|
||||
_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
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -25,7 +25,7 @@ namespace DCFApixels.DragonECS
|
||||
[SerializeField]
|
||||
private ScriptableEntityTemplateBase[] _templates;
|
||||
[SerializeReference]
|
||||
[ReferenceButton(true, typeof(ITemplateNode))]
|
||||
[ReferenceDropDown(true)]
|
||||
[FormerlySerializedAs("_components")]
|
||||
private ITemplateNode[] _componentTemplates;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
Loading…
Reference in New Issue
Block a user