using System.CodeDom.Compiler; using System.Reflection; using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization.Metadata; using GraphicsManager; using GraphicsManager.Interfaces; using GraphicsManager.Objects; using GraphicsManager.Objects.Core; using Luski.Classes; using Luski.Classes.ThemeSub; using Luski.GUI; using Luski.net; using Luski.net.Enums; using Luski.net.Interfaces; using Luski.net.Structures.Public; using Luski.Shared.PublicServers.V1.Enums; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Desktop; namespace Luski; public static class Globals { #pragma warning disable CS8618 public static List> ServersLoading = new(); public static ServerList ServerList; public static Dictionary> AllowedBehindObjects = new(); public static ThemeStart Theme { get { return LuskiThemes.LuskiThemeList.Where(s => s.Name == Settings.Theme).First(); } } public static ServerThemeProperties GetTheme(this PublicServer ser) { IEnumerable l = Theme.ServerOverrides.Where(s => s.Address == ser.Domain); ServerTheme[] serverThemes = l as ServerTheme[] ?? l.ToArray(); if (serverThemes.Any()) return serverThemes[0].Properties; return Theme.GlobalServerTemplate; } private static List AddedExperiments = new(); private static List EnabledExperiments = new(); public static List MissingExperiments = new(); private static Dictionary ExperimentSelectorInfos = new(); public static IReadOnlyList Experiments => AddedExperiments.AsReadOnly(); private static int LastExpCount = 0; public static Color4 DodgerBlue = new Color4(30, 144, 255, 255); public static double GetScale() { if (Settings.Scale is not null) return Settings.Scale.Value; return Monitors.GetMonitorFromWindow(ms).HorizontalScale; } public static int ScaleInt(this int i) { return (int)(GetScale() * i); } public static int ScaleInt(this double i) { return (int)(GetScale() * i); } public static double ScaleDouble(this int i) { return (GetScale() * i); } public static double ScaleDouble(this double i) { return (GetScale() * i); } public static uint ScaleFont(this uint i) { if (Globals.Settings.ScaleFonts) return (uint)(GetScale() * i); return i; } public static void PrintParent(IParent par) { void PrintP(int index, IParent p, Vector3i l) { string sp = ""; for (int i = 0; i < index; i++) { sp += " "; } for (int i = 0; i < p.Controls.Length; i++) { if (p.Controls[i].IgnoreHover) continue; Console.WriteLine(sp + p.Controls[i] + ": " + p.Controls[i].Location + " " + (p.Controls[i].Location + l) + " "+ p.Controls[i].Size); if (p.Controls[i] is IParent pp) PrintP(index + 1, pp, l + pp.Position); } } Console.WriteLine(par + ": " + par.Position + par.Size); PrintP(1,par, par.Position); } public static void RegisterExperiment(ExperimentInfo exp) { IEnumerable found = MissingExperiments.Where(e => e.Name == exp.Name); ExperimentJson[] experimentInfos = found as ExperimentJson[] ?? found.ToArray(); if (experimentInfos.Length > 0) { MissingExperiments.Remove(experimentInfos[0]); EnabledExperiments.Add(exp); } AddedExperiments.Add(exp); foreach (ExperimentSelectorInfo esi in exp.Options) { ExperimentSelectorInfos.Add(esi, exp); } } public static void Toggle(this ExperimentSelectorInfo exp) { if (!ExperimentSelectorInfos.TryGetValue(exp, out ExperimentInfo EI)) return; if (Settings.Experiments.Any(e => e.Name == EI.Name)) { ExperimentJson ej = Settings.Experiments.Where(e => e.Name == EI.Name).First(); if (EI.Selected == EI.Options.IndexOf(exp)) { Settings.Experiments.Remove(ej); EnabledExperiments.Remove(EI); EI.Selected = null; LastExpCount--; exp.SendTog(false); } else { EI.Options[EI.Selected!.Value].SendTog(false); ej.Selected = EI.Options.IndexOf(exp); EI.Selected = ej.Selected; exp.SendTog(true); } } else { LastExpCount++; ExperimentJson ej = new() { Name = EI.Name, Selected = EI.Options.IndexOf(exp) }; Settings.Experiments.Add(ej); EI.Selected = ej.Selected; if (!EnabledExperiments.Contains(EI)) EnabledExperiments.Add(EI); exp.SendTog(true); } Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings); } public static bool IsEnabled(this ExperimentSelectorInfo exp) { if (!ExperimentSelectorInfos.TryGetValue(exp, out ExperimentInfo EI)) return false; if (LastExpCount != Settings.Experiments.Count) { //rescan foreach (ExperimentJson experiment in Settings.Experiments) { IEnumerable found = AddedExperiments.Where(e => e.Name == experiment.Name); ExperimentInfo[] experimentInfos = found as ExperimentInfo[] ?? found.ToArray(); if (experimentInfos.Count() > 0) { if (!EnabledExperiments.Contains(EI)) EnabledExperiments.Add(experimentInfos[0]); experimentInfos[0].Selected = experiment.Selected; } else { MissingExperiments.Add(experiment); } } LastExpCount = Settings.Experiments.Count; } //detect return EnabledExperiments.Contains(EI) && EI.Selected.HasValue && EI.Options.Count > EI.Selected && EI.Options[EI.Selected.Value] == exp; } private static Dictionary> TextureResources = new(); public static Texture GetTextureResource(this TextureManager tm, string File) { if (!TextureResources.ContainsKey(tm)) TextureResources.Add(tm, new()); if (TextureResources[tm].TryGetValue(File, out Texture? t)) return t; t = tm.AddTexture(GetResource($"Textures.{File}")); TextureResources[tm].Add(File,t); return t; } public static Stream GetResource(string File) { return Tools.GetResourceStream(Assembly.GetExecutingAssembly(), $"Luski.Resources.{File}"); } public static void AddBehindObject(this Window w, IRenderObject obj) { if (!AllowedBehindObjects.ContainsKey(w)) AllowedBehindObjects.Add(w, new()); if (AllowedBehindObjects[w].Count > 0) { obj.AllowHoverFromBehind = AllowedBehindObjects[w][0].AllowHoverFromBehind; } w.Controls.Add(obj); AllowedBehindObjects[w].Add(obj); } public static void ToggleBehindObjects(this Window w) { if (!AllowedBehindObjects.ContainsKey(w)) AllowedBehindObjects.Add(w, new()); if (AllowedBehindObjects[w].Count > 0) { bool new_val = !AllowedBehindObjects[w][0].AllowHoverFromBehind; foreach (IRenderObject v in AllowedBehindObjects[w]) { v.AllowHoverFromBehind = new_val; } } } public static void RemoveBehindObject(this Window w, IRenderObject obj, bool purge = true) { if (!AllowedBehindObjects.ContainsKey(w)) AllowedBehindObjects.Add(w, new()); AllowedBehindObjects[w].Remove(obj); w.Controls.Remove(obj, purge); obj.Clean(); obj = null!; } public static bool Download { get; set; } = false; public static API Luski { get; } = new(); public static MainScreenWindow ms; public static Color4 ToColor4(this Color col) { return new(col.R, col.G, col.B, col.A); } public static Color ToColor(this Color4 col) { return new((byte)(col.R*byte.MaxValue), (byte)(col.G*byte.MaxValue), (byte)(col.B*byte.MaxValue), (byte)(col.A*byte.MaxValue)); } public static Texture GetAlphaCircle(this TextureManager tm) { return tm.GetTextureResource("Status.png"); } public static Dictionary UserTextureMap = new(); public static Dictionary ProfileTextureMap = new(); private static async Task GetIcon(this SocketUser User) { if (UserTextureMap.TryGetValue(User.Id, out Texture? t)) return t; Stream UserStream = await User.GetAvatar(CancellationToken.None); t = Globals.ms.TextureManager.AddTexture(UserStream); UserTextureMap.Add(User.Id, t); UserStream.Dispose(); t.Unit = TextureUnit.Texture1; return t; } public static async Task MakeRct(this TUser User, Vector2i Size, bool IsProfile) where TUser : IUser { Texture t = ms.TextureManager.GetTextureResource("Status.png"); if (User.PictureType == PictureType.none) { UserControl r = new(t); r.Size = Size; r.Shader = Rectangle.DefaultAlphaShader[ms.Context]; Color c = await User.GetColor(); r.BackgroundColor = new(25, 25, 25, 255); Label l = new(DefaultFont) { Color = c.ToColor4() }; l.Text = User.DisplayName[0].ToString(); var y = l.GetSizeOfChar(0); l.Location = new((r.Size.X - l.Size.X)/2, (int)(r.Size.Y - (l.Font.PixelHeight - y.Y) - (r.Size.Y / 2) - (y.Y/2)), 0); r.Controls.Add(l); return r; } else { Rectangle r = new(t); r.Size = Size; r.Shader = Rectangle.DefaultAlphaTextureShader[ms.Context]; r.Textures.Add(await User.GetIcon(IsProfile)); return r; } } private static async Task GetIcon(this IUser User, bool IsProfile) { if (IsProfile) { if (ProfileTextureMap.TryGetValue(User.Id, out Texture? t)) return t; Stream UserStream = await User.GetAvatar(CancellationToken.None); t = Globals.ms.TextureManager.AddTexture(UserStream); ProfileTextureMap.Add(User.Id, t); UserStream.Dispose(); t.Unit = TextureUnit.Texture1; return t; } else { if (UserTextureMap.TryGetValue(User.Id, out Texture? t)) return t; Stream UserStream = await User.GetAvatar(CancellationToken.None); t = Globals.ms.TextureManager.AddTexture(UserStream); UserTextureMap.Add(User.Id, t); UserStream.Dispose(); t.Unit = TextureUnit.Texture1; return t; } } public static Settings Settings { get; set; } public static FontFamily DefaultFontFamly { get; set; } public static FontInteraction DefaultFont { get; set; } public static FontInteraction TopTimeFont { get; set; } public static FontInteraction MessageFont { get; set; } public static FontInteraction SmallTimeFont { get; set; } public static PublicServer? GetCurentPublicServer() { if (Luski.LoadedServers.Count > 0) return Luski.LoadedServers[0]; else return null; } public static UpdaterSettings UpdaterSettings { get; set; } public static Texture LuskiTexture; public static TResult GetSettings(string path, JsonTypeInfo TypeInfo) where TResult : new() { TResult? @out; if (!File.Exists(path)) { @out = new(); File.WriteAllText(path, JsonSerializer.Serialize(@out, TypeInfo)); } try { @out = JsonSerializer.Deserialize(File.ReadAllText(path), TypeInfo); if (@out is null) { @out = new(); } } catch { @out = new(); } File.WriteAllText(path, JsonSerializer.Serialize(@out, TypeInfo)); return @out; } public static TResult GetSettings(Stream data, JsonTypeInfo TypeInfo) where TResult : new() { TResult? @out; try { @out = JsonSerializer.Deserialize(data, TypeInfo); if (@out is null) { @out = new(); } } catch { @out = new(); } return @out; } public static void SaveSettings(this TResult json, string path, JsonTypeInfo TypeInfo) where TResult : new() { File.WriteAllText(path, JsonSerializer.Serialize(json, TypeInfo)); } public static string JT { get { string tmp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "JacobTech"); if (OperatingSystem.IsLinux()) { tmp = Path.Combine(Environment.GetEnvironmentVariable("HOME")!, ".config/"); tmp += "JacobTech"; } if (!Directory.Exists(tmp)) Directory.CreateDirectory(tmp); if (!Directory.Exists(Path.Combine(tmp, "Luski"))) Directory.CreateDirectory(Path.Combine(tmp, "Luski")); return tmp; } } public static WindowIcon Icon { get; set; } public static string LuskiPath { get { return Path.Combine(JT, "Luski"); } } public static bool Empty(string? str) { return (string.IsNullOrEmpty(str) || string.IsNullOrWhiteSpace(str)); } } #pragma warning restore CS8618