DragonECS/src/Debug/TypeMeta.cs

375 lines
10 KiB
C#
Raw Normal View History

2024-06-05 14:39:19 +08:00
using DCFApixels.DragonECS.Internal;
2024-06-11 02:30:00 +08:00
using DCFApixels.DragonECS.PoolsCore;
using DCFApixels.DragonECS.RunnersCore;
2024-06-05 14:39:19 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace DCFApixels.DragonECS
{
public interface ITypeMeta
{
Type Type { get; }
string Name { get; }
MetaColor Color { get; }
MetaDescription Description { get; }
MetaGroup Group { get; }
2024-06-08 02:08:20 +08:00
IReadOnlyList<string> Tags { get; }
2024-06-05 14:39:19 +08:00
}
2024-06-11 02:30:00 +08:00
[MetaGroup(EcsConsts.FRAMEWORK_GROUP)]
2024-06-08 02:08:20 +08:00
[MetaColor(MetaColor.DragonRose)]
2024-06-11 02:30:00 +08:00
[MetaDescription(EcsConsts.AUTHOR, "Intended for extending meta information of types, for customization of type display in the editor. You can get it by using the object.GetMeta() or Type.ToMeta() extension method.")]
2024-06-05 14:39:19 +08:00
[DebuggerTypeProxy(typeof(DebuggerProxy))]
2024-06-11 02:30:00 +08:00
/// <summary> Expanding meta information over Type. </summary>
2024-06-05 14:39:19 +08:00
public sealed class TypeMeta : ITypeMeta
{
private static readonly Dictionary<Type, TypeMeta> _metaCache = new Dictionary<Type, TypeMeta>();
internal readonly Type _type;
private bool _isCustomName;
private bool _isCustomColor;
private bool _isHidden;
private string _name;
private MetaColor _color;
private MetaDescription _description;
private MetaGroup _group;
2024-06-08 02:08:20 +08:00
private IReadOnlyList<string> _tags;
2024-06-05 14:39:19 +08:00
private int _typeCode;
private InitFlag _initFlags = InitFlag.None;
2024-06-11 02:30:00 +08:00
private EcsMemberType _memberType;
2024-06-05 14:39:19 +08:00
#region Constructors
public static TypeMeta Get(Type type)
{
if (_metaCache.TryGetValue(type, out TypeMeta result) == false)
{
result = new TypeMeta(type);
_metaCache.Add(type, result);
}
return result;
}
private TypeMeta(Type type)
{
_type = type;
2024-06-11 02:30:00 +08:00
Type runnerType = typeof(EcsRunner<>);
Type processMember = typeof(IEcsProcess);
if (type.IsInterface == false && processMember.IsAssignableFrom(type) && runnerType.IsAssignableFrom(type) == false)
{
_memberType = EcsMemberType.System;
return;
}
_memberType = EcsMemberType.Other;
2024-06-05 14:39:19 +08:00
}
#endregion
#region Type
public Type Type
{
get { return _type; }
}
#endregion
2024-06-11 02:30:00 +08:00
#region EcsMemberType
public EcsMemberType EcsMemberType
{
get { return _memberType; }
}
#endregion
2024-06-05 14:39:19 +08:00
#region Name
private void InitName()
{
if (_initFlags.HasFlag(InitFlag.Name) == false)
{
(_name, _isCustomName) = MetaGenerator.GetMetaName(_type);
_initFlags |= InitFlag.Name;
}
}
public bool IsCustomName
{
get
{
InitName();
return _isCustomName;
}
}
public string Name
{
get
{
InitName();
return _name;
}
}
#endregion
#region Color
private void InitColor()
{
if (_initFlags.HasFlag(InitFlag.Color) == false)
{
(_color, _isCustomColor) = MetaGenerator.GetColor(_type);
_initFlags |= InitFlag.Color;
}
}
public bool IsCustomColor
{
get
{
InitColor();
return _isCustomColor;
}
}
public MetaColor Color
{
get
{
InitColor();
return _color;
}
}
#endregion
#region Description
public MetaDescription Description
{
get
{
if (_initFlags.HasFlag(InitFlag.Description) == false)
{
_description = MetaGenerator.GetDescription(_type);
_initFlags |= InitFlag.Description;
}
return _description;
}
}
#endregion
#region Group
public MetaGroup Group
{
get
{
if (_initFlags.HasFlag(InitFlag.Group) == false)
{
_group = MetaGenerator.GetGroup(_type);
_initFlags |= InitFlag.Group;
}
return _group;
}
}
#endregion
#region Tags
private void InitTags()
{
if (_initFlags.HasFlag(InitFlag.Tags) == false)
{
_tags = MetaGenerator.GetTags(_type);
_initFlags |= InitFlag.Tags;
_isHidden = _tags.Contains(MetaTags.HIDDEN);
}
}
2024-06-08 02:08:20 +08:00
public IReadOnlyList<string> Tags
2024-06-05 14:39:19 +08:00
{
get
{
InitTags();
return _tags;
}
}
public bool IsHidden
{
get
{
InitTags();
return _isHidden;
}
}
#endregion
#region TypeCode
public int TypeCode
{
get
{
if (_initFlags.HasFlag(InitFlag.TypeCode) == false)
{
_typeCode = EcsTypeCode.Get(_type);
_initFlags |= InitFlag.TypeCode;
}
return _typeCode;
}
}
#endregion
#region InitializeAll
public TypeMeta InitializeAll()
{
if (_initFlags != InitFlag.All)
{
_ = Name;
_ = Group;
_ = Color;
_ = Description;
_ = Tags;
_ = TypeCode;
}
return this;
}
#endregion
#region InitFlag
[Flags]
private enum InitFlag : byte
{
None = 0,
Name = 1 << 0,
Group = 1 << 1,
Color = 1 << 2,
Description = 1 << 3,
Tags = 1 << 4,
TypeCode = 1 << 5,
2024-06-11 02:30:00 +08:00
MemberType = 1 << 6,
2024-06-05 14:39:19 +08:00
2024-06-11 02:30:00 +08:00
All = Name | Group | Color | Description | Tags | TypeCode | MemberType
2024-06-05 14:39:19 +08:00
}
#endregion
#region Other
public override string ToString()
{
return Name;
}
2024-06-08 02:08:20 +08:00
public override int GetHashCode()
{
return _color.GetHashCode() ^ _name[0].GetHashCode() ^ _name[_name.Length - 1].GetHashCode();
}
2024-06-05 14:39:19 +08:00
private class DebuggerProxy : ITypeMeta
{
private readonly TypeMeta _meta;
public Type Type
{
get { return _meta.Type; }
}
public string Name
{
get { return _meta.Name; }
}
public MetaColor Color
{
get { return _meta.Color; }
}
public MetaDescription Description
{
get { return _meta.Description; }
}
public MetaGroup Group
{
get { return _meta.Group; }
}
2024-06-08 02:08:20 +08:00
public IReadOnlyList<string> Tags
2024-06-05 14:39:19 +08:00
{
get { return _meta.Tags; }
}
public DebuggerProxy(TypeMeta meta)
{
_meta = meta;
}
}
#endregion
#region MetaGenerator
private static class MetaGenerator
{
private const int GENERIC_NAME_DEPTH = 3;
2024-06-11 02:30:00 +08:00
//private static HashSet<Type> _;
#region GetMemberType
public static EcsMemberType GetMemberType(Type type)
{
throw new NotImplementedException();
}
#endregion
2024-06-05 14:39:19 +08:00
#region GetMetaName
public static (string, bool) GetMetaName(Type type)
{
bool isCustom = type.TryGetCustomAttribute(out MetaNameAttribute atr) && string.IsNullOrEmpty(atr.name) == false;
if (isCustom)
{
if ((type.IsGenericType && atr.isHideGeneric == false) == false)
{
return (atr.name, isCustom);
}
string genericParams = "";
Type[] typeParameters = type.GetGenericArguments();
for (int i = 0; i < typeParameters.Length; ++i)
{
string paramTypeName = EcsDebugUtility.GetGenericTypeName(typeParameters[i], GENERIC_NAME_DEPTH);
genericParams += (i == 0 ? paramTypeName : $", {paramTypeName}");
}
return ($"{atr.name}<{genericParams}>", isCustom);
}
return (EcsDebugUtility.GetGenericTypeName(type, GENERIC_NAME_DEPTH), isCustom);
}
#endregion
#region GetColor
private static MetaColor AutoColor(Type type)
{
return new MetaColor(type.Name).UpContrast();//.Desaturate(0.48f) / 1.18f;
}
public static (MetaColor, bool) GetColor(Type type)
{
bool isCustom = type.TryGetCustomAttribute(out MetaColorAttribute atr);
return (isCustom ? atr.color : AutoColor(type), isCustom);
}
#endregion
#region GetGroup
public static MetaGroup GetGroup(Type type)
{
return type.TryGetCustomAttribute(out MetaGroupAttribute atr) ? atr.Data : MetaGroup.Empty;
}
#endregion
#region GetDescription
public static MetaDescription GetDescription(Type type)
{
bool isCustom = type.TryGetCustomAttribute(out MetaDescriptionAttribute atr);
return isCustom ? atr.Data : MetaDescription.Empty;
}
#endregion
#region GetTags
2024-06-08 02:08:20 +08:00
public static IReadOnlyList<string> GetTags(Type type)
2024-06-05 14:39:19 +08:00
{
var atr = type.GetCustomAttribute<MetaTagsAttribute>();
return atr != null ? atr.Tags : Array.Empty<string>();
}
#endregion
}
#endregion
}
2024-06-11 02:30:00 +08:00
public enum EcsMemberType : byte
{
Undefined = 0,
Component = 1,
System = 2,
Other = 3,
}
2024-06-05 14:39:19 +08:00
}