Add quick interactions locally
This commit is contained in:
174
Quick Interactions/CSharp/Client/CrabUI/Global/CUIReflection.cs
Normal file
174
Quick Interactions/CSharp/Client/CrabUI/Global/CUIReflection.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user