14
.gitignore
vendored
@ -77,3 +77,17 @@ fabric.properties
|
|||||||
# Android studio 3.1+ serialized cache file
|
# Android studio 3.1+ serialized cache file
|
||||||
.idea/caches/build_file_checksums.ser
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
16
Luski.sln
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luski", "Luski\Luski.csproj", "{02A83482-752B-4EB8-A952-51961D6EE684}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{02A83482-752B-4EB8-A952-51961D6EE684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{02A83482-752B-4EB8-A952-51961D6EE684}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{02A83482-752B-4EB8-A952-51961D6EE684}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{02A83482-752B-4EB8-A952-51961D6EE684}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
9
Luski/Classes/ExperimentInfo.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ExperimentInfo
|
||||||
|
{
|
||||||
|
public string DisplayName { get; set; } = default!;
|
||||||
|
public string Name { get; set; } = default!;
|
||||||
|
public List<ExperimentSelectorInfo> Options { get; set; } = default!;
|
||||||
|
public int? Selected { get; set; } = null;
|
||||||
|
}
|
13
Luski/Classes/ExperimentJson.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ExperimentJson
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("selected")]
|
||||||
|
public int Selected { get; set; } = default!;
|
||||||
|
}
|
14
Luski/Classes/ExperimentSelectorInfo.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ExperimentSelectorInfo
|
||||||
|
{
|
||||||
|
public event Func<bool,Task>? EventToggled;
|
||||||
|
public string Name { get; set; } = default!;
|
||||||
|
public string Description { get; set; } = default!;
|
||||||
|
public bool RequiresRestart { get; set; } = false;
|
||||||
|
|
||||||
|
internal void SendTog(bool b)
|
||||||
|
{
|
||||||
|
if (EventToggled is not null) EventToggled.Invoke(b);
|
||||||
|
}
|
||||||
|
}
|
48
Luski/Classes/LuskiThemes.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public static class LuskiThemes
|
||||||
|
{
|
||||||
|
public static void LoadThemeFromDir(string dir)
|
||||||
|
{
|
||||||
|
ThemeStart ts = Globals.GetSettings(Path.Combine(dir, "theme.json"), ThemeStartContext.Default.ThemeStart);
|
||||||
|
LuskiThemes.LuskiThemeList.Add(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoadThemeFromZip(string ZIP)
|
||||||
|
{
|
||||||
|
ZipArchive zf = ZipFile.OpenRead(ZIP);
|
||||||
|
ZipArchiveEntry? json = zf.GetEntry("theme.json");
|
||||||
|
ThemeStart ts = Globals.GetSettings(json?.Open()!, ThemeStartContext.Default.ThemeStart);
|
||||||
|
LuskiThemes.LuskiThemeList.Add(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public readonly static ThemeStart Dark = new()
|
||||||
|
{
|
||||||
|
Name = "Dark",
|
||||||
|
Description = "A dark theme but still a bit lit."
|
||||||
|
};
|
||||||
|
public static ThemeStart Amoled = new()
|
||||||
|
{
|
||||||
|
Name = "Amoled",
|
||||||
|
Description = "A dark theme that is truly dark."
|
||||||
|
};
|
||||||
|
public static ThemeStart Light = new()
|
||||||
|
{
|
||||||
|
Name = "Light",
|
||||||
|
Description = "A light theme for the insane.",
|
||||||
|
GlobalServerTemplate = new()
|
||||||
|
{
|
||||||
|
SelectionColor = new("000000")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<ThemeStart> LuskiThemeList = new()
|
||||||
|
{
|
||||||
|
Light,
|
||||||
|
Dark,
|
||||||
|
Amoled
|
||||||
|
};
|
||||||
|
}
|
25
Luski/Classes/ServerInfo.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ServerInfo
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("domain")]
|
||||||
|
public string Domain { get; set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("version")]
|
||||||
|
public string Version { get; set; } = "v1";
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("is_main")]
|
||||||
|
public bool Main { get; set; } = false;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("is_secure")]
|
||||||
|
public bool Secure { get; set; } = true;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("pre_encrypt")]
|
||||||
|
public bool PreGenEncryption { get; set; } = true;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("show_server_messages")]
|
||||||
|
public bool ShowMessage { get; set; } = false;
|
||||||
|
}
|
21
Luski/Classes/ServerList.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ServerList
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("servers")]
|
||||||
|
public ServerInfo[] Servers { get; set; } = Array.Empty<ServerInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ServerList))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = true,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class ServerListContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
129
Luski/Classes/Settings.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("scale")]
|
||||||
|
public double? Scale { get; set; } = null;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("perscrollpixels")]
|
||||||
|
public uint PerScrollPixels { get; set; } = 20;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("multithreadpercent")]
|
||||||
|
public uint MultiThreadPercent { get; set; } = 50;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("loadperchannel")]
|
||||||
|
public int LoadPerChannel { get; set; } = 50;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("theme")]
|
||||||
|
public string Theme { get; set; } = "Dark";
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("experiments")]
|
||||||
|
public List<ExperimentJson> Experiments { get; set; } = Array.Empty<ExperimentJson>().ToList();
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("default_display")]
|
||||||
|
public int Display { get; set; } = 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the log value for the console. Default value of -25 to enable all logs by default except for DrawFrames and InfoOpenGL even if new ones are added.
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Console Logs")]
|
||||||
|
[JsonPropertyName("log")]
|
||||||
|
public ConsoleLog Logs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _Logs;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_Logs = value;
|
||||||
|
if (Globals.ms is not null)
|
||||||
|
{
|
||||||
|
Globals.ms.LogFrames = (_Logs & ConsoleLog.DrawFrames) == ConsoleLog.DrawFrames;
|
||||||
|
Globals.ms.ShowMissingChar = (_Logs & ConsoleLog.ShowMissingChar) == ConsoleLog.ShowMissingChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Scale Fonts")]
|
||||||
|
[JsonPropertyName("scale_fonts")]
|
||||||
|
public bool ScaleFonts
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _ScaleFonts;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_ScaleFonts = value;
|
||||||
|
if (Globals.ms is not null)
|
||||||
|
{
|
||||||
|
Globals.DefaultFont.PixelHeight = Globals.Settings.DefaultFontPX.ScaleFont();
|
||||||
|
Globals.MessageFont.PixelHeight = Globals.Settings.MessageFontPX.ScaleFont();
|
||||||
|
Globals.TopTimeFont.PixelHeight = Globals.Settings.TopTimeFonttPX.ScaleFont();
|
||||||
|
Globals.SmallTimeFont.PixelHeight = ((uint)11).ScaleFont();
|
||||||
|
Label._characters[Globals.ms.Context][Globals.DefaultFont].Clear();
|
||||||
|
Label._characters[Globals.ms.Context][Globals.MessageFont].Clear();
|
||||||
|
Label._characters[Globals.ms.Context][Globals.TopTimeFont].Clear();
|
||||||
|
Label._characters[Globals.ms.Context][Globals.SmallTimeFont].Clear();
|
||||||
|
|
||||||
|
Globals.ms.ForceUpdate(new(Globals.ms.ClientSize));
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("default_font_px")]
|
||||||
|
public uint DefaultFontPX { get; set; } = 20;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("top_time_font_px")]
|
||||||
|
public uint TopTimeFonttPX { get; set; } = 12;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("message_font_px")]
|
||||||
|
public uint MessageFontPX { get; set; } = 17;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("message_font_line_space_px")]
|
||||||
|
public uint MessageFontLineSpacePX { get; set; } = 5;
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("24 Hour Time")]
|
||||||
|
[JsonPropertyName("24hour_time")]
|
||||||
|
public bool DayTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _DayTime;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_DayTime = value;
|
||||||
|
if (DayTimeChanged is not null) DayTimeChanged.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private bool _ScaleFonts = true;
|
||||||
|
[JsonIgnore]
|
||||||
|
private ConsoleLog _Logs = (ConsoleLog)(-25);
|
||||||
|
[JsonIgnore]
|
||||||
|
private bool _DayTime = false;
|
||||||
|
public event Func<Task>? DayTimeChanged;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Settings))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = true,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class SettingsContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
32
Luski/Classes/ThemeStart.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.Classes.ThemeSub;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class ThemeStart
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("global_server_template")]
|
||||||
|
public ServerThemeProperties GlobalServerTemplate { get; set; } = new();
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("server_overrides")]
|
||||||
|
public ServerTheme[] ServerOverrides { get; set; } = Array.Empty<ServerTheme>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ThemeStart))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = true,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class ThemeStartContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
14
Luski/Classes/ThemeSub/ServerTheme.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Luski.Classes.ThemeSub;
|
||||||
|
|
||||||
|
public class ServerTheme
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("address")]
|
||||||
|
public string Address { get; set; } = default!;
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("properties")]
|
||||||
|
public ServerThemeProperties Properties { get; set; } = new();
|
||||||
|
}
|
11
Luski/Classes/ThemeSub/ServerThemeProperties.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
namespace Luski.Classes.ThemeSub;
|
||||||
|
|
||||||
|
public class ServerThemeProperties
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("selection_color")]
|
||||||
|
public Color SelectionColor { get; set; } = new("FFFFFF");
|
||||||
|
}
|
46
Luski/Classes/UpdaterSettings.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
|
||||||
|
namespace Luski.Classes;
|
||||||
|
|
||||||
|
public class UpdaterSettings
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Self Contained")]
|
||||||
|
[JsonPropertyName("self_contained")]
|
||||||
|
public bool SelfContained { get; set; } = false;
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("updater")]
|
||||||
|
public string? Updater { get; set; } = null;
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("platform")]
|
||||||
|
public string Platform { get; set; } = "linux-x64";
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Auto Launch")]
|
||||||
|
[JsonPropertyName("auto_launch")]
|
||||||
|
public bool AutoLaunch { get; set; } = true;
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Auto Update")]
|
||||||
|
[JsonPropertyName("auto_update")]
|
||||||
|
public bool AutoUpdate { get; set; } = false;
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[Description("Check For Updates")]
|
||||||
|
[JsonPropertyName("update_check")]
|
||||||
|
public bool AutoUpdateCheck { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(UpdaterSettings))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = true,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class UpdaterSettingsContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
21
Luski/ConsoleLog.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Luski;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ConsoleLog : long
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
[Description("Show OpenGL Major Errors")]
|
||||||
|
BigErrosForOpenGL = 1,
|
||||||
|
[Description("Show OpenGL Medium Errors")]
|
||||||
|
MediumErrosForOpenGL = 2,
|
||||||
|
[Description("Show OpenGL Small Errors")]
|
||||||
|
LowErrosForOpenGL = 4,
|
||||||
|
[Description("Show OpenGL Info")]
|
||||||
|
InfoForOpenGL = 8,
|
||||||
|
[Description("Show Draw Frams")]
|
||||||
|
DrawFrames = 16,
|
||||||
|
[Description("Show Missing Charters")]
|
||||||
|
ShowMissingChar = 32
|
||||||
|
}
|
12
Luski/GUI/MainScreen/Interfaces/IChannelAdder.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.Interfaces;
|
||||||
|
|
||||||
|
public interface IChannelAdder
|
||||||
|
{
|
||||||
|
public bool Extended { get; set; }
|
||||||
|
public SocketCategory CurrentCategory { get; }
|
||||||
|
public Task<Channel> AddChannel(SocketChannel chan);
|
||||||
|
public Task<Category> AddCategory(SocketCategory Cat, DateTime? dt = null);
|
||||||
|
}
|
8
Luski/GUI/MainScreen/Interfaces/IChannelPick.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using Luski.net.Structures.Main;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.Interfaces;
|
||||||
|
|
||||||
|
public interface IChannelPick
|
||||||
|
{
|
||||||
|
public MainSocketTextChannel Channel { get; }
|
||||||
|
}
|
95
Luski/GUI/MainScreen/UI/AccountButton.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Interfaces;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class AccountButton : UserControl
|
||||||
|
{
|
||||||
|
private IServerOverlay SM;
|
||||||
|
public Label l;
|
||||||
|
public required Action OnPageLoad;
|
||||||
|
|
||||||
|
public AccountButton(string Text, IServerOverlay SM)
|
||||||
|
:base(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
this.SM = SM;
|
||||||
|
base.Size = new(297.ScaleInt(), 40.ScaleInt());
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
l = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = Text,
|
||||||
|
Color = Color4.Gray,
|
||||||
|
IgnoreHover = true,
|
||||||
|
};
|
||||||
|
l.Location = new((base.Size.X / 2) - (l.Size.X / 2),
|
||||||
|
((base.Size.Y - l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
Controls.Add(l);
|
||||||
|
base.BackgroundColor = new(0, 0, 0, 0);
|
||||||
|
Clicked += OnClicked;
|
||||||
|
MouseEnter += o =>
|
||||||
|
{
|
||||||
|
if (!Selected)
|
||||||
|
{
|
||||||
|
BackgroundColor = new(141, 151, 165, 30);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
MouseLeave += o =>
|
||||||
|
{
|
||||||
|
if (!Selected)
|
||||||
|
{
|
||||||
|
BackgroundColor = new(0,0,0,0);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (!Selected) await ToggleSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Selected { get; private set; }
|
||||||
|
|
||||||
|
public async Task ToggleSelected()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Color4 bc = new(141,151,165,51), f= Color4.White;
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
bc = new (0,0,0,0);
|
||||||
|
f = Color4.Gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = true;
|
||||||
|
Selected = !Selected;
|
||||||
|
|
||||||
|
if (SM.Selected is not null && SM.Selected != this)
|
||||||
|
{
|
||||||
|
await SM.Selected.ToggleSelected();
|
||||||
|
}
|
||||||
|
BackgroundColor = bc;
|
||||||
|
l.Color = f;
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
SM.Selected = this;
|
||||||
|
SM.page.Controls.Clear();
|
||||||
|
OnPageLoad.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
Luski/GUI/MainScreen/UI/AddServerIcon.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using GraphicsManager.Objects;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class AddServerIcon : UserControl
|
||||||
|
{
|
||||||
|
public Rectangle Button;
|
||||||
|
public AddServerIcon()
|
||||||
|
{
|
||||||
|
Button = new(Globals.ms.TextureManager.GetTextureResource("add.png"))
|
||||||
|
{
|
||||||
|
Location = new(18.ScaleInt(), 8.ScaleInt(), 0),
|
||||||
|
Size = new(32.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = Color4.White,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Controls.Add(Button);
|
||||||
|
base.BackgroundColor = new(26, 26, 26, 255);
|
||||||
|
base.Size = new(68.ScaleInt(), 48.ScaleInt());
|
||||||
|
}
|
||||||
|
}
|
606
Luski/GUI/MainScreen/UI/AddServerOverlay.cs
Normal file
@ -0,0 +1,606 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using Luski.Interfaces;
|
||||||
|
using Luski.net;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using Rectangle = GraphicsManager.Objects.Rectangle;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class AddServerOverlay : UserControl, IServerOverlay
|
||||||
|
{
|
||||||
|
private UserControl Form, btn;
|
||||||
|
private DropDown<VersionDropButton> version;
|
||||||
|
|
||||||
|
public AccountButton? Selected { get; set; }
|
||||||
|
public UserControl page { get; set; }
|
||||||
|
private TextBox? UserName, Password, DisplayName, tb;
|
||||||
|
|
||||||
|
private Rectangle? rec;
|
||||||
|
|
||||||
|
public AddServerOverlay()
|
||||||
|
{
|
||||||
|
base.Size = Globals.ms.ClientSize;
|
||||||
|
BackgroundColor = new(0, 0, 0, 130);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Form = new(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
Size = new(350.ScaleInt(), 347.ScaleInt()),
|
||||||
|
BackgroundColor = new(32,32,32,255),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
TextureDisplay = TextureDisplay.Center
|
||||||
|
};
|
||||||
|
Label t;
|
||||||
|
Form.Controls.Add(t=new Label(Globals.DefaultFont) { Scale = 1.6f, Text = "Add Server", Color = Globals.DodgerBlue });
|
||||||
|
t.Location = new((Form.Size.X / 2) - (t.Size.X / 2), t.Location.Y, 0);
|
||||||
|
|
||||||
|
#region Server Loc
|
||||||
|
Label? ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = net.API.DefaultVersion,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Vector2i s =new((int)(ll.Size.X * 1.6f),27.ScaleInt());
|
||||||
|
ll = null;
|
||||||
|
|
||||||
|
Rectangle line = new Rectangle()
|
||||||
|
{
|
||||||
|
Size = new Vector2i(1.ScaleInt()),
|
||||||
|
BackgroundColor = Globals.DodgerBlue
|
||||||
|
};
|
||||||
|
|
||||||
|
tb = new()
|
||||||
|
{
|
||||||
|
Location = new(10.ScaleInt(),50.ScaleInt(), 0),
|
||||||
|
Size = s,
|
||||||
|
WatermarkText = "Server Address",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
};
|
||||||
|
tb.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
tb.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete) && string.IsNullOrWhiteSpace(tb.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
tb.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
(rec is null || rec.Textures.Count > 1) &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
if (Selected!.l.Text != "Login")
|
||||||
|
{
|
||||||
|
if (DisplayName!.Textures[0].handel == good.handel) btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(UserName!.Textures[0].handel != good.handel ||
|
||||||
|
Password!.Textures[0].handel != good.handel ||
|
||||||
|
(rec is not null && rec!.Textures.Count == 1) ||
|
||||||
|
btn!.Textures[0].handel == good.handel ||
|
||||||
|
tb.Textures[0].handel != good.handel ||
|
||||||
|
(DisplayName is not null && DisplayName.Textures[0].handel != good.handel)))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
tb.Size = new(Form.Size.X - tb.Location.X - tb.Location.X - tb.Location.X - s.X, tb.Size.Y);
|
||||||
|
|
||||||
|
Form.Controls.Add(tb);
|
||||||
|
|
||||||
|
version = new DropDown<VersionDropButton>(Form.Textures[0], line)
|
||||||
|
{
|
||||||
|
DropDownParentOverride = Form,
|
||||||
|
Size = s,
|
||||||
|
BackgroundColor = new(255,20,20,255),
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter,
|
||||||
|
Shader = Form.Shader,
|
||||||
|
Location = new(tb.Location.X + tb.Size.X + tb.Location.X, tb.Location.Y, 0)
|
||||||
|
};
|
||||||
|
foreach (string v in Globals.Luski.SupportedVersions)
|
||||||
|
{
|
||||||
|
VersionDropButton option = new VersionDropButton(s, v)
|
||||||
|
{
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Label ll2 = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = v,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
ll2.Location = new((version.Size.X / 2) - (ll2.Size.X / 2),
|
||||||
|
((version.Size.Y - ll2.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
version.Controls.Add(ll2);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
version.AddOption(option);
|
||||||
|
if (v == net.API.DefaultVersion)
|
||||||
|
{
|
||||||
|
version.SetSelected(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version.OpenStatusChanged += VersionOnOpenStatusChanged;
|
||||||
|
version.OptionSelected += VersionOnOptionSelected;
|
||||||
|
|
||||||
|
|
||||||
|
version.DropDownContainer.Textures.Add(Globals.ms.TextureManager.GetTextureResource("RoundedRectangleBottom.png"));
|
||||||
|
version.DropDownContainer.TextureDisplay = TextureDisplay.Center;
|
||||||
|
version.DropDownContainer.Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
version.DropDownContainer.BackgroundColor = version.BackgroundColor;
|
||||||
|
version.OpenStatusChanged += b =>
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
version.Textures[0] = Globals.ms.TextureManager.GetTextureResource("RoundedRectangleTop.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version.Textures[0] = Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Buttons
|
||||||
|
|
||||||
|
AccountButton ca = new AccountButton("Create Account", this)
|
||||||
|
{
|
||||||
|
Location = new(tb.Location.X, tb.Location.Y + tb.Location.X + tb.Size.Y, 0),
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
btn.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
page!.Controls.Add(UserName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, 10.ScaleInt(), 0),
|
||||||
|
Size = new(page.Size.X, 30.ScaleInt()),
|
||||||
|
WatermarkText = "Username",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
UserName.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
UserName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
DisplayName!.Textures[0].handel == good.handel &&
|
||||||
|
rec!.Textures.Count > 1 &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(Password!.Textures[0].handel != good.handel ||
|
||||||
|
DisplayName!.Textures[0].handel != good.handel ||
|
||||||
|
rec!.Textures.Count == 1 ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(Password = new()
|
||||||
|
{
|
||||||
|
Location = new(0, UserName.Location.Y + UserName.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X, UserName.Size.Y),
|
||||||
|
WatermarkText = "Password",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false,
|
||||||
|
PasswordChar = '●'
|
||||||
|
});
|
||||||
|
Password.Textures[0] = UserName.Textures[0];
|
||||||
|
Password.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(Password.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Password.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
Password.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel && UserName!.Textures[0].handel == good.handel && DisplayName!.Textures[0].handel == good.handel && rec!.Textures.Count > 1 && btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel && (UserName!.Textures[0].handel != good.handel || DisplayName!.Textures[0].handel != good.handel || rec!.Textures.Count == 1 || btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(rec = new(Globals.ms.TextureManager.GetAlphaCircle())
|
||||||
|
{
|
||||||
|
Size = new(50.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Red,
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
IgnoreHover = false
|
||||||
|
});
|
||||||
|
rec.Location = new(page.Size.X - rec.Size.X, page.Size.Y - rec.Size.Y, 0);
|
||||||
|
|
||||||
|
page.Controls.Add(DisplayName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, Password.Location.Y + Password.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X- tb.Location.X - rec.Size.X, Password.Size.Y ),
|
||||||
|
WatermarkText = "Display Name",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
DisplayName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) &&
|
||||||
|
string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DisplayName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
DisplayName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel && UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel && rec!.Textures.Count > 1 &&
|
||||||
|
btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel && (UserName!.Textures[0].handel != good.handel ||
|
||||||
|
Password!.Textures[0].handel != good.handel ||
|
||||||
|
rec!.Textures.Count == 1 ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
rec.FilesDroped += RecOnFilesDroped;
|
||||||
|
DisplayName.Textures[0] = UserName.Textures[0];
|
||||||
|
rec.ForceDistanceUpdate(page);
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
Globals.ms.ForceUpdate(new(Size));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ca.Size = new((Form.Size.X - tb.Location.X - tb.Location.X - (tb.Location.X / 2)) / 2, ca.Size.Y);
|
||||||
|
ca.l.Location = new((ca.Size.X - ca.l.Size.X) / 2,
|
||||||
|
((ca.Size.Y - ca.l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
ca.l.ForceDistanceUpdate(ca);
|
||||||
|
Form.Controls.Add(ca);
|
||||||
|
|
||||||
|
AccountButton lo = new AccountButton("Login", this)
|
||||||
|
{
|
||||||
|
Location = new(ca.Location.X + ca.Size.X + (tb.Location.X / 2),ca.Location.Y, 0),
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
page!.Controls.Add(UserName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, 22.ScaleInt(), 0),
|
||||||
|
Size = new(page.Size.X, 31.ScaleInt()),
|
||||||
|
WatermarkText = "Username",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
UserName.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
UserName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(Password!.Textures[0].handel != good.handel ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(Password = new()
|
||||||
|
{
|
||||||
|
Location = new(0, UserName.Location.Y + UserName.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X, UserName.Size.Y),
|
||||||
|
WatermarkText = "Password",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false,
|
||||||
|
PasswordChar = '●'
|
||||||
|
});
|
||||||
|
Password.Textures[0] = UserName.Textures[0];
|
||||||
|
Password.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) &&
|
||||||
|
string.IsNullOrWhiteSpace(Password.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Password.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
Password.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
UserName!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(UserName!.Textures[0].handel != good.handel ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
DisplayName = null!;
|
||||||
|
rec = null!;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lo.Size = ca.Size;
|
||||||
|
lo.l.Location = new((lo.Size.X / 2) - (lo.l.Size.X / 2),
|
||||||
|
((lo.Size.Y - lo.l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
lo.l.ForceDistanceUpdate(lo);
|
||||||
|
Form.Controls.Add(lo);
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Form.Controls.Add(version);
|
||||||
|
|
||||||
|
page = new()
|
||||||
|
{
|
||||||
|
Location = new(tb.Location.X, ca.Location.Y + ca.Size.Y + tb.Location.X, 0),
|
||||||
|
BackgroundColor = Form.BackgroundColor
|
||||||
|
};
|
||||||
|
page.Size = new(Form.Size.X - tb.Location.X - tb.Location.X, Form.Size.Y - tb.Location.X - page.Location.Y - ca.Size.Y - tb.Location.X);
|
||||||
|
Console.Write(page.Size.Y - tb.Location.X - tb.Location.X - (50*2*3));
|
||||||
|
Console.WriteLine(page.Size);
|
||||||
|
Form.Controls.Add(page);
|
||||||
|
|
||||||
|
btn = new(Globals.ms.TextureManager.GetTextureResource("BadTextbox.png"))
|
||||||
|
{
|
||||||
|
Location = new(page.Location.X, page.Location.Y + page.Size.Y + tb.Location.X, 0),
|
||||||
|
Size = new(page.Size.X, ca.Size.Y),
|
||||||
|
TextureDisplay = TextureDisplay.Center
|
||||||
|
};
|
||||||
|
_ = ca.ToggleSelected();
|
||||||
|
Label sub = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "Submit",
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
sub.Location = new((btn.Size.X / 2) - (sub.Size.X / 2),
|
||||||
|
((btn.Size.Y - sub.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
sub.ForceDistanceUpdate(btn);
|
||||||
|
btn.Controls.Add(sub);
|
||||||
|
Form.Controls.Add(btn);
|
||||||
|
|
||||||
|
Form.Location = new((base.Size.X - Form.Size.X) / 2, (base.Size.Y - Form.Size.Y) / 2, 0);
|
||||||
|
Controls.Add(Form);
|
||||||
|
btn.Clicked += BtnOnClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task BtnOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (btn.Textures[0].handel == Globals.ms.TextureManager.GetTextureResource("BadTextbox.png").handel)
|
||||||
|
return;
|
||||||
|
bool s = true;
|
||||||
|
string d = tb!.Text;
|
||||||
|
if (d.Contains("://"))
|
||||||
|
{
|
||||||
|
string[] a = d.Split("://");
|
||||||
|
d = a[1];
|
||||||
|
if (a[0] == "http") s = false;
|
||||||
|
}
|
||||||
|
ServerInfo si = new()
|
||||||
|
{
|
||||||
|
Domain = d,
|
||||||
|
Version = version.SelectedOption.l.Text,
|
||||||
|
Main = false,
|
||||||
|
Secure = s
|
||||||
|
};
|
||||||
|
bool g = await Globals.Luski.TryGetPublicServer(out PublicServer ps, si.Domain, si.Version, si.Secure);
|
||||||
|
|
||||||
|
if (!g)
|
||||||
|
{
|
||||||
|
Texture b = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
tb!.Textures[0] = b;
|
||||||
|
btn.Textures[0] = b;
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g && !ps.IsLogedIn)
|
||||||
|
{
|
||||||
|
if (DisplayName is null)
|
||||||
|
{
|
||||||
|
g = await ps.Login(UserName!.Text, Password!.Text, CancellationToken.None);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g = await ps.CreateAccount(UserName!.Text, Password!.Text, DisplayName.Text, pfp,
|
||||||
|
CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g)
|
||||||
|
{
|
||||||
|
Texture b = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName!.Textures[0] = b;
|
||||||
|
Password!.Textures[0] = b;
|
||||||
|
btn.Textures[0] = b;
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var l = Globals.ServerList.Servers.ToList();
|
||||||
|
l.Add(si);
|
||||||
|
Globals.ServerList.Servers = l.ToArray();
|
||||||
|
Globals.ServerList.SaveSettings(Path.Combine(Globals.LuskiPath, "Servers.json"), ServerListContext.Default.ServerList);
|
||||||
|
ServerIcon<PublicServer> ss = new ServerIcon<PublicServer>(ps);
|
||||||
|
Globals.ms.ser.Controls.Insert(Globals.ms.ser.Controls.Length - 1, ss);
|
||||||
|
await ss.LoadServer();
|
||||||
|
Globals.ms.Controls.Remove(this);
|
||||||
|
Globals.ms.ForceUpdate(new(Size));
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task VersionOnOptionSelected(VersionDropButton arg)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task VersionOnOpenStatusChanged(bool arg)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string pfp = "";
|
||||||
|
|
||||||
|
private Task RecOnFilesDroped(string[] arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg[0]);
|
||||||
|
if (!arg[0].ToLower().EndsWith("png")) return Task.CompletedTask;
|
||||||
|
|
||||||
|
pfp = arg[0];
|
||||||
|
if (rec!.Textures.Count() ==1 )
|
||||||
|
{
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if (UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
if (DisplayName is not null)
|
||||||
|
{
|
||||||
|
if (Password!.Textures[0].handel == good.handel) btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
Texture tex = Globals.ms.TextureManager.AddTexture(File.OpenRead(arg[0]));
|
||||||
|
tex.Unit = TextureUnit.Texture1;
|
||||||
|
rec.Shader = Rectangle.DefaultAlphaTextureShader[Globals.ms.Context];
|
||||||
|
rec.Textures.Add(tex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rec.Textures[1] = Globals.ms.TextureManager.AddTexture(File.OpenRead(arg[0]));
|
||||||
|
rec.Textures[1].Unit = TextureUnit.Texture1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window!.TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
30
Luski/GUI/MainScreen/UI/FullScreenMedia.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class FullScreenMedia : UserControl
|
||||||
|
{
|
||||||
|
public Rectangle IMG;
|
||||||
|
|
||||||
|
public FullScreenMedia(Texture t)
|
||||||
|
{
|
||||||
|
base.Size = Globals.ms.ClientSize;
|
||||||
|
IMG = new(t)
|
||||||
|
{
|
||||||
|
Size = t.RawSize!.Value,
|
||||||
|
Location = new((base.Size.X - t.RawSize!.Value.X) / 2, (base.Size.Y - t.RawSize!.Value.Y) / 2, 0),
|
||||||
|
Anchor = ObjectAnchor.All
|
||||||
|
};
|
||||||
|
BackgroundColor = new(0, 0, 0, 130);
|
||||||
|
Controls.Add(IMG);
|
||||||
|
IMG.ForceDistanceUpdate(this);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FullScreenMedia GetDisplay(Texture t)
|
||||||
|
{
|
||||||
|
return new FullScreenMedia(t);
|
||||||
|
}
|
||||||
|
}
|
52
Luski/GUI/MainScreen/UI/LuskiContextMenu.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Graphics.ES20;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class LuskiContextMenu : BetterContextMenu
|
||||||
|
{
|
||||||
|
public LuskiContextMenu()
|
||||||
|
:base(Globals.ms.TextureManager.GetTextureResource("Context.png"))
|
||||||
|
{
|
||||||
|
Margins = new(5.ScaleInt());
|
||||||
|
TextureDisplay = TextureDisplay.Center;
|
||||||
|
SpaceBetweenObjects = 8.ScaleInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label AddLabel(string text, Color4 color)
|
||||||
|
{
|
||||||
|
return AddLabel(Globals.DefaultFont, text, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label AddLabel(string text)
|
||||||
|
{
|
||||||
|
Label l = AddLabel(Globals.DefaultFont, text, Color4.Gray);
|
||||||
|
l.Clicked += o =>
|
||||||
|
{
|
||||||
|
HideContext(Window!);
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
l.MouseEnter += o =>
|
||||||
|
{
|
||||||
|
l.Color = Color4.White;
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
l.MouseLeave += o =>
|
||||||
|
{
|
||||||
|
l.Color = Color4.Gray;
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void AddLine()
|
||||||
|
{
|
||||||
|
AddLine(Color4.White, 1.ScaleInt());
|
||||||
|
}
|
||||||
|
}
|
192
Luski/GUI/MainScreen/UI/LuskiControls/DropDown.cs
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class DropDown<TSelection> : UserControl where TSelection : DropDownOption
|
||||||
|
{
|
||||||
|
public readonly FlowLayout DropDownContainer;
|
||||||
|
|
||||||
|
private IParent ip;
|
||||||
|
|
||||||
|
public required IParent DropDownParentOverride
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ip = value;
|
||||||
|
DropDownContainer.TransferOwners(Globals.ms, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool IsOpen;
|
||||||
|
public event Func<bool, Task>? OpenStatusChanged;
|
||||||
|
|
||||||
|
public DropDown(TSelection defaultOption)
|
||||||
|
{
|
||||||
|
ip = this;
|
||||||
|
DropDownContainer = new()
|
||||||
|
{
|
||||||
|
Visible = false
|
||||||
|
};
|
||||||
|
Clicked += OnClicked;
|
||||||
|
WindowLoaded += OnWindowLoaded;
|
||||||
|
AddOption(defaultOption);
|
||||||
|
SelectedOption = defaultOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DropDown(Texture t, TSelection defaultOption)
|
||||||
|
:base(t)
|
||||||
|
{
|
||||||
|
ip = this;
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
DropDownContainer = new()
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right
|
||||||
|
};
|
||||||
|
Clicked += OnClicked;
|
||||||
|
WindowLoaded += OnWindowLoaded;
|
||||||
|
DropDownContainer.Size = new(base.Size.X, DropDownContainer.Size.Y + defaultOption.Size.Y);
|
||||||
|
DropDownContainer.Controls.Add(defaultOption);
|
||||||
|
defaultOption.Clicked += OptionOnClicked;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
SelectedOption = defaultOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSelected(TSelection obj)
|
||||||
|
{
|
||||||
|
SelectedOption = obj;
|
||||||
|
Controls.Clear();
|
||||||
|
obj.LoadDisplay.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DropDown(Texture t, IRenderObject spacer, TSelection defaultOption)
|
||||||
|
:base(t)
|
||||||
|
{
|
||||||
|
ip = this;
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
DropDownContainer = new()
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right
|
||||||
|
};
|
||||||
|
Clicked += OnClicked;
|
||||||
|
WindowLoaded += OnWindowLoaded;
|
||||||
|
DropDownContainer.Size = new(base.Size.X, DropDownContainer.Size.Y + spacer.Size.Y);
|
||||||
|
DropDownContainer.Controls.Add(spacer);
|
||||||
|
DropDownContainer.Size = new(base.Size.X, DropDownContainer.Size.Y + defaultOption.Size.Y);
|
||||||
|
DropDownContainer.Controls.Add(defaultOption);
|
||||||
|
defaultOption.Clicked += OptionOnClicked;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
SelectedOption = defaultOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DropDown(Texture t, IRenderObject spacer)
|
||||||
|
:base(t)
|
||||||
|
{
|
||||||
|
ip = this;
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
DropDownContainer = new()
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right
|
||||||
|
};
|
||||||
|
Clicked += OnClicked;
|
||||||
|
WindowLoaded += OnWindowLoaded;
|
||||||
|
DropDownContainer.Size = new(base.Size.X, DropDownContainer.Size.Y + spacer.Size.Y);
|
||||||
|
DropDownContainer.Controls.Add(spacer);
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
}
|
||||||
|
|
||||||
|
public TSelection SelectedOption { get; private set; }
|
||||||
|
|
||||||
|
private Task OnWindowLoaded(IRenderObject arg)
|
||||||
|
{
|
||||||
|
SelectedOption.LoadDisplay.Invoke();
|
||||||
|
Window!.MouseDown += WindowOnMouseDown;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WindowOnMouseDown(MouseButtonEventArgs obj)
|
||||||
|
{
|
||||||
|
if (IsOpen && !MouseInside)
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
DropDownContainer.Visible = IsOpen;
|
||||||
|
if (OpenStatusChanged is not null) OpenStatusChanged.Invoke(IsOpen);
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
if (IsOpen)
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
DropDownContainer.Visible = IsOpen;
|
||||||
|
if (OpenStatusChanged is not null) OpenStatusChanged.Invoke(IsOpen);
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
DropDownContainer.Location = this.GetParentLocation(DropDownParentOverride)+ new Vector3i(0, Size.Y, 0);
|
||||||
|
DropDownParentOverride.Controls.Add(DropDownContainer);
|
||||||
|
DropDownContainer.Size = new(Size.X, DropDownContainer.Size.Y);
|
||||||
|
DropDownContainer.ForceDistanceUpdate(DropDownParentOverride);
|
||||||
|
IsOpen = true;
|
||||||
|
DropDownContainer.Visible = IsOpen;
|
||||||
|
DropDownParentOverride.Controls.MoveControlToEnd(DropDownContainer);
|
||||||
|
if (OpenStatusChanged is not null) OpenStatusChanged.Invoke(IsOpen);
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddOption(TSelection Option)
|
||||||
|
{
|
||||||
|
DropDownContainer.Size = new(Size.X, DropDownContainer.Size.Y + Option.Size.Y);
|
||||||
|
DropDownContainer.Controls.Add(Option);
|
||||||
|
Option.Clicked += OptionOnClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<TSelection, Task>? OptionSelected;
|
||||||
|
|
||||||
|
private Task OptionOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TSelection but =(arg as TSelection)!;
|
||||||
|
if (but == SelectedOption)
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
DropDownContainer.Visible = IsOpen;
|
||||||
|
if (OpenStatusChanged is not null) OpenStatusChanged.Invoke(IsOpen);
|
||||||
|
TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
SelectedOption = but;
|
||||||
|
Controls.Clear();
|
||||||
|
SelectedOption.LoadDisplay.Invoke();
|
||||||
|
IsOpen = false;
|
||||||
|
DropDownContainer.Visible = IsOpen;
|
||||||
|
if (OpenStatusChanged is not null) OpenStatusChanged.Invoke(IsOpen);
|
||||||
|
if (OptionSelected is not null) OptionSelected.Invoke(SelectedOption);
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
19
Luski/GUI/MainScreen/UI/LuskiControls/DropDownOption.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class DropDownOption : UserControl
|
||||||
|
{
|
||||||
|
public DropDownOption()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DropDownOption(Texture t) : base(t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public required Action LoadDisplay;
|
||||||
|
}
|
70
Luski/GUI/MainScreen/UI/LuskiControls/RoleView.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class RoleView : FlowLayout
|
||||||
|
{
|
||||||
|
private Label l;
|
||||||
|
private string n = "Offline";
|
||||||
|
public int i = 0;
|
||||||
|
public Role? r;
|
||||||
|
public RoleView(Role? r = null)
|
||||||
|
{
|
||||||
|
this.r = r;
|
||||||
|
if (r is not null) n = r.DisplayName;
|
||||||
|
l = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = " " + n + " — " + i,
|
||||||
|
};
|
||||||
|
base.Size = new(0, 30.ScaleInt());
|
||||||
|
base.BackgroundColor = new(34, 34, 34, 255);
|
||||||
|
Controls.Add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<long, UserView> uuu = new();
|
||||||
|
public List<SocketUser> Users = new();
|
||||||
|
|
||||||
|
public async Task AddUser(SocketUser user, Role TopRole)
|
||||||
|
{
|
||||||
|
UserView f = await UserView.Make(user, TopRole, r is null);
|
||||||
|
uuu.Add(user.Id, f);
|
||||||
|
bool ff = false;
|
||||||
|
for (int j = 0; j < Users.Count; j++)
|
||||||
|
{
|
||||||
|
if (string.Compare(Users[j].DisplayName, user.DisplayName) > 0)
|
||||||
|
{
|
||||||
|
Users.Insert(j, user);
|
||||||
|
Controls.Insert(j+1, f);
|
||||||
|
ff = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ff)
|
||||||
|
{
|
||||||
|
Users.Add(user);
|
||||||
|
Controls.Add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = new(Size.X, Size.Y + f.Size.Y);
|
||||||
|
i++;
|
||||||
|
l.Text = " " + n + " — " + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUser(long id)
|
||||||
|
{
|
||||||
|
Vector2i Sizes = new(Size.X, Size.Y - uuu[id].Size.Y);
|
||||||
|
i--;
|
||||||
|
l.Text = " " + n + " — " + i;
|
||||||
|
Users.Remove(uuu[id].User);
|
||||||
|
Controls.Remove(uuu[id]);
|
||||||
|
uuu.Remove(id);
|
||||||
|
for (int j = 0; j < Controls.Length; j++)
|
||||||
|
{
|
||||||
|
ReportSizeUpdate(Controls[j]);
|
||||||
|
}
|
||||||
|
Size = Sizes;
|
||||||
|
}
|
||||||
|
}
|
334
Luski/GUI/MainScreen/UI/LuskiControls/TextBox.cs
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
using System.Timers;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class TextBox : UserControl
|
||||||
|
{
|
||||||
|
private Label _watermark, _label;
|
||||||
|
private bool use;
|
||||||
|
private Rectangle Pointer;
|
||||||
|
private Timer t;
|
||||||
|
|
||||||
|
public int CursorLocation { get; set; } = 0;
|
||||||
|
|
||||||
|
public TextBox()
|
||||||
|
:base(Globals.ms.TextureManager.GetTextureResource("Textbox.png"))
|
||||||
|
{
|
||||||
|
t = new(500);
|
||||||
|
t.Elapsed += TOnElapsed;
|
||||||
|
TextureDisplay = TextureDisplay.Center;
|
||||||
|
_label = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
HoverMouse = MouseCursor.IBeam,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
_watermark = new(_label.Font)
|
||||||
|
{
|
||||||
|
Text = "Text Box",
|
||||||
|
Color = new(128, 128, 128, 255),
|
||||||
|
HoverMouse = MouseCursor.IBeam,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Pointer = new()
|
||||||
|
{
|
||||||
|
Size = new(1.ScaleInt(),
|
||||||
|
(int)_label.LineHeight ),
|
||||||
|
Location = _watermark.Location,
|
||||||
|
BackgroundColor = Color4.White,
|
||||||
|
Visible = false
|
||||||
|
};
|
||||||
|
Controls.Add(Pointer);
|
||||||
|
|
||||||
|
Controls.Add(_label);
|
||||||
|
Controls.Add(_watermark);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TOnElapsed(object? sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
Globals.ms.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
Pointer.Visible = !Pointer.Visible;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<KeyboardKeyEventArgs, Task>? KeyPress;
|
||||||
|
|
||||||
|
public override void UnFocus()
|
||||||
|
{
|
||||||
|
use = false;
|
||||||
|
t.Stop();
|
||||||
|
Pointer.Visible = false;
|
||||||
|
if (Window is not null && Window.focused == this)
|
||||||
|
Window.focused = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
public override void Focus()
|
||||||
|
{
|
||||||
|
if (Window is not null)
|
||||||
|
{
|
||||||
|
if (Window.focused is not null)
|
||||||
|
{
|
||||||
|
Window.focused.UnFocus();
|
||||||
|
}
|
||||||
|
t.Start();
|
||||||
|
|
||||||
|
Window.focused = this;
|
||||||
|
use = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadToParent(IParent parent, IWindow window)
|
||||||
|
{
|
||||||
|
if (Loaded) return;
|
||||||
|
window.MouseDown += Window_MouseDown;
|
||||||
|
window.KeyDown += Window_KeyDown;
|
||||||
|
window.TextInput += WindowOnTextInput;
|
||||||
|
if (!window.Context.IsCurrent) window.Context.MakeCurrent();
|
||||||
|
base.LoadToParent(parent, window);
|
||||||
|
Pointer.Location = _watermark.Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WindowOnTextInput(TextInputEventArgs obj)
|
||||||
|
{
|
||||||
|
if (!use) return;
|
||||||
|
Text = Text.Insert((int)CursorLocation, obj.AsString);
|
||||||
|
CursorLocation += obj.AsString.Length;
|
||||||
|
var f = _label.GetCharLocation((int)CursorLocation);
|
||||||
|
Pointer.Location = _label.Location + new Vector3i(f.X, f.Y, 0);
|
||||||
|
Pointer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public char? PasswordChar { get => _label.PasswordChar; set => _label.PasswordChar = value; }
|
||||||
|
|
||||||
|
private TextLocation tl = TextLocation.TopLeft;
|
||||||
|
|
||||||
|
public TextLocation TextLocation
|
||||||
|
{
|
||||||
|
get => tl;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
tl = value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(Text))
|
||||||
|
{
|
||||||
|
_label.Location = value switch
|
||||||
|
{
|
||||||
|
TextLocation.LineCenter => new(10.ScaleInt(),
|
||||||
|
((Size.Y - _label.Size.Y) / 2), Location.Z),
|
||||||
|
_ => _label.Location
|
||||||
|
};
|
||||||
|
_watermark.Location = _label.Location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_watermark.Location = value switch
|
||||||
|
{
|
||||||
|
TextLocation.LineCenter => new(10.ScaleInt(),
|
||||||
|
((Size.Y - _watermark.Size.Y) / 2), Location.Z),
|
||||||
|
_ => _watermark.Location
|
||||||
|
};
|
||||||
|
_label.Location = _watermark.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Visible
|
||||||
|
{
|
||||||
|
get => base.Visible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == base.Visible) return;
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_label.Text))
|
||||||
|
{
|
||||||
|
_label.Visible = true;
|
||||||
|
_watermark.Visible = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_label.Visible = false;
|
||||||
|
_watermark.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_label.Visible = value;
|
||||||
|
_watermark.Visible = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Visible = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontInteraction Font { get => _label.Font; }
|
||||||
|
public FontInteraction WatermarkFont { get => _watermark.Font; }
|
||||||
|
|
||||||
|
public Color4 TextColor { get => _label.Color; set => _label.Color = value; }
|
||||||
|
public Color4 WatermarkColor { get => _watermark.Color; set => _watermark.Color = value; }
|
||||||
|
|
||||||
|
public bool AllowMultiLine { get; set; } = true;
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get => _label.Text;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int old = _label.Size.Y;
|
||||||
|
_label.Text = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
bool f = false;
|
||||||
|
if (!_label.Visible)
|
||||||
|
{
|
||||||
|
f = true;
|
||||||
|
_label.Visible = true;
|
||||||
|
_label.Location = TextLocation switch
|
||||||
|
{
|
||||||
|
TextLocation.LineCenter => new(10.ScaleInt(), ((Size.Y - _label.Size.Y) / 2), Location.Z),
|
||||||
|
_ => _label.Location
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
_label.Location = TextLocation switch
|
||||||
|
{
|
||||||
|
TextLocation.TrueCenterLeft => new(Location.X + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight), Location.Z),
|
||||||
|
TextLocation.PostiveTureCenterLeft => new(Location.X + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight, Location.Z),
|
||||||
|
TextLocation.PxLeft => new(Location.X + 5, Location.Y + ((Size.Y - _label.Size.Y) / 2), Location.Z),
|
||||||
|
_ => new(Location.X + 5, Location.Y + 5, Location.Z)
|
||||||
|
};*/
|
||||||
|
_watermark.Location = _label.Location;
|
||||||
|
}
|
||||||
|
if (_watermark.Visible) _watermark.Visible = false;
|
||||||
|
if (!f && TextLocation == TextLocation.LineCenter && old != _label.Size.Y)
|
||||||
|
{
|
||||||
|
//_label.Location = new(Location.X + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight), Location.Z);
|
||||||
|
_watermark.Location = _label.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_label.Visible) _label.Visible = false;
|
||||||
|
if (!_watermark.Visible)
|
||||||
|
{
|
||||||
|
_watermark.Visible = true;
|
||||||
|
_watermark.Location = TextLocation switch
|
||||||
|
{
|
||||||
|
TextLocation.LineCenter => new(10.ScaleInt(), ((Size.Y - _watermark.Size.Y) / 2), Location.Z),
|
||||||
|
_ => _watermark.Location
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
_watermark.Location = TextLocation switch
|
||||||
|
{
|
||||||
|
TextLocation.TrueCenterLeft => new(Location.X + 5, Location.Y + ((Size.Y - _watermark.TrueHeight) / 2) - (_watermark.Size.Y - _watermark.TrueHeight), Location.Z),
|
||||||
|
TextLocation.PostiveTureCenterLeft => new(Location.X + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight, Location.Z),
|
||||||
|
TextLocation.PxLeft => new(Location.X + 5, Location.Y + ((Size.Y - _watermark.Size.Y) / 2), Location.Z),
|
||||||
|
_ => new(Location.X + 5, Location.Y + 5, Location.Z)
|
||||||
|
};*/
|
||||||
|
_label.Location = _label.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string WatermarkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _watermark.Text;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_watermark.Text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<Task>? OnNewLine;
|
||||||
|
public event Func<Task>? OnRemoveLine;
|
||||||
|
|
||||||
|
private void Window_KeyDown(KeyboardKeyEventArgs obj)
|
||||||
|
{
|
||||||
|
if (!use) return;
|
||||||
|
if (obj.Key == Keys.Left)
|
||||||
|
{
|
||||||
|
CursorLocation--;
|
||||||
|
var f = _label.GetCharLocation((int)CursorLocation);
|
||||||
|
Pointer.Location = _label.Location + new Vector3i(f.X, f.Y, 0);
|
||||||
|
Pointer.Visible = true;
|
||||||
|
}
|
||||||
|
if (obj.Key == Keys.Right)
|
||||||
|
{
|
||||||
|
if (CursorLocation != Text.Length)
|
||||||
|
{
|
||||||
|
CursorLocation++;
|
||||||
|
var f = _label.GetCharLocation((int)CursorLocation);
|
||||||
|
Pointer.Location = _label.Location + new Vector3i(f.X, f.Y, 0);
|
||||||
|
Pointer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (obj.Key == Keys.CapsLock || obj.Key == Keys.Menu || obj.Key == Keys.LeftSuper || obj.Key == Keys.RightSuper || obj.Key == Keys.End || obj.Key == Keys.Home || obj.Key == Keys.PageDown || obj.Key == Keys.PageUp || obj.Key == Keys.Insert || obj.Key == Keys.Up || obj.Key == Keys.Down || obj.Key == Keys.Left || obj.Key == Keys.Right) return;
|
||||||
|
if (obj.Key == Keys.Backspace)
|
||||||
|
{
|
||||||
|
if (!(Text.Length > 0)) return;
|
||||||
|
if (Text[CursorLocation- 1] == '\n')
|
||||||
|
{
|
||||||
|
Size = new(Size.X, Size.Y - (int)_label.Font.PixelHeight);
|
||||||
|
if (OnRemoveLine is not null) OnRemoveLine.Invoke();
|
||||||
|
}
|
||||||
|
Text = Text.Remove(CursorLocation - 1, 1);
|
||||||
|
CursorLocation--;
|
||||||
|
var f = _label.GetCharLocation(CursorLocation);
|
||||||
|
Pointer.Location = _label.Location + new Vector3i(f.X, f.Y, 0);
|
||||||
|
Pointer.Visible = true;
|
||||||
|
}
|
||||||
|
if (obj.Key == Keys.Delete)
|
||||||
|
{
|
||||||
|
if (CursorLocation == Text.Length) return;
|
||||||
|
if (Text[CursorLocation] == '\n')
|
||||||
|
{
|
||||||
|
Size = new(Size.X, Size.Y - (int)_label.Font.PixelHeight);
|
||||||
|
if (OnRemoveLine is not null) OnRemoveLine.Invoke();
|
||||||
|
}
|
||||||
|
Text = Text.Remove(CursorLocation, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.Key == Keys.Enter)
|
||||||
|
{
|
||||||
|
if (AllowMultiLine && obj.Shift)
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
Size = new(Size.X, Size.Y + (int)_label.Font.PixelHeight);
|
||||||
|
if (OnNewLine is not null) OnNewLine.Invoke().Wait();
|
||||||
|
BlockDraw = false;
|
||||||
|
Text += '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (obj.Key == Keys.V && obj.Control && Window is not null) Text += Window.ClipboardString;
|
||||||
|
if (KeyPress is not null) _ = KeyPress.Invoke(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_MouseDown(MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (MouseInside && e.Button == MouseButton.Button1)
|
||||||
|
{
|
||||||
|
use = true;
|
||||||
|
Focus();
|
||||||
|
}
|
||||||
|
else UnFocus();
|
||||||
|
}
|
||||||
|
}
|
52
Luski/GUI/MainScreen/UI/LuskiControls/ToggleSwitch.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class ToggleSwitch : UserControl
|
||||||
|
{
|
||||||
|
public ToggleSwitch()
|
||||||
|
:base(Globals.ms.TextureManager.GetTextureResource("Toggle.png"))
|
||||||
|
{
|
||||||
|
base.Size = new(40.ScaleInt(), 24.ScaleInt());
|
||||||
|
base.BackgroundColor = OffBackgroundColor;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
Clicked += o =>
|
||||||
|
{
|
||||||
|
Value = !Value;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<ToggleSwitch, Task>? ValueChanged;
|
||||||
|
|
||||||
|
public override void LoadToParent(IParent Parent, IWindow Window)
|
||||||
|
{
|
||||||
|
Value = !Value;
|
||||||
|
Value = !Value;
|
||||||
|
base.LoadToParent(Parent, Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Vector2i Size
|
||||||
|
{
|
||||||
|
get => base.Size;
|
||||||
|
private set => base.Size = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Value
|
||||||
|
{
|
||||||
|
get => val;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value) BackgroundColor = OnBackgroundColor;
|
||||||
|
else BackgroundColor = OffBackgroundColor;
|
||||||
|
val = value;
|
||||||
|
if (Loaded && ValueChanged is not null) ValueChanged.Invoke(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 OnBackgroundColor { get; set; }= new(35, 165, 90, 255);
|
||||||
|
public Color4 OffBackgroundColor { get; set; } = new(128, 132, 142, 255);
|
||||||
|
private bool val = true;
|
||||||
|
}
|
36
Luski/GUI/MainScreen/UI/LuskiControls/UserView.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class UserView : UserControl
|
||||||
|
{
|
||||||
|
public SocketUser User { get; set; }
|
||||||
|
|
||||||
|
private UserView(IRenderObject user, SocketUser u, Role r, bool offline)
|
||||||
|
{
|
||||||
|
this.User = u;
|
||||||
|
base.Size = new(244.ScaleInt(), 44.ScaleInt());
|
||||||
|
base.BackgroundColor = new(34, 34, 34, 255);
|
||||||
|
user.Location = new(8.ScaleInt(), 6.ScaleInt(), 0);
|
||||||
|
user.ForceDistanceUpdate(this);
|
||||||
|
Label uname = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = u.DisplayName,
|
||||||
|
Color = r.Color.ToColor4()
|
||||||
|
};
|
||||||
|
if (offline) uname.Color = new(uname.Color.R, uname.Color.G, uname.Color.B, uname.Color.A * 0.6f);
|
||||||
|
uname.Location = new(user.Location.X + user.Size.X + 8.ScaleInt(),
|
||||||
|
(user.Location.Y + (user.Size.Y / 2) - (uname.Size.Y / 2)), 0);
|
||||||
|
Controls.Add(uname);
|
||||||
|
Controls.Add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<UserView> Make(SocketUser u, Role r, bool offline)
|
||||||
|
{
|
||||||
|
UserView m = new(await u.MakeRct(new(32.ScaleInt()), true), u, r, offline);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
39
Luski/GUI/MainScreen/UI/LuskiControls/VersionDropButton.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
|
||||||
|
public class VersionDropButton : DropDownOption
|
||||||
|
{
|
||||||
|
public Label l;
|
||||||
|
|
||||||
|
public VersionDropButton(Vector2i size, string v)
|
||||||
|
:base(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
base.Size = size;
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
l = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = v,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
l.Location = new((base.Size.X / 2) - (l.Size.X / 2),
|
||||||
|
((base.Size.Y - l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
Controls.Add(l);
|
||||||
|
BackgroundColor = new(0, 0, 0, 0);
|
||||||
|
MouseEnter += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(141, 151, 165, 30);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
MouseLeave += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(0,0,0,0);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
78
Luski/GUI/MainScreen/UI/PublicServers/AddChannel.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.GUI.MainScreen.Interfaces;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class AddChannel : UserControl
|
||||||
|
{
|
||||||
|
private TextBox cn, cd;
|
||||||
|
private UserControl btn;
|
||||||
|
private SocketCategory Cat;
|
||||||
|
private IChannelAdder CA;
|
||||||
|
|
||||||
|
public AddChannel(IChannelAdder CA, SocketCategory cat)
|
||||||
|
{
|
||||||
|
this.CA = CA;
|
||||||
|
Cat = cat;
|
||||||
|
base.Size = Globals.ms.ClientSize;
|
||||||
|
base.BackgroundColor = new(0, 0, 0, 130);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
FlowLayout fl = new()
|
||||||
|
{
|
||||||
|
SpaceBetweenObjects = 5.ScaleInt(),
|
||||||
|
Size = new(350.ScaleInt(), 220.ScaleInt()),
|
||||||
|
BackgroundColor = new(32,32,32,255),
|
||||||
|
//Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
//TextureDisplay = TextureDisplay.Center
|
||||||
|
};
|
||||||
|
fl.Location = new((base.Size.X - fl.Size.X) / 2, (base.Size.Y - fl.Size.Y) / 2, 0);
|
||||||
|
fl.Controls.Add(new Label(Globals.DefaultFont) {Text = "Channel Name"});
|
||||||
|
fl.Controls.Add(cn =new TextBox()
|
||||||
|
{
|
||||||
|
WatermarkText = "Channel Name",
|
||||||
|
Size = new(34.ScaleInt()),
|
||||||
|
Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left | ObjectAnchor.Right,
|
||||||
|
TextLocation = TextLocation.LineCenter
|
||||||
|
});
|
||||||
|
fl.Controls.Add(new Label(Globals.DefaultFont) {Text = "Channel Description"});
|
||||||
|
fl.Controls.Add(cd =new TextBox()
|
||||||
|
{
|
||||||
|
WatermarkText = "Channel Description",
|
||||||
|
Size = cn.Size,
|
||||||
|
Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left | ObjectAnchor.Right,
|
||||||
|
TextLocation = TextLocation.LineCenter
|
||||||
|
});
|
||||||
|
fl.Controls.Add(new Label(Globals.DefaultFont) {Text = "\n "});
|
||||||
|
fl.Controls.Add(btn = new(Globals.ms.TextureManager.GetTextureResource("Textbox.png"))
|
||||||
|
{
|
||||||
|
Size = new(40.ScaleInt()),
|
||||||
|
TextureDisplay = TextureDisplay.Center
|
||||||
|
});
|
||||||
|
Label sub = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "Submit",
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
sub.Location = new((btn.Size.X / 2) - (sub.Size.X / 2),
|
||||||
|
((btn.Size.Y - sub.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
btn.Clicked += BtnOnClicked;
|
||||||
|
sub.ForceDistanceUpdate(btn);
|
||||||
|
btn.Controls.Add(sub);
|
||||||
|
fl.ForceDistanceUpdate(this);
|
||||||
|
Controls.Add(fl);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task BtnOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
SocketChannel chan = await Cat.Server.MakeChannel(Cat, cn.Text, cd.Text);
|
||||||
|
await CA.AddChannel(chan);
|
||||||
|
Globals.ms.Controls.Remove(this);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
}
|
||||||
|
}
|
206
Luski/GUI/MainScreen/UI/PublicServers/Category.cs
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.GUI.MainScreen.Interfaces;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class Category : UserControl, IChannelAdder
|
||||||
|
{
|
||||||
|
public FlowLayout Members;
|
||||||
|
public SocketCategory CurrentCategory { get; set; }
|
||||||
|
private List<Category> cc = new();
|
||||||
|
private List<Channel> cl = new();
|
||||||
|
private Label ee;
|
||||||
|
private ChannelSelector CS;
|
||||||
|
|
||||||
|
public event Func<int, Task>? AddY;
|
||||||
|
|
||||||
|
private Label Name;
|
||||||
|
public UserControl tmp;
|
||||||
|
|
||||||
|
public static Task<Category> MakeCat(SocketCategory cat, ChannelSelector cs)
|
||||||
|
{
|
||||||
|
Category c = new();
|
||||||
|
c.CurrentCategory = cat;
|
||||||
|
c.CS = cs;
|
||||||
|
c.Anchor = ObjectAnchor.All;
|
||||||
|
c.Size = new(307.ScaleInt(), 40.ScaleInt());
|
||||||
|
c.tmp = new()
|
||||||
|
{
|
||||||
|
Size = c.Size,
|
||||||
|
Anchor = ObjectAnchor.Top | ObjectAnchor.Left,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
c.tmp.Clicked += c.TmpOnClicked;
|
||||||
|
c.tmp.HoverMouse = MouseCursor.Hand;
|
||||||
|
c.Controls.Add(c.tmp);
|
||||||
|
c.tmp.Controls.Add(c.ee = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = ">",
|
||||||
|
Location = new(5.ScaleInt()),
|
||||||
|
Color = cat.Color.ToColor4(),
|
||||||
|
DIR = new(1,0),
|
||||||
|
IgnoreHover = true
|
||||||
|
});
|
||||||
|
c.tmp.Controls.Add(c.Name = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = cat.Name,
|
||||||
|
Color = c.ee.Color,
|
||||||
|
IgnoreHover = true
|
||||||
|
});
|
||||||
|
c.Clicked += c.AllOnClicked;
|
||||||
|
c.Name.Location = new(26.ScaleInt(), (((c.Size.Y - c.Name.Size.Y)/2)), 0);
|
||||||
|
c.Members = new()
|
||||||
|
{
|
||||||
|
Anchor = ObjectAnchor.All,
|
||||||
|
Location = new(20.ScaleInt(), c.Size.Y, 0),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
c.ee.Location = new(c.ee.Location.X, c.Name.Location.Y, 0);
|
||||||
|
c.Members.Size = new(c.Size.X - c.Members.Location.X, 0);
|
||||||
|
c.Controls.Add(c.Members);
|
||||||
|
c.Members.ForceDistanceUpdate(c);
|
||||||
|
c.tmp.HoverMouse = MouseCursor.Hand;
|
||||||
|
return Task.FromResult(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Category()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
private async Task TmpOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
if (!Extended)
|
||||||
|
{
|
||||||
|
DateTime dt = DateTime.UtcNow;
|
||||||
|
SocketChannel[] Channels = await CurrentCategory.GetChannels();
|
||||||
|
Console.WriteLine(DateTime.UtcNow - dt);
|
||||||
|
foreach (SocketChannel v in Channels)
|
||||||
|
{
|
||||||
|
Channel c = await AddChannel(v);
|
||||||
|
c.LoadToParent(Members, Window!);
|
||||||
|
_ = CatOnAddY(c.Size.Y);
|
||||||
|
}
|
||||||
|
Console.WriteLine(DateTime.UtcNow - dt);
|
||||||
|
|
||||||
|
SocketCategory[] cats = await CurrentCategory.GetCategories();
|
||||||
|
Console.WriteLine(DateTime.UtcNow - dt);
|
||||||
|
foreach (SocketCategory v in cats)
|
||||||
|
{
|
||||||
|
var c = await AddCategory(v, dt);
|
||||||
|
c.LoadToParent(Members, Window!);
|
||||||
|
_ = CatOnAddY(c.Size.Y);
|
||||||
|
}
|
||||||
|
Console.WriteLine(DateTime.UtcNow - dt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (AddY is not null) await AddY.Invoke(-Members.Size.Y);
|
||||||
|
this.Size = new(this.Size.X, this.Size.Y -Members.Size.Y);
|
||||||
|
Members.Size = new(Members.Size.X, 0);
|
||||||
|
//Members.Controls.Clear(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
|
||||||
|
Extended = !Extended;
|
||||||
|
|
||||||
|
// Window!.ForceUpdate(new(Window.Size));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool e;
|
||||||
|
public bool Extended
|
||||||
|
{
|
||||||
|
get => e;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
ee.DIR = new(0,1);
|
||||||
|
ee.Location = new(ee.Location.X, (ee.Location.Y - ee.Size.Y), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ee.DIR = new(1,0);
|
||||||
|
ee.Location = new(ee.Location.X, (ee.Location.Y + ee.Size.Y), 0);
|
||||||
|
}
|
||||||
|
e = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task AllOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (ClickCon is not null) _ = ClickCon.Invoke(this);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<Category, Task>? ClickCon;
|
||||||
|
|
||||||
|
public async Task<Category> AddCategory(SocketCategory Cat, DateTime? dt = null)
|
||||||
|
{
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
Category[] tc = cc.Where(s => s.CurrentCategory.ID == Cat.ID).ToArray();
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
if (tc.Length > 0)
|
||||||
|
{
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
var cat2 = tc[0];
|
||||||
|
if (!Members.Controls.Contains(cat2))
|
||||||
|
{
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
Members.Controls.Add(cat2);
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
//Size = new(Size.X, Size.Y + cat2.Size.Y);
|
||||||
|
_ = CatOnAddY(cat2.Size.Y);
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
if (AddY is not null) _ = AddY.Invoke(cat2.Size.Y);
|
||||||
|
if (dt is not null) Console.WriteLine("c: {0}",DateTime.UtcNow - dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat2;
|
||||||
|
}
|
||||||
|
var cat = await Category.MakeCat(Cat, CS);
|
||||||
|
cc.Add(cat);
|
||||||
|
Members.Controls.Add(cat);
|
||||||
|
cat.Size = new(this.Size.X, cat.Size.Y);
|
||||||
|
cat.Members.BackgroundColor = BackgroundColor;
|
||||||
|
cat.BackgroundColor = BackgroundColor;
|
||||||
|
cat.tmp.BackgroundColor = BackgroundColor;
|
||||||
|
Size = new(Size.X, Size.Y + cat.Size.Y);
|
||||||
|
cat.AddY += CatOnAddY;
|
||||||
|
if (AddY is not null) await AddY.Invoke(cat.Size.Y);
|
||||||
|
return cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CatOnAddY(int arg)
|
||||||
|
{
|
||||||
|
this.Size = new(Size.X, Size.Y + arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Channel> AddChannel(SocketChannel chan)
|
||||||
|
{
|
||||||
|
Channel[] tc = cl.Where(s => s.CurrentChannel.ID == chan.ID).ToArray();
|
||||||
|
if (tc.Length > 0)
|
||||||
|
{
|
||||||
|
Channel cat2 = tc[0];
|
||||||
|
if (!Members.Controls.Contains(cat2))
|
||||||
|
{
|
||||||
|
Members.Controls.Add(cat2);
|
||||||
|
Size = new(Size.X, Size.Y + cat2.Size.Y);
|
||||||
|
if (AddY is not null) _ = AddY.Invoke(cat2.Size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat2;
|
||||||
|
}
|
||||||
|
Channel cat = await Channel.MakeChannel(chan, CS);
|
||||||
|
cl.Add(cat);
|
||||||
|
cat.BackgroundColor = BackgroundColor;
|
||||||
|
Size = new(Size.X, Size.Y + cat.Size.Y);
|
||||||
|
Members.Controls.Add(cat);
|
||||||
|
if (AddY is not null) await AddY.Invoke(cat.Size.Y);
|
||||||
|
return cat;
|
||||||
|
}
|
||||||
|
}
|
160
Luski/GUI/MainScreen/UI/PublicServers/Channel.cs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using Luski.Shared.PublicServers.V1.Enums;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class Channel : UserControl
|
||||||
|
{
|
||||||
|
private ChannelSelector CS;
|
||||||
|
public SocketChannel CurrentChannel { get; set; }
|
||||||
|
|
||||||
|
private Channel(Stream UserIcon, ChannelSelector cs, SocketChannel chan)
|
||||||
|
: base(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
CS = cs;
|
||||||
|
CurrentChannel = chan;
|
||||||
|
base.Size = new(307.ScaleInt(), 34.ScaleInt());
|
||||||
|
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
int i = 4.ScaleInt();
|
||||||
|
r = new Rectangle(Globals.ms.TextureManager.GetAlphaCircle())
|
||||||
|
{
|
||||||
|
Location = new(i,i,0),
|
||||||
|
Size = new (32.ScaleInt()),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Texture tex;
|
||||||
|
tex = Globals.ms.TextureManager.AddTexture(UserIcon);
|
||||||
|
GC.Collect();
|
||||||
|
UserIcon.Dispose();
|
||||||
|
tex.Unit = TextureUnit.Texture1;
|
||||||
|
r.Textures.Add(tex);
|
||||||
|
r.Shader = Rectangle.DefaultAlphaTextureShader[Globals.ms.Context];
|
||||||
|
Controls.Add(r);
|
||||||
|
ChannelName = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = chan.Name,
|
||||||
|
Color = chan.Color.ToColor4(),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Controls.Add(ChannelName);
|
||||||
|
Clicked += AllOnClicked;
|
||||||
|
ChannelName.Location = new(40.ScaleInt(),
|
||||||
|
((base.Size.Y - ChannelName.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
base.HoverMouse = MouseCursor.Hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Channel(ChannelSelector cs, SocketChannel chan)
|
||||||
|
: base(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
CS = cs;
|
||||||
|
CurrentChannel = chan;
|
||||||
|
base.Size = new(307.ScaleInt(), 34.ScaleInt());
|
||||||
|
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
int i = 4.ScaleInt();
|
||||||
|
GC.Collect();
|
||||||
|
ChannelName = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = chan.Name,
|
||||||
|
Color = chan.Color.ToColor4(),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Controls.Add(ChannelName);
|
||||||
|
Clicked += AllOnClicked;
|
||||||
|
ChannelName.Location = new(i,
|
||||||
|
((base.Size.Y - ChannelName.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
base.HoverMouse = MouseCursor.Hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Selected { get; private set; }
|
||||||
|
|
||||||
|
public async Task ToggleSelected()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Color4 bc = new(141,151,165,51);
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
bc = CS.BackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = true;
|
||||||
|
Selected = !Selected;
|
||||||
|
|
||||||
|
if (CS.Selected is not null && CS.Selected != this)
|
||||||
|
{
|
||||||
|
await CS.Selected.ToggleSelected();
|
||||||
|
}
|
||||||
|
BackgroundColor = bc;
|
||||||
|
Task? mm = null;
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
CS.Selected = this;
|
||||||
|
IReadOnlyList<SocketMessage> m;
|
||||||
|
m = await CurrentChannel.GetMessages(CancellationToken.None, Globals.Settings.LoadPerChannel);
|
||||||
|
Globals.ms.pc.ClearChat();
|
||||||
|
await Globals.ms.pc.LoadChannel(CurrentChannel);
|
||||||
|
mm = Globals.ms.pc.AddMessages(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mm is not null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Waiting");
|
||||||
|
Task.WaitAll(mm);
|
||||||
|
Globals.ms.pc.MessageFlow.ForceScrollUpdate();
|
||||||
|
Globals.ms.pc.MessageFlow.ScrollToBottom();
|
||||||
|
Console.WriteLine("Done");
|
||||||
|
}
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Label ChannelName;
|
||||||
|
public Rectangle r;
|
||||||
|
|
||||||
|
public static async Task<Channel> MakeChannel(SocketChannel chan, ChannelSelector cs)
|
||||||
|
{
|
||||||
|
Channel c;
|
||||||
|
if (chan.PictureType == PictureType.none) c = new(cs, chan);
|
||||||
|
else c = new(await chan.GetPicture(CancellationToken.None), cs, chan);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task EditChannelButtonOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
arg.ContextMenu!.HideContext(Window!);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ExportKeysButtonOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
//_ = CurrentChannel.SendKeysToUsers(CancellationToken.None);
|
||||||
|
ContextMenu!.HideContext(Window!);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AllOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (!Selected) await ToggleSelected();
|
||||||
|
//if (ClickCon is not null) _ = ClickCon.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//public event Func<Channel, Task>? ClickCon;
|
||||||
|
}
|
138
Luski/GUI/MainScreen/UI/PublicServers/ChannelSelector.cs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.GUI.MainScreen.Interfaces;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using Luski.Shared.PublicServers.V1.Enums;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class ChannelSelector : FlowLayout, IChannelAdder
|
||||||
|
{
|
||||||
|
public SocketCategory CurrentCategory { get; }
|
||||||
|
private readonly List<Category> cc = new();
|
||||||
|
private readonly List<Channel> LoadedChannels = new();
|
||||||
|
public Channel? Selected;
|
||||||
|
|
||||||
|
private ChannelSelector(SocketCategory Cat)
|
||||||
|
{
|
||||||
|
CurrentCategory = Cat;
|
||||||
|
Cat.Server.MessageReceived += ServerOnMessageReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<ChannelSelector> MakeSelector(SocketCategory Cat)
|
||||||
|
{
|
||||||
|
ChannelSelector cs = new(Cat);
|
||||||
|
if (await Cat.Server.User.HasAccessToCategory(Cat, ServerPermission.CreateChannels))
|
||||||
|
{
|
||||||
|
LuskiContextMenu lcm = new();
|
||||||
|
Label l = lcm.AddLabel("Create Channel");
|
||||||
|
l.Clicked += cs.LOnClicked;
|
||||||
|
cs.ContextMenu = lcm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
Globals.ms.Controls.Add(new AddChannel(this, CurrentCategory));
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ServerOnMessageReceived(SocketMessage arg)
|
||||||
|
{
|
||||||
|
if (Selected is null || arg.ChannelID != Selected.CurrentChannel.ID) return;
|
||||||
|
bool u = Globals.ms.pc.MessageFlow.MaxScrollValue == Globals.ms.pc.MessageFlow.ScrollValue;
|
||||||
|
await Globals.ms.pc.AddMessage(arg, u);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Load(SocketChannel currentchannel, List<SocketCategory> parents)
|
||||||
|
{
|
||||||
|
IChannelAdder b = this;
|
||||||
|
SocketChannel[] chanspp = await b.CurrentCategory.GetChannels();
|
||||||
|
foreach (SocketChannel v in chanspp)
|
||||||
|
{
|
||||||
|
Channel f = await b.AddChannel(v);
|
||||||
|
if (v.ID == currentchannel.ID)
|
||||||
|
{
|
||||||
|
await f.ToggleSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SocketCategory[] cats = await b.CurrentCategory.GetCategories();
|
||||||
|
foreach (SocketCategory v in cats)
|
||||||
|
{
|
||||||
|
await b.AddCategory(v);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
}
|
||||||
|
foreach (SocketCategory par in parents)
|
||||||
|
{
|
||||||
|
b.Extended = true;
|
||||||
|
b = await b.AddCategory(par);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
chanspp = await par.GetChannels();
|
||||||
|
foreach (SocketChannel v in chanspp)
|
||||||
|
{
|
||||||
|
Channel f = await b.AddChannel(v);
|
||||||
|
if (v.ID == currentchannel.ID)
|
||||||
|
{
|
||||||
|
await f.ToggleSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cats = await par.GetCategories();
|
||||||
|
foreach (SocketCategory v in cats)
|
||||||
|
{
|
||||||
|
await b.AddCategory(v);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Channel> AddChannel(SocketChannel chan)
|
||||||
|
{
|
||||||
|
Channel[] tc = LoadedChannels.Where(s => s.CurrentChannel.ID == chan.ID).ToArray();
|
||||||
|
if (tc.Length > 0)
|
||||||
|
{
|
||||||
|
Channel cat23 = tc[0];
|
||||||
|
if (!Controls.Contains(cat23))
|
||||||
|
{
|
||||||
|
Controls.Add(cat23);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat23;
|
||||||
|
}
|
||||||
|
Channel cat2 = await Channel.MakeChannel(chan, this);
|
||||||
|
LoadedChannels.Add(cat2);
|
||||||
|
cat2.BackgroundColor = BackgroundColor;
|
||||||
|
Controls.Add(cat2);
|
||||||
|
return cat2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Extended { get; set; } = true;
|
||||||
|
|
||||||
|
public async Task<Category> AddCategory(SocketCategory Cat, DateTime? dt = null)
|
||||||
|
{
|
||||||
|
Category[] tc = cc.Where(s => s.CurrentCategory.ID == Cat.ID).ToArray();
|
||||||
|
if (tc.Length > 0)
|
||||||
|
{
|
||||||
|
Category cat23 = tc[0];
|
||||||
|
if (!Controls.Contains(cat23))
|
||||||
|
{
|
||||||
|
Controls.Add(cat23);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat23;
|
||||||
|
}
|
||||||
|
Category cat = await Category.MakeCat(Cat, this);
|
||||||
|
cc.Add(cat);
|
||||||
|
cat.BackgroundColor = BackgroundColor;
|
||||||
|
cat.tmp.BackgroundColor = BackgroundColor;
|
||||||
|
cat.Members.BackgroundColor = BackgroundColor;
|
||||||
|
Controls.Add(cat);
|
||||||
|
return cat;
|
||||||
|
}
|
||||||
|
}
|
304
Luski/GUI/MainScreen/UI/PublicServers/ChatMessage.cs
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
using Luski.net.Structures.Main;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
using Label = GraphicsManager.Objects.Label;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class ChatMessage : UserControl
|
||||||
|
{
|
||||||
|
private SocketMessage Msg { get; }
|
||||||
|
private SocketChannel ch { get; }
|
||||||
|
|
||||||
|
public PublicChat pc;
|
||||||
|
|
||||||
|
private IRenderObject LastObject;
|
||||||
|
public List<IRenderObject> MessageObjs = new();
|
||||||
|
private Label FirstL;
|
||||||
|
|
||||||
|
public readonly double HorPadding = 12.ScaleDouble(),
|
||||||
|
VerticalPadding = 0.ScaleDouble();
|
||||||
|
|
||||||
|
private static Dictionary<MainSocketRemoteUser, List<ChatMessage>> Messages = new();
|
||||||
|
|
||||||
|
public static async Task<ChatMessage> MakeChatMessage(PublicChat p, SocketMessage message)
|
||||||
|
{
|
||||||
|
IUser auth = await message.GetAuthor(CancellationToken.None);
|
||||||
|
Color c = await auth.GetColor();
|
||||||
|
Color4 c4 = new(c.R, c.G, c.B, c.A);
|
||||||
|
return new ChatMessage(p, message, await message.GetParent(CancellationToken.None), auth, await auth.MakeRct(new(40.ScaleInt()), message.IsProfile), c4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ChatMessage(PublicChat p, SocketMessage message, SocketChannel chan, IUser Author, IRenderObject UserIcon, Color4 UserNameColor)
|
||||||
|
{
|
||||||
|
pc = p;
|
||||||
|
Label label1;
|
||||||
|
base.Size = new(723.5.ScaleInt(), 37.ScaleInt());
|
||||||
|
ch = chan;
|
||||||
|
base.BackgroundColor = new(40, 40, 40, 255);
|
||||||
|
Msg = message;
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Right;
|
||||||
|
|
||||||
|
DateTime time = chan.Epoch.AddMilliseconds(Msg.TimeStamp).ToLocalTime();
|
||||||
|
|
||||||
|
string time_str;
|
||||||
|
if (Globals.Settings.DayTime)
|
||||||
|
{
|
||||||
|
if (time.Date == DateTime.Now.ToLocalTime().Date)
|
||||||
|
{
|
||||||
|
time_str = $"Today at {time:HH:mm}";
|
||||||
|
}
|
||||||
|
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
|
||||||
|
{
|
||||||
|
time_str = $"Yesterday at {time:HH:mm}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_str = $"{time:M/dd/yyyy HH:mm}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (time.Date == DateTime.Now.ToLocalTime().Date)
|
||||||
|
{
|
||||||
|
time_str = $"Today at {time.ToShortTimeString().Replace('\u202f', ' ')}";
|
||||||
|
}
|
||||||
|
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
|
||||||
|
{
|
||||||
|
time_str = $"Yesterday at {time.ToShortTimeString().Replace('\u202f', ' ')}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_str = $"{time:M/dd/yyyy h:mm tt}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserIcon.Location = new(10.ScaleInt(), 2.ScaleInt(), 0);
|
||||||
|
Controls.Add(UserIcon);
|
||||||
|
Controls.Add(label1 = new Label(Globals.DefaultFont) { Color = UserNameColor, Text = Author.DisplayName });
|
||||||
|
label1.Location = new(
|
||||||
|
54.ScaleInt(),
|
||||||
|
//(int)(UserIcon.Location.Y + (UserIcon.Size.Y / 2) - (label1.Font.CurrentFonts[0].Face.Size.Metrics.NominalHeight / 2) - label1.Size.Y + label1.Font.PixelHeight),
|
||||||
|
UserIcon.Location.Y,
|
||||||
|
0);
|
||||||
|
Label label2;
|
||||||
|
LastObject = label1;
|
||||||
|
FirstL = label1;
|
||||||
|
Controls.Add(label2 = new Label(Globals.TopTimeFont) { Location = new(label1.Location.X + label1.Size.X + 8.ScaleInt(), (int)(label1.Location.Y + label1.Font.PixelHeight - Globals.TopTimeFont.PixelHeight), 0), Text = time_str});
|
||||||
|
if (!string.IsNullOrWhiteSpace(Msg.Context))
|
||||||
|
{
|
||||||
|
Label l;
|
||||||
|
Controls.Add(l = new Label(Globals.MessageFont) { Location = new(LastObject.Location.X, (int)(UserIcon.Location.Y + UserIcon.Size.Y - Globals.MessageFont.PixelHeight), 0), Text = message.Context});
|
||||||
|
LastObject = l;
|
||||||
|
MessageObjs.Add(l);
|
||||||
|
}
|
||||||
|
Globals.Settings.DayTimeChanged += () =>
|
||||||
|
{
|
||||||
|
if (Globals.Settings.DayTime)
|
||||||
|
{
|
||||||
|
if (time.Date == DateTime.Now.ToLocalTime().Date)
|
||||||
|
{
|
||||||
|
time_str = $"Today at {time:HH:mm}";
|
||||||
|
}
|
||||||
|
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
|
||||||
|
{
|
||||||
|
time_str = $"Yesterday at {time:HH:mm}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_str = $"{time:M/dd/yyyy HH:mm}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (time.Date == DateTime.Now.ToLocalTime().Date)
|
||||||
|
{
|
||||||
|
time_str = $"Today at {time.ToShortTimeString().Replace('\u202f', ' ')}";
|
||||||
|
}
|
||||||
|
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
|
||||||
|
{
|
||||||
|
time_str = $"Yesterday at {time.ToShortTimeString().Replace('\u202f', ' ')}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_str = $"{time:M/dd/yyyy h:mm tt}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label2.Text = time_str;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Msg.Files.Count > 0)
|
||||||
|
{
|
||||||
|
int row = 1;
|
||||||
|
int files_on_row = 0;
|
||||||
|
for (int i = 0; i < Msg.Files.Count; i++)
|
||||||
|
{
|
||||||
|
double lx = (HorPadding * files_on_row) + LastObject.Location.X + (333 * (files_on_row + 1));
|
||||||
|
if (lx > base.Size.X)
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
files_on_row = 0;
|
||||||
|
lx = (HorPadding * files_on_row) + LastObject.Location.X + (333 * (files_on_row + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
files_on_row++;
|
||||||
|
IRenderObject cem = ContentEmbed.GetEmbed(this, Msg.Files[i], Msg.ChannelID).Result;
|
||||||
|
cem.Location = new((int)(lx - 333), (int)(LastObject.Location.Y + 2 + LastObject.Size.Y + (HorPadding * row) + (66 * (row - 1))), 0);
|
||||||
|
LastObject = cem;
|
||||||
|
Controls.Add(cem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LastObject is Label ll) base.Size = new(base.Size.X, (int)(ll.Location.Y + ll.Size.Y + VerticalPadding));
|
||||||
|
else base.Size = new(base.Size.X ,(int)(LastObject.Location.Y + LastObject.Size.Y + VerticalPadding));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task AddMessage(SocketMessage msg)
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
Label newLabel;
|
||||||
|
if (!string.IsNullOrWhiteSpace(msg.Context))
|
||||||
|
{
|
||||||
|
newLabel = new(Globals.MessageFont)
|
||||||
|
{
|
||||||
|
Text = msg.Context,
|
||||||
|
Tag = msg
|
||||||
|
};
|
||||||
|
if (LastObject is Label l)
|
||||||
|
{
|
||||||
|
newLabel.Location = new(FirstL.Location.X, (int)(l.Location.Y + l.Size.Y + VerticalPadding), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newLabel.Location = new(FirstL.Location.X, Size.Y, 0);
|
||||||
|
}
|
||||||
|
bool result = Uri.TryCreate(newLabel.Text, UriKind.Absolute, out Uri? uriResult)
|
||||||
|
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
newLabel.HoverMouse = MouseCursor.Hand;
|
||||||
|
newLabel.Color = Color4.Aqua;
|
||||||
|
newLabel.Clicked += NewLabelOnClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
newLabel.MouseEnter += NewLabel_MouseEnter;
|
||||||
|
newLabel.MouseLeave += NewLabel_MouseLeave;
|
||||||
|
Controls.Add(newLabel);
|
||||||
|
MessageObjs.Add(newLabel);
|
||||||
|
LastObject = newLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (msg.Files.Count > 0)
|
||||||
|
{
|
||||||
|
int row = 1;
|
||||||
|
int filesonrow = 0;
|
||||||
|
for (int i = 0; i < msg.Files.Count; i++)
|
||||||
|
{
|
||||||
|
double lx = (HorPadding * filesonrow) + LastObject.Location.X + (333 * (filesonrow + 1));
|
||||||
|
if (lx > Size.X)
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
filesonrow = 0;
|
||||||
|
lx = (HorPadding * filesonrow) + LastObject.Location.X + (333 * (filesonrow + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
filesonrow++;
|
||||||
|
IRenderObject cem = await ContentEmbed.GetEmbed(this, msg.Files[i], msg.ChannelID);
|
||||||
|
cem.Location = new((int)(lx - 333), (int)(LastObject.Location.Y + 2 + LastObject.Size.Y + (HorPadding * row) + (66 * (row - 1))), 0);
|
||||||
|
LastObject = cem;
|
||||||
|
Controls.Add(cem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (LastObject is Label ll) Size = new(Size.X, (int)(ll.Location.Y + ll.Size.Y + VerticalPadding));
|
||||||
|
else Size = new(Size.X ,(int)(LastObject.Location.Y + LastObject.Size.Y + VerticalPadding));
|
||||||
|
BlockDraw = false;
|
||||||
|
//if (Parent is not null) Globals.ms.pc.MessageFlow.ReportSizeUpdate(this);
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task NewLabelOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Label m = (arg as Label)!;
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
Process.Start(m.Text);
|
||||||
|
else if (OperatingSystem.IsLinux())
|
||||||
|
{
|
||||||
|
if (m.Tag is string s) Process.Start("xdg-open", s);
|
||||||
|
else Process.Start("xdg-open", m.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly List<Label> Labels = new();
|
||||||
|
private async Task NewLabel_MouseLeave(IRenderObject sender)
|
||||||
|
{
|
||||||
|
if (sender is not Label label) return;
|
||||||
|
if (label.Tag is not SocketMessage Message) return;
|
||||||
|
DateTime time = (await Message.GetParent(CancellationToken.None)).Epoch.AddMilliseconds(Message.TimeStamp).ToLocalTime();
|
||||||
|
string b;
|
||||||
|
if (!Globals.Settings.DayTime) b = time.ToString("h:mm tt");
|
||||||
|
else b = time.ToString("HH:mm");
|
||||||
|
Globals.Settings.DayTimeChanged += () =>
|
||||||
|
{
|
||||||
|
if (!Globals.Settings.DayTime) b = time.ToString("h:mm tt");
|
||||||
|
else b = time.ToString("HH:mm");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
};
|
||||||
|
Label[] l = Labels.Where(s => s.Text == b).ToArray();
|
||||||
|
if (l.Any())
|
||||||
|
{
|
||||||
|
Controls.Remove(l.First());
|
||||||
|
Labels.Remove(l.First());
|
||||||
|
}
|
||||||
|
Window!.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task NewLabel_MouseEnter(IRenderObject sender)
|
||||||
|
{
|
||||||
|
if (sender is not Label label) return;
|
||||||
|
if (label.Tag is not SocketMessage Message) return;
|
||||||
|
DateTime time = (await Message.GetParent(CancellationToken.None)).Epoch.AddMilliseconds(Message.TimeStamp).ToLocalTime();
|
||||||
|
Label m;
|
||||||
|
if (!Globals.Settings.DayTime) m = new( Globals.SmallTimeFont)
|
||||||
|
{
|
||||||
|
Text = time.ToString("h:mm tt"),
|
||||||
|
};
|
||||||
|
else m = new( Globals.SmallTimeFont)
|
||||||
|
{
|
||||||
|
Text = time.ToString("HH:mm"),
|
||||||
|
};
|
||||||
|
Globals.Settings.DayTimeChanged += () =>
|
||||||
|
{
|
||||||
|
if (!Globals.Settings.DayTime) m.Text = time.ToString("h:mm tt");
|
||||||
|
else m.Text = time.ToString("HH:mm");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
m.Location = new(
|
||||||
|
label.Location.X - m.Size.X - 5.ScaleInt(),
|
||||||
|
(int)(label.Location.Y + label.Font.PixelHeight - Globals.SmallTimeFont.PixelHeight),
|
||||||
|
0);
|
||||||
|
|
||||||
|
Controls.Add(m);
|
||||||
|
Labels.Add(m);
|
||||||
|
Window!.TryDraw();
|
||||||
|
}
|
||||||
|
}
|
129
Luski/GUI/MainScreen/UI/PublicServers/ContentEmbed.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using GraphicsManager;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
using Rectangle = GraphicsManager.Objects.Rectangle;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class ContentEmbed : UserControl
|
||||||
|
{
|
||||||
|
readonly SocketFile file;
|
||||||
|
public static Texture? t = null;
|
||||||
|
public static Texture? DownloadIcon = null;
|
||||||
|
long channel;
|
||||||
|
private static bool isopen;
|
||||||
|
public static async Task<IRenderObject> GetEmbed(ChatMessage m, SocketFile file, long channel)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (file.Name.ToLower().EndsWith(".png") || file.Name.ToLower().EndsWith(".jpg"))
|
||||||
|
{
|
||||||
|
Stream data = await file.GetCache(CancellationToken.None);
|
||||||
|
Texture t = Globals.ms.TextureManager.AddTexture(data);
|
||||||
|
data.Dispose();
|
||||||
|
Rectangle r;
|
||||||
|
double s = 322.ScaleDouble();
|
||||||
|
double scale = s / t.RawSize!.Value.X;
|
||||||
|
m.Controls.Add(r = new Rectangle(t)
|
||||||
|
{
|
||||||
|
Size = new((int)s, (int)(scale * t.RawSize.Value.Y)),
|
||||||
|
Shader = Texture.TextureShader[Globals.ms.Context],
|
||||||
|
HoverMouse = MouseCursor.Hand,
|
||||||
|
Tag = m.pc
|
||||||
|
});
|
||||||
|
r.Clicked += ROnClicked;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ContentEmbed c;
|
||||||
|
m.Controls.Add(c = new ContentEmbed(file, channel));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task ROnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (isopen) return Task.CompletedTask;
|
||||||
|
isopen = true;
|
||||||
|
FullScreenMedia r;
|
||||||
|
|
||||||
|
Globals.ms.Controls.Add(r = FullScreenMedia.GetDisplay(((Rectangle)arg).Textures[0]));
|
||||||
|
if (arg.Tag is PublicChat pc)
|
||||||
|
{
|
||||||
|
pc.MessageFlow.AllowHoverFromBehind = false;
|
||||||
|
r.Tag = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Clicked += RrOnClicked;
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task RrOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
isopen = false;
|
||||||
|
Globals.ms.Controls.Remove(arg);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
FullScreenMedia fsm = (arg as FullScreenMedia)!;
|
||||||
|
fsm.Clicked -= RrOnClicked;
|
||||||
|
if (fsm.Tag is PublicChat pc)
|
||||||
|
{
|
||||||
|
pc.MessageFlow.AllowHoverFromBehind = true;
|
||||||
|
}
|
||||||
|
fsm.Clean();
|
||||||
|
fsm = null!;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentEmbed(SocketFile file, long channel)
|
||||||
|
{
|
||||||
|
Label fileNameLabel, fileSizeLabel;
|
||||||
|
this.channel = channel;
|
||||||
|
this.file = file;
|
||||||
|
string fst = "";
|
||||||
|
ulong size = (ulong)file.Size;
|
||||||
|
if (size < 1000)
|
||||||
|
fst = size + " bytes";
|
||||||
|
else if (size < 1000000)
|
||||||
|
fst = Math.Round(size / (double)1000, 2) + " KB";
|
||||||
|
else if (size < 1000000000)
|
||||||
|
fst = Math.Round(size / (double)1000000, 2) + " MB";
|
||||||
|
else if (size < 1000000000000) fst = Math.Round(size / (double)1000000000, 2) + " GB";
|
||||||
|
base.Size = new(333, 66);
|
||||||
|
BackgroundColor = new(40, 40, 40, 255);
|
||||||
|
Controls.Add(fileSizeLabel = new Label(Globals.DefaultFont) { Text = fst, Location = new(64, 39, 0) });
|
||||||
|
Controls.Add(fileNameLabel = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Color = new(102 / (float)255, 227 / (float)255, 170 / (float)255, 1), Text = file.Name,
|
||||||
|
Location = new(64, 6, 0)
|
||||||
|
});
|
||||||
|
fileNameLabel.Clicked += FileNameLabelOnClicked;
|
||||||
|
if (DownloadIcon is null)
|
||||||
|
{
|
||||||
|
Stream tempp =
|
||||||
|
Tools.GetResourceStream(Assembly.GetExecutingAssembly(), "Luski.Resources.Textures.Download.png");
|
||||||
|
DownloadIcon = Globals.ms.TextureManager.AddTexture(tempp);
|
||||||
|
tempp.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Add(new Rectangle(DownloadIcon)
|
||||||
|
{ Location = new(8, 6, 0), Size = new(50, 50) });
|
||||||
|
int temp = fileNameLabel.Size.X + fileNameLabel.Location.X;
|
||||||
|
int temp2 = fileSizeLabel.Size.X + fileSizeLabel.Location.X;
|
||||||
|
//if (temp >= temp2) Size = new(temp + 4, Size.Y);
|
||||||
|
//else Size = new(temp2 + 4, Size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task FileNameLabelOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
string dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Downloads", "LuskiDownloads");
|
||||||
|
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
|
||||||
|
//Thread t = new(() => file.DownloadBytes(Path.Join(dir, file.Name), channel, CancellationToken.None));
|
||||||
|
//t.Start();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
544
Luski/GUI/MainScreen/UI/PublicServers/PublicChat.cs
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using GraphicsManager;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using Luski.Shared.PublicServers.V1.Enums;
|
||||||
|
using OpenTK.Graphics.ES11;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using MatrixMode = OpenTK.Graphics.OpenGL.MatrixMode;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
|
||||||
|
public class PublicChat : UserControl
|
||||||
|
{
|
||||||
|
|
||||||
|
public FlowLayout MessageFlow;
|
||||||
|
private Label title, desc;
|
||||||
|
private TextBox tb;
|
||||||
|
private SocketChannel? Channel;
|
||||||
|
UserControl titlecon;
|
||||||
|
private Rectangle? UserCon;
|
||||||
|
private SocketMessage? first;
|
||||||
|
private FlowLayout? memberflow = null;
|
||||||
|
|
||||||
|
public PublicChat()
|
||||||
|
{
|
||||||
|
|
||||||
|
base.Size = new(980.ScaleInt(), 866.ScaleInt());
|
||||||
|
base.BackgroundColor = new(40,40,40,255);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
Controls.Add(MessageFlow = new()
|
||||||
|
{
|
||||||
|
Size = new(base.Size.X, 785.ScaleInt()),
|
||||||
|
Location = new(0, 52.ScaleInt(), 0),
|
||||||
|
BackgroundColor = new(40,40,40,255),
|
||||||
|
Anchor = ObjectAnchor.All,
|
||||||
|
HScrollPixels = Globals.Settings.PerScrollPixels,
|
||||||
|
});
|
||||||
|
MessageFlow.FlowUpdate += MessageFlowOnFlowUpdate;
|
||||||
|
if (LuskiExperiments.GUI.MessageLiveSize.IsEnabled()) MessageFlow.SizeChanged += OnSizeChanged;
|
||||||
|
LuskiExperiments.GUI.MessageLiveSize.EventToggled += MessageLiveSizeOnEventToggled;
|
||||||
|
|
||||||
|
Task MessageLiveSizeOnEventToggled(bool arg)
|
||||||
|
{
|
||||||
|
if (arg) MessageFlow.SizeChanged += OnSizeChanged;
|
||||||
|
else MessageFlow.SizeChanged -= OnSizeChanged;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
Controls.Add(titlecon = new UserControl()
|
||||||
|
{
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right,
|
||||||
|
Size = new(980.ScaleInt(), 48.ScaleInt()),
|
||||||
|
BackgroundColor = new(50,50,50,255),
|
||||||
|
});
|
||||||
|
UserCon =
|
||||||
|
new(Globals.ms.TextureManager.GetTextureResource("person.png"))
|
||||||
|
{
|
||||||
|
Size = new(24.ScaleInt()),
|
||||||
|
Location = new(944.ScaleInt(), 12.ScaleInt(),0),
|
||||||
|
Anchor = ObjectAnchor.Right | ObjectAnchor.Top,
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = Color4.LightGray
|
||||||
|
};
|
||||||
|
UserCon.MouseEnter += o => { UserCon.BackgroundColor = Color4.White; return Task.CompletedTask; };
|
||||||
|
UserCon.MouseLeave += o => { UserCon.BackgroundColor = Color4.LightGray; return Task.CompletedTask; };
|
||||||
|
UserCon.Clicked += UserConOnClicked;
|
||||||
|
titlecon.Controls.Add(UserCon);
|
||||||
|
|
||||||
|
|
||||||
|
titlecon.ForceDistanceUpdate(this);
|
||||||
|
titlecon.Controls.Add(title = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
//Location = new(
|
||||||
|
});
|
||||||
|
titlecon.Controls.Add(desc = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Color = new(161,161,161,255),
|
||||||
|
Location = new(title.Location.X + title.Size.X + 5, title.Location.Y, 0)
|
||||||
|
});
|
||||||
|
|
||||||
|
Controls.Add(tb = new()
|
||||||
|
{
|
||||||
|
// InsideColor = new(28, 28, 28, 255),
|
||||||
|
//BorderColor = Color4.DarkCyan,
|
||||||
|
Location = new(10.ScaleInt(), 824.ScaleInt(), 0),
|
||||||
|
Size = new(960.ScaleInt(), 34.ScaleInt()),
|
||||||
|
Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left | ObjectAnchor.Right,
|
||||||
|
HoverMouse = MouseCursor.IBeam,
|
||||||
|
//Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
//Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = Color4.Red,
|
||||||
|
TextLocation = TextLocation.LineCenter
|
||||||
|
});
|
||||||
|
tb.KeyPress += TbOnKeyPress;
|
||||||
|
tb.OnRemoveLine += TbOnOnRemoveLine;
|
||||||
|
tb.OnNewLine += TbOnOnNewLine;
|
||||||
|
tb.ForceDistanceUpdate(this);
|
||||||
|
//tb.KeyPress += TbOnKeyPress;
|
||||||
|
//Globals.Luski.MainServer.MessageReceived += LuskiOnMessageReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ssss = false;
|
||||||
|
|
||||||
|
private Task OnSizeChanged(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (ssss) return Task.CompletedTask;
|
||||||
|
ssss = true;
|
||||||
|
BlockDraw = true;
|
||||||
|
bool off = false;
|
||||||
|
for (int j = 0; j < MessageFlow.Controls.Length; j++)
|
||||||
|
{
|
||||||
|
if (MessageFlow.Controls[j] is ChatMessage cm && cm.Controls.Length != 0 && cm.Location.Y + cm.Size.Y >= 0 && !off)
|
||||||
|
{
|
||||||
|
if (cm.MessageObjs[0] is Label First)
|
||||||
|
{
|
||||||
|
First.MaxSize = new(MessageFlow.Size.X - First.Location.X - 10.ScaleInt(), Int32.MaxValue);
|
||||||
|
First.ForceDistanceUpdate(cm);
|
||||||
|
}
|
||||||
|
for (int i = 1; i < cm.MessageObjs.Count; i++)
|
||||||
|
{
|
||||||
|
cm.MessageObjs[i].Location = new(cm.MessageObjs[i].Location.X,
|
||||||
|
cm.MessageObjs[i - 1].Location.Y + cm.MessageObjs[i - 1].Size.Y,
|
||||||
|
cm.MessageObjs[i].Location.Z);
|
||||||
|
cm.MessageObjs[i].ForceDistanceUpdate(cm);
|
||||||
|
if (cm.MessageObjs[i] is Label l)
|
||||||
|
{
|
||||||
|
l.MaxSize = new(MessageFlow.Size.X - l.Location.X - 10.ScaleInt(), Int32.MaxValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ny = cm.MessageObjs.Last().Size.Y + cm.MessageObjs.Last().Location.Y + (int)cm.VerticalPadding;
|
||||||
|
if (cm.Location.Y + ny > MessageFlow.Size.Y) off = true;
|
||||||
|
|
||||||
|
if (cm.Size.Y != ny)
|
||||||
|
{
|
||||||
|
cm.Size = new(Size.X, ny);
|
||||||
|
MessageFlow.ReportSizeUpdate(cm);
|
||||||
|
}
|
||||||
|
ssss = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MessageFlowOnFlowUpdate(bool arg1, uint arg2, uint arg3)
|
||||||
|
{
|
||||||
|
if (!loadingm && arg1 && arg3 == 0 && (arg2 != 0 || MessageFlow.MaxScrollValue == 0))
|
||||||
|
{
|
||||||
|
loadingm = true;
|
||||||
|
var messages = await Channel!.GetMessages(CancellationToken.None, first!, Globals.Settings.LoadPerChannel);
|
||||||
|
if (messages.Count == 0) return;
|
||||||
|
index = 0;
|
||||||
|
fakeIndex = false;
|
||||||
|
lastmIndex = null;
|
||||||
|
lastUserIndex = null;
|
||||||
|
LastChatMessageIndex = null;
|
||||||
|
await AddMessagesIndex(messages);
|
||||||
|
MessageFlow.ForceScrollUpdate();
|
||||||
|
first = messages.Last();
|
||||||
|
if (Globals.Settings.LoadPerChannel == messages.Count)loadingm = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TbOnKeyPress(KeyboardKeyEventArgs arg)
|
||||||
|
{
|
||||||
|
//var t = Matrix4.Identity * Matrix4.CreateScale(2 / (float)Size.X, 2 / (float)Size.Y, 1) * Matrix4.CreateTranslation(-1.0f, -1.0f, 0.0f);
|
||||||
|
//var tt = Matrix4.CreateOrthographicOffCenter(0.0f, Size.X, 0.0f, Size.Y, 1, -1);
|
||||||
|
if (arg.Key == Keys.Enter && !arg.Shift)
|
||||||
|
{
|
||||||
|
|
||||||
|
await Channel!.SendMessage(tb.Text);
|
||||||
|
tb.Text = string.Empty;
|
||||||
|
tb.CursorLocation = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task TbOnOnRemoveLine()
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
tb.Location = new(tb.Location.X, tb.Location.Y + (int)tb.Font.PixelHeight, 0);
|
||||||
|
MessageFlow.Size = new(MessageFlow.Size.X, MessageFlow.Size.Y + (int)tb.Font.PixelHeight);
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task TbOnOnNewLine()
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
tb.Location = new(tb.Location.X, tb.Location.Y - (int)tb.Font.PixelHeight, 0);
|
||||||
|
MessageFlow.Size = new(MessageFlow.Size.X, MessageFlow.Size.Y - (int)tb.Font.PixelHeight);
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool um_open = false;
|
||||||
|
private bool SeperateOffline = true;
|
||||||
|
|
||||||
|
|
||||||
|
private async Task UserConOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
um_open = !um_open;
|
||||||
|
if (um_open)
|
||||||
|
{
|
||||||
|
if (memberflow is null)
|
||||||
|
{
|
||||||
|
int x = 232.ScaleInt();
|
||||||
|
memberflow = new()
|
||||||
|
{
|
||||||
|
BackgroundColor = new(34, 34, 34, 255),
|
||||||
|
Size = new(x, Size.Y - titlecon.Size.Y),
|
||||||
|
Location = new(Size.X - x, titlecon.Size.Y, 0),
|
||||||
|
Anchor = ObjectAnchor.Top | ObjectAnchor.Right | ObjectAnchor.Bottom
|
||||||
|
};
|
||||||
|
memberflow.ForceDistanceUpdate(this);
|
||||||
|
Controls.Add(memberflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memberflow.Controls.Length == 0)
|
||||||
|
{
|
||||||
|
Dictionary<long, RoleView> Roles = new();
|
||||||
|
RoleView? Offline = null;
|
||||||
|
Dictionary<long, RoleView> Users = new();
|
||||||
|
|
||||||
|
foreach (var m in (await Channel!.GetMembers()))
|
||||||
|
{
|
||||||
|
Role top_role = (await m.GetRoles())[0];
|
||||||
|
|
||||||
|
if (m.Status == UserStatus.Offline && SeperateOffline)
|
||||||
|
{
|
||||||
|
if (Offline is null)
|
||||||
|
{
|
||||||
|
Offline = new();
|
||||||
|
memberflow.Controls.Add(Offline);
|
||||||
|
}
|
||||||
|
await Offline.AddUser(m, top_role);
|
||||||
|
Users.Add(m.Id, Offline);
|
||||||
|
memberflow.ReportSizeUpdate(Offline);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!Roles.ContainsKey(top_role.ID))
|
||||||
|
{
|
||||||
|
Roles.Add(top_role.ID, new(top_role));
|
||||||
|
int _index_ = 0;
|
||||||
|
for (int index_ = memberflow.Controls.Length-1; index_ >= 0; index_--)
|
||||||
|
{
|
||||||
|
RoleView r = ((RoleView)memberflow.Controls[index_]);
|
||||||
|
if (r.r is null) continue;
|
||||||
|
if (r.r.Index > top_role.Index)
|
||||||
|
{
|
||||||
|
_index_ = index_ + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memberflow.Controls.Insert(_index_, Roles[top_role.ID]);
|
||||||
|
}
|
||||||
|
await Roles[top_role.ID].AddUser(m, top_role);
|
||||||
|
Users.Add(m.Id, Roles[top_role.ID]);
|
||||||
|
memberflow.ReportSizeUpdate(Roles[top_role.ID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task OnServerOnStatusUpdate(UserStatus status, SocketUser user)
|
||||||
|
{
|
||||||
|
if (!SeperateOffline && !Users.ContainsKey(user.Id)) return;
|
||||||
|
Role top_role2 = (await user.GetRoles())[0];
|
||||||
|
Globals.ms.Invoke(async () =>
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
if (status == UserStatus.Offline && user.Status != UserStatus.Offline)
|
||||||
|
{
|
||||||
|
Offline!.RemoveUser(user.Id);
|
||||||
|
if (Offline.i == 0)
|
||||||
|
{
|
||||||
|
memberflow.Controls.Remove(Offline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Roles.ContainsKey(top_role2.ID))
|
||||||
|
{
|
||||||
|
Roles.Add(top_role2.ID, new(top_role2));
|
||||||
|
int _index_ = 0;
|
||||||
|
for (int index_ = memberflow.Controls.Length - 1; index_ >= 0; index_--)
|
||||||
|
{
|
||||||
|
RoleView r = ((RoleView)memberflow.Controls[index_]);
|
||||||
|
if (r.r is null) continue;
|
||||||
|
if (r.r.Index > top_role2.Index)
|
||||||
|
{
|
||||||
|
_index_ = index_ + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memberflow.Controls.Insert(_index_, Roles[top_role2.ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Roles[top_role2.ID].AddUser(user, top_role2);
|
||||||
|
memberflow.ReportSizeUpdate(Roles[top_role2.ID]);
|
||||||
|
if (Offline is not null) memberflow.ReportSizeUpdate(Offline);
|
||||||
|
Users[user.Id] = Roles[top_role2.ID];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != UserStatus.Offline && user.Status == UserStatus.Offline)
|
||||||
|
{
|
||||||
|
Users[user.Id].RemoveUser(user.Id);
|
||||||
|
bool g = true;
|
||||||
|
if (Users[user.Id].i == 0)
|
||||||
|
{
|
||||||
|
if (Roles.ContainsKey(top_role2.ID)) Roles.Remove(top_role2.ID);
|
||||||
|
g = false;
|
||||||
|
memberflow.Controls.Remove(Users[user.Id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Offline is null)
|
||||||
|
{
|
||||||
|
Offline = new();
|
||||||
|
memberflow.Controls.Add(Offline);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Offline.AddUser(user, top_role2);
|
||||||
|
memberflow.ReportSizeUpdate(Offline);
|
||||||
|
if (g) memberflow.ReportSizeUpdate(Users[user.Id]);
|
||||||
|
Users[user.Id] = Offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel!.Server.StatusUpdate += OnServerOnStatusUpdate;
|
||||||
|
}
|
||||||
|
TryDraw();
|
||||||
|
memberflow.Visible = true;
|
||||||
|
|
||||||
|
MessageFlow.Size = new(MessageFlow.Size.X - memberflow.Size.X, MessageFlow.Size.Y);
|
||||||
|
MessageFlow.ForceDistanceUpdate(this);
|
||||||
|
tb.Size = new(tb.Size.X - memberflow.Size.X, tb.Size.Y);
|
||||||
|
tb.ForceDistanceUpdate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memberflow!.Visible = false;
|
||||||
|
MessageFlow.Size = new(MessageFlow.Size.X + memberflow.Size.X, MessageFlow.Size.Y);
|
||||||
|
MessageFlow.ForceDistanceUpdate(this);
|
||||||
|
tb.Size = new(tb.Size.X + memberflow.Size.X, tb.Size.Y);
|
||||||
|
tb.ForceDistanceUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SocketMessage? lastm;
|
||||||
|
private long? lastUser;
|
||||||
|
private bool fake = false;
|
||||||
|
public ChatMessage? LastChatMessage;
|
||||||
|
|
||||||
|
private SocketMessage? lastmIndex;
|
||||||
|
private long? lastUserIndex;
|
||||||
|
private bool fakeIndex = false;
|
||||||
|
public ChatMessage? LastChatMessageIndex;
|
||||||
|
private bool loadingm = false;
|
||||||
|
|
||||||
|
public async Task LoadChannel(SocketChannel channel)
|
||||||
|
{
|
||||||
|
Channel = channel;
|
||||||
|
BlockDraw = true;
|
||||||
|
Globals.ms.BlockDraw = true;
|
||||||
|
if (memberflow is not null)
|
||||||
|
{
|
||||||
|
await UserConOnClicked(UserCon!);
|
||||||
|
memberflow.Controls.Clear();
|
||||||
|
await UserConOnClicked(UserCon!);
|
||||||
|
}
|
||||||
|
title.Text = channel.Name;
|
||||||
|
var five = 5.ScaleInt();
|
||||||
|
title.Location = new(five + five,
|
||||||
|
(titlecon.Size.Y - ((int)(title.Font.PixelHeight * ((float)title.Font.CurrentFonts[0].Face.Height /
|
||||||
|
title.Font.CurrentFonts[0].Face.UnitsPerEM)))) / 2,
|
||||||
|
title.Location.Z);
|
||||||
|
desc.Text = channel.Description;
|
||||||
|
desc.Location = new((int)(title.Location.X + title.Size.X + five),
|
||||||
|
(titlecon.Size.Y - ((int)(desc.Font.PixelHeight * ((float)desc.Font.CurrentFonts[0].Face.Height /
|
||||||
|
desc.Font.CurrentFonts[0].Face.UnitsPerEM)))) / 2,
|
||||||
|
desc.Location.Z);
|
||||||
|
if (Window is not null)
|
||||||
|
{
|
||||||
|
Window.Title = $"{channel.Name} | {channel.Server.Name} - Luski";
|
||||||
|
}
|
||||||
|
tb.WatermarkText = $"Message {channel.Name}";
|
||||||
|
tb.Text = "";
|
||||||
|
tb.CursorLocation = 0;
|
||||||
|
tb.Focus();
|
||||||
|
Globals.ms.BlockDraw = false;
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearChat()
|
||||||
|
{
|
||||||
|
MessageFlow.Controls.Clear();
|
||||||
|
MessageFlow.ScrollUpdatesInterval = 33;
|
||||||
|
lastm = null;
|
||||||
|
lastUser = null;
|
||||||
|
LastChatMessage = null;
|
||||||
|
first = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMessages(IEnumerable<SocketMessage> messages, bool reverse = true)
|
||||||
|
{
|
||||||
|
MessageFlow.BlockDraw = true;
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
foreach (SocketMessage message in messages.Reverse())
|
||||||
|
{
|
||||||
|
await AddMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (SocketMessage message in messages)
|
||||||
|
{
|
||||||
|
await AddMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageFlow.BlockDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMessagesIndex(IEnumerable<SocketMessage> messages)
|
||||||
|
{
|
||||||
|
MessageFlow.BlockDraw = true;
|
||||||
|
index = 0;
|
||||||
|
foreach (SocketMessage message in messages.Reverse())
|
||||||
|
{
|
||||||
|
await AddMessageIndex(message);
|
||||||
|
}
|
||||||
|
MessageFlow.BlockDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMessage(SocketMessage Message, bool scrool = false)
|
||||||
|
{
|
||||||
|
if (first is null) first = Message;
|
||||||
|
bool hasbeentenmin = false;
|
||||||
|
if (lastm is not null)
|
||||||
|
{
|
||||||
|
DateTime chan = Channel!.Epoch.AddMilliseconds(lastm.ID >> 22).ToLocalTime();
|
||||||
|
hasbeentenmin =
|
||||||
|
Channel!.Epoch.AddMilliseconds(lastm.ID >> 22).ToLocalTime().AddMinutes(10) <
|
||||||
|
Channel!.Epoch.AddMilliseconds(Message.ID >> 22).ToLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
lastm = Message;
|
||||||
|
if (lastUser is null || lastUser != Message.AuthorID || hasbeentenmin || fake != Message.IsProfile)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Window is null || !Globals.ms.InvokeRequired)
|
||||||
|
{
|
||||||
|
MessageFlow.Controls.Add(LastChatMessage = await ChatMessage.MakeChatMessage(this, Message));
|
||||||
|
if (scrool) MessageFlow.ScrollToBottom();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Globals.ms.Invoke(async () =>
|
||||||
|
{
|
||||||
|
LastChatMessage = await ChatMessage.MakeChatMessage(this, Message);
|
||||||
|
MessageFlow.Controls.Add(LastChatMessage);
|
||||||
|
if (scrool) MessageFlow.ScrollToBottom();
|
||||||
|
Window.TryDraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Window is null || !Globals.ms.InvokeRequired)
|
||||||
|
{
|
||||||
|
await LastChatMessage!.AddMessage(Message);
|
||||||
|
if (scrool) MessageFlow.ScrollToBottom();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Globals.ms.Invoke(() =>
|
||||||
|
{
|
||||||
|
LastChatMessage!.AddMessage(Message);
|
||||||
|
if (scrool) MessageFlow.ScrollToBottom();
|
||||||
|
Window!.TryDraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fake = Message.IsProfile;
|
||||||
|
lastUser = Message.AuthorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public async Task AddMessageIndex(SocketMessage Message)
|
||||||
|
{
|
||||||
|
bool hasbeentenmin = false;
|
||||||
|
if (lastmIndex is not null)
|
||||||
|
hasbeentenmin =
|
||||||
|
Channel!.Epoch.AddMilliseconds(lastmIndex.ID >> 22).ToLocalTime().AddMinutes(10) <
|
||||||
|
Channel!.Epoch.AddMilliseconds(Message.ID >> 22).ToLocalTime();
|
||||||
|
lastmIndex = Message;
|
||||||
|
if (lastUserIndex is null || lastUserIndex != Message.AuthorID || hasbeentenmin || fake != Message.IsProfile)
|
||||||
|
{
|
||||||
|
if (Window is null || !Globals.ms.InvokeRequired)
|
||||||
|
{
|
||||||
|
MessageFlow.Controls.Insert(index, LastChatMessageIndex = await ChatMessage.MakeChatMessage(this, Message));
|
||||||
|
LastChatMessageIndex.LoadToParent(MessageFlow, Globals.ms);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastChatMessageIndex = await ChatMessage.MakeChatMessage(this, Message);
|
||||||
|
Globals.ms.Invoke(() =>
|
||||||
|
{
|
||||||
|
MessageFlow.Controls.Insert(index, LastChatMessageIndex);
|
||||||
|
LastChatMessageIndex.LoadToParent(MessageFlow, Globals.ms);
|
||||||
|
index++;
|
||||||
|
Window.TryDraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Window is null || !Globals.ms.InvokeRequired)
|
||||||
|
{
|
||||||
|
await LastChatMessageIndex!.AddMessage(Message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Globals.ms.Invoke(() =>
|
||||||
|
{
|
||||||
|
LastChatMessageIndex!.AddMessage(Message);
|
||||||
|
Window!.TryDraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fakeIndex = Message.IsProfile;
|
||||||
|
lastUserIndex = Message.AuthorID;
|
||||||
|
}
|
||||||
|
}
|
87
Luski/GUI/MainScreen/UI/ServerIcon.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using GraphicsManager;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.net;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class ServerIcon<TServer> : UserControl where TServer : Server
|
||||||
|
{
|
||||||
|
private Rectangle SelectedRect;
|
||||||
|
private static ServerIcon<MainServer>? ser1;
|
||||||
|
private static ServerIcon<PublicServer>? ser2;
|
||||||
|
|
||||||
|
public async Task LoadServer()
|
||||||
|
{
|
||||||
|
if (ser1 is not null)
|
||||||
|
{
|
||||||
|
ser1.SelectedRect.BackgroundColor = new(26, 26, 26, 255);
|
||||||
|
ser1 = null;
|
||||||
|
}
|
||||||
|
if (ser2 is not null)
|
||||||
|
{
|
||||||
|
ser2.SelectedRect.BackgroundColor = new(26, 26, 26, 255);
|
||||||
|
ser2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedRect.BackgroundColor = new(255, 255, 255, 255);
|
||||||
|
Globals.UserTextureMap.Clear();
|
||||||
|
if (typeof(TServer).FullName == typeof(PublicServer).FullName)
|
||||||
|
{
|
||||||
|
ser2 = this as ServerIcon<PublicServer>;
|
||||||
|
await Globals.ms.LoadPublicServer(ser2!.Server);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ser1 = this as ServerIcon<MainServer>;
|
||||||
|
await Globals.ms.LoadMainServer(ser1!.Server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerIcon(TServer Server)
|
||||||
|
{
|
||||||
|
Rectangle r = new(Globals.ms.TextureManager.GetTextureResource("rc.png"))
|
||||||
|
{
|
||||||
|
Location = new(18.ScaleInt(), 8.ScaleInt(), 0),
|
||||||
|
Size = new(32.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaTextureShader[Globals.ms.Context],
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Rectangle rr = new(r.Textures[0])
|
||||||
|
{
|
||||||
|
Location = new(17.ScaleInt(), 7.ScaleInt(), 0),
|
||||||
|
Size = new(34.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = new(26, 26, 26, 255),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
SelectedRect = new(r.Textures[0])
|
||||||
|
{
|
||||||
|
Location = new(14.ScaleInt(), 4.ScaleInt(), 0),
|
||||||
|
Size = new(40.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = new(26, 26, 26, 255),
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
this.Server = Server;
|
||||||
|
Texture t = Globals.ms.TextureManager.AddTexture(Server.GetAvatar(CancellationToken.None).Result);
|
||||||
|
t.Unit = TextureUnit.Texture1;
|
||||||
|
r.Textures.Add(t);
|
||||||
|
Controls.Add(SelectedRect);
|
||||||
|
Controls.Add(rr);
|
||||||
|
Controls.Add(r);
|
||||||
|
base.BackgroundColor = new(26, 26, 26, 255);
|
||||||
|
this.Clicked += OnClicked;
|
||||||
|
base.Size = new(68.ScaleInt(), 48.ScaleInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
await LoadServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TServer Server { get; }
|
||||||
|
}
|
592
Luski/GUI/MainScreen/UI/ServerLoginOverlay.cs
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using Luski.Interfaces;
|
||||||
|
using Luski.net;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using Rectangle = GraphicsManager.Objects.Rectangle;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class ServerLoginOverlay : UserControl, IServerOverlay
|
||||||
|
{
|
||||||
|
private UserControl Form, btn;
|
||||||
|
private DropDown<VersionDropButton> version;
|
||||||
|
|
||||||
|
public AccountButton? Selected { get; set; }
|
||||||
|
public UserControl page { get; set; }
|
||||||
|
private TextBox? UserName, Password, DisplayName, tb;
|
||||||
|
|
||||||
|
private Rectangle? rec;
|
||||||
|
|
||||||
|
public ServerLoginOverlay(string address)
|
||||||
|
{
|
||||||
|
base.Size = Globals.ms.ClientSize;
|
||||||
|
base.BackgroundColor = new(0, 0, 0, 130);
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Form = new(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png"))
|
||||||
|
{
|
||||||
|
Size = new(350.ScaleInt(), 347.ScaleInt()),
|
||||||
|
BackgroundColor = new(32,32,32,255),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
TextureDisplay = TextureDisplay.Center
|
||||||
|
};
|
||||||
|
Label t;
|
||||||
|
Form.Controls.Add(t=new Label(Globals.DefaultFont) { Scale = 1.6f, Text = "Server Login", Color = Globals.DodgerBlue });
|
||||||
|
t.Location = new((Form.Size.X / 2) - (t.Size.X / 2), t.Location.Y, 0);
|
||||||
|
|
||||||
|
#region Server Loc
|
||||||
|
Label? ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = net.API.DefaultVersion,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
Vector2i s =new((int)(ll.Size.X * 1.6f),27.ScaleInt());
|
||||||
|
ll = null;
|
||||||
|
|
||||||
|
Rectangle line = new Rectangle()
|
||||||
|
{
|
||||||
|
Size = new Vector2i(1.ScaleInt()),
|
||||||
|
BackgroundColor = Globals.DodgerBlue
|
||||||
|
};
|
||||||
|
|
||||||
|
tb = new()
|
||||||
|
{
|
||||||
|
Location = new(10.ScaleInt(),50.ScaleInt(), 0),
|
||||||
|
Size = s,
|
||||||
|
Text = address,
|
||||||
|
WatermarkText = "Server Address",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
};
|
||||||
|
tb.Textures[0] = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
tb.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete) && string.IsNullOrWhiteSpace(tb.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
tb.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
(rec is null || rec.Textures.Count > 1) &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
if (Selected!.l.Text != "Login")
|
||||||
|
{
|
||||||
|
if (DisplayName!.Textures[0].handel == good.handel) btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(UserName!.Textures[0].handel != good.handel ||
|
||||||
|
Password!.Textures[0].handel != good.handel ||
|
||||||
|
(rec is not null && rec!.Textures.Count == 1) ||
|
||||||
|
btn!.Textures[0].handel == good.handel ||
|
||||||
|
tb.Textures[0].handel != good.handel ||
|
||||||
|
(DisplayName is not null && DisplayName.Textures[0].handel != good.handel)))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
tb.Size = new(Form.Size.X - tb.Location.X - tb.Location.X - tb.Location.X - s.X, tb.Size.Y);
|
||||||
|
|
||||||
|
Form.Controls.Add(tb);
|
||||||
|
|
||||||
|
version = new DropDown<VersionDropButton>(Form.Textures[0], line)
|
||||||
|
{
|
||||||
|
DropDownParentOverride = Form,
|
||||||
|
Size = s,
|
||||||
|
BackgroundColor = new(255,20,20,255),
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter,
|
||||||
|
Shader = Form.Shader,
|
||||||
|
Location = new(tb.Location.X + tb.Size.X + tb.Location.X, tb.Location.Y, 0)
|
||||||
|
};
|
||||||
|
foreach (string v in Globals.Luski.SupportedVersions)
|
||||||
|
{
|
||||||
|
VersionDropButton option = new VersionDropButton(s, v)
|
||||||
|
{
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Label ll2 = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = v,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true,
|
||||||
|
|
||||||
|
};
|
||||||
|
ll2.Location = new((version.Size.X / 2) - (ll2.Size.X / 2),
|
||||||
|
((version.Size.Y - ll2.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
version.Controls.Add(ll2);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
version.AddOption(option);
|
||||||
|
if (v == net.API.DefaultVersion)
|
||||||
|
{
|
||||||
|
version.SetSelected(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version.OpenStatusChanged += VersionOnOpenStatusChanged;
|
||||||
|
version.OptionSelected += VersionOnOptionSelected;
|
||||||
|
|
||||||
|
|
||||||
|
version.DropDownContainer.Textures.Add(Globals.ms.TextureManager.GetTextureResource("RoundedRectangleBottom.png"));
|
||||||
|
version.DropDownContainer.TextureDisplay = TextureDisplay.Center;
|
||||||
|
version.DropDownContainer.Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
version.DropDownContainer.BackgroundColor = version.BackgroundColor;
|
||||||
|
version.OpenStatusChanged += b =>
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
version.Textures[0] = Globals.ms.TextureManager.GetTextureResource("RoundedRectangleTop.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version.Textures[0] = Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Buttons
|
||||||
|
|
||||||
|
AccountButton ca = new AccountButton("Create Account", this)
|
||||||
|
{
|
||||||
|
Location = new(tb.Location.X, tb.Location.Y + tb.Location.X + tb.Size.Y, 0),
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
btn.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
page!.Controls.Add(UserName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, 10.ScaleInt(), 0),
|
||||||
|
Size = new(page.Size.X, 30.ScaleInt()),
|
||||||
|
WatermarkText = "Username",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
UserName.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
UserName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
DisplayName!.Textures[0].handel == good.handel &&
|
||||||
|
rec!.Textures.Count > 1 &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(Password!.Textures[0].handel != good.handel ||
|
||||||
|
DisplayName!.Textures[0].handel != good.handel ||
|
||||||
|
rec!.Textures.Count == 1 ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(Password = new()
|
||||||
|
{
|
||||||
|
Location = new(0, UserName.Location.Y + UserName.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X, UserName.Size.Y),
|
||||||
|
WatermarkText = "Password",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false,
|
||||||
|
PasswordChar = '●'
|
||||||
|
});
|
||||||
|
Password.Textures[0] = UserName.Textures[0];
|
||||||
|
Password.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(Password.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Password.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
Password.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel && UserName!.Textures[0].handel == good.handel && DisplayName!.Textures[0].handel == good.handel && rec!.Textures.Count > 1 && btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel && (UserName!.Textures[0].handel != good.handel || DisplayName!.Textures[0].handel != good.handel || rec!.Textures.Count == 1 || btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(rec = new(Globals.ms.TextureManager.GetAlphaCircle())
|
||||||
|
{
|
||||||
|
Size = new(50.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Red,
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
IgnoreHover = false
|
||||||
|
});
|
||||||
|
rec.Location = new(page.Size.X - rec.Size.X, page.Size.Y - rec.Size.Y, 0);
|
||||||
|
|
||||||
|
page.Controls.Add(DisplayName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, Password.Location.Y + Password.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X- tb.Location.X - rec.Size.X, Password.Size.Y ),
|
||||||
|
WatermarkText = "Display Name",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
DisplayName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) &&
|
||||||
|
string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DisplayName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
DisplayName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel && UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel && rec!.Textures.Count > 1 &&
|
||||||
|
btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel && (UserName!.Textures[0].handel != good.handel ||
|
||||||
|
Password!.Textures[0].handel != good.handel ||
|
||||||
|
rec!.Textures.Count == 1 ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
rec.FilesDroped += RecOnFilesDroped;
|
||||||
|
DisplayName.Textures[0] = UserName.Textures[0];
|
||||||
|
rec.ForceDistanceUpdate(page);
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
Globals.ms.ForceUpdate(new(Size));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ca.Size = new((Form.Size.X - tb.Location.X - tb.Location.X - (tb.Location.X / 2)) / 2, ca.Size.Y);
|
||||||
|
ca.l.Location = new((ca.Size.X - ca.l.Size.X) / 2,
|
||||||
|
((ca.Size.Y - ca.l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
ca.l.ForceDistanceUpdate(ca);
|
||||||
|
Form.Controls.Add(ca);
|
||||||
|
|
||||||
|
AccountButton lo = new AccountButton("Login", this)
|
||||||
|
{
|
||||||
|
Location = new(ca.Location.X + ca.Size.X + (tb.Location.X / 2),ca.Location.Y, 0),
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
page!.Controls.Add(UserName = new()
|
||||||
|
{
|
||||||
|
Location = new(0, 22.ScaleInt(), 0),
|
||||||
|
Size = new(page.Size.X, 31.ScaleInt()),
|
||||||
|
WatermarkText = "Username",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
UserName.Textures[0] = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) && string.IsNullOrWhiteSpace(UserName.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserName.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
UserName.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(Password!.Textures[0].handel != good.handel ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
page.Controls.Add(Password = new()
|
||||||
|
{
|
||||||
|
Location = new(0, UserName.Location.Y + UserName.Size.Y + UserName.Location.Y + UserName.Location.Y, 0),
|
||||||
|
Size = new(page.Size.X, UserName.Size.Y),
|
||||||
|
WatermarkText = "Password",
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false,
|
||||||
|
PasswordChar = '●'
|
||||||
|
});
|
||||||
|
Password.Textures[0] = UserName.Textures[0];
|
||||||
|
Password.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Texture t;
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if ((args.Key == Keys.Backspace || args.Key == Keys.Delete || args.Alt || args.Shift || args.Control || args.Key == Keys.Enter || args.Key == Keys.KeyPadEnter || args.Key== Keys.Space) &&
|
||||||
|
string.IsNullOrWhiteSpace(Password.Text))
|
||||||
|
{
|
||||||
|
t = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = good;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Password.Textures[0].handel != t.handel)
|
||||||
|
{
|
||||||
|
Password.Textures[0] = t;
|
||||||
|
if (t.handel == good.handel &&
|
||||||
|
UserName!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel &&
|
||||||
|
tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else if (t.handel != good.handel &&
|
||||||
|
(UserName!.Textures[0].handel != good.handel ||
|
||||||
|
btn!.Textures[0].handel == good.handel || tb.Textures[0].handel != good.handel))
|
||||||
|
{
|
||||||
|
btn!.Textures[0] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
DisplayName = null!;
|
||||||
|
rec = null!;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lo.Size = ca.Size;
|
||||||
|
lo.l.Location = new((lo.Size.X / 2) - (lo.l.Size.X / 2),
|
||||||
|
((lo.Size.Y - lo.l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
lo.l.ForceDistanceUpdate(lo);
|
||||||
|
Form.Controls.Add(lo);
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Form.Controls.Add(version);
|
||||||
|
|
||||||
|
page = new()
|
||||||
|
{
|
||||||
|
Location = new(tb.Location.X, ca.Location.Y + ca.Size.Y + tb.Location.X, 0),
|
||||||
|
BackgroundColor = Form.BackgroundColor
|
||||||
|
};
|
||||||
|
page.Size = new(Form.Size.X - tb.Location.X - tb.Location.X, Form.Size.Y - tb.Location.X - page.Location.Y - ca.Size.Y - tb.Location.X);
|
||||||
|
Form.Controls.Add(page);
|
||||||
|
|
||||||
|
btn = new(Globals.ms.TextureManager.GetTextureResource("BadTextbox.png"))
|
||||||
|
{
|
||||||
|
Location = new(page.Location.X, page.Location.Y + page.Size.Y + tb.Location.X, 0),
|
||||||
|
Size = new(page.Size.X, ca.Size.Y),
|
||||||
|
TextureDisplay = TextureDisplay.Center
|
||||||
|
};
|
||||||
|
_ = lo.ToggleSelected();
|
||||||
|
Label sub = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "Submit",
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
sub.Location = new((btn.Size.X / 2) - (sub.Size.X / 2),
|
||||||
|
((btn.Size.Y - sub.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
sub.ForceDistanceUpdate(btn);
|
||||||
|
btn.Controls.Add(sub);
|
||||||
|
Form.Controls.Add(btn);
|
||||||
|
Form.Location = new((base.Size.X - Form.Size.X) / 2, (base.Size.Y - Form.Size.Y) / 2, 0);
|
||||||
|
Controls.Add(Form);
|
||||||
|
btn.Clicked += BtnOnClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task BtnOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (btn.Textures[0].handel == Globals.ms.TextureManager.GetTextureResource("BadTextbox.png").handel)
|
||||||
|
return;
|
||||||
|
bool s = true;
|
||||||
|
string d = tb!.Text;
|
||||||
|
if (d.Contains("://"))
|
||||||
|
{
|
||||||
|
string[] a = d.Split("://");
|
||||||
|
d = a[1];
|
||||||
|
if (a[0] == "http") s = false;
|
||||||
|
}
|
||||||
|
ServerInfo si = new()
|
||||||
|
{
|
||||||
|
Domain = d,
|
||||||
|
Version = version.SelectedOption.l.Text,
|
||||||
|
Main = false,
|
||||||
|
Secure = s
|
||||||
|
};
|
||||||
|
IEnumerable<PublicServer> sers = Globals.Luski.LoadedServers.Where(s => s.Domain == tb.Text);
|
||||||
|
if (sers.Any())
|
||||||
|
{
|
||||||
|
bool g;
|
||||||
|
PublicServer ps = sers.First();
|
||||||
|
if (DisplayName is null)
|
||||||
|
{
|
||||||
|
g = await ps.Login(UserName!.Text, Password!.Text, CancellationToken.None);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g = await ps.CreateAccount(UserName!.Text, Password!.Text, DisplayName.Text, pfp,
|
||||||
|
CancellationToken.None);
|
||||||
|
}
|
||||||
|
if (!g)
|
||||||
|
{
|
||||||
|
Texture b = Globals.ms.TextureManager.GetTextureResource("BadTextbox.png");
|
||||||
|
UserName!.Textures[0] = b;
|
||||||
|
Password!.Textures[0] = b;
|
||||||
|
btn.Textures[0] = b;
|
||||||
|
_ = Globals.ms.LoadPublicServer(ps);
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.ms.Controls.Remove(this);
|
||||||
|
Globals.ms.ForceUpdate(new(Size));
|
||||||
|
Globals.ms.TryDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task VersionOnOptionSelected(VersionDropButton arg)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task VersionOnOpenStatusChanged(bool arg)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string pfp = "";
|
||||||
|
|
||||||
|
private Task RecOnFilesDroped(string[] arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg[0]);
|
||||||
|
if (!arg[0].ToLower().EndsWith("png")) return Task.CompletedTask;
|
||||||
|
|
||||||
|
pfp = arg[0];
|
||||||
|
if (rec!.Textures.Count() ==1 )
|
||||||
|
{
|
||||||
|
Texture good = Globals.ms.TextureManager.GetTextureResource("Textbox.png");
|
||||||
|
if (UserName!.Textures[0].handel == good.handel &&
|
||||||
|
Password!.Textures[0].handel == good.handel &&
|
||||||
|
btn!.Textures[0].handel != good.handel && tb.Textures[0].handel == good.handel)
|
||||||
|
{
|
||||||
|
if (DisplayName is not null)
|
||||||
|
{
|
||||||
|
if (Password!.Textures[0].handel == good.handel) btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
else btn.Textures[0] = good;
|
||||||
|
}
|
||||||
|
Texture tex = Globals.ms.TextureManager.AddTexture(File.OpenRead(arg[0]));
|
||||||
|
tex.Unit = TextureUnit.Texture1;
|
||||||
|
rec.Shader = Rectangle.DefaultAlphaTextureShader[Globals.ms.Context];
|
||||||
|
rec.Textures.Add(tex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rec.Textures[1] = Globals.ms.TextureManager.AddTexture(File.OpenRead(arg[0]));
|
||||||
|
rec.Textures[1].Unit = TextureUnit.Texture1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window!.TryDraw();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
452
Luski/GUI/MainScreen/UI/SettingsMenu.cs
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
public class SettingsMenu : UserControl
|
||||||
|
{
|
||||||
|
private string BehindName;
|
||||||
|
public FlowLayout page;
|
||||||
|
public CategoryButton? Selected, apper;
|
||||||
|
private FlowLayout fl;
|
||||||
|
private Category? AppSettings;
|
||||||
|
private FontInteraction f;
|
||||||
|
private DropDown<ThemeDropButton> ThemeDrop;
|
||||||
|
public SettingsMenu()
|
||||||
|
{
|
||||||
|
LuskiExperiments.Settings.Theme.EventToggled += ThemeOnEventToggled;
|
||||||
|
BehindName = Globals.ms.Title;
|
||||||
|
Globals.ms.Title = "Settings - Luski";
|
||||||
|
base.BackgroundColor = new(34, 34, 34, 255);
|
||||||
|
base.Size = Globals.ms.ClientSize;
|
||||||
|
Anchor = ObjectAnchor.All;
|
||||||
|
if (CategoryButton.seltec is null)
|
||||||
|
{
|
||||||
|
CategoryButton.seltec = Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png");
|
||||||
|
}
|
||||||
|
fl = new()
|
||||||
|
{
|
||||||
|
BackgroundColor = new(20, 20, 20, 255),
|
||||||
|
Size = new(307.ScaleInt(), base.Size.Y),
|
||||||
|
Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom
|
||||||
|
};
|
||||||
|
f = Globals.DefaultFont.Clone();
|
||||||
|
f.FontSize = FontSize.Bold;
|
||||||
|
f.PixelHeight = (uint)(f.PixelHeight * 1.4f);
|
||||||
|
AppSettings = new("APP SETTINGS");
|
||||||
|
CategoryButton cb3 = new("General", this)
|
||||||
|
{
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
page!.Controls.Add(new Label(f)
|
||||||
|
{
|
||||||
|
Text = " \nGeneral\n "
|
||||||
|
});
|
||||||
|
foreach (PropertyInfo prop in typeof(Settings).GetProperties())
|
||||||
|
{
|
||||||
|
object PropVal = prop.GetValue(Globals.Settings)!;
|
||||||
|
Type PropType = prop.PropertyType;
|
||||||
|
if (PropType.IsEnum)
|
||||||
|
{
|
||||||
|
IEnumerable<Enum> values = Enum.GetValues(PropType).Cast<Enum>();
|
||||||
|
foreach (var val in values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MemberInfo[] memberInfos =
|
||||||
|
PropType.GetMember(val.ToString());
|
||||||
|
MemberInfo? enumValueMemberInfo = memberInfos.FirstOrDefault(m =>
|
||||||
|
m.DeclaringType == PropType);
|
||||||
|
object[] valueAttributes =
|
||||||
|
enumValueMemberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
if (valueAttributes.Length == 0) continue;
|
||||||
|
string description = ((DescriptionAttribute)valueAttributes[0]).Description;
|
||||||
|
|
||||||
|
AddBool(description, ((Enum)PropVal).HasFlag(val), bb =>
|
||||||
|
{
|
||||||
|
long va = Convert.ToInt64(val);
|
||||||
|
long v = Convert.ToInt64(PropVal);
|
||||||
|
if (bb)
|
||||||
|
{
|
||||||
|
object e = Enum.Parse(PropType, (v + va).ToString());
|
||||||
|
PropVal = e;
|
||||||
|
prop.SetValue(Globals.Settings, e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var e = Enum.Parse(PropType, (v - va).ToString());
|
||||||
|
PropVal = e;
|
||||||
|
prop.SetValue(Globals.Settings, e);
|
||||||
|
}
|
||||||
|
Globals.Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PropType.FullName == typeof(bool).FullName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
object[] valueAttributes =
|
||||||
|
prop.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
string description = ((DescriptionAttribute)valueAttributes[0]).Description;
|
||||||
|
AddBool(description, (bool)PropVal, b =>
|
||||||
|
{
|
||||||
|
prop.SetValue(Globals.Settings, b);
|
||||||
|
Globals.Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AppSettings.AddButton(cb3);
|
||||||
|
|
||||||
|
fl.Controls.Add(AppSettings);
|
||||||
|
|
||||||
|
if (LuskiExperiments.Settings.Theme.IsEnabled())
|
||||||
|
{
|
||||||
|
Label Top = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Location = new(5.ScaleInt(), 5.ScaleInt(), 0),
|
||||||
|
Text = LuskiThemes.Dark.Name
|
||||||
|
};
|
||||||
|
CategoryButton cb2 = new("Appearance", this)
|
||||||
|
{
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
page!.Controls.Add(new Label(f)
|
||||||
|
{
|
||||||
|
Text = " \nAppearance\n "
|
||||||
|
});
|
||||||
|
ThemeDropButton LightDD;
|
||||||
|
ThemeDrop = new(CategoryButton.seltec!,new Rectangle()
|
||||||
|
{
|
||||||
|
Size = new(base.Size.X - 2, 1.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Location = new(1, base.Size.Y - 1.ScaleInt(), 0),
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Right | ObjectAnchor.Bottom
|
||||||
|
}, LightDD = new(LuskiThemes.Light)
|
||||||
|
{
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
Label ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = LuskiThemes.Light.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
ll.Location = new(10.ScaleInt(),
|
||||||
|
((ThemeDrop.Size.Y - ll.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
ThemeDrop.Controls.Add(ll);
|
||||||
|
},
|
||||||
|
Size = new(297.ScaleInt(), 40.ScaleInt()),
|
||||||
|
}){DropDownParentOverride = Globals.ms,Size = new(40.ScaleInt()),
|
||||||
|
Location = new(Top.Location.X, Top.Location.Y, 0),
|
||||||
|
BackgroundColor = new(40, 40, 40, 255),
|
||||||
|
Anchor = ObjectAnchor.Right | ObjectAnchor.Left,};
|
||||||
|
foreach (ThemeStart themeStart in LuskiThemes.LuskiThemeList)
|
||||||
|
{
|
||||||
|
if (themeStart.Name == LuskiThemes.Light.Name) continue;
|
||||||
|
ThemeDropButton tdb;
|
||||||
|
ThemeDrop.AddOption(tdb = new(themeStart)
|
||||||
|
{
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
Label ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = themeStart.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
ll.Location = new(10.ScaleInt(),
|
||||||
|
((ThemeDrop.Size.Y - ll.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
ThemeDrop.Controls.Add(ll);
|
||||||
|
},
|
||||||
|
Size = new(297.ScaleInt(), 40.ScaleInt()),
|
||||||
|
});
|
||||||
|
if (themeStart.Name == Globals.Settings.Theme) ThemeDrop.SetSelected(tdb);
|
||||||
|
}
|
||||||
|
ThemeDrop.DropDownContainer.Textures.Add(Globals.ms.TextureManager.GetTextureResource("RoundedRectangleBottom.png"));
|
||||||
|
ThemeDrop.DropDownContainer.TextureDisplay = TextureDisplay.Center;
|
||||||
|
ThemeDrop.DropDownContainer.Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
ThemeDrop.DropDownContainer.BackgroundColor = ThemeDrop.BackgroundColor;
|
||||||
|
Rectangle line = new()
|
||||||
|
{
|
||||||
|
Size = new(base.Size.X - 2, 1.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Location = new(1, base.Size.Y - 1.ScaleInt(), 0),
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Right | ObjectAnchor.Bottom
|
||||||
|
};
|
||||||
|
ThemeDrop.OpenStatusChanged += b =>
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
Size = new(base.Size.X, base.Size.Y + ( b ? ThemeDrop.DropDownContainer.Size.Y : -1 * ThemeDrop.DropDownContainer.Size.Y));
|
||||||
|
line!.Location = new(line.Location.X,
|
||||||
|
line.Location.Y + (b ? ThemeDrop.DropDownContainer.Size.Y : -1 * ThemeDrop.DropDownContainer.Size.Y), 0);
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
ThemeDrop.Textures[0] = Globals.ms.TextureManager.GetTextureResource("RoundedRectangleTop.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThemeDrop.Textures[0] = CategoryButton.seltec!;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
page!.Controls.Add(ThemeDrop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AppSettings.AddButton(cb2);
|
||||||
|
fl.Controls.Insert(0, AppSettings);
|
||||||
|
fl.ScrollToBottom();
|
||||||
|
}
|
||||||
|
page = new()
|
||||||
|
{
|
||||||
|
BackgroundColor = this.BackgroundColor,
|
||||||
|
Location = new(fl.Size.X + 40.ScaleInt(), 0, 0),
|
||||||
|
Size = new(Globals.ms.ClientSize.X - fl.Size.X - 80.ScaleInt(), Globals.ms.Size.Y),
|
||||||
|
AllowHoverFromBehind = true,
|
||||||
|
Anchor = ObjectAnchor.All,
|
||||||
|
HScrollPixels = Globals.Settings.PerScrollPixels
|
||||||
|
};
|
||||||
|
Controls.Add(page);
|
||||||
|
void AddBool(string Name, bool s, Action<bool> a)
|
||||||
|
{
|
||||||
|
ToggleSwitch ts = new()
|
||||||
|
{
|
||||||
|
Value = s
|
||||||
|
};
|
||||||
|
UserControl tc = new()
|
||||||
|
{
|
||||||
|
Size = ts.Size,
|
||||||
|
BackgroundColor = page.BackgroundColor
|
||||||
|
};
|
||||||
|
Label l;
|
||||||
|
tc.Controls.Add(l =new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = Name + ": "
|
||||||
|
});
|
||||||
|
tc.Size = l.Size;
|
||||||
|
tc.Controls.Add(ts);
|
||||||
|
ts.Location = new(l.Size.X + 10.ScaleInt(), 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
ts.ValueChanged += @switch =>
|
||||||
|
{
|
||||||
|
a.Invoke(@switch .Value);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
page.Controls.Add(tc);
|
||||||
|
}
|
||||||
|
page.ForceDistanceUpdate(this);
|
||||||
|
Category As = new("ADVANCED SETTINGS");
|
||||||
|
CategoryButton cb = new("Experiments", this)
|
||||||
|
{
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
page!.Controls.Add(new Label(f)
|
||||||
|
{
|
||||||
|
Text = " \nExperiments\n "
|
||||||
|
});
|
||||||
|
ExperimentGUI? g = null;
|
||||||
|
foreach (ExperimentInfo exp in Globals.Experiments)
|
||||||
|
{
|
||||||
|
g = new(exp);
|
||||||
|
page.Controls.Add(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g is not null)
|
||||||
|
{
|
||||||
|
g.line.WindowLoaded += _ =>
|
||||||
|
{
|
||||||
|
page.ParentResize(new(Globals.ms.ClientSize));
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CategoryButton us = new("Updater Config", this)
|
||||||
|
{
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
page!.Controls.Add(new Label(f)
|
||||||
|
{
|
||||||
|
Text = " \nUpdater Config\n "
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TextBox t;
|
||||||
|
page!.Controls.Add(t =new TextBox()
|
||||||
|
{
|
||||||
|
Text = Globals.UpdaterSettings.Updater!,
|
||||||
|
WatermarkText = "Updater File",
|
||||||
|
TextureDisplay = TextureDisplay.Center,
|
||||||
|
Size = new(page.Size.X, 34.ScaleInt()),
|
||||||
|
TextLocation = TextLocation.LineCenter,
|
||||||
|
AllowMultiLine = false
|
||||||
|
});
|
||||||
|
foreach (PropertyInfo prop in typeof(UpdaterSettings).GetProperties())
|
||||||
|
{
|
||||||
|
object PropVal = prop.GetValue(Globals.UpdaterSettings)!;
|
||||||
|
Type PropType = prop.PropertyType;
|
||||||
|
if (PropType.IsEnum)
|
||||||
|
{
|
||||||
|
IEnumerable<Enum> values = Enum.GetValues(PropType).Cast<Enum>();
|
||||||
|
foreach (var val in values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MemberInfo[] memberInfos =
|
||||||
|
PropType.GetMember(val.ToString());
|
||||||
|
MemberInfo? enumValueMemberInfo = memberInfos.FirstOrDefault(m =>
|
||||||
|
m.DeclaringType == PropType);
|
||||||
|
object[] valueAttributes =
|
||||||
|
enumValueMemberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
if (valueAttributes.Length == 0) continue;
|
||||||
|
string description = ((DescriptionAttribute)valueAttributes[0]).Description;
|
||||||
|
|
||||||
|
AddBool(description, ((Enum)PropVal).HasFlag(val), bb =>
|
||||||
|
{
|
||||||
|
long va = Convert.ToInt64(val);
|
||||||
|
long v = Convert.ToInt64(PropVal);
|
||||||
|
if (bb)
|
||||||
|
{
|
||||||
|
object e = Enum.Parse(PropType, (v + va).ToString());
|
||||||
|
PropVal = e;
|
||||||
|
prop.SetValue(Globals.Settings, e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var e = Enum.Parse(PropType, (v - va).ToString());
|
||||||
|
PropVal = e;
|
||||||
|
prop.SetValue(Globals.Settings, e);
|
||||||
|
}
|
||||||
|
Globals.UpdaterSettings.SaveSettings(Path.Combine(Globals.LuskiPath, "UpdaterSettings.json"), UpdaterSettingsContext.Default.UpdaterSettings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PropType.FullName == typeof(bool).FullName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
object[] valueAttributes =
|
||||||
|
prop.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
string description = ((DescriptionAttribute)valueAttributes[0]).Description;
|
||||||
|
AddBool(description, (bool)PropVal, b =>
|
||||||
|
{
|
||||||
|
prop.SetValue(Globals.Settings, b);
|
||||||
|
Globals.UpdaterSettings.SaveSettings(Path.Combine(Globals.LuskiPath, "UpdaterSettings.json"), UpdaterSettingsContext.Default.UpdaterSettings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ForceDistanceUpdate(page);
|
||||||
|
t.KeyPress += args =>
|
||||||
|
{
|
||||||
|
Globals.UpdaterSettings.Updater = t.Text;
|
||||||
|
Globals.UpdaterSettings.SaveSettings(Path.Combine(Globals.LuskiPath, "UpdaterSettings.json"), UpdaterSettingsContext.Default.UpdaterSettings);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
Globals.ms.ForceUpdate(new(Globals.ms.ClientSize));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
As.AddButton(cb);
|
||||||
|
As.AddButton(us);
|
||||||
|
fl.Controls.Add(As);
|
||||||
|
|
||||||
|
|
||||||
|
fl.ForceDistanceUpdate(this);
|
||||||
|
_ = cb3.ToggleSelected();
|
||||||
|
|
||||||
|
Rectangle closebtn = new(Globals.ms.TextureManager.GetTextureResource("close.png"))
|
||||||
|
{
|
||||||
|
Location = new(Globals.ms.ClientSize.X - 40.ScaleInt(), 8.ScaleInt(),0),
|
||||||
|
Size = new(32.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context],
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Anchor = ObjectAnchor.Top | ObjectAnchor.Right
|
||||||
|
};
|
||||||
|
closebtn.MouseEnter += _ =>
|
||||||
|
{
|
||||||
|
closebtn.BackgroundColor = Color4.White;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
closebtn.MouseLeave += _ =>
|
||||||
|
{
|
||||||
|
closebtn.BackgroundColor = Color4.Gray;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
closebtn.Clicked += ClosebtnOnClicked;
|
||||||
|
closebtn.ForceDistanceUpdate(this);
|
||||||
|
Controls.Add(closebtn);
|
||||||
|
Controls.Add(fl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ThemeOnEventToggled(bool arg)
|
||||||
|
{
|
||||||
|
if (arg)
|
||||||
|
{
|
||||||
|
apper = new("Appearance", this)
|
||||||
|
{
|
||||||
|
OnPageLoad = () =>
|
||||||
|
{
|
||||||
|
page.Controls.Add(new Label(f)
|
||||||
|
{
|
||||||
|
Text = " \nAppearance\n "
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AppSettings!.AddButton(apper);
|
||||||
|
fl.ScrollToBottom();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppSettings!.RemoveButton(apper);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ClosebtnOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
Globals.ms.Controls.Remove(this);
|
||||||
|
Globals.ms.Title = BehindName;
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
65
Luski/GUI/MainScreen/UI/SettingsPanel/Category.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
|
||||||
|
public class Category : UserControl
|
||||||
|
{
|
||||||
|
private Label Top;
|
||||||
|
private static FontInteraction? fi;
|
||||||
|
private Rectangle line;
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => Top.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category(string Name)
|
||||||
|
{
|
||||||
|
if (fi is null)
|
||||||
|
{
|
||||||
|
fi = Globals.DefaultFont.Clone();
|
||||||
|
fi.FontSize = FontSize.Bold;
|
||||||
|
}
|
||||||
|
Top = new(fi)
|
||||||
|
{
|
||||||
|
Location = new(5.ScaleInt(), 5.ScaleInt(), 0),
|
||||||
|
Text = Name
|
||||||
|
};
|
||||||
|
BackgroundColor = new(255, 255, 255, 0);
|
||||||
|
base.Size = new(307.ScaleInt(), 20.ScaleInt() + Top.Size.Y);
|
||||||
|
Top.Location = new((base.Size.X - Top.Size.X) / 2, Top.Location.Y, 0);
|
||||||
|
line = new()
|
||||||
|
{
|
||||||
|
Size = new(base.Size.X, 1.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Location = new(0, base.Size.Y - 1.ScaleInt(), 0)
|
||||||
|
};
|
||||||
|
line.ForceDistanceUpdate(this);
|
||||||
|
Controls.Add(line);
|
||||||
|
Controls.Add(Top);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddButton(CategoryButton cb)
|
||||||
|
{
|
||||||
|
Controls.Add(cb);
|
||||||
|
int f = 5.ScaleInt();
|
||||||
|
cb.Location = new (line.Location.X + f, line.Location.Y - f, 0);
|
||||||
|
line.Location = new(line.Location.X, line.Location.Y + cb.Size.Y + f, 0);
|
||||||
|
Size = new(Size.X, Size.Y + cb.Size.Y + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveButton(CategoryButton cb)
|
||||||
|
{
|
||||||
|
int f = 5.ScaleInt();
|
||||||
|
line.Location = new(line.Location.X, line.Location.Y - cb.Size.Y - f, 0);
|
||||||
|
Controls.Remove(cb);
|
||||||
|
Size = new(Size.X, Size.Y - cb.Size.Y + f);
|
||||||
|
for (int i = 0; i < Controls.Length; i++)
|
||||||
|
{
|
||||||
|
ReportSizeUpdate(Controls[i]);
|
||||||
|
}
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
}
|
96
Luski/GUI/MainScreen/UI/SettingsPanel/CategoryButton.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
|
||||||
|
public class CategoryButton : UserControl
|
||||||
|
{
|
||||||
|
public static Texture? seltec = null;
|
||||||
|
private SettingsMenu SM;
|
||||||
|
private Label l;
|
||||||
|
public required Action OnPageLoad;
|
||||||
|
|
||||||
|
public CategoryButton(string Text, SettingsMenu SM)
|
||||||
|
:base(seltec)
|
||||||
|
{
|
||||||
|
this.SM = SM;
|
||||||
|
base.Size = new(297.ScaleInt(), 40.ScaleInt());
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
l = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = Text,
|
||||||
|
Color = Color4.Gray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
l.Location = new(5.ScaleInt(),
|
||||||
|
((base.Size.Y - l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
Controls.Add(l);
|
||||||
|
BackgroundColor = new(0, 0, 0, 0);
|
||||||
|
Clicked += OnClicked;
|
||||||
|
MouseEnter += o =>
|
||||||
|
{
|
||||||
|
if (!Selected)
|
||||||
|
{
|
||||||
|
BackgroundColor = new(141, 151, 165, 30);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
MouseLeave += o =>
|
||||||
|
{
|
||||||
|
if (!Selected)
|
||||||
|
{
|
||||||
|
BackgroundColor = new(0,0,0,0);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
if (!Selected) await ToggleSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Selected { get; private set; }
|
||||||
|
|
||||||
|
public async Task ToggleSelected()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Color4 bc = new(141,151,165,51), f= Color4.White;
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
bc = new (0,0,0,0);
|
||||||
|
f = Color4.Gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = true;
|
||||||
|
Selected = !Selected;
|
||||||
|
|
||||||
|
if (SM.Selected is not null && SM.Selected != this)
|
||||||
|
{
|
||||||
|
await SM.Selected.ToggleSelected();
|
||||||
|
}
|
||||||
|
BackgroundColor = bc;
|
||||||
|
l.Color = f;
|
||||||
|
if (Selected)
|
||||||
|
{
|
||||||
|
SM.Selected = this;
|
||||||
|
Globals.ms.Title = $"Settings | {l.Text} - Luski";
|
||||||
|
SM.page.Controls.Clear();
|
||||||
|
OnPageLoad.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
TryDraw();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
|
||||||
|
public class ExperimentDropButton : DropDownOption
|
||||||
|
{
|
||||||
|
private Label l, d;
|
||||||
|
public ExperimentSelectorInfo ESI;
|
||||||
|
|
||||||
|
public ExperimentDropButton(ExperimentSelectorInfo esi)
|
||||||
|
:base(CategoryButton.seltec!)
|
||||||
|
{
|
||||||
|
ESI = esi;
|
||||||
|
base.Size = new(297.ScaleInt(), 40.ScaleInt());
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
l = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = esi.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
l.Location = new(10.ScaleInt(),
|
||||||
|
((base.Size.Y - l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
d = new(Globals.MessageFont)
|
||||||
|
{
|
||||||
|
Text = esi.Description,
|
||||||
|
Color = Color4.Gray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
d.Location = new(l.Location.X + l.Size.X + l.Location.X,
|
||||||
|
l.Location.Y + (int)l.Font.PixelHeight - (int)d.Font.PixelHeight
|
||||||
|
, 0);
|
||||||
|
Controls.Add(d);
|
||||||
|
Controls.Add(l);
|
||||||
|
BackgroundColor = new(0, 0, 0, 0);
|
||||||
|
MouseEnter += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(141, 151, 165, 30);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
MouseLeave += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(0,0,0,0);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
163
Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentGUI.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
|
||||||
|
public class ExperimentGUI : UserControl
|
||||||
|
{
|
||||||
|
private Label Top;
|
||||||
|
public Rectangle line;
|
||||||
|
public DropDown<ExperimentDropButton> dd;
|
||||||
|
private static Texture? TopOpen, BottomOpen;
|
||||||
|
private ExperimentSelectorInfo? currentEnabled;
|
||||||
|
|
||||||
|
private static ExperimentSelectorInfo DisabledESI = new()
|
||||||
|
{
|
||||||
|
Name = "Disabled"
|
||||||
|
};
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => Top.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExperimentGUI(ExperimentInfo ei)
|
||||||
|
{
|
||||||
|
TextureDisplay = TextureDisplay.Center;
|
||||||
|
if (TopOpen is null)
|
||||||
|
{
|
||||||
|
TopOpen = Globals.ms.TextureManager.GetTextureResource("RoundedRectangleTop.png");
|
||||||
|
}
|
||||||
|
if (BottomOpen is null)
|
||||||
|
{
|
||||||
|
BottomOpen = Globals.ms.TextureManager.GetTextureResource("RoundedRectangleBottom.png");
|
||||||
|
}
|
||||||
|
Top = new(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Location = new(5.ScaleInt(), 5.ScaleInt(), 0),
|
||||||
|
Text = ei.DisplayName
|
||||||
|
};
|
||||||
|
Label n = new(Globals.MessageFont)
|
||||||
|
{
|
||||||
|
Text = ei.Name,
|
||||||
|
Location = new(Top.Location.X, Top.Location.Y + Top.Size.Y + Top.Location.Y, 0),
|
||||||
|
Color = Color4.Gray
|
||||||
|
};
|
||||||
|
Controls.Add(n);
|
||||||
|
BackgroundColor = new(255, 255, 255, 0);
|
||||||
|
ExperimentDropButton Disabled = new(DisabledESI)
|
||||||
|
{
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
Label ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = DisabledESI.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
ll.Location = new(10.ScaleInt(),
|
||||||
|
((dd!.Size.Y - ll.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
dd.Controls.Add(ll);
|
||||||
|
},
|
||||||
|
Size = new(297.ScaleInt(), 40.ScaleInt())
|
||||||
|
};
|
||||||
|
dd = new(CategoryButton.seltec!, new Rectangle()
|
||||||
|
{
|
||||||
|
Size = new(1.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Gray
|
||||||
|
}, Disabled)
|
||||||
|
{
|
||||||
|
Size = new(40.ScaleInt()),
|
||||||
|
Location = new(Top.Location.X, n.Location.Y + n.Size.Y + Top.Location.Y, 0),
|
||||||
|
BackgroundColor = new(40, 40, 40, 255),
|
||||||
|
Anchor = ObjectAnchor.Right | ObjectAnchor.Left,
|
||||||
|
DropDownParentOverride = this
|
||||||
|
};
|
||||||
|
dd.DropDownContainer.Textures.Add(BottomOpen);
|
||||||
|
dd.DropDownContainer.TextureDisplay = TextureDisplay.Center;
|
||||||
|
dd.DropDownContainer.Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
dd.DropDownContainer.BackgroundColor = dd.BackgroundColor;
|
||||||
|
dd.OpenStatusChanged += b =>
|
||||||
|
{
|
||||||
|
BlockDraw = true;
|
||||||
|
Size = new(base.Size.X, base.Size.Y + ( b ? dd.DropDownContainer.Size.Y : -1 * dd.DropDownContainer.Size.Y));
|
||||||
|
line!.Location = new(line.Location.X,
|
||||||
|
line.Location.Y + (b ? dd.DropDownContainer.Size.Y : -1 * dd.DropDownContainer.Size.Y), 0);
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
dd.Textures[0] = TopOpen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd.Textures[0] = CategoryButton.seltec!;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
int i = -1;
|
||||||
|
foreach (ExperimentSelectorInfo o in ei.Options)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ExperimentDropButton oo = new ExperimentDropButton(o)
|
||||||
|
{
|
||||||
|
Tag = i,
|
||||||
|
LoadDisplay = () =>
|
||||||
|
{
|
||||||
|
Label ll = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = o.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
ll.Location = new(10.ScaleInt(),
|
||||||
|
((dd.Size.Y - ll.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
dd.Controls.Add(ll);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dd.AddOption(oo);
|
||||||
|
if (o.IsEnabled())
|
||||||
|
{
|
||||||
|
dd.SetSelected(oo);
|
||||||
|
currentEnabled = o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dd.OptionSelected += DdOnOptionSelected;
|
||||||
|
Controls.Add(dd);
|
||||||
|
base.Size = new(Globals.ms.ClientSize.X - 307.ScaleInt() - 80.ScaleInt(), 15.ScaleInt() + dd.Size.Y + dd.Location.Y );
|
||||||
|
dd.Size = new(base.Size.X - Top.Location.X - Top.Location.X, dd.Size.Y);
|
||||||
|
dd.ForceDistanceUpdate(this);
|
||||||
|
|
||||||
|
line = new()
|
||||||
|
{
|
||||||
|
Size = new(base.Size.X - 2, 1.ScaleInt()),
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Location = new(1, base.Size.Y - 1.ScaleInt(), 0),
|
||||||
|
Anchor = ObjectAnchor.Left | ObjectAnchor.Right | ObjectAnchor.Bottom
|
||||||
|
};
|
||||||
|
line.ForceDistanceUpdate(this);
|
||||||
|
Controls.Add(line);
|
||||||
|
Controls.Add(Top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task DdOnOptionSelected(ExperimentDropButton arg)
|
||||||
|
{
|
||||||
|
if (arg.ESI == DisabledESI)
|
||||||
|
{
|
||||||
|
currentEnabled!.Toggle();
|
||||||
|
currentEnabled = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentEnabled = arg.ESI;
|
||||||
|
arg.ESI.Toggle();
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
55
Luski/GUI/MainScreen/UI/SettingsPanel/ThemeDropButton.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI.MainScreen.UI.LuskiControls;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace Luski.GUI.MainScreen.UI.SettingsPanel;
|
||||||
|
|
||||||
|
public class ThemeDropButton : DropDownOption
|
||||||
|
{
|
||||||
|
private Label l, d;
|
||||||
|
public ThemeStart ESI;
|
||||||
|
|
||||||
|
public ThemeDropButton(ThemeStart esi)
|
||||||
|
:base(CategoryButton.seltec!)
|
||||||
|
{
|
||||||
|
ESI = esi;
|
||||||
|
base.Size = new(297.ScaleInt(), 40.ScaleInt());
|
||||||
|
TextureDisplay = TextureDisplay.HorizontalCenter;
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context];
|
||||||
|
l = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = esi.Name,
|
||||||
|
Color = Color4.DarkGray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
l.Location = new(10.ScaleInt(),
|
||||||
|
((base.Size.Y - l.Size.Y) / 2)
|
||||||
|
, 0);
|
||||||
|
d = new(Globals.MessageFont)
|
||||||
|
{
|
||||||
|
Text = esi.Description,
|
||||||
|
Color = Color4.Gray,
|
||||||
|
IgnoreHover = true
|
||||||
|
};
|
||||||
|
d.Location = new(l.Location.X + l.Size.X + l.Location.X,
|
||||||
|
l.Location.Y + (int)l.Font.PixelHeight - (int)d.Font.PixelHeight
|
||||||
|
, 0);
|
||||||
|
Controls.Add(d);
|
||||||
|
Controls.Add(l);
|
||||||
|
BackgroundColor = new(0, 0, 0, 0);
|
||||||
|
MouseEnter += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(141, 151, 165, 30);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
MouseLeave += o =>
|
||||||
|
{
|
||||||
|
BackgroundColor = new(0,0,0,0);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
433
Luski/GUI/MainScreenWindow.cs
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Globals;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using Luski.GUI.MainScreen.UI;
|
||||||
|
using Luski.GUI.MainScreen.UI.PublicServers;
|
||||||
|
using Luski.net;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using OpenTK.Graphics.GL;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using DebugProc = OpenTK.Graphics.OpenGL4.DebugProc;
|
||||||
|
using DebugSeverity = OpenTK.Graphics.OpenGL4.DebugSeverity;
|
||||||
|
using DebugSource = OpenTK.Graphics.OpenGL4.DebugSource;
|
||||||
|
using DebugType = OpenTK.Graphics.OpenGL4.DebugType;
|
||||||
|
using Window = GraphicsManager.Window;
|
||||||
|
|
||||||
|
namespace Luski.GUI;
|
||||||
|
|
||||||
|
public class MainScreenWindow : Window
|
||||||
|
{
|
||||||
|
public static readonly NativeWindowSettings Settings = new()
|
||||||
|
{
|
||||||
|
Title = "Luski",
|
||||||
|
WindowBorder = WindowBorder.Resizable,
|
||||||
|
APIVersion = new Version(3, 2),
|
||||||
|
API = ContextAPI.OpenGL,
|
||||||
|
StartFocused = true,
|
||||||
|
Size = new Vector2i(624, 1090),
|
||||||
|
Icon = Globals.Icon,
|
||||||
|
SharedContext = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
public TabControl? tc;
|
||||||
|
private FlowLayout? channelpicker, friends, friend_request;
|
||||||
|
private RoundedButton? FriendManagerBtn;
|
||||||
|
private static DebugProc DebugMessageDelegate = OnDebugMessage;
|
||||||
|
|
||||||
|
private static void OnDebugMessage(
|
||||||
|
DebugSource source, // Source of the debugging message.
|
||||||
|
DebugType type, // Type of the debugging message.
|
||||||
|
int id, // ID associated with the message.
|
||||||
|
DebugSeverity severity, // Severity of the message.
|
||||||
|
int length, // Length of the string in pMessage.
|
||||||
|
IntPtr pMessage, // Pointer to message string.
|
||||||
|
IntPtr pUserParam) // The pointer you gave to OpenGL, explained later.
|
||||||
|
{
|
||||||
|
string message = Marshal.PtrToStringAnsi(pMessage, length);
|
||||||
|
|
||||||
|
switch (severity)
|
||||||
|
{
|
||||||
|
case DebugSeverity.DebugSeverityHigh:
|
||||||
|
if ((Globals.Settings.Logs & ConsoleLog.BigErrosForOpenGL) == ConsoleLog.BigErrosForOpenGL)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||||
|
Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DebugSeverity.DebugSeverityMedium:
|
||||||
|
if ((Globals.Settings.Logs & ConsoleLog.MediumErrosForOpenGL) == ConsoleLog.MediumErrosForOpenGL)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DebugSeverity.DebugSeverityLow:
|
||||||
|
if ((Globals.Settings.Logs & ConsoleLog.LowErrosForOpenGL) == ConsoleLog.LowErrosForOpenGL)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
|
Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ((Globals.Settings.Logs & ConsoleLog.InfoForOpenGL) == ConsoleLog.InfoForOpenGL)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine(message);
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MainScreenWindow() : base(Settings)
|
||||||
|
{
|
||||||
|
Globals.ms = this;
|
||||||
|
Size = new(1332.ScaleInt(), 866.ScaleInt());
|
||||||
|
ShowMissingChar = true;
|
||||||
|
LogFrames = ((Globals.Settings.Logs & ConsoleLog.DrawFrames) == ConsoleLog.DrawFrames);
|
||||||
|
VSync = VSyncMode.On;
|
||||||
|
|
||||||
|
GL.DebugMessageCallback(DebugMessageDelegate, IntPtr.Zero);
|
||||||
|
GL.Enable(EnableCap.DebugOutput);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Globals.DefaultFontFamly = FontFamily.LoadFontFamily(Globals.GetResource("Fonts.OpenSans.zip"), "OpenSans");
|
||||||
|
Globals.DefaultFont = FontInteraction.Load(Globals.DefaultFontFamly);
|
||||||
|
string fams = Path.Combine(Globals.LuskiPath, "FontFamilies");
|
||||||
|
if (!Directory.Exists(fams)) Directory.CreateDirectory(fams);
|
||||||
|
DirectoryInfo di = new DirectoryInfo(fams);
|
||||||
|
|
||||||
|
foreach (FileInfo fam in di.GetFiles())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (fam.FullName.ToLower().EndsWith(".zip"))
|
||||||
|
Globals.DefaultFont.AddFamily(FontFamily.LoadFontFamily(File.Open(fam.FullName, FileMode.Open), fam.Name));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Globals.DefaultFont.PixelHeight = Globals.Settings.DefaultFontPX.ScaleFont();
|
||||||
|
Globals.DefaultFont.FontSize = FontSize.Regular;
|
||||||
|
Globals.TopTimeFont = Globals.DefaultFont.Clone();
|
||||||
|
Globals.TopTimeFont.PixelHeight = Globals.Settings.TopTimeFonttPX.ScaleFont();
|
||||||
|
Globals.TopTimeFont.FontSize = FontSize.Regular;
|
||||||
|
Globals.MessageFont = Globals.DefaultFont.Clone();
|
||||||
|
Globals.MessageFont.PixelHeight = Globals.Settings.MessageFontPX.ScaleFont();
|
||||||
|
Globals.MessageFont.ExtraLinePixels = Globals.Settings.MessageFontLineSpacePX.ScaleFont();
|
||||||
|
Globals.MessageFont.FontSize = FontSize.Regular;
|
||||||
|
Globals.SmallTimeFont = Globals.DefaultFont.Clone();
|
||||||
|
Globals.SmallTimeFont.PixelHeight = ((uint)11).ScaleFont();
|
||||||
|
Globals.LuskiTexture = TextureManager.GetTextureResource("Luski.png");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CenterWindow(Globals.Settings.Display);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CenterWindow();
|
||||||
|
}
|
||||||
|
WindowLoaded += OnWindowLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnWindowLoaded(Window arg)
|
||||||
|
{
|
||||||
|
if (Globals.UpdaterSettings.AutoUpdateCheck && new HttpClient()
|
||||||
|
.GetAsync(
|
||||||
|
$"https://www.jacobtech.com/Updater/GetProgramVersion?directory=Luski&branch=main&selfcontained={Globals.UpdaterSettings.SelfContained.ToString().ToLower()}&platform={Globals.UpdaterSettings.Platform}")
|
||||||
|
.Result.Content.ReadAsStringAsync().Result !=
|
||||||
|
FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion)
|
||||||
|
{
|
||||||
|
var update = new UpdateWindow();
|
||||||
|
var result = update.ShowDialogue(this);
|
||||||
|
if (result == UpdateWindow.DialogueResult.Yes)
|
||||||
|
{
|
||||||
|
Globals.Download = true;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await LoginOnChangeToApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlowLayout ser;
|
||||||
|
private UserControl? SerBox;
|
||||||
|
public PublicChat pc;
|
||||||
|
|
||||||
|
public async Task LoadPublicServer(PublicServer? Server)
|
||||||
|
{
|
||||||
|
GL.Enable(EnableCap.DepthTest);
|
||||||
|
GL.Enable(EnableCap.Multisample);
|
||||||
|
GL.DepthFunc(DepthFunction.Always);
|
||||||
|
if (Server is null) return;
|
||||||
|
if (!Server.IsLogedIn)
|
||||||
|
{
|
||||||
|
ServerLoginOverlay SLO = new(Server.Domain);
|
||||||
|
Controls.Add(SLO);
|
||||||
|
ForceUpdate(new(ClientSize));
|
||||||
|
Globals.PrintParent(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BlockDraw = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#region Box Init
|
||||||
|
|
||||||
|
if (SerBox is null)
|
||||||
|
{
|
||||||
|
SerBox = new()
|
||||||
|
{
|
||||||
|
Location = new(ser.Size.X, 0, 0),
|
||||||
|
Size = new(Size.X - ser.Size.X, ClientSize.Y),
|
||||||
|
Anchor = ObjectAnchor.All,
|
||||||
|
BackgroundColor = new(20, 20, 20, 255)
|
||||||
|
};
|
||||||
|
Controls.Add(SerBox);
|
||||||
|
SerBox.LoadToParent(this, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerBox.Controls.Clear();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Channel Selector Init
|
||||||
|
|
||||||
|
SocketChannel current_channel = await Server.User.GetSelectedChannel(CancellationToken.None);
|
||||||
|
List<SocketCategory> parents = new();
|
||||||
|
SocketCategory? cur = await current_channel.GetParent();
|
||||||
|
while (cur is not null)
|
||||||
|
{
|
||||||
|
parents.Add(cur);
|
||||||
|
cur = await cur.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
parents.Reverse();
|
||||||
|
ChannelSelector cs = await ChannelSelector.MakeSelector(parents[0]);
|
||||||
|
cs.BackgroundColor = new(34, 34, 34, 255);
|
||||||
|
cs.Size = new(307.ScaleInt(), SerBox.Size.Y - 54.ScaleInt());
|
||||||
|
cs.Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom;
|
||||||
|
|
||||||
|
parents.RemoveAt(0);
|
||||||
|
SerBox.Controls.Add(cs);
|
||||||
|
cs.ForceDistanceUpdate(SerBox);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Chat Init
|
||||||
|
|
||||||
|
pc = new()
|
||||||
|
{
|
||||||
|
Anchor = ObjectAnchor.All,
|
||||||
|
Location = new(cs.Size.X, 0, 0),
|
||||||
|
Size = new(SerBox.Size.X - cs.Size.X, SerBox.Size.Y),
|
||||||
|
};
|
||||||
|
SerBox.Controls.Add(pc);
|
||||||
|
pc.LoadToParent(SerBox, this);
|
||||||
|
pc.ForceDistanceUpdate();
|
||||||
|
pc.MessageFlow.ForceDistanceUpdate(pc);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Channel Selector Loader
|
||||||
|
|
||||||
|
_ = cs.Load(current_channel, parents);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region User Icon
|
||||||
|
Role[] ra = await Server.User.GetRoles();
|
||||||
|
Color c = ra[0].Color;
|
||||||
|
Color4 c4 = new(c.R, c.G, c.B, c.A);
|
||||||
|
IRenderObject u = await Server.User.MakeRct(new(46.ScaleInt()), false);
|
||||||
|
int ii = 4.ScaleInt();
|
||||||
|
u.Location = new(ii, cs.Size.Y + ii, 0);
|
||||||
|
u.Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left;
|
||||||
|
SerBox.Controls.Add(u);
|
||||||
|
u.LoadToParent(SerBox, this);
|
||||||
|
u.ForceDistanceUpdate();
|
||||||
|
Label ul = new Label(Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Anchor = u.Anchor,
|
||||||
|
Text = Server.User.DisplayName,
|
||||||
|
Color = c4
|
||||||
|
};
|
||||||
|
|
||||||
|
ul.Location = new(u.Location.X + u.Size.X + 5.ScaleInt(),
|
||||||
|
(u.Location.Y + ((u.Size.Y - ul.Size.Y) / 2)), 0);
|
||||||
|
SerBox.Controls.Add(ul);
|
||||||
|
Rectangle setting = new(TextureManager.GetTextureResource("settings.png"))
|
||||||
|
{
|
||||||
|
Location = new(cs.Size.X - 40.ScaleInt(), cs.Size.Y + 11.ScaleInt(),0),
|
||||||
|
Size = new(32.ScaleInt()),
|
||||||
|
Shader = Rectangle.DefaultAlphaShader[Context],
|
||||||
|
BackgroundColor = Color4.Gray,
|
||||||
|
Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left
|
||||||
|
};
|
||||||
|
setting.MouseEnter += o =>
|
||||||
|
{
|
||||||
|
setting.BackgroundColor = Color4.White;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
setting.MouseLeave += o =>
|
||||||
|
{
|
||||||
|
setting.BackgroundColor = Color4.Gray;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
setting.Clicked += SettingOnClicked;
|
||||||
|
setting.ForceDistanceUpdate(SerBox);
|
||||||
|
SerBox.Controls.Add(setting);
|
||||||
|
ForceUpdate(new (Size));
|
||||||
|
TryDraw();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task SettingOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
SettingsMenu sm = new();
|
||||||
|
Controls.Add(sm);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadMainServer(MainServer Server)
|
||||||
|
{
|
||||||
|
if (SerBox is null)
|
||||||
|
SerBox = new()
|
||||||
|
{
|
||||||
|
Location = new(ser.Size.X, 0, 0),
|
||||||
|
Size = new(Size.X - ser.Size.X, Size.Y),
|
||||||
|
Anchor = ObjectAnchor.All
|
||||||
|
};
|
||||||
|
Controls.Add(SerBox);
|
||||||
|
SerBox.ForceDistanceUpdate();
|
||||||
|
SerBox.Controls.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Task> LoginOnChangeToApp()
|
||||||
|
{
|
||||||
|
Controls.Clear();
|
||||||
|
BlockDraw = true;
|
||||||
|
Title = "Luski";
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
GLFW.SetWindowSizeLimits(WindowPtr, 500.ScaleInt(), 250.ScaleInt(),GLFW.DontCare, GLFW.DontCare);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CenterWindow(Globals.Settings.Display);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CenterWindow();
|
||||||
|
}
|
||||||
|
WindowBorder = WindowBorder.Resizable;
|
||||||
|
BackgroundColor = new Color4(20, 20, 20, 255);
|
||||||
|
|
||||||
|
Controls.Add(ser = new FlowLayout()
|
||||||
|
{
|
||||||
|
BackgroundColor = new(26, 26, 26, 255),
|
||||||
|
Size = new(68.ScaleInt(), ClientSize.Y),
|
||||||
|
Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom,
|
||||||
|
Location = new(0,0,0)
|
||||||
|
});
|
||||||
|
ser.LoadToParent(this,this);
|
||||||
|
DrawFrame();
|
||||||
|
DateTime utcNow = DateTime.UtcNow;
|
||||||
|
Task.WhenAll(Globals.ServersLoading.ToArray()).Wait();
|
||||||
|
foreach (PublicServer pser in Globals.Luski.LoadedServers)
|
||||||
|
{
|
||||||
|
ServerIcon<PublicServer> si = new ServerIcon<PublicServer>(pser);
|
||||||
|
ser.Controls.Add(si);
|
||||||
|
si.LoadToParent(ser, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddServerIcon asi = new();
|
||||||
|
asi.Clicked += AddButtonClicked;
|
||||||
|
ser.Controls.Add(asi);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ser.Controls.Length > 1) (ser.Controls[0] as ServerIcon<PublicServer>)!.LoadServer().Start();
|
||||||
|
DrawFrame();
|
||||||
|
MainShow += OnMainShow;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(ResizeEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task AddButtonClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
AddServerOverlay aso = new();
|
||||||
|
aso.Clicked += AsoOnClicked;
|
||||||
|
Controls.Add(aso);
|
||||||
|
|
||||||
|
TryDraw();
|
||||||
|
OnResize(new(Size));
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task AsoOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
Globals.ms.Controls.Remove(arg);
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
AddServerOverlay aso = (arg as AddServerOverlay)!;
|
||||||
|
aso.Clicked -= AsoOnClicked;
|
||||||
|
aso.Clean();
|
||||||
|
aso = null!;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnMainShow()
|
||||||
|
{
|
||||||
|
if (Globals.Luski.MainServer is not null && Globals.Luski.MainServer.IsLogedIn)
|
||||||
|
{
|
||||||
|
Globals.Luski.MainServer.OnError += LuskiOnOnError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<Task>? MainShow;
|
||||||
|
|
||||||
|
private Task LuskiOnOnError(Exception arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
106
Luski/GUI/UpdateWindow.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using GraphicsManager;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
|
||||||
|
namespace Luski.GUI;
|
||||||
|
|
||||||
|
public class UpdateWindow : Window
|
||||||
|
{
|
||||||
|
private RoundedButton? yes, no;
|
||||||
|
private static readonly NativeWindowSettings Settings = new()
|
||||||
|
{
|
||||||
|
Title = "Update Available",
|
||||||
|
WindowBorder = WindowBorder.Fixed,
|
||||||
|
APIVersion = new Version(3, 2),
|
||||||
|
StartFocused = true,
|
||||||
|
Size = new Vector2i(481, 838),
|
||||||
|
Icon = Globals.Icon,
|
||||||
|
SharedContext = null
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum DialogueResult
|
||||||
|
{
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
Closed
|
||||||
|
}
|
||||||
|
|
||||||
|
private DialogueResult Result = DialogueResult.Closed;
|
||||||
|
|
||||||
|
public UpdateWindow() : base(Settings)
|
||||||
|
{
|
||||||
|
Label t;
|
||||||
|
Controls.Add(t = new Label(Globals.DefaultFont) { Scale = 1.2f, Location = new(17.5.ScaleInt()), Text = "Luski has detected that your\nclient is on an older version\nfor your branch."});
|
||||||
|
if (!Globals.Empty(Globals.UpdaterSettings.Updater))
|
||||||
|
{
|
||||||
|
t.Text += "\n\nWould you like to update?";
|
||||||
|
Controls.Add(yes = new(Globals.LuskiTexture, Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "Yes",
|
||||||
|
Location = new(t.Location.X, t.Location.Y + t.Size.Y + (int)(t.Scale * t.Font.PixelHeight), 0),
|
||||||
|
Size = new(t.Size.X, 33.5.ScaleInt())
|
||||||
|
});
|
||||||
|
Controls.Add(no = new(Globals.LuskiTexture, Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "No", Location = new(t.Location.X, yes.Location.Y + yes.Size.Y + 20, 0),
|
||||||
|
Size = new(yes.Size.X, 35.5.ScaleInt())
|
||||||
|
});
|
||||||
|
Size = new(t.Location.X + t.Location.X + t.Size.X, no.Location.Y + no.Size.Y + t.Location.X);
|
||||||
|
yes.Clicked += YesOnClicked;
|
||||||
|
no.Clicked += NoOnClicked;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t.Text += "\n\nNo updater path was set\nSet a path for auto updates";
|
||||||
|
Controls.Add(no = new(Globals.LuskiTexture, Globals.DefaultFont)
|
||||||
|
{
|
||||||
|
Text = "Ok",
|
||||||
|
Location = new(t.Location.X, t.Location.Y + t.Size.Y + (int)(t.Scale * t.Font.PixelHeight), 0),
|
||||||
|
Size = new(t.Size.X, 35.5.ScaleInt()),
|
||||||
|
});
|
||||||
|
Size = new(t.Location.X + t.Location.X + t.Size.X, no.Location.Y + no.Size.Y + t.Location.X);
|
||||||
|
no.Clicked += NoOnClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CenterWindow(Globals.Settings.Display);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CenterWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task NoOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
Result = DialogueResult.No;
|
||||||
|
base.Close();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task YesOnClicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
Result = DialogueResult.Yes;
|
||||||
|
base.Close();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogueResult ShowDialogue(Window? Parent = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Parent is not null) Parent.DrawFrame();
|
||||||
|
StartRender();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsVisible = false;
|
||||||
|
//Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
436
Luski/Globals.cs
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
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<Task<bool>> ServersLoading = new();
|
||||||
|
public static ServerList ServerList;
|
||||||
|
public static Dictionary<Window, List<IRenderObject>> 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<ServerTheme> 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<ExperimentInfo> AddedExperiments = new();
|
||||||
|
private static List<ExperimentInfo> EnabledExperiments = new();
|
||||||
|
public static List<ExperimentJson> MissingExperiments = new();
|
||||||
|
private static Dictionary<ExperimentSelectorInfo, ExperimentInfo> ExperimentSelectorInfos = new();
|
||||||
|
public static IReadOnlyList<ExperimentInfo> Experiments => AddedExperiments.AsReadOnly();
|
||||||
|
|
||||||
|
private static int LastExpCount = 0;
|
||||||
|
|
||||||
|
public static Color4 DodgerBlue = new Color4(30, 144, 255, 255);
|
||||||
|
private static bool msc = true;
|
||||||
|
private static double mscale = -1;
|
||||||
|
|
||||||
|
public static double GetScale()
|
||||||
|
{
|
||||||
|
if (Settings.Scale is not null) return Settings.Scale.Value;
|
||||||
|
if (msc)
|
||||||
|
{
|
||||||
|
msc = false;
|
||||||
|
mscale = Monitors.GetMonitorFromWindow(ms).HorizontalScale;
|
||||||
|
}
|
||||||
|
return mscale;
|
||||||
|
}
|
||||||
|
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<ExperimentJson> 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<ExperimentInfo> 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<TextureManager, Dictionary<string, Texture>> 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<long, Texture> UserTextureMap = new();
|
||||||
|
public static Dictionary<long, Texture> ProfileTextureMap = new();
|
||||||
|
|
||||||
|
private static async Task<Texture> 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<IRenderObject> MakeRct<TUser>(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<Texture> 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<TResult>(string path, JsonTypeInfo<TResult> 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<TResult>(Stream data, JsonTypeInfo<TResult> 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<TResult>(this TResult json, string path, JsonTypeInfo<TResult> 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
|
10
Luski/Interfaces/IServerOverlay.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using GraphicsManager.Objects;
|
||||||
|
using Luski.GUI.MainScreen.UI;
|
||||||
|
|
||||||
|
namespace Luski.Interfaces;
|
||||||
|
|
||||||
|
public interface IServerOverlay
|
||||||
|
{
|
||||||
|
public AccountButton? Selected { get; set; }
|
||||||
|
public UserControl page { get; set; }
|
||||||
|
}
|
8
Luski/Interfaces/IThemeObject.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
|
||||||
|
namespace Luski.Interfaces;
|
||||||
|
|
||||||
|
public interface IThemeObject
|
||||||
|
{
|
||||||
|
public IRenderObject MakeObject(params object[] param);
|
||||||
|
}
|
41
Luski/Luski.csproj
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<FileVersion>0.0.0.1</FileVersion>
|
||||||
|
<Company>JacobTech, LLC</Company>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<DefineConstants />
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<NoWarn>1701;1702;IL2121;MSB3246</NoWarn>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GraphicsManager" Version="1.0.9-alpha72" />
|
||||||
|
<PackageReference Include="Luski.net" Version="2.0.0-alpha89" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources/**"></EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="GUI\Windows\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>Luski.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
BIN
Luski/Luski.ico
Executable file
After Width: | Height: | Size: 39 KiB |
78
Luski/LuskiExperiments.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using Luski.Classes;
|
||||||
|
|
||||||
|
namespace Luski;
|
||||||
|
|
||||||
|
public static class LuskiExperiments
|
||||||
|
{
|
||||||
|
public static List<ExperimentInfo> LuskiExperimentsList = new()
|
||||||
|
{
|
||||||
|
Parents.MainServer,
|
||||||
|
Parents.ThemeEdit,
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
DisplayName = "Proper Message Label Size",
|
||||||
|
Name = "2024_04_label_size",
|
||||||
|
Options = new()
|
||||||
|
{
|
||||||
|
GUI.MessageLiveSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class Parents
|
||||||
|
{
|
||||||
|
public static ExperimentInfo MainServer = new()
|
||||||
|
{
|
||||||
|
DisplayName = "Main Servers",
|
||||||
|
Name = "2023_12_main_servers",
|
||||||
|
Options = new()
|
||||||
|
{
|
||||||
|
MainServers.EnableLuskiMainServers,
|
||||||
|
MainServers.EnableMainServers,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public static ExperimentInfo ThemeEdit = new()
|
||||||
|
{
|
||||||
|
DisplayName = "Theme Editor",
|
||||||
|
Name = "2023_12_theme_edit",
|
||||||
|
Options = new()
|
||||||
|
{
|
||||||
|
Settings.Theme,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Settings
|
||||||
|
{
|
||||||
|
public static readonly ExperimentSelectorInfo Theme = new()
|
||||||
|
{
|
||||||
|
Name = "Appearance Tab",
|
||||||
|
Description = "Adds a tab to edit the theme options.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MainServers
|
||||||
|
{
|
||||||
|
public static readonly ExperimentSelectorInfo EnableMainServers = new()
|
||||||
|
{
|
||||||
|
Name = "Enable Main Servers",
|
||||||
|
Description = "Will allow the Luski client to connect to all main servers.",
|
||||||
|
RequiresRestart = true,
|
||||||
|
};
|
||||||
|
public static readonly ExperimentSelectorInfo EnableLuskiMainServers = new()
|
||||||
|
{
|
||||||
|
Name = "Enable Luski Main Servers",
|
||||||
|
Description = "Will force the Luski client to connect to Luski main servers.",
|
||||||
|
RequiresRestart = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GUI
|
||||||
|
{
|
||||||
|
public static readonly ExperimentSelectorInfo MessageLiveSize = new()
|
||||||
|
{
|
||||||
|
Name = "Proper Label Size",
|
||||||
|
Description = "Live updates messages to be the right length during resize.", RequiresRestart = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
120
Luski/Program.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Luski;
|
||||||
|
using Luski.Classes;
|
||||||
|
using Luski.GUI;
|
||||||
|
using OpenTK.Windowing.Common.Input;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
using Image = OpenTK.Windowing.Common.Input.Image;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Globals.Settings = Globals.GetSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings);
|
||||||
|
foreach (ExperimentInfo le in LuskiExperiments.LuskiExperimentsList)
|
||||||
|
{
|
||||||
|
Globals.RegisterExperiment(le);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerList serverlist = Globals.GetSettings(Path.Combine(Globals.LuskiPath, "Servers.json"), ServerListContext.Default.ServerList);
|
||||||
|
Globals.ServerList = serverlist;
|
||||||
|
string themes = Path.Combine(Globals.LuskiPath, "Themes");
|
||||||
|
if (!Directory.Exists(themes)) Directory.CreateDirectory(themes);
|
||||||
|
DirectoryInfo di = new DirectoryInfo(themes);
|
||||||
|
|
||||||
|
foreach (DirectoryInfo Theme in di.GetDirectories())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LuskiThemes.LoadThemeFromDir(Theme.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (FileInfo Theme in di.GetFiles())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Theme.FullName.ToLower().EndsWith(".zip")) LuskiThemes.LoadThemeFromDir(Theme.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (serverlist.Servers.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (ServerInfo server in serverlist.Servers)
|
||||||
|
{
|
||||||
|
switch (server.Main)
|
||||||
|
{
|
||||||
|
case false:
|
||||||
|
Globals.ServersLoading.Add(Task.Run(async () =>
|
||||||
|
{
|
||||||
|
return await Globals.Luski.TryGetPublicServer(out _, server.Domain, server.Version,
|
||||||
|
server.Secure, server.PreGenEncryption, server.ShowMessage);
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case true:
|
||||||
|
if (LuskiExperiments.MainServers.EnableMainServers.IsEnabled()) Globals.Luski.GetMainServer(server.Domain, server.Version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.UpdaterSettings = Globals.GetSettings(Path.Combine(Globals.LuskiPath, "UpdaterSettings.json"), UpdaterSettingsContext.Default.UpdaterSettings);
|
||||||
|
if (Globals.UpdaterSettings.Updater is null) Globals.UpdaterSettings.Updater = string.Empty;
|
||||||
|
Image<Rgba32> Logo = SixLabors.ImageSharp.Image.Load<Rgba32>(Globals.GetResource("Textures.Luski.png"));
|
||||||
|
Logo.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> m);
|
||||||
|
byte[] pixels = new byte[4 * Logo.Width * Logo.Height];
|
||||||
|
Logo.CopyPixelDataTo(pixels);
|
||||||
|
|
||||||
|
Globals.Icon = new WindowIcon(new Image(Logo.Width, Logo.Height, pixels));
|
||||||
|
|
||||||
|
Logo.Dispose();
|
||||||
|
Globals.ms = new MainScreenWindow();
|
||||||
|
Globals.ms.CustomF11 = false;
|
||||||
|
Globals.ms.DrawFrame();
|
||||||
|
pixels = Array.Empty<byte>();
|
||||||
|
Globals.ms.StartRender();
|
||||||
|
Globals.ms.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Globals.Download)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Auto Update Starting");
|
||||||
|
List<string> arguments = new List<string>
|
||||||
|
{
|
||||||
|
"--process",
|
||||||
|
Process.GetCurrentProcess().ProcessName,
|
||||||
|
"--remotedirectory",
|
||||||
|
"Luski",
|
||||||
|
"--localdirectory",
|
||||||
|
AppDomain.CurrentDomain.BaseDirectory,
|
||||||
|
"--branch",
|
||||||
|
"main",
|
||||||
|
"--selfcontained",
|
||||||
|
Globals.UpdaterSettings.SelfContained.ToString().ToLower(),
|
||||||
|
"--platform",
|
||||||
|
Globals.UpdaterSettings.Platform,
|
||||||
|
"--setconfig",
|
||||||
|
Path.Combine(Globals.LuskiPath, "UpdaterSettings.json")
|
||||||
|
};
|
||||||
|
if (Globals.UpdaterSettings.AutoLaunch)
|
||||||
|
{
|
||||||
|
arguments.Add("--dll");
|
||||||
|
arguments.Add(AppDomain.CurrentDomain.FriendlyName);
|
||||||
|
}
|
||||||
|
Process p = new();
|
||||||
|
p.StartInfo.FileName = Globals.UpdaterSettings.Updater;
|
||||||
|
p.StartInfo.UseShellExecute = true;
|
||||||
|
p.StartInfo.CreateNoWindow = true;
|
||||||
|
p.StartInfo.WorkingDirectory = new FileInfo(Globals.UpdaterSettings.Updater!).Directory!.FullName;
|
||||||
|
p.StartInfo.Arguments = $"\"{string.Join("\" \"", arguments)}\"";
|
||||||
|
p.Start();
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
BIN
Luski/Resources/Fonts/OpenSans.zip
Normal file
BIN
Luski/Resources/Textures/BadTextbox.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
Luski/Resources/Textures/Context.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Luski/Resources/Textures/ContextBetter.jpg
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Luski/Resources/Textures/ContextBetter.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Luski/Resources/Textures/Download.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
Luski/Resources/Textures/Luski.png
Normal file
After Width: | Height: | Size: 204 KiB |
BIN
Luski/Resources/Textures/RoundedRectangle.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Luski/Resources/Textures/RoundedRectangleBottom.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Luski/Resources/Textures/RoundedRectangleTop.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Luski/Resources/Textures/Status.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
Luski/Resources/Textures/Textbox.old.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
Luski/Resources/Textures/Textbox.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
Luski/Resources/Textures/TextboxOutline.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
Luski/Resources/Textures/Toggle.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Luski/Resources/Textures/ac.png
Normal file
After Width: | Height: | Size: 406 B |
BIN
Luski/Resources/Textures/add.png
Normal file
After Width: | Height: | Size: 127 B |
BIN
Luski/Resources/Textures/al.png
Normal file
After Width: | Height: | Size: 943 B |
BIN
Luski/Resources/Textures/ar.png
Normal file
After Width: | Height: | Size: 845 B |
BIN
Luski/Resources/Textures/close.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
Luski/Resources/Textures/person.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
Luski/Resources/Textures/rc.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Luski/Resources/Textures/settings.png
Normal file
After Width: | Height: | Size: 487 B |