CrabUI
Loading...
Searching...
No Matches
CUIReflection.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5using System.Diagnostics;
6using System.Runtime.CompilerServices;
7using System.IO;
8
9using Barotrauma;
10using Microsoft.Xna.Framework;
11using Microsoft.Xna.Framework.Input;
12using Microsoft.Xna.Framework.Graphics;
13using HarmonyLib;
14using System.Xml;
15using System.Xml.Linq;
16
17namespace CrabUI
18{
19
20 public class TypeTreeNode
21 {
22 public Type T;
23 public TypeTreeNode Parent;
24 public List<TypeTreeNode> Children = new();
25 public CUITypeMetaData Meta => CUITypeMetaData.Get(T);
26 public void Add(TypeTreeNode child)
27 {
28 child.Parent = this;
29 Children.Add(child);
30 }
31 public TypeTreeNode(Type t) => T = t;
32 public override string ToString() => T?.ToString() ?? "null";
33 public void RunRecursive(Action<TypeTreeNode> action)
34 {
35 action(this);
36 foreach (TypeTreeNode child in Children)
37 {
38 child.RunRecursive(action);
39 }
40 }
41
42 }
43 [CUIInternal]
44 public class CUIReflection
45 {
46 internal static void InitStatic()
47 {
48 CUI.OnInit += () =>
49 {
50 Stopwatch sw = Stopwatch.StartNew();
51 FindCUITypes();
52 FormCUITypeTree();
53 CUIDebug.Log($"CUIReflection.Initialize took {sw.ElapsedMilliseconds}ms");
54 };
55 CUI.OnDispose += () =>
56 {
57 CUITypes.Clear();
58 CUILayoutTypes.Clear();
59 CUITypeTree.Clear();
60 };
61 }
62
63
64
65 public record TypePair(Type type, Type baseType);
66
67 public static Dictionary<Type, TypeTreeNode> CUITypeTree = new();
68
69 public static Dictionary<string, Type> CUILayoutTypes = new();
70 public static Dictionary<string, Type> CUITypes = new Dictionary<string, Type>();
71
72 public static void FormCUITypeTree()
73 {
74 List<TypePair> Pustoe = CUITypes.Values.Select(t => new TypePair(t, t.BaseType)).ToList();
75 List<TypePair> Porojnee = new List<TypePair>();
76
77 while (Pustoe.Count > 0)
78 {
79 Porojnee = new List<TypePair>();
80 foreach (TypePair pair in Pustoe)
81 {
82 // Tree root CUIComponent
83 if (pair.baseType == typeof(object))
84 {
85 CUITypeTree[pair.type] = new TypeTreeNode(pair.type);
86 continue;
87 }
88
89 // Derived class
90 if (CUITypeTree.ContainsKey(pair.baseType))
91 {
92 CUITypeTree[pair.type] = new TypeTreeNode(pair.type);
93 CUITypeTree[pair.baseType].Add(CUITypeTree[pair.type]);
94 continue;
95 }
96
97 // Base class not in tree yet
98 Porojnee.Add(pair);
99 }
100
101 Pustoe.Clear();
102 Pustoe = Porojnee;
103 }
104
105 //foreach (TypeTreeNode node in CUITypeTree.Values) CUI.Log(node);
106 }
107
108 public static void FindCUITypes()
109 {
110 Assembly CUIAssembly = Assembly.GetAssembly(typeof(CUI));
111 Assembly CallingAssembly = Assembly.GetCallingAssembly();
112
113 CUITypes["CUIComponent"] = typeof(CUIComponent);
114 CUILayoutTypes["CUILayout"] = typeof(CUILayout);
115
116
117 //TODO Nested types might have same name, think how to separate them
118 // lua and style resolver uses them
119 // string name = t.Name;
120 // if (t.DeclaringType != null) name = $"{t.DeclaringType.Name}.{t.Name}";
121 // CUITypes[name] = t;
122 foreach (Type t in CallingAssembly.GetTypes())
123 {
124 if (t.IsSubclassOf(typeof(CUIComponent))) CUITypes[t.Name] = t;
125 if (t.IsSubclassOf(typeof(CUILayout))) CUILayoutTypes[t.Name] = t;
126 }
127
128 foreach (Type t in CUIAssembly.GetTypes())
129 {
130 if (t.IsSubclassOf(typeof(CUIComponent))) CUITypes[t.Name] = t;
131 if (t.IsSubclassOf(typeof(CUILayout))) CUILayoutTypes[t.Name] = t;
132 }
133 }
134
135 public static Type GetComponentTypeByName(string name)
136 {
137 return CUITypes.GetValueOrDefault(name);
138 }
139
140 public static object GetDefault(object obj)
141 {
142 FieldInfo defField = obj.GetType().GetField("Default", BindingFlags.Static | BindingFlags.Public);
143 if (defField == null) return null;
144 return defField.GetValue(null);
145 }
146
147 public static object GetNestedValue(object obj, string nestedName)
148 {
149 string[] names = nestedName.Split('.');
150
151 foreach (string name in names)
152 {
153 FieldInfo fi = obj.GetType().GetField(name, AccessTools.all);
154 PropertyInfo pi = obj.GetType().GetProperty(name, AccessTools.all);
155
156 if (fi != null)
157 {
158 obj = fi.GetValue(obj);
159 continue;
160 }
161
162 if (pi != null)
163 {
164 obj = pi.GetValue(obj);
165 continue;
166 }
167
168 return null;
169 }
170
171 return obj;
172 }
173 }
174}