CrabUI
Loading...
Searching...
No Matches
CUI.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5using System.Diagnostics;
6using System.IO;
7
8using Barotrauma;
9using Microsoft.Xna.Framework;
10using Microsoft.Xna.Framework.Input;
11using Microsoft.Xna.Framework.Graphics;
12using HarmonyLib;
13
14using System.Runtime.CompilerServices;
15[assembly: IgnoresAccessChecksTo("Barotrauma")]
16[assembly: IgnoresAccessChecksTo("DedicatedServer")]
17[assembly: IgnoresAccessChecksTo("BarotraumaCore")]
18
19namespace CrabUI
20{
21 /// <summary>
22 /// In fact a static class managing static things
23 /// </summary>
24 public partial class CUI
25 {
26 public static Vector2 GameScreenSize => new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
27 public static Rectangle GameScreenRect => new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
28
29
30 private static string modDir;
31 /// <summary>
32 /// Root folder of the mod, used to deduce lua folder location
33 /// </summary>
34 public static string ModDir
35 {
36 get => modDir;
37 set
38 {
39 modDir = value;
40 LuaFolder = Path.Combine(value, @"Lua");
41 }
42 }
43
44 /// <summary>
45 /// If false CUI won't waste time on registering lua types and creating types file
46 /// </summary>
47 public static bool UseLua { get; set; } = true;
48 /// <summary>
49 /// Should point to lua folder, if you want lua types file
50 /// </summary>
51 public static string LuaFolder { get; set; }
52
53 private static string assetsPath;
54 /// <summary>
55 /// Path to assets folder with all CUI stuff
56 /// </summary>
57 public static string AssetsPath
58 {
59 get => assetsPath;
60 set
61 {
62 assetsPath = value;
63 PalettesPath = Path.Combine(value, @"Palettes");
64 }
65 }
66 public static string CUITexturePath = "CUI.png";
67 public static string PalettesPath { get; set; }
68
69
70
71 /// <summary>
72 /// If set CUI will also check this folder when loading textures
73 /// </summary>
74 public static string PGNAssets { get; set; }
75
76 /// <summary>
77 /// A singleton
78 /// </summary>
79 public static CUI Instance;
80 /// <summary>
81 /// Orchestrates Drawing and updates, there could be only one
82 /// CUI.Main is located under vanilla GUI
83 /// </summary>
84 public static CUIMainComponent Main => Instance?.main;
85 /// <summary>
86 /// Orchestrates Drawing and updates, there could be only one
87 /// CUI.TopMain is located above vanilla GUI
88 /// </summary>
89 public static CUIMainComponent TopMain => Instance?.topMain;
90 /// <summary>
91 /// Snapshot of mouse and keyboard state
92 /// </summary>
93 public static CUIInput Input => Instance?.input;
94 /// <summary>
95 /// Safe texture manager
96 /// </summary
97 public static CUITextureManager TextureManager => Instance?.textureManager;
98 /// <summary>
99 /// Adapter to vanilla focus system, don't use
100 /// </summary>
101 public static CUIFocusResolver FocusResolver => Instance?.focusResolver;
102 public static CUILuaRegistrar LuaRegistrar => Instance?.luaRegistrar;
103
104 public static CUIComponent FocusedComponent
105 {
106 get => FocusResolver.FocusedCUIComponent;
107 set => FocusResolver.FocusedCUIComponent = value;
108 }
109
110 /// <summary>
111 /// This affects logging
112 /// </summary>
113 public static bool Debug;
114 /// <summary>
115 /// If true other compiled mods that use CUI will break
116 /// But if false then you'll have to setup hooks with lua or separate compiled plugin
117 /// </summary>
118 public static bool UseCursedPatches { get; set; } = true;
119 /// <summary>
120 /// It's used as harmony id and lua hooks id, it's deduced automatically from calling assembly name
121 /// It's should be unique per mod or there will be conflicts
122 /// You can set it to any string if you want
123 /// </summary>
124 public static string HookIdentifier
125 {
126 get => hookIdentifier;
127 set
128 {
129 hookIdentifier = value?.Replace(' ', '_');
130 }
131 }
132 private static string hookIdentifier;
133 public static string CUIHookID => $"CrabUI.{HookIdentifier}";
134 public static Harmony harmony;
135 public static Random Random = new Random();
136
137 /// <summary>
138 /// Called on first Initialize
139 /// </summary>
140 public static event Action OnInit;
141 /// <summary>
142 /// Called on last Dispose
143 /// </summary>
144 public static event Action OnDispose;
145 public static bool Disposed { get; set; } = true;
146 public static event Action<TextInputEventArgs> OnWindowTextInput;
147 public static event Action<TextInputEventArgs> OnWindowKeyDown;
148 //public static event Action<TextInputEventArgs> OnWindowKeyUp;
149
150 //TODO Still doesn't trigger when someone ends round in multiplayer
151 public static event Action OnPauseMenuToggled;
152 public static void InvokeOnPauseMenuToggled() => OnPauseMenuToggled?.Invoke();
153
154 public static bool InputBlockingMenuOpen
155 {
156 get
157 {
158 if (IsBlockingPredicates == null) return false;
159 return IsBlockingPredicates.Any(p => p());
160 }
161 }
162 public static List<Func<bool>> IsBlockingPredicates => Instance?.isBlockingPredicates;
163 private List<Func<bool>> isBlockingPredicates = new List<Func<bool>>();
164 /// <summary>
165 /// In theory multiple mods could use same CUI instance,
166 /// i clean it up when UserCount drops to 0
167 /// </summary>
168 public static int UserCount = 0;
169
170 /// <summary>
171 /// An object that contains current mouse and keyboard states
172 /// It scans states at the start on Main.Update
173 /// </summary>
174 private CUIInput input = new CUIInput();
175 private CUIMainComponent main;
176 private CUIMainComponent topMain;
177 private CUITextureManager textureManager = new CUITextureManager();
178 private CUIFocusResolver focusResolver = new CUIFocusResolver();
179 private CUILuaRegistrar luaRegistrar = new CUILuaRegistrar();
180
181 public static void ReEmitWindowTextInput(object sender, TextInputEventArgs e) => OnWindowTextInput?.Invoke(e);
182 public static void ReEmitWindowKeyDown(object sender, TextInputEventArgs e) => OnWindowKeyDown?.Invoke(e);
183 //public static void ReEmitWindowKeyUp(object sender, TextInputEventArgs e) => OnWindowKeyUp?.Invoke(e);
184
185
186 private void CreateMains()
187 {
188 main = new CUIMainComponent() { AKA = "Main Component" };
189 topMain = new CUIMainComponent() { AKA = "Top Main Component" };
190 }
191
192 /// <summary>
193 /// Should be called in IAssemblyPlugin.Initialize
194 /// \todo make it CUI instance member when plugin system settle
195 /// </summary>
196 public static void Initialize()
197 {
198 CUIDebug.Log($"CUI.Initialize {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
199 if (Instance == null)
200 {
201 GhostDetector.Activate();
202 Disposed = false;
203 HookIdentifier ??= Assembly.GetCallingAssembly().GetName().Name ?? "";
204
205 Instance = new CUI();
206
207 Stopwatch sw = Stopwatch.StartNew();
208 if (HookIdentifier == null || HookIdentifier == "") CUI.Warning($"Warning: CUI.HookIdentifier is not set, this mod may conflict with other mods that use CUI");
209
210 InitStatic();
211 // this should init only static stuff that doesn't depend on instance
212 OnInit?.Invoke();
213
214 Instance.CreateMains();
215
216 GameMain.Instance.Window.TextInput += ReEmitWindowTextInput;
217 GameMain.Instance.Window.KeyDown += ReEmitWindowKeyDown;
218 //GameMain.Instance.Window.KeyUp += ReEmitWindowKeyUp;
219 CUIDebug.Log($"CUI.OnInit?.Invoke took {sw.ElapsedMilliseconds}ms");
220
221 sw.Restart();
222
223 harmony = new Harmony(CUIHookID);
224 PatchAll();
225 CUIDebug.Log($"CUI.PatchAll took {sw.ElapsedMilliseconds}ms");
226
227 AddCommands();
228 AddDebugCommands();
229
230 sw.Restart();
231 LuaRegistrar.Register();
232 CUIDebug.Log($"CUI.LuaRegistrar.Register took {sw.ElapsedMilliseconds}ms");
233 }
234
235 UserCount++;
236
237 CUIDebug.Log($"CUI.Initialized {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
238 }
239
240 public static void OnLoadCompleted()
241 {
242 //Idk doesn't work
243 //CUIMultiModResolver.FindOtherInputs();
244 }
245
246
247 /// <summary>
248 /// Should be called in IAssemblyPlugin.Dispose
249 /// </summary>
250 public static void Dispose()
251 {
252 GhostDetector.Deactivate();
253 CUIDebug.Log($"CUI.Dispose {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
254
255 UserCount--;
256
257 if (UserCount <= 0)
258 {
259 RemoveCommands();
260 // harmony.UnpatchAll(harmony.Id);
261 harmony.UnpatchAll();
262
263 TextureManager.Dispose();
264 CUIDebugEventComponent.CapturedIDs.Clear();
265 OnDispose?.Invoke();
266 Disposed = true;
267
268 Instance.isBlockingPredicates.Clear();
269 Errors.Clear();
270
271 LuaRegistrar.Deregister();
272
273 Instance = null;
274 UserCount = 0;
275
276 CUIDebug.Log($"CUI.Disposed {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
277 }
278
279 GameMain.Instance.Window.TextInput -= ReEmitWindowTextInput;
280 GameMain.Instance.Window.KeyDown -= ReEmitWindowKeyDown;
281 //GameMain.Instance.Window.KeyUp -= ReEmitWindowKeyUp;
282 }
283
284 //HACK Why it's set to run in static constructor?
285 // it runs perfectly fine in CUI.Initialize
286 //TODO component inits doesn't depend on the order
287 // why am i responsible for initing them here?
288 internal static void InitStatic()
289 {
290 CUITextureManager.InitStatic();
291 CUIInterpolate.InitStatic();
292 CUIAnimation.InitStatic();
293 CUIReflection.InitStatic();
294 CUIMultiModResolver.InitStatic();
295 CUIPalette.InitStatic();
296 CUIMap.CUIMapLink.InitStatic();
297 CUIMenu.InitStatic();
298 CUIComponent.InitStatic();
299 CUITypeMetaData.InitStatic();
300 CUIStyleLoader.InitStatic();
301 AttachedItems.InitStatic();
302 }
303 }
304}
WIP, can animate any property on any object Can run back and forth in [0..1] interval and interpolate...
Base class for all components.
In fact a static class managing static things.
Definition CUIErrors.cs:16
static Action OnDispose
Called on last Dispose.
Definition CUI.cs:144
static int UserCount
In theory multiple mods could use same CUI instance, i clean it up when UserCount drops to 0.
Definition CUI.cs:168
static bool Debug
This affects logging.
Definition CUI.cs:113
static string HookIdentifier
It's used as harmony id and lua hooks id, it's deduced automatically from calling assembly name It'...
Definition CUI.cs:125
static Action OnInit
Called on first Initialize.
Definition CUI.cs:140
static CUIMainComponent TopMain
Orchestrates Drawing and updates, there could be only one CUI.TopMain is located above vanilla GUI.
Definition CUI.cs:89
static CUITextureManager TextureManager
Safe texture manager </summary.
Definition CUI.cs:97
static void Dispose()
Should be called in IAssemblyPlugin.Dispose.
Definition CUI.cs:250
static string PGNAssets
If set CUI will also check this folder when loading textures.
Definition CUI.cs:74
static string AssetsPath
Path to assets folder with all CUI stuff.
Definition CUI.cs:58
static string ModDir
Root folder of the mod, used to deduce lua folder location.
Definition CUI.cs:35
static CUIMainComponent Main
Orchestrates Drawing and updates, there could be only one CUI.Main is located under vanilla GUI.
Definition CUI.cs:84
static string LuaFolder
Should point to lua folder, if you want lua types file.
Definition CUI.cs:51
static void Log(object msg, Color? color=null, [CallerFilePath] string source="", [CallerLineNumber] int lineNumber=0)
Prints a message to console.
static bool UseCursedPatches
If true other compiled mods that use CUI will break But if false then you'll have to setup hooks with...
Definition CUI.cs:118
static CUI Instance
A singleton.
Definition CUI.cs:79
static CUIFocusResolver FocusResolver
Adapter to vanilla focus system, don't use.
Definition CUI.cs:101
static bool UseLua
If false CUI won't waste time on registering lua types and creating types file.
Definition CUI.cs:47
static void Initialize()
Should be called in IAssemblyPlugin.Initialize.
Definition CUI.cs:196
Containing a snapshot of current mouse and keyboard state.
Definition CUIInput.cs:17
Class containing a few interpolate functions for CUIAnimation.
Orchestrating drawing and updating of it's children Also a CUIComponent, but it's draw and update m...
Swipable and zoomable plane Allows you to place components in a plane and connect them with lines l...
Definition CUIMap.cs:19
Class for loading textures without duplicates Also disposes all loaded textures automatically.