DragonECS/src/Debug/EcsDebugUtility.cs

217 lines
8.7 KiB
C#
Raw Normal View History

2023-05-23 01:47:28 +08:00
using System;
2023-06-16 11:53:59 +08:00
using System.Collections.Generic;
2023-06-22 10:50:47 +08:00
using System.Linq;
2023-05-23 01:47:28 +08:00
using System.Reflection;
2023-06-22 10:50:47 +08:00
using System.Text;
2023-05-23 01:47:28 +08:00
namespace DCFApixels.DragonECS
{
public static class EcsDebugUtility
{
2023-06-16 12:34:54 +08:00
#region GetGenericTypeName
2023-05-26 04:25:09 +08:00
public static string GetGenericTypeFullName<T>(int maxDepth = 2) => GetGenericTypeFullName(typeof(T), maxDepth);
public static string GetGenericTypeFullName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, true);
2023-05-23 01:47:28 +08:00
public static string GetGenericTypeName<T>(int maxDepth = 2) => GetGenericTypeName(typeof(T), maxDepth);
2023-05-26 04:25:09 +08:00
public static string GetGenericTypeName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, false);
private static string GetGenericTypeNameInternal(Type type, int maxDepth, bool isFull)
2023-05-23 01:47:28 +08:00
{
#if (DEBUG && !DISABLE_DEBUG)
2023-06-16 12:34:54 +08:00
string result = isFull ? type.FullName : type.Name;
2023-05-23 01:47:28 +08:00
if (!type.IsGenericType || maxDepth == 0)
2023-06-16 12:34:54 +08:00
return result;
2023-05-23 01:47:28 +08:00
2023-06-16 12:34:54 +08:00
int iBacktick = result.IndexOf('`');
2023-05-23 01:47:28 +08:00
if (iBacktick > 0)
2023-06-16 12:34:54 +08:00
result = result.Remove(iBacktick);
2023-05-23 01:47:28 +08:00
2023-06-16 12:34:54 +08:00
result += "<";
2023-05-23 01:47:28 +08:00
Type[] typeParameters = type.GetGenericArguments();
for (int i = 0; i < typeParameters.Length; ++i)
{
2023-05-26 04:25:09 +08:00
string typeParamName = GetGenericTypeNameInternal(typeParameters[i], maxDepth - 1, false);//чтобы строка не была слишком длинной, используются сокращенные имена для типов аргументов
2023-06-16 12:34:54 +08:00
result += (i == 0 ? typeParamName : "," + typeParamName);
2023-05-23 01:47:28 +08:00
}
2023-06-16 12:34:54 +08:00
result += ">";
return result;
2023-05-23 02:11:00 +08:00
#else //optimization for release build
2023-05-23 01:47:28 +08:00
return type.Name;
#endif
}
2023-06-16 12:34:54 +08:00
#endregion
2023-05-23 01:47:28 +08:00
2023-06-22 10:50:47 +08:00
#region AutoToString
public static string AutoToString<T>(this T self, bool isWriteName = true) where T : struct
{
return AutoToString(self, typeof(T), isWriteName);
}
private static string AutoToString(object target, Type type, bool isWriteName)
{
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
string[] values = new string[fields.Length];
for (int i = 0; i < fields.Length; i++)
values[i] = fields[i].GetValue(target).ToString();
if(isWriteName)
return $"{type.Name}({string.Join(", ", values)})";
else
return $"({string.Join(", ", values)})";
}
#endregion
2023-06-16 12:34:54 +08:00
#region GetName
2023-05-23 01:47:28 +08:00
public static string GetName<T>() => GetName(typeof(T));
2023-06-16 12:34:54 +08:00
public static string GetName(Type type) => type.TryGetCustomAttribute(out DebugNameAttribute atr) ? atr.name : GetGenericTypeName(type);
2023-06-16 11:53:59 +08:00
public static bool TryGetCustomName<T>(out string name) => TryGetCustomName(typeof(T), out name);
public static bool TryGetCustomName(Type type, out string name)
{
2023-06-16 12:34:54 +08:00
if (type.TryGetCustomAttribute(out DebugNameAttribute atr))
2023-06-16 11:53:59 +08:00
{
name = atr.name;
return true;
}
name = string.Empty;
return false;
}
2023-06-16 12:34:54 +08:00
#endregion
2023-05-23 01:47:28 +08:00
2023-06-16 12:34:54 +08:00
#region GetDescription
2023-05-23 01:47:28 +08:00
public static string GetDescription<T>() => GetDescription(typeof(T));
2023-06-16 12:34:54 +08:00
public static string GetDescription(Type type) => type.TryGetCustomAttribute(out DebugDescriptionAttribute atr) ? atr.description : string.Empty;
2023-06-16 11:53:59 +08:00
public static bool TryGetDescription<T>(out string text) => TryGetDescription(typeof(T), out text);
public static bool TryGetDescription(Type type, out string text)
{
2023-06-16 12:34:54 +08:00
if (type.TryGetCustomAttribute(out DebugDescriptionAttribute atr))
2023-06-16 11:53:59 +08:00
{
text = atr.description;
return true;
}
text = string.Empty;
return false;
}
2023-06-16 12:34:54 +08:00
#endregion
2023-06-16 11:53:59 +08:00
#region GetColor
private static Random random = new Random();
private static Dictionary<string, WordColor> _words = new Dictionary<string, WordColor>();
private class WordColor
{
public int wordsCount;
public DebugColorAttribute.Color color;
}
private class NameColor
{
public List<WordColor> colors = new List<WordColor>();
public NameColor(IEnumerable<string> nameWords)
{
foreach (var word in nameWords)
{
if(!_words.TryGetValue(word, out WordColor color))
{
color = new WordColor();
_words.Add(word, color);
color.color = new DebugColorAttribute.Color((byte)random.Next(), (byte)random.Next(), (byte)random.Next()).UpContrastColor() / 2;
}
color.wordsCount++;
colors.Add(color);
}
}
private int CalcTotalWordsColor()
{
int result = 0;
for (int i = 0, iMax = colors.Count; i < iMax; i++)
{
result += colors[i].wordsCount;
}
return result;
}
public DebugColorAttribute.Color CalcColor()
{
float r = 0, g = 0, b = 0;
int totalWordsCount = CalcTotalWordsColor();
for (int i = 0, iMax = colors.Count; i < iMax; i++)
{
var color = colors[i];
float m = (float)color.wordsCount / totalWordsCount;
r += m * color.color.r;
g += m * color.color.g;
b += m * color.color.b;
}
return new DebugColorAttribute.Color((byte)r, (byte)g, (byte)b);
}
}
private static Dictionary<Type, NameColor> _names = new Dictionary<Type, NameColor>();
private static DebugColorAttribute.Color CalcNameColorFor(Type type)
{
Type targetType = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
if(!_names.TryGetValue(targetType, out NameColor nameColor))
{
nameColor = new NameColor(SplitString(targetType.Name));
_names.Add(targetType, nameColor);
}
return nameColor.CalcColor();
}
public static List<string> SplitString(string s)
{
string subs;
List<string> words = new List<string>();
int start = 0;
for (int i = 1; i < s.Length; i++)
{
if (char.IsUpper(s[i]))
{
subs = s.Substring(start, i - start);
if (subs.Length > 2 && subs.ToLower() != "system")
words.Add(subs);
start = i;
}
}
subs = s.Substring(start);
if (subs.Length > 2 && subs.ToLower() != "system")
words.Add(subs);
return words;
}
2023-05-23 01:47:28 +08:00
public static (byte, byte, byte) GetColorRGB<T>() => GetColorRGB(typeof(T));
public static (byte, byte, byte) GetColorRGB(Type type)
{
var atr = type.GetCustomAttribute<DebugColorAttribute>();
2023-06-16 11:53:59 +08:00
return atr != null ? (atr.r, atr.g, atr.b)
#if DEBUG //optimization for release build
: CalcNameColorFor(type).ToTuple();
#else
: ((byte)0, (byte)0, (byte)0);
#endif
}
public static bool TryGetColorRGB<T>(out (byte, byte, byte) color) => TryGetColorRGB(typeof(T), out color);
public static bool TryGetColorRGB(Type type, out (byte, byte, byte) color)
{
var atr = type.GetCustomAttribute<DebugColorAttribute>();
if(atr != null)
{
color = (atr.r, atr.g, atr.b);
return true;
}
color = ((byte)0, (byte)0, (byte)0);
return false;
2023-05-23 01:47:28 +08:00
}
2023-06-16 11:53:59 +08:00
#endregion
2023-05-31 04:09:55 +08:00
2023-06-16 12:34:54 +08:00
#region IsHidden
2023-05-31 04:09:55 +08:00
public static bool IsHidden<T>() => IsHidden(typeof(T));
2023-06-16 12:34:54 +08:00
public static bool IsHidden(Type type) => type.TryGetCustomAttribute(out DebugHideAttribute _);
#endregion
#region ReflectionExtensions
internal static bool TryGetCustomAttribute<T>(this Type self, out T attribute) where T : Attribute
2023-05-31 04:09:55 +08:00
{
2023-06-16 12:34:54 +08:00
attribute = self.GetCustomAttribute<T>();
return attribute != null;
2023-05-31 04:09:55 +08:00
}
2023-06-16 12:34:54 +08:00
internal static bool TryGetCustomAttribute<T>(this MemberInfo self, out T attribute) where T : Attribute
{
attribute = self.GetCustomAttribute<T>();
return attribute != null;
}
#endregion
2023-05-23 01:47:28 +08:00
}
}