This commit is contained in:
Mikhail 2026-04-14 12:34:01 +08:00
parent 4ddcbb9d56
commit 10185a6525
3 changed files with 240 additions and 333 deletions

View File

@ -4,12 +4,204 @@ using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEditor.IMGUI.Controls; using UnityEditor.IMGUI.Controls;
using UnityEngine; using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
{ {
internal class DragonFieldDropDown : MetaObjectsDropDown<DragonFieldDropDown.Cahce>
{
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<(Cahce template, ITypeMeta meta)> itemMetaPairs = Cahce.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 Cahce
{
private static Cahce[] _all;
internal static IReadOnlyList<Cahce> All
{
get { return _all; }
}
static Cahce() { StaticInit(); }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void StaticInit()
{
List<Cahce> list = new List<Cahce>(UnityEditorUtility._serializableTypes.Length);
foreach (var type in UnityEditorUtility._serializableTypes)
{
Cahce element = new Cahce(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 Cahce(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();
}
}
}
internal class SystemsDropDown : MetaObjectsDropDown<Type> internal class SystemsDropDown : MetaObjectsDropDown<Type>
{ {
public SystemsDropDown() public SystemsDropDown()
@ -86,94 +278,7 @@ 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 RuntimeComponentsDropDown : MetaObjectsDropDown<IEcsPool> internal class RuntimeComponentsDropDown : MetaObjectsDropDown<IEcsPool>
{ {
public RuntimeComponentsDropDown(IEnumerable<IEcsPool> pools) public RuntimeComponentsDropDown(IEnumerable<IEcsPool> pools)
@ -329,10 +434,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
return true; return true;
} }
public override bool Equals(object obj) public override bool Equals(object obj) { return obj is Key key && Equals(key); }
{
return obj is Key key && Equals(key);
}
public override int GetHashCode() public override int GetHashCode()
{ {
unchecked unchecked

View File

@ -184,8 +184,8 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
} }
[System.Serializable]
public abstract class ComponentTemplate<T> : ComponentTemplateBase<T> public class ComponentTemplate<T> : ComponentTemplateBase<T>
where T : struct, IEcsComponent where T : struct, IEcsComponent
{ {
public override void Apply(short worldID, int entityID) public override void Apply(short worldID, int entityID)
@ -193,7 +193,8 @@ namespace DCFApixels.DragonECS
EcsPool<T>.Apply(ref component, entityID, worldID); EcsPool<T>.Apply(ref component, entityID, worldID);
} }
} }
public abstract class TagComponentTemplate<T> : ComponentTemplateBase<T> [System.Serializable]
public class TagComponentTemplate<T> : ComponentTemplateBase<T>
where T : struct, IEcsTagComponent where T : struct, IEcsTagComponent
{ {
public override void Apply(short worldID, int entityID) public override void Apply(short worldID, int entityID)

View File

@ -3,9 +3,6 @@
#endif #endif
using DCFApixels.DragonECS.Unity.Internal; using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine; using UnityEngine;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
@ -38,9 +35,6 @@ namespace DCFApixels.DragonECS
} }
#if UNITY_EDITOR #if UNITY_EDITOR
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
{ {
@ -61,24 +55,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
private bool _isInit = false; private bool _isInit = false;
private bool _hasSerializableData; private bool _hasSerializableData;
#region CheckSkip // this is a damn hack to prevent the drawer from being called recursively when multiple attributes are attached to it
[ThreadStatic] private static GUIContent _unrecursiveLable;
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;
}
#endregion
#region Properties #region Properties
private float Padding => Spacing; private float Padding => Spacing;
@ -88,6 +66,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
#endregion #endregion
#region Init #region Init
protected override void OnStaticInit()
{
if(_unrecursiveLable == null)
{
_unrecursiveLable = new GUIContent();
}
}
protected override void OnInit(SerializedProperty property) protected override void OnInit(SerializedProperty property)
{ {
PredicateTypesKey key; PredicateTypesKey key;
@ -170,7 +155,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected override float GetCustomHeight(SerializedProperty property, GUIContent label) protected override float GetCustomHeight(SerializedProperty property, GUIContent label)
{ {
if (CheckSkip()) { return EditorGUI.GetPropertyHeight(property, label); } if (ReferenceEquals(_unrecursiveLable, label)) { return EditorGUI.GetPropertyHeight(property, label); }
_unrecursiveLable.text = label.text;
_unrecursiveLable.tooltip = label.tooltip;
label = _unrecursiveLable;
//if (CheckSkip()) { return EditorGUI.GetPropertyHeight(property, label); }
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference; bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
SerializedProperty componentProp = property; SerializedProperty componentProp = property;
@ -203,6 +192,18 @@ namespace DCFApixels.DragonECS.Unity.Editors
return DamagedComponentHeight; return DamagedComponentHeight;
} }
} }
else
{
var fieldType = fieldInfo.FieldType;
if (typeof(ComponentTemplateBase).IsAssignableFrom(fieldType))
{
componentProp = property.FindPropertyRelative("component");
if (componentProp == null)
{
componentProp = property;
}
}
}
{ {
float result = EditorGUIUtility.singleLineHeight; float result = EditorGUIUtility.singleLineHeight;
@ -220,8 +221,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected override void DrawCustom(Rect rect, SerializedProperty property, GUIContent label) protected override void DrawCustom(Rect rect, SerializedProperty property, GUIContent label)
{ {
if (CheckSkip()) { EditorGUI.PropertyField(rect, property, label, true); return; } if (ReferenceEquals(_unrecursiveLable, label)) { EditorGUI.PropertyField(rect, property, label, true); return; }
_unrecursiveLable.text = label.text;
_unrecursiveLable.tooltip = label.tooltip;
label = _unrecursiveLable;
//if (CheckSkip()) { EditorGUI.PropertyField(rect, property, label, true); return; }
bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference; bool isSerializeReference = property.propertyType == SerializedPropertyType.ManagedReference;
var e = Event.current; var e = Event.current;
var rootProperty = property; var rootProperty = property;
@ -268,7 +274,16 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
else else
{ {
meta = fieldInfo.FieldType.GetMeta(); var fieldType = fieldInfo.FieldType;
if (typeof(ComponentTemplateBase).IsAssignableFrom(fieldType))
{
componentProp = property.FindPropertyRelative("component");
if (componentProp == null)
{
componentProp = property;
}
}
meta = fieldType.GetMeta();
} }
@ -379,216 +394,5 @@ namespace DCFApixels.DragonECS.Unity.Editors
EditorGUI.HelpBox(position, message, MessageType.Warning); 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 #endif