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,31 +99,60 @@ namespace DCFApixels.DragonECS.Unity.Editors
//Event.current.Use(); //Event.current.Use();
} }
internal class Cahce
{
private static Cahce[] _all;
internal static IReadOnlyList<Cahce> All
{
get { return _all; }
} }
static Cahce() { StaticInit(); }
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)] [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void StaticInit() private static void StaticInit()
{ {
List<Cahce> list = new List<Cahce>(UnityEditorUtility._serializableTypes.Length); AllDict = new HashSet<Type>(All);
foreach (var type in UnityEditorUtility._serializableTypes) RuntimeDict = new Dictionary<Type, DragonFieldCahce>();
{
Cahce element = new Cahce(type);
list.Add(element);
} }
_all = list.ToArray(); public static DragonFieldCahce GetInfoFor(Type type)
{
if (RuntimeDict.TryGetValue(type, out var info))
{
return info;
}
if (AllDict.Contains(type))
{
info = new DragonFieldCahce(type);
RuntimeDict.Add(type, info);
return info;
}
return null;
}
public static bool TryGetInfoFor(Type type, out DragonFieldCahce info)
{
if (RuntimeDict.TryGetValue(type, out info))
{
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 Type;
public readonly Type ComponentType; public readonly Type ComponentType;
public readonly string WrappedFieldName;
public bool HasWrappedFieldName
{
get { return string.IsNullOrEmpty(WrappedFieldName) == false; }
}
public readonly bool IsUnique; public readonly bool IsUnique;
private TypeMeta _meta; private TypeMeta _meta;
public TypeMeta Meta public TypeMeta Meta
@ -170,18 +199,29 @@ namespace DCFApixels.DragonECS.Unity.Editors
return _defaultValueDummy; return _defaultValueDummy;
} }
} }
public Cahce(Type type) public DragonFieldCahce(Type type)
{ {
Type = type; Type = type;
IsUnique = false; IsUnique = false;
if(type.TryGetAttribute<DragonMemnberWrapperAttribute>(out var atr))
{
WrappedFieldName = atr.WrappedFieldName;
var field = type.GetField(atr.WrappedFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.FieldType.IsConcreteType())
{
ComponentType = field.FieldType;
}
}
if (type.GetInterfaces().Contains(typeof(IComponentTemplate))) if (type.GetInterfaces().Contains(typeof(IComponentTemplate)))
{ {
var ct = (IComponentTemplate)Activator.CreateInstance(type); var ct = (IComponentTemplate)Activator.CreateInstance(type);
IsUnique = ct.IsUnique; IsUnique = ct.IsUnique;
ComponentType = ct.ComponentType; ComponentType = ct.ComponentType;
} }
else
if(ComponentType == null)
{ {
ComponentType = Type; ComponentType = Type;
} }
@ -200,7 +240,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
return Type.ToString(); return Type.ToString();
} }
} }
}
internal class SystemsDropDown : MetaObjectsDropDown<Type> internal class SystemsDropDown : MetaObjectsDropDown<Type>
{ {

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) if (componentProp == null)
{ {
componentProp = property; 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);
}
meta = fieldType.GetMeta();
}
if (componentProp == null) if (componentProp == null)
{ {
componentProp = property; componentProp = property;
} }
}
meta = fieldType.GetMeta();
}