Add quick interactions locally
This commit is contained in:
301
Quick Interactions/CSharp/Client/CrabUI/CUI.cs
Normal file
301
Quick Interactions/CSharp/Client/CrabUI/CUI.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
using Barotrauma;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using HarmonyLib;
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: IgnoresAccessChecksTo("Barotrauma")]
|
||||
[assembly: IgnoresAccessChecksTo("DedicatedServer")]
|
||||
[assembly: IgnoresAccessChecksTo("BarotraumaCore")]
|
||||
|
||||
namespace QICrabUI
|
||||
{
|
||||
/// <summary>
|
||||
/// In fact a static class managing static things
|
||||
/// </summary>
|
||||
public partial class CUI
|
||||
{
|
||||
public static Vector2 GameScreenSize => new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
public static Rectangle GameScreenRect => new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
|
||||
|
||||
private static string modDir;
|
||||
public static string ModDir
|
||||
{
|
||||
get => modDir;
|
||||
set
|
||||
{
|
||||
modDir = value;
|
||||
LuaFolder = Path.Combine(value, @"Lua");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool UseLua { get; set; } = true;
|
||||
public static string LuaFolder { get; set; }
|
||||
|
||||
private static string assetsPath;
|
||||
public static string AssetsPath
|
||||
{
|
||||
get => assetsPath;
|
||||
set
|
||||
{
|
||||
assetsPath = value;
|
||||
PalettesPath = Path.Combine(value, @"Palettes");
|
||||
}
|
||||
}
|
||||
public static string CUITexturePath = "CUI.png";
|
||||
public static string PalettesPath { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If set CUI will also check this folder when loading textures
|
||||
/// </summary>
|
||||
public static string PGNAssets
|
||||
{
|
||||
get => TextureManager.PGNAssets;
|
||||
set => TextureManager.PGNAssets = value;
|
||||
}
|
||||
|
||||
private static List<CUI> Instances = new List<CUI>();
|
||||
/// <summary>
|
||||
/// The singleton
|
||||
/// </summary>
|
||||
public static CUI Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Instances.Count == 0) return null;
|
||||
return Instances.First();
|
||||
}
|
||||
set
|
||||
{
|
||||
Instances.Clear();
|
||||
if (value != null) Instances.Add(value);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Orchestrates Drawing and updates, there could be only one
|
||||
/// CUI.Main is located under vanilla GUI
|
||||
/// </summary>
|
||||
public static CUIMainComponent Main => Instance?.main;
|
||||
/// <summary>
|
||||
/// Orchestrates Drawing and updates, there could be only one
|
||||
/// CUI.TopMain is located above vanilla GUI
|
||||
/// </summary>
|
||||
public static CUIMainComponent TopMain => Instance?.topMain;
|
||||
/// <summary>
|
||||
/// Snapshot of mouse and keyboard state
|
||||
/// </summary>
|
||||
public static CUIInput Input => Instance?.input;
|
||||
/// <summary>
|
||||
/// Safe texture manager
|
||||
/// </summary
|
||||
public static CUITextureManager TextureManager => Instance?.textureManager;
|
||||
/// <summary>
|
||||
/// Adapter to vanilla focus system, don't use
|
||||
/// </summary>
|
||||
public static CUIFocusResolver FocusResolver => Instance?.focusResolver;
|
||||
public static CUILuaRegistrar LuaRegistrar => Instance?.luaRegistrar;
|
||||
|
||||
public static CUIComponent FocusedComponent
|
||||
{
|
||||
get => FocusResolver.FocusedCUIComponent;
|
||||
set => FocusResolver.FocusedCUIComponent = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This affects logging
|
||||
/// </summary>
|
||||
public static bool Debug;
|
||||
/// <summary>
|
||||
/// Will break the mod if it's compiled
|
||||
/// </summary>
|
||||
public static bool UseCursedPatches { get; set; } = false;
|
||||
/// <summary>
|
||||
/// It's important to set it, if 2 CUIs try to add a hook with same id one won't be added
|
||||
/// </summary>
|
||||
public static string HookIdentifier
|
||||
{
|
||||
get => hookIdentifier;
|
||||
set
|
||||
{
|
||||
hookIdentifier = value?.Replace(' ', '_');
|
||||
}
|
||||
}
|
||||
private static string hookIdentifier = "";
|
||||
public static string CUIHookID => $"QICrabUI.{HookIdentifier}";
|
||||
public static Harmony harmony;
|
||||
public static Random Random = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Called on first Initialize
|
||||
/// </summary>
|
||||
public static event Action OnInit;
|
||||
/// <summary>
|
||||
/// Called on last Dispose
|
||||
/// </summary>
|
||||
public static event Action OnDispose;
|
||||
public static bool Disposed { get; set; } = true;
|
||||
public static event Action<TextInputEventArgs> OnWindowTextInput;
|
||||
public static event Action<TextInputEventArgs> OnWindowKeyDown;
|
||||
//public static event Action<TextInputEventArgs> OnWindowKeyUp;
|
||||
|
||||
//TODO this doesn't trigger when you press menu button, i need to go inside thet method
|
||||
public static event Action OnPauseMenuToggled;
|
||||
public static void InvokeOnPauseMenuToggled() => OnPauseMenuToggled?.Invoke();
|
||||
|
||||
public static bool InputBlockingMenuOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsBlockingPredicates == null) return false;
|
||||
return IsBlockingPredicates.Any(p => p());
|
||||
}
|
||||
}
|
||||
public static List<Func<bool>> IsBlockingPredicates => Instance?.isBlockingPredicates;
|
||||
private List<Func<bool>> isBlockingPredicates = new List<Func<bool>>();
|
||||
/// <summary>
|
||||
/// In theory multiple mods could use same CUI instance,
|
||||
/// i clean it up when UserCount drops to 0
|
||||
/// </summary>
|
||||
public static int UserCount = 0;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An object that contains current mouse and keyboard states
|
||||
/// It scans states at the start on Main.Update
|
||||
/// </summary>
|
||||
private CUIInput input = new CUIInput();
|
||||
private CUIMainComponent main;
|
||||
private CUIMainComponent topMain;
|
||||
private CUITextureManager textureManager = new CUITextureManager();
|
||||
private CUIFocusResolver focusResolver = new CUIFocusResolver();
|
||||
private CUILuaRegistrar luaRegistrar = new CUILuaRegistrar();
|
||||
|
||||
public static void ReEmitWindowTextInput(object sender, TextInputEventArgs e) => OnWindowTextInput?.Invoke(e);
|
||||
public static void ReEmitWindowKeyDown(object sender, TextInputEventArgs e) => OnWindowKeyDown?.Invoke(e);
|
||||
//public static void ReEmitWindowKeyUp(object sender, TextInputEventArgs e) => OnWindowKeyUp?.Invoke(e);
|
||||
|
||||
|
||||
private void CreateMains()
|
||||
{
|
||||
main = new CUIMainComponent() { AKA = "Main Component" };
|
||||
topMain = new CUIMainComponent() { AKA = "Top Main Component" };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called in IAssemblyPlugin.Initialize
|
||||
/// \todo make it CUI instance member when plugin system settle
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
CUIDebug.Log($"CUI.Initialize {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
|
||||
if (Instance == null)
|
||||
{
|
||||
Disposed = false;
|
||||
Instance = new CUI();
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
if (HookIdentifier == null || HookIdentifier == "") CUI.Warning($"Warning: CUI.HookIdentifier is not set, this mod may conflict with other mods that use CUI");
|
||||
|
||||
InitStatic();
|
||||
// this should init only static stuff that doesn't depend on instance
|
||||
OnInit?.Invoke();
|
||||
|
||||
Instance.CreateMains();
|
||||
|
||||
GameMain.Instance.Window.TextInput += ReEmitWindowTextInput;
|
||||
GameMain.Instance.Window.KeyDown += ReEmitWindowKeyDown;
|
||||
//GameMain.Instance.Window.KeyUp += ReEmitWindowKeyUp;
|
||||
CUIDebug.Log($"CUI.OnInit?.Invoke took {sw.ElapsedMilliseconds}ms");
|
||||
|
||||
sw.Restart();
|
||||
|
||||
harmony = new Harmony(CUIHookID);
|
||||
PatchAll();
|
||||
CUIDebug.Log($"CUI.PatchAll took {sw.ElapsedMilliseconds}ms");
|
||||
|
||||
AddCommands();
|
||||
|
||||
sw.Restart();
|
||||
LuaRegistrar.Register();
|
||||
CUIDebug.Log($"CUI.LuaRegistrar.Register took {sw.ElapsedMilliseconds}ms");
|
||||
}
|
||||
|
||||
UserCount++;
|
||||
|
||||
CUIDebug.Log($"CUI.Initialized {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
|
||||
}
|
||||
|
||||
public static void OnLoadCompleted()
|
||||
{
|
||||
//Idk doesn't work
|
||||
//CUIMultiModResolver.FindOtherInputs();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Should be called in IAssemblyPlugin.Dispose
|
||||
/// </summary>
|
||||
public static void Dispose()
|
||||
{
|
||||
CUIDebug.Log($"CUI.Dispose {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
|
||||
|
||||
UserCount--;
|
||||
|
||||
if (UserCount <= 0)
|
||||
{
|
||||
RemoveCommands();
|
||||
// harmony.UnpatchAll(harmony.Id);
|
||||
harmony.UnpatchAll();
|
||||
TextureManager.Dispose();
|
||||
CUIDebugEventComponent.CapturedIDs.Clear();
|
||||
OnDispose?.Invoke();
|
||||
Disposed = true;
|
||||
|
||||
Instance.isBlockingPredicates.Clear();
|
||||
Errors.Clear();
|
||||
|
||||
LuaRegistrar.Deregister();
|
||||
|
||||
Instance = null;
|
||||
UserCount = 0;
|
||||
|
||||
CUIDebug.Log($"CUI.Disposed {HookIdentifier} Instance:[{Instance?.GetHashCode()}] UserCount:{UserCount}", Color.Lime);
|
||||
}
|
||||
|
||||
GameMain.Instance.Window.TextInput -= ReEmitWindowTextInput;
|
||||
GameMain.Instance.Window.KeyDown -= ReEmitWindowKeyDown;
|
||||
//GameMain.Instance.Window.KeyUp -= ReEmitWindowKeyUp;
|
||||
}
|
||||
|
||||
//HACK Why it's set to run in static constructor?
|
||||
// it runs perfectly fine in CUI.Initialize
|
||||
//TODO component inits doesn't depend on the order
|
||||
// why am i responsible for initing them here?
|
||||
internal static void InitStatic()
|
||||
{
|
||||
CUIExtensions.InitStatic();
|
||||
CUIInterpolate.InitStatic();
|
||||
CUIAnimation.InitStatic();
|
||||
CUIReflection.InitStatic();
|
||||
CUIMultiModResolver.InitStatic();
|
||||
CUIPalette.InitStatic();
|
||||
CUIMap.CUIMapLink.InitStatic();
|
||||
CUIMenu.InitStatic();
|
||||
CUIComponent.InitStatic();
|
||||
CUITypeMetaData.InitStatic();
|
||||
CUIStyleLoader.InitStatic();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user