174 lines
4.5 KiB
C#
174 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.IO;
|
|
|
|
using Barotrauma;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using HarmonyLib;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
|
|
namespace QICrabUI
|
|
{
|
|
|
|
public class TypeTreeNode
|
|
{
|
|
public Type T;
|
|
public TypeTreeNode Parent;
|
|
public List<TypeTreeNode> Children = new();
|
|
public CUITypeMetaData Meta => CUITypeMetaData.Get(T);
|
|
public void Add(TypeTreeNode child)
|
|
{
|
|
child.Parent = this;
|
|
Children.Add(child);
|
|
}
|
|
public TypeTreeNode(Type t) => T = t;
|
|
public override string ToString() => T?.ToString() ?? "null";
|
|
public void RunRecursive(Action<TypeTreeNode> action)
|
|
{
|
|
action(this);
|
|
foreach (TypeTreeNode child in Children)
|
|
{
|
|
child.RunRecursive(action);
|
|
}
|
|
}
|
|
|
|
}
|
|
[CUIInternal]
|
|
public class CUIReflection
|
|
{
|
|
internal static void InitStatic()
|
|
{
|
|
CUI.OnInit += () =>
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
FindCUITypes();
|
|
FormCUITypeTree();
|
|
CUIDebug.Log($"CUIReflection.Initialize took {sw.ElapsedMilliseconds}ms");
|
|
};
|
|
CUI.OnDispose += () =>
|
|
{
|
|
CUITypes.Clear();
|
|
CUILayoutTypes.Clear();
|
|
CUITypeTree.Clear();
|
|
};
|
|
}
|
|
|
|
|
|
|
|
public record TypePair(Type type, Type baseType);
|
|
|
|
public static Dictionary<Type, TypeTreeNode> CUITypeTree = new();
|
|
|
|
public static Dictionary<string, Type> CUILayoutTypes = new();
|
|
public static Dictionary<string, Type> CUITypes = new Dictionary<string, Type>();
|
|
|
|
public static void FormCUITypeTree()
|
|
{
|
|
List<TypePair> Pustoe = CUITypes.Values.Select(t => new TypePair(t, t.BaseType)).ToList();
|
|
List<TypePair> Porojnee = new List<TypePair>();
|
|
|
|
while (Pustoe.Count > 0)
|
|
{
|
|
Porojnee = new List<TypePair>();
|
|
foreach (TypePair pair in Pustoe)
|
|
{
|
|
// Tree root CUIComponent
|
|
if (pair.baseType == typeof(object))
|
|
{
|
|
CUITypeTree[pair.type] = new TypeTreeNode(pair.type);
|
|
continue;
|
|
}
|
|
|
|
// Derived class
|
|
if (CUITypeTree.ContainsKey(pair.baseType))
|
|
{
|
|
CUITypeTree[pair.type] = new TypeTreeNode(pair.type);
|
|
CUITypeTree[pair.baseType].Add(CUITypeTree[pair.type]);
|
|
continue;
|
|
}
|
|
|
|
// Base class not in tree yet
|
|
Porojnee.Add(pair);
|
|
}
|
|
|
|
Pustoe.Clear();
|
|
Pustoe = Porojnee;
|
|
}
|
|
|
|
//foreach (TypeTreeNode node in CUITypeTree.Values) CUI.Log(node);
|
|
}
|
|
|
|
public static void FindCUITypes()
|
|
{
|
|
Assembly CUIAssembly = Assembly.GetAssembly(typeof(CUI));
|
|
Assembly CallingAssembly = Assembly.GetCallingAssembly();
|
|
|
|
CUITypes["CUIComponent"] = typeof(CUIComponent);
|
|
CUILayoutTypes["CUILayout"] = typeof(CUILayout);
|
|
|
|
|
|
//TODO Nested types might have same name, think how to separate them
|
|
// lua and style resolver uses them
|
|
// string name = t.Name;
|
|
// if (t.DeclaringType != null) name = $"{t.DeclaringType.Name}.{t.Name}";
|
|
// CUITypes[name] = t;
|
|
foreach (Type t in CallingAssembly.GetTypes())
|
|
{
|
|
if (t.IsSubclassOf(typeof(CUIComponent))) CUITypes[t.Name] = t;
|
|
if (t.IsSubclassOf(typeof(CUILayout))) CUILayoutTypes[t.Name] = t;
|
|
}
|
|
|
|
foreach (Type t in CUIAssembly.GetTypes())
|
|
{
|
|
if (t.IsSubclassOf(typeof(CUIComponent))) CUITypes[t.Name] = t;
|
|
if (t.IsSubclassOf(typeof(CUILayout))) CUILayoutTypes[t.Name] = t;
|
|
}
|
|
}
|
|
|
|
public static Type GetComponentTypeByName(string name)
|
|
{
|
|
return CUITypes.GetValueOrDefault(name);
|
|
}
|
|
|
|
public static object GetDefault(object obj)
|
|
{
|
|
FieldInfo defField = obj.GetType().GetField("Default", BindingFlags.Static | BindingFlags.Public);
|
|
if (defField == null) return null;
|
|
return defField.GetValue(null);
|
|
}
|
|
|
|
public static object GetNestedValue(object obj, string nestedName)
|
|
{
|
|
string[] names = nestedName.Split('.');
|
|
|
|
foreach (string name in names)
|
|
{
|
|
FieldInfo fi = obj.GetType().GetField(name, AccessTools.all);
|
|
PropertyInfo pi = obj.GetType().GetProperty(name, AccessTools.all);
|
|
|
|
if (fi != null)
|
|
{
|
|
obj = fi.GetValue(obj);
|
|
continue;
|
|
}
|
|
|
|
if (pi != null)
|
|
{
|
|
obj = pi.GetValue(obj);
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
}
|
|
} |