This commit is contained in:
Mikhail 2026-04-14 17:06:58 +08:00
parent 224a689ab6
commit fe3163ab3d
5 changed files with 169 additions and 101 deletions

View File

@ -15,6 +15,7 @@ namespace DCFApixels.DragonECS
[MetaDescription(AUTHOR, "Component-reference to Unity object for EcsPool.")] [MetaDescription(AUTHOR, "Component-reference to Unity object for EcsPool.")]
[MetaID("DragonECS_734F667C9201B80F1913388C2A8BB689")] [MetaID("DragonECS_734F667C9201B80F1913388C2A8BB689")]
[MetaTags(MetaTags.ENGINE_MEMBER)] [MetaTags(MetaTags.ENGINE_MEMBER)]
[MetaProxy(typeof(UnityComponent<>.MetaProxy))]
public struct UnityComponent<T> : IEcsComponent, IEnumerable<T>//IntelliSense hack public struct UnityComponent<T> : IEcsComponent, IEnumerable<T>//IntelliSense hack
where T : Component where T : Component
{ {
@ -34,6 +35,16 @@ namespace DCFApixels.DragonECS
{ {
return $"UnityComponent<{typeof(T).GetMeta().TypeName}>"; return $"UnityComponent<{typeof(T).GetMeta().TypeName}>";
} }
private class MetaProxy : MetaProxyBase
{
protected TypeMeta Meta = typeof(T).GetMeta();
public override string Name { get { return Meta?.Name; } }
public override MetaColor? Color { get { return Meta != null && Meta.IsCustomColor ? Meta.Color : null; } }
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 MetaProxy(Type type) : base(type) { }
}
} }
internal static class UnityComponentConsts internal static class UnityComponentConsts

View File

@ -11,7 +11,7 @@ using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
{ {
internal class DragonFieldDropDown : MetaObjectsDropDown<DragonFieldDropDown.Cahce> internal class DragonFieldDropDown : MetaObjectsDropDown<DragonFieldCahce>
{ {
private DragonFieldDropDown() { } private DragonFieldDropDown() { }
@ -25,15 +25,15 @@ namespace DCFApixels.DragonECS.Unity.Editors
if (_dropDownsCache.TryGetValue(key, out var result) == false) if (_dropDownsCache.TryGetValue(key, out var result) == false)
{ {
result = new DragonFieldDropDown(); result = new DragonFieldDropDown();
IEnumerable<(Cahce template, ITypeMeta meta)> itemMetaPairs = Cahce.All.ToArray() IEnumerable<(DragonFieldCahce template, ITypeMeta meta)> itemMetaPairs = DragonFieldCahce.All.ToArray()
.Where(o => .Where(o =>
{ {
return key.Check(o.Type); return key.Check(o);
}) })
.Select(o => .Select(o =>
{ {
return (o, (ITypeMeta)o.Meta); var info = DragonFieldCahce.GetInfoFor(o);
return (info, (ITypeMeta)info.Meta);
}); });
//TODO оптимизировать или вырезать //TODO оптимизировать или вырезать
@ -99,106 +99,145 @@ namespace DCFApixels.DragonECS.Unity.Editors
//Event.current.Use(); //Event.current.Use();
} }
}
internal class Cahce internal class DragonFieldCahce
{
internal static Type[] All => UnityEditorUtility._serializableTypes;
internal static HashSet<Type> AllDict;
internal static Dictionary<Type, DragonFieldCahce> RuntimeDict;
static DragonFieldCahce() { StaticInit(); }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void StaticInit()
{ {
private static Cahce[] _all; AllDict = new HashSet<Type>(All);
internal static IReadOnlyList<Cahce> All RuntimeDict = new Dictionary<Type, DragonFieldCahce>();
}
public static DragonFieldCahce GetInfoFor(Type type)
{
if (RuntimeDict.TryGetValue(type, out var info))
{ {
get { return _all; } return info;
} }
static Cahce() { StaticInit(); } if (AllDict.Contains(type))
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void StaticInit()
{ {
List<Cahce> list = new List<Cahce>(UnityEditorUtility._serializableTypes.Length); info = new DragonFieldCahce(type);
foreach (var type in UnityEditorUtility._serializableTypes) RuntimeDict.Add(type, info);
{ return info;
Cahce element = new Cahce(type);
list.Add(element);
}
_all = list.ToArray();
} }
return null;
}
public readonly Type Type; public static bool TryGetInfoFor(Type type, out DragonFieldCahce info)
public readonly Type ComponentType; {
public readonly bool IsUnique; if (RuntimeDict.TryGetValue(type, out info))
private TypeMeta _meta;
public TypeMeta Meta
{ {
get return true;
}
if (AllDict.Contains(type))
{
info = new DragonFieldCahce(type);
RuntimeDict.Add(type, info);
return true;
}
info = null;
return false;
}
public readonly Type Type;
public readonly Type ComponentType;
public readonly string WrappedFieldName;
public bool HasWrappedFieldName
{
get { return string.IsNullOrEmpty(WrappedFieldName) == false; }
}
public readonly bool IsUnique;
private TypeMeta _meta;
public TypeMeta Meta
{
get
{
if (_meta == null)
{ {
if (_meta == null)
{ {
{ _meta = Type.GetMeta();
_meta = Type.GetMeta();
}
} }
return _meta;
} }
return _meta;
} }
private bool _defaultValueTypeInit = false; }
private object _defaultValueDummy; private bool _defaultValueTypeInit = false;
public object DefaultValue private object _defaultValueDummy;
public object DefaultValue
{
get
{ {
get if (_defaultValueTypeInit == false)
{ {
if (_defaultValueTypeInit == false) if (Type.IsValueType)
{ {
if (Type.IsValueType) FieldInfo field;
field = Type.GetField("Default", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type)
{ {
FieldInfo field; _defaultValueDummy = field.GetValue(null).Clone_Reflection();
field = Type.GetField("Default", BindingFlags.Static | BindingFlags.Public); }
if (_defaultValueDummy == null)
{
field = Type.GetField("Empty", BindingFlags.Static | BindingFlags.Public);
if (field != null && field.FieldType == Type) if (field != null && field.FieldType == Type)
{ {
_defaultValueDummy = field.GetValue(null).Clone_Reflection(); _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; _defaultValueTypeInit = true;
} }
return _defaultValueDummy;
} }
public Cahce(Type type) }
{ public DragonFieldCahce(Type type)
Type = type; {
IsUnique = false; Type = type;
IsUnique = false;
if (type.GetInterfaces().Contains(typeof(IComponentTemplate))) if(type.TryGetAttribute<DragonMemnberWrapperAttribute>(out var atr))
{
var ct = (IComponentTemplate)Activator.CreateInstance(type);
IsUnique = ct.IsUnique;
ComponentType = ct.ComponentType;
}
else
{
ComponentType = Type;
}
}
public object CreateInstance()
{ {
if (DefaultValue != null) WrappedFieldName = atr.WrappedFieldName;
var field = type.GetField(atr.WrappedFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.FieldType.IsConcreteType())
{ {
return DefaultValue.Clone_Reflection(); ComponentType = field.FieldType;
} }
return Activator.CreateInstance(Type);
} }
public override string ToString() if (type.GetInterfaces().Contains(typeof(IComponentTemplate)))
{ {
return Type.ToString(); var ct = (IComponentTemplate)Activator.CreateInstance(type);
IsUnique = ct.IsUnique;
ComponentType = ct.ComponentType;
} }
if(ComponentType == null)
{
ComponentType = Type;
}
}
public object CreateInstance()
{
if (DefaultValue != null)
{
return DefaultValue.Clone_Reflection();
}
return Activator.CreateInstance(Type);
}
public override string ToString()
{
return Type.ToString();
} }
} }

View File

@ -1,6 +1,7 @@
#if DISABLE_DEBUG #if DISABLE_DEBUG
#undef DEBUG #undef DEBUG
#endif #endif
using DCFApixels.DragonECS.Unity;
using DCFApixels.DragonECS.Unity.Internal; using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -8,10 +9,23 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using UnityEngine; using UnityEngine;
using static DCFApixels.DragonECS.IComponentTemplate;
namespace DCFApixels.DragonECS.Unity
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
public sealed class DragonMemnberWrapperAttribute : Attribute
{
public string WrappedFieldName;
public DragonMemnberWrapperAttribute(string wrappedFieldName)
{
WrappedFieldName = wrappedFieldName;
}
}
}
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public interface IComponentTemplate : ITemplateNode public interface IComponentTemplate : ITemplateNode
{ {
#region Properties #region Properties
@ -35,6 +49,7 @@ namespace DCFApixels.DragonECS
[Serializable] [Serializable]
[MetaProxy(typeof(ComponentTemplateMetaProxy))] [MetaProxy(typeof(ComponentTemplateMetaProxy))]
[DragonMemnberWrapper("component")]
public abstract class ComponentTemplateBase : IComponentTemplate public abstract class ComponentTemplateBase : IComponentTemplate
{ {
#region Properties #region Properties
@ -45,17 +60,18 @@ namespace DCFApixels.DragonECS
#region Methods #region Methods
public abstract object GetRaw(); public abstract object GetRaw();
public abstract void SetRaw(object raw); public abstract void SetRaw(object raw);
public virtual void OnGizmos(Transform transform, GizmosMode mode) { } public virtual void OnGizmos(Transform transform, IComponentTemplate.GizmosMode mode) { }
public virtual void OnValidate(UnityEngine.Object obj) { } public virtual void OnValidate(UnityEngine.Object obj) { }
public abstract void Apply(short worldID, int entityID); public abstract void Apply(short worldID, int entityID);
#endregion #endregion
#region MetaProxy
protected class ComponentTemplateMetaProxy : MetaProxyBase protected class ComponentTemplateMetaProxy : MetaProxyBase
{ {
protected TypeMeta Meta; protected TypeMeta Meta;
public override string Name { get { return Meta?.Name; } } public override string Name { get { return Meta?.Name; } }
public override MetaColor? Color { get { return Meta?.Color; } } public override MetaColor? Color { get { return Meta != null && Meta.IsCustomColor ? Meta.Color : null; } }
public override MetaGroup Group { get { return Meta?.Group; } } public override MetaGroup Group { get { return Meta?.Group; } }
public override MetaDescription Description { get { return Meta?.Description; } } public override MetaDescription Description { get { return Meta?.Description; } }
public override IEnumerable<string> Tags { get { return Meta?.Tags; } } public override IEnumerable<string> Tags { get { return Meta?.Tags; } }
@ -74,6 +90,7 @@ namespace DCFApixels.DragonECS
} }
} }
#endregion
} }
[Serializable] [Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]

View File

@ -178,9 +178,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
try try
{ {
if (instance is ComponentTemplateBase customTemplate) if(DragonFieldCahce.RuntimeDict.TryGetValue(instance.GetType(), out var info) && info.HasWrappedFieldName)
{ {
componentProp = property.FindPropertyRelative("component"); componentProp = property.FindPropertyRelative(info.WrappedFieldName);
} }
} }
catch catch
@ -194,16 +194,16 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
else else
{ {
var fieldType = fieldInfo.FieldType; var fieldType = PropertyType;
if (typeof(ComponentTemplateBase).IsAssignableFrom(fieldType)) if (DragonFieldCahce.RuntimeDict.TryGetValue(fieldType, out var info) && info.HasWrappedFieldName)
{ {
componentProp = property.FindPropertyRelative("component"); componentProp = property.FindPropertyRelative(info.WrappedFieldName);
if (componentProp == null)
{
componentProp = property;
}
} }
} }
if (componentProp == null)
{
componentProp = property;
}
{ {
float result = EditorGUIUtility.singleLineHeight; float result = EditorGUIUtility.singleLineHeight;
@ -239,18 +239,17 @@ namespace DCFApixels.DragonECS.Unity.Editors
Rect srcRect = rect; Rect srcRect = rect;
if (isSerializeReference) if (isSerializeReference)
{ {
var template = property.managedReferenceValue; var instance = property.managedReferenceValue;
if (DragonFieldCahce.TryGetInfoFor(instance.GetType(), out var info) && info.HasWrappedFieldName)
if (template is ComponentTemplateBase)
{ {
componentProp = property.FindPropertyRelative("component"); componentProp = property.FindPropertyRelative(info.WrappedFieldName);
} }
if (componentProp == null) if (componentProp == null)
{ {
DrawDamagedComponent(rect, "Damaged component template."); DrawDamagedComponent(rect, "Damaged component template.");
return; return;
} }
if (template == null) if (instance == null)
{ {
isDrawProperty = false; isDrawProperty = false;
} }
@ -258,34 +257,36 @@ namespace DCFApixels.DragonECS.Unity.Editors
//meta = template as ITypeMeta; //meta = template as ITypeMeta;
if (meta == null) if (meta == null)
{ {
if (template is IComponentTemplate componentTemplate) if (info != null)
{ {
meta = componentTemplate.ComponentType.GetMeta(); meta = info.ComponentType.GetMeta();
} }
else else
{ {
meta = template.GetMeta(); meta = instance.GetMeta();
} }
} }
if (isDrawDropDown && template != null && ReferenceDropDownAttribute.IsHideButtonIfNotNull) EcsDebug.PrintJson(meta);
if (isDrawDropDown && instance != null && ReferenceDropDownAttribute.IsHideButtonIfNotNull)
{ {
isDrawDropDown = false; isDrawDropDown = false;
} }
} }
else else
{ {
var fieldType = fieldInfo.FieldType; var fieldType = PropertyType;
if (typeof(ComponentTemplateBase).IsAssignableFrom(fieldType)) if (DragonFieldCahce.RuntimeDict.TryGetValue(fieldType, out var info) && info.HasWrappedFieldName)
{ {
componentProp = property.FindPropertyRelative("component"); componentProp = property.FindPropertyRelative(info.WrappedFieldName);
if (componentProp == null)
{
componentProp = property;
}
} }
meta = fieldType.GetMeta(); meta = fieldType.GetMeta();
} }
if (componentProp == null)
{
componentProp = property;
}