diff --git a/Luski/Classes/ExperimentInfo.cs b/Luski/Classes/ExperimentInfo.cs new file mode 100644 index 0000000..7522679 --- /dev/null +++ b/Luski/Classes/ExperimentInfo.cs @@ -0,0 +1,9 @@ +namespace Luski.Classes; + +public class ExperimentInfo +{ + public string DisplayName { get; set; } = default!; + public string Name { get; set; } = default!; + public List Options { get; set; } = default!; + public int? Selected { get; set; } = null; +} \ No newline at end of file diff --git a/Luski/Classes/ExperimentJson.cs b/Luski/Classes/ExperimentJson.cs new file mode 100644 index 0000000..64f3af8 --- /dev/null +++ b/Luski/Classes/ExperimentJson.cs @@ -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!; +} \ No newline at end of file diff --git a/Luski/Classes/ExperimentSelectorInfo.cs b/Luski/Classes/ExperimentSelectorInfo.cs new file mode 100644 index 0000000..40581ed --- /dev/null +++ b/Luski/Classes/ExperimentSelectorInfo.cs @@ -0,0 +1,14 @@ +namespace Luski.Classes; + +public class ExperimentSelectorInfo +{ + public event Func? 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); + } +} \ No newline at end of file diff --git a/Luski/Clesses/ServerInfo.cs b/Luski/Classes/ServerInfo.cs similarity index 94% rename from Luski/Clesses/ServerInfo.cs rename to Luski/Classes/ServerInfo.cs index 479e808..498e128 100644 --- a/Luski/Clesses/ServerInfo.cs +++ b/Luski/Classes/ServerInfo.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Luski.Clesses; +namespace Luski.Classes; public class ServerInfo { diff --git a/Luski/Clesses/ServerList.cs b/Luski/Classes/ServerList.cs similarity index 96% rename from Luski/Clesses/ServerList.cs rename to Luski/Classes/ServerList.cs index f2c74fb..373eac4 100644 --- a/Luski/Clesses/ServerList.cs +++ b/Luski/Classes/ServerList.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Luski.Clesses; +namespace Luski.Classes; public class ServerList { diff --git a/Luski/Clesses/Settings.cs b/Luski/Classes/Settings.cs similarity index 81% rename from Luski/Clesses/Settings.cs rename to Luski/Classes/Settings.cs index f9fef7f..988fd8c 100644 --- a/Luski/Clesses/Settings.cs +++ b/Luski/Classes/Settings.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Luski.Clesses; +namespace Luski.Classes; public class Settings { @@ -16,6 +16,10 @@ public class Settings [JsonInclude] [JsonPropertyName("loadperchannel")] public int LoadPerChannel { get; set; } = 50; + [JsonInclude] + [JsonPropertyName("experiments")] + public List Experiments { get; set; } = Array.Empty().ToList(); + } [JsonSerializable(typeof(Settings))] diff --git a/Luski/Clesses/UpdaterSettings.cs b/Luski/Classes/UpdaterSettings.cs similarity index 97% rename from Luski/Clesses/UpdaterSettings.cs rename to Luski/Classes/UpdaterSettings.cs index 8df4964..1488b80 100644 --- a/Luski/Clesses/UpdaterSettings.cs +++ b/Luski/Classes/UpdaterSettings.cs @@ -1,7 +1,7 @@ using System.Text.Json.Serialization; using Luski.net.Enums; -namespace Luski.Clesses; +namespace Luski.Classes; public class UpdaterSettings { diff --git a/Luski/GUI/MainScreen/UI/AddServerIcon.cs b/Luski/GUI/MainScreen/UI/AddServerIcon.cs index 2e1d384..9ea6330 100644 --- a/Luski/GUI/MainScreen/UI/AddServerIcon.cs +++ b/Luski/GUI/MainScreen/UI/AddServerIcon.cs @@ -1,10 +1,4 @@ -using System.Reflection; -using GraphicsManager; -using GraphicsManager.Interfaces; using GraphicsManager.Objects; -using GraphicsManager.Objects.Core; -using Luski.net; -using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; namespace Luski.GUI.MainScreen.UI; @@ -14,8 +8,7 @@ public class AddServerIcon : UserControl public Rectangle Button; public AddServerIcon() { - Button = new(Globals.ms.TextureManager.AddTexture(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.add.png"))) + Button = new(Globals.ms.TextureManager.GetTextureResource("add.png")) { Location = new((int)(18 * Globals.Settings.Scale), (int)(8 * Globals.Settings.Scale), 0), Size = new((int)(32 * Globals.Settings.Scale)), diff --git a/Luski/GUI/MainScreen/UI/LuskiControls/DropDown.cs b/Luski/GUI/MainScreen/UI/LuskiControls/DropDown.cs new file mode 100644 index 0000000..7197561 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/LuskiControls/DropDown.cs @@ -0,0 +1,167 @@ +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 : 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? 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 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? OptionSelected; + + private Task OptionOnClicked(IRenderObject arg) + { + 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(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/LuskiControls/DropDownOption.cs b/Luski/GUI/MainScreen/UI/LuskiControls/DropDownOption.cs new file mode 100644 index 0000000..5767ab2 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/LuskiControls/DropDownOption.cs @@ -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; +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/LuskiControls/TextBox.cs b/Luski/GUI/MainScreen/UI/LuskiControls/TextBox.cs new file mode 100644 index 0000000..d868fb6 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/LuskiControls/TextBox.cs @@ -0,0 +1,203 @@ +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; + +namespace Luski.GUI.MainScreen.UI.LuskiControls; + +public class TextBox : UserControl +{ + private Label _watermark, _label; + private bool use; + + public TextBox() + :base(Globals.ms.TextureManager.GetTextureResource("Textbox.png")) + { + TextureDisplay = TextureDisplay.HorizontalCenter; + Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context]; + _label = new Label(Globals.DefaultFont) + { + HoverMouse = MouseCursor.IBeam, + IgnoreHover = true + }; + _watermark = new(_label.Font) + { + Color = new(128, 128, 128, 255), + HoverMouse = MouseCursor.IBeam, + IgnoreHover = true + }; + Controls.Add(_label); + Controls.Add(_watermark); + } + + public event Func? KeyPress; + + public override void UnFocus() + { + use = 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(); + } + + 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); + } + + private void WindowOnTextInput(TextInputEventArgs obj) + { + if (!use) return; + Text += obj.AsString; + } + + + public char? PasswordChar { get => _label.PasswordChar; set => _label.PasswordChar = value; } + public TextLocation TextLocation { get; set; } = TextLocation.PostiveTureCenterLeft; + + 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 string Text + { + get => _label.Text; + set + { + int old = _label.TrueHeight; + _label.Text = value; + if (!string.IsNullOrEmpty(value)) + { + bool f = false; + if (!_label.Visible) + { + f = true; + _label.Visible = true; + _label.Location = TextLocation switch + { + TextLocation.PostiveTureCenterLeft => new(5, ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight, 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.TrueCenterLeft && old != _label.TrueHeight) + { + //_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.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; + } + } + + private void Window_KeyDown(KeyboardKeyEventArgs obj) + { + if (!use) return; + 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 || obj.Key == Keys.Delete) + { + if (!(Text.Length > 0)) return; + Text = Text.Remove(Text.Length - 1, 1); + } + 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 use = false; + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/PublicServers/Category.cs b/Luski/GUI/MainScreen/UI/PublicServers/Category.cs index 0b4f193..69749d2 100644 --- a/Luski/GUI/MainScreen/UI/PublicServers/Category.cs +++ b/Luski/GUI/MainScreen/UI/PublicServers/Category.cs @@ -108,7 +108,7 @@ public class Category : UserControl, IChannelAdder Extended = !Extended; - Window!.ForceUpdate(new(Window.Size)); + // Window!.ForceUpdate(new(Window.Size)); } private bool e; diff --git a/Luski/GUI/MainScreen/UI/PublicServers/Channel.cs b/Luski/GUI/MainScreen/UI/PublicServers/Channel.cs index 6026285..4d8e027 100644 --- a/Luski/GUI/MainScreen/UI/PublicServers/Channel.cs +++ b/Luski/GUI/MainScreen/UI/PublicServers/Channel.cs @@ -11,20 +11,15 @@ namespace Luski.GUI.MainScreen.UI.PublicServers; public class Channel : UserControl { - //private Rectangle SelectedRct, SelectedRctL, SelectedRctR; private ChannelSelector CS; - //public readonly static Texture[] SelectedTextures = new Texture[] {null!, null!, null!}; - - public static Texture? seltec = null; - public SocketChannel CurrentChannel { get; set; } private Channel(Stream UserIcon, ChannelSelector cs, SocketChannel chan) - :base(seltec) + : base(Globals.ms.TextureManager.GetTextureResource("RoundedRectangle.png")) { CS = cs; CurrentChannel = chan; - Size = new((int)(307 * Globals.Settings.Scale), (int)(40* Globals.Settings.Scale)); + base.Size = new((int)(307 * Globals.Settings.Scale), (int)(40* Globals.Settings.Scale)); TextureDisplay = TextureDisplay.HorizontalCenter; Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context]; @@ -52,10 +47,10 @@ public class Channel : UserControl Controls.Add(ChannelName); Clicked += AllOnClicked; ChannelName.Location = new((int)(40 * Globals.Settings.Scale), - (Size.Y / 2) - ((int)ChannelName.Font.PixelHeight) + (ChannelName.PostiveTrueHeight / 2) + (base.Size.Y / 2) - ((int)ChannelName.Font.PixelHeight) + (ChannelName.PostiveTrueHeight / 2) , 0); ContextMenu = new((int)(150 * Globals.Settings.Scale)); - HoverMouse = MouseCursor.Hand; + base.HoverMouse = MouseCursor.Hand; } public bool Selected { get; private set; } @@ -78,18 +73,27 @@ public class Channel : UserControl await CS.Selected.ToggleSelected(); } BackgroundColor = bc; + Task? mm = null; if (Selected) { CS.Selected = this; IReadOnlyList m; - m = await CurrentChannel.GetMessages(CancellationToken.None, 200); + m = await CurrentChannel.GetMessages(CancellationToken.None, Globals.Settings.LoadPerChannel); //m = Array.Empty(); Globals.ms.pc.ClearChat(); await Globals.ms.pc.LoadChannel(CurrentChannel); - _ = Globals.ms.pc.AddMessages(m); + mm = Globals.ms.pc.AddMessages(m); + if (m.Count > 0)Globals.ms.pc.MessageFlow.ScrollToBottom(); } + + if (mm is not null) + { + Console.WriteLine("Waiting"); + Task.WaitAll(mm); + Console.WriteLine("Done"); + } BlockDraw = false; TryDraw(); } diff --git a/Luski/GUI/MainScreen/UI/PublicServers/ChatMessage.cs b/Luski/GUI/MainScreen/UI/PublicServers/ChatMessage.cs index 1171e71..2a76852 100644 --- a/Luski/GUI/MainScreen/UI/PublicServers/ChatMessage.cs +++ b/Luski/GUI/MainScreen/UI/PublicServers/ChatMessage.cs @@ -117,6 +117,7 @@ public class ChatMessage : UserControl public async Task AddMessage(SocketMessage msg) { + BlockDraw = true; Label newLabel; if (!string.IsNullOrWhiteSpace(msg.Context)) { @@ -171,6 +172,8 @@ public class ChatMessage : UserControl } 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; + TryDraw(); } private Task NewLabelOnClicked(IRenderObject arg) @@ -206,7 +209,7 @@ public class ChatMessage : UserControl Controls.Remove(l.First()); Labels.Remove(l.First()); } - Window!.DrawFrame(); + Window!.TryDraw(); return Task.CompletedTask; } @@ -223,7 +226,7 @@ public class ChatMessage : UserControl Controls.Add(m); Labels.Add(m); - Window!.DrawFrame(); + Window!.TryDraw(); return Task.CompletedTask; } } \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/PublicServers/PublicChat.cs b/Luski/GUI/MainScreen/UI/PublicServers/PublicChat.cs index c0508b0..a4ff983 100644 --- a/Luski/GUI/MainScreen/UI/PublicServers/PublicChat.cs +++ b/Luski/GUI/MainScreen/UI/PublicServers/PublicChat.cs @@ -1,5 +1,8 @@ +using System.Reflection; +using GraphicsManager; using GraphicsManager.Enums; using GraphicsManager.Objects; +using Luski.GUI.MainScreen.UI.LuskiControls; using Luski.net.Structures.Public; using OpenTK.Mathematics; using OpenTK.Windowing.Common.Input; @@ -11,12 +14,14 @@ public class PublicChat : UserControl public FlowLayout MessageFlow; private Label title, desc; - //private Textbox tb; + private TextBox tb; private SocketChannel? Channel; + UserControl titlecon; + private Rectangle? UserCon; public PublicChat() { - UserControl titlecon; + base.Size = new((int)(980 * Globals.Settings.Scale), (int)(866 * Globals.Settings.Scale)); BackgroundColor = new(50, 50, 50, 255); Anchor = ObjectAnchor.All; @@ -29,7 +34,27 @@ public class PublicChat : UserControl HScrollPixels = Globals.Settings.PerScrollPixels, }); - Controls.Add(titlecon = new UserControl(){Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right, Size = new((int)(980 * Globals.Settings.Scale), (int)(52 * Globals.Settings.Scale)), BackgroundColor = BackgroundColor}); + Controls.Add(titlecon = new UserControl() + { + Anchor = ObjectAnchor.Left | ObjectAnchor.Top | ObjectAnchor.Right, + Size = new((int)(980 * Globals.Settings.Scale), (int)(48 * Globals.Settings.Scale)), + BackgroundColor = BackgroundColor + }); + if (LuskiExperiments.ServerExperiments.MemberList.IsEnabled()) + { + UserCon = + new(Globals.ms.TextureManager.GetTextureResource("person.png")) + { + Size = new((int)(24 * Globals.Settings.Scale)), + Location = new((int)(944 * Globals.Settings.Scale),(int)(12 * Globals.Settings.Scale),0), + Anchor = ObjectAnchor.Right | ObjectAnchor.Top, + Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context], + BackgroundColor = Color4.Red + }; + titlecon.Controls.Add(UserCon); + } + LuskiExperiments.ServerExperiments.MemberList.EventToggled += MemberListOnEventToggled; + titlecon.ForceDistanceUpdate(this); titlecon.Controls.Add(title = new Label(Globals.DefaultFont) { @@ -42,20 +67,47 @@ public class PublicChat : UserControl Color = new(161,161,161,255), Location = new(title.Location.X + title.Size.X + 5, title.Location.Y, 0) }); - /* - Controls.Add(tb = new Textbox(Globals.DefaultFont, Globals.DefaultFont) + + Controls.Add(tb = new() { - InsideColor = new(28, 28, 28, 255), - BorderColor = Color4.DarkCyan, - Location = new((int)(10 * Globals.Settings.Scale), (int)(824 * Globals.Settings.Scale)), + // InsideColor = new(28, 28, 28, 255), + //BorderColor = Color4.DarkCyan, + Location = new((int)(10 * Globals.Settings.Scale), (int)(824 * Globals.Settings.Scale), 0), Size = new((int)(960 * Globals.Settings.Scale), (int)(34 * Globals.Settings.Scale)), Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left | ObjectAnchor.Right, - HoverMouse = MouseCursor.IBeam - });*/ + HoverMouse = MouseCursor.IBeam, + //Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context], + BackgroundColor = Color4.Red + }); + tb.ForceDistanceUpdate(this); //tb.KeyPress += TbOnKeyPress; //Globals.Luski.MainServer.MessageReceived += LuskiOnMessageReceived; } - + + private Task MemberListOnEventToggled(bool arg) + { + if (arg) + { + UserCon = + new(Globals.ms.TextureManager.GetTextureResource("person.png")) + { + Size = new((int)(24 * Globals.Settings.Scale)), + Location = new(base.Size.X - (int)(36 * Globals.Settings.Scale),(int)(12 * Globals.Settings.Scale),0), + Anchor = ObjectAnchor.Right | ObjectAnchor.Top, + Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context], + BackgroundColor = Color4.Red + }; + titlecon.Controls.Add(UserCon); + } + else + { + titlecon.Controls.Remove(UserCon!); + UserCon = null; + } + + return Task.CompletedTask; + } + private SocketMessage? lastm; private long? lastUser; private ChatMessage? LastChatMessage; @@ -70,7 +122,7 @@ public class PublicChat : UserControl { Window.Title = $"{channel.Name} | {channel.Server.Name} - Luski"; } - //this.tb.WatermarkText = $"Message {channel.Name}"; + tb.WatermarkText = $"Message {channel.Name}"; } public void ClearChat() @@ -83,6 +135,7 @@ public class PublicChat : UserControl public async Task AddMessages(IEnumerable messages, bool reverse = true) { + MessageFlow.BlockDraw = true; if (reverse) { foreach (SocketMessage message in messages.Reverse()) @@ -97,6 +150,7 @@ public class PublicChat : UserControl await AddMessage(message); } } + MessageFlow.BlockDraw = false; } public async Task AddMessage(SocketMessage Message) @@ -104,8 +158,8 @@ public class PublicChat : UserControl bool hasbeentenmin = false; if (lastm is not null) hasbeentenmin = - new DateTime(2022, 1, 1, 0, 0, 0, 0).AddMilliseconds(lastm.ID >> 22).ToLocalTime().AddMinutes(10) < - new DateTime(2022, 1, 1, 0, 0, 0, 0).AddMilliseconds(Message.ID >> 22).ToLocalTime(); + 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) { @@ -119,7 +173,7 @@ public class PublicChat : UserControl Globals.ms.Invoke(() => { MessageFlow.Controls.Add(LastChatMessage); - Window.DrawFrame(); + Window.TryDraw(); }); } } @@ -130,7 +184,13 @@ public class PublicChat : UserControl await LastChatMessage!.AddMessage(Message); } else - Globals.ms.Invoke(() => { LastChatMessage!.AddMessage(Message); Window!.DrawFrame(); }); + { + Globals.ms.Invoke(() => + { + LastChatMessage!.AddMessage(Message); + Window!.TryDraw(); + }); + } } lastUser = Message.AuthorID; diff --git a/Luski/GUI/MainScreen/UI/ServerIcon.cs b/Luski/GUI/MainScreen/UI/ServerIcon.cs index d9a9308..ba77566 100644 --- a/Luski/GUI/MainScreen/UI/ServerIcon.cs +++ b/Luski/GUI/MainScreen/UI/ServerIcon.cs @@ -43,8 +43,7 @@ public class ServerIcon : UserControl where TServer : Server public ServerIcon(TServer Server) { - Rectangle r = new(Globals.ms.TextureManager.AddTexture(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.rc.png"))) + Rectangle r = new(Globals.ms.TextureManager.GetTextureResource("rc.png")) { Location = new((int)(18 * Globals.Settings.Scale), (int)(8 * Globals.Settings.Scale), 0), Size = new((int)(32 * Globals.Settings.Scale)), diff --git a/Luski/GUI/MainScreen/UI/SettingsMenu.cs b/Luski/GUI/MainScreen/UI/SettingsMenu.cs new file mode 100644 index 0000000..e63793a --- /dev/null +++ b/Luski/GUI/MainScreen/UI/SettingsMenu.cs @@ -0,0 +1,171 @@ +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects; +using GraphicsManager.Objects.Core; +using Luski.Classes; +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; + private FlowLayout fl; + private Category? AppSettings; + private FontInteraction f; + public SettingsMenu() + { + LuskiExperiments.Settings.Theme.EventToggled += ThemeOnEventToggled; + BehindName = Globals.ms.Title; + Globals.ms.Title = "Settings - Luski"; + BackgroundColor = new(34, 34, 34, 255); + base.Size = Globals.ms.Size; + 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((int)(307 * Globals.Settings.Scale), 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); + + + if (LuskiExperiments.Settings.Theme.IsEnabled()) + { + AppSettings = new("APP SETTINGS"); + CategoryButton cb2 = new("Appearance", this) + { + OnPageLoad = () => + { + page!.Controls.Add(new Label(f) + { + Text = " \nAppearance\n " + }); + } + }; + AppSettings.AddButton(cb2); + fl.Controls.Insert(0, AppSettings); + fl.ScrollToBottom(); + } + + + 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.Size)); + return Task.CompletedTask; + }; + } + } + }; + CategoryButton us = new("Updater Config", this) + { + OnPageLoad = () => + { + page!.Controls.Add(new Label(f) + { + Text = " \nUpdater Config\n " + }); + } + }; + As.AddButton(cb); + As.AddButton(us); + fl.Controls.Add(As); + page = new() + { + BackgroundColor = this.BackgroundColor, + Location = new(fl.Size.X + (int)(40 * Globals.Settings.Scale), 0, 0), + Size = new(Globals.ms.Size.X - fl.Size.X - ((int)(80 * Globals.Settings.Scale)), Globals.ms.Size.Y), + AllowHoverFromBehind = true, + Anchor = ObjectAnchor.All, + HScrollPixels = Globals.Settings.PerScrollPixels + }; + Controls.Add(page); + _ = cb.ToggleSelected(); + fl.ForceDistanceUpdate(this); + + Rectangle closebtn = new(Globals.ms.TextureManager.GetTextureResource("close.png")) + { + Location = new(Globals.ms.Size.X - (int)(40 * Globals.Settings.Scale), (int)(8 * Globals.Settings.Scale),0), + Size = new((int)(32 * Globals.Settings.Scale)), + 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) + { + AppSettings = new("APP SETTINGS"); + CategoryButton cb = new("Appearance", this) + { + OnPageLoad = () => + { + page.Controls.Add(new Label(f) + { + Text = " \nAppearance\n " + }); + } + }; + AppSettings.AddButton(cb); + fl.Controls.Insert(0, AppSettings); + fl.ScrollToBottom(); + } + else + { + fl.Controls.Remove(AppSettings!); + } + + return Task.CompletedTask; + } + + private Task ClosebtnOnClicked(IRenderObject arg) + { + Globals.ms.Controls.Remove(this); + Globals.ms.Title = BehindName; + Globals.ms.DrawFrame(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/SettingsPanel/Category.cs b/Luski/GUI/MainScreen/UI/SettingsPanel/Category.cs new file mode 100644 index 0000000..a2d9c05 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/SettingsPanel/Category.cs @@ -0,0 +1,52 @@ +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((int)(5 * Globals.Settings.Scale), (int)(5 * Globals.Settings.Scale), 0), + Text = Name + }; + BackgroundColor = new(255, 255, 255, 0); + base.Size = new((int)(307 * Globals.Settings.Scale), (int)(20 * Globals.Settings.Scale) + Top.Size.Y); + Top.Location = new((base.Size.X - Top.Size.X) / 2, Top.Location.Y, 0); + line = new() + { + Size = new(base.Size.X, (int)Globals.Settings.Scale), + BackgroundColor = Color4.Gray, + Location = new(0, base.Size.Y - (int)Globals.Settings.Scale, 0) + }; + line.ForceDistanceUpdate(this); + Controls.Add(line); + Controls.Add(Top); + } + + public void AddButton(CategoryButton cb) + { + Controls.Add(cb); + int f = (int)(5 * Globals.Settings.Scale); + 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); + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/SettingsPanel/CategoryButton.cs b/Luski/GUI/MainScreen/UI/SettingsPanel/CategoryButton.cs new file mode 100644 index 0000000..d209123 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/SettingsPanel/CategoryButton.cs @@ -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((int)(297 * Globals.Settings.Scale), (int)(40* Globals.Settings.Scale)); + TextureDisplay = TextureDisplay.HorizontalCenter; + Shader = Rectangle.DefaultAlphaShader[Globals.ms.Context]; + l = new Label(Globals.DefaultFont) + { + Text = Text, + Color = Color4.Gray, + IgnoreHover = true + }; + l.Location = new((int)(5 * Globals.Settings.Scale), + (base.Size.Y / 2) - ((int)l.Font.PixelHeight) + (l.PostiveTrueHeight / 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); + } + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentDropButton.cs b/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentDropButton.cs new file mode 100644 index 0000000..1b6105f --- /dev/null +++ b/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentDropButton.cs @@ -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((int)(297 * Globals.Settings.Scale), (int)(40* Globals.Settings.Scale)); + 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((int)(10 * Globals.Settings.Scale), + (base.Size.Y / 2) - ((int)l.Font.PixelHeight) + (l.PostiveTrueHeight / 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; + }; + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentGUI.cs b/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentGUI.cs new file mode 100644 index 0000000..ef77081 --- /dev/null +++ b/Luski/GUI/MainScreen/UI/SettingsPanel/ExperimentGUI.cs @@ -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 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) + { + 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((int)(5 * Globals.Settings.Scale), (int)(5 * Globals.Settings.Scale), 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((int)(10 * Globals.Settings.Scale), + (dd!.Size.Y / 2) - ((int)ll.Font.PixelHeight) + (ll.PostiveTrueHeight / 2) + , 0); + dd.Controls.Add(ll); + }, + Size = new((int)(297 * Globals.Settings.Scale), (int)(40* Globals.Settings.Scale)) + }; + dd = new(CategoryButton.seltec!, new Rectangle() + { + Size = new((int)Globals.Settings.Scale), + BackgroundColor = Color4.Gray + }, Disabled) + { + Size = new((int)(40 * Globals.Settings.Scale)), + 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.HorizontalCenter; + 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((int)(10 * Globals.Settings.Scale), + (dd.Size.Y / 2) - ((int)ll.Font.PixelHeight) + (ll.PostiveTrueHeight / 2) + , 0); + dd.Controls.Add(ll); + } + }; + dd.AddOption(oo); + if (o.IsEnabled()) + { + Console.WriteLine($"Default for {ei.DisplayName}: {o.Name}"); + dd.SetSelected(oo); + currentEnabled = o; + } + } + dd.OptionSelected += DdOnOptionSelected; + Controls.Add(dd); + base.Size = new(Globals.ms.Size.X - (int)(307 * Globals.Settings.Scale) - (int)(80 * Globals.Settings.Scale), (int)(15 * Globals.Settings.Scale) + 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, (int)Globals.Settings.Scale), + BackgroundColor = Color4.Gray, + Location = new(1, base.Size.Y - (int)Globals.Settings.Scale, 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; + } +} \ No newline at end of file diff --git a/Luski/GUI/MainScreenWindow.cs b/Luski/GUI/MainScreenWindow.cs index 2c6994d..33d8914 100644 --- a/Luski/GUI/MainScreenWindow.cs +++ b/Luski/GUI/MainScreenWindow.cs @@ -98,8 +98,7 @@ public class MainScreenWindow : Window Globals.MessageFont.ExtraLinePixels = (uint)(5 * Globals.Settings.Scale); Globals.MessageFont.FontSize = FontSize.Regular; Globals.SmallTimeFont = Globals.DefaultFont.Clone(); - Globals.LuskiTexture = TextureManager.AddTexture(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.Luski.png")); + Globals.LuskiTexture = TextureManager.GetTextureResource("Luski.png"); CenterWindow(0); if ((Globals.Luski.MainServer is not null && !Globals.Luski.MainServer.IsLogedIn) || !Globals.Luski.LoadedServers.Any(s => s.IsLogedIn)) @@ -188,9 +187,6 @@ public class MainScreenWindow : Window #region Channel Selector Init SocketChannel current_channel = await Server.User.GetSelectedChannel(CancellationToken.None); - Channel.seltec = Globals.ms.TextureManager.AddTexture( - Tools.GetResourceStream(Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.RoundedRectangle.png")); List parents = new(); SocketCategory? cur = await current_channel.GetParent(); while (cur is not null) @@ -203,7 +199,7 @@ public class MainScreenWindow : Window ChannelSelector cs = new(parents[0]) { BackgroundColor = new(34, 34, 34, 255), - Size = new((int)(307 * Globals.Settings.Scale), SerBox.Size.Y - 106), + Size = new((int)(307 * Globals.Settings.Scale), SerBox.Size.Y - (int)(54 * Globals.Settings.Scale)), Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom }; parents.RemoveAt(0); @@ -238,13 +234,12 @@ public class MainScreenWindow : Window Role[] ra = await Server.User.GetRoles(); Color c = ra[0].Color; Color4 c4 = new(c.R, c.G, c.B, c.A); - Rectangle u = new Rectangle(TextureManager.AddTexture(Tools.GetResourceStream( - Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.Status.png"))) + Rectangle u = new Rectangle(TextureManager.GetTextureResource("Status.png")) { Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left, Size = new((int)(46 * Globals.Settings.Scale)), - Location = new((int)(4 * Globals.Settings.Scale), (int)(812 * Globals.Settings.Scale), 0) + Location = new((int)(4 * Globals.Settings.Scale), SerBox.Size.Y, 0) }; + u.Location = new(u.Location.X, cs.Size.Y + u.Location.X, 0); u.Shader = Rectangle.DefaultAlphaTextureShader[Context]; u.Textures.Add(await Server.User.GetIcon()); SerBox.Controls.Add(u); @@ -261,6 +256,28 @@ public class MainScreenWindow : Window (u.Location.Y + (u.Size.Y / 2) - (ul.PostiveTrueHeight / 2) - ul.Size.Y + ul.TrueHeight), 0); SerBox.Controls.Add(ul); + Rectangle setting = new(TextureManager.GetTextureResource("settings.png")) + { + Location = new(cs.Size.X - (int)(40 * Globals.Settings.Scale), cs.Size.Y + (int)(Globals.Settings.Scale * 11),0), + Size = new((int)(32 * Globals.Settings.Scale)), + 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); + #endregion } catch (Exception e) @@ -271,6 +288,14 @@ public class MainScreenWindow : Window 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) diff --git a/Luski/GUI/StartPage/UI/CreateAccount.cs b/Luski/GUI/StartPage/UI/CreateAccount.cs index af9c067..97d1f71 100644 --- a/Luski/GUI/StartPage/UI/CreateAccount.cs +++ b/Luski/GUI/StartPage/UI/CreateAccount.cs @@ -75,7 +75,7 @@ public class CreateAccount : UserControl rec.Textures[1].Unit = TextureUnit.Texture1; } - Window!.DrawFrame(); + Window!.TryDraw(); return Task.CompletedTask; } diff --git a/Luski/Globals.cs b/Luski/Globals.cs index f1fd9db..55ef74c 100644 --- a/Luski/Globals.cs +++ b/Luski/Globals.cs @@ -4,7 +4,7 @@ using System.Text.Json.Serialization.Metadata; using GraphicsManager; using GraphicsManager.Interfaces; using GraphicsManager.Objects.Core; -using Luski.Clesses; +using Luski.Classes; using Luski.GUI; using Luski.net; using Luski.net.Interfaces; @@ -19,6 +19,109 @@ public static class Globals { #pragma warning disable CS8618 public static Dictionary> AllowedBehindObjects = new(); + + private static List AddedExperiments = new(); + private static List EnabledExperiments = new(); + public static List MissingExperiments = new(); + private static Dictionary ExperimentSelectorInfos = new(); + public static IReadOnlyList Experiments => AddedExperiments.AsReadOnly(); + + private static int LastExpCount = 0; + + public static void RegisterExperiment(ExperimentInfo exp) + { + IEnumerable found = MissingExperiments.Where(e => e.Name == exp.Name); + ExperimentJson[] experimentInfos = found as ExperimentJson[] ?? found.ToArray(); + if (experimentInfos.Length > 0) + { + MissingExperiments.Remove(experimentInfos[0]); + EnabledExperiments.Add(exp); + } + AddedExperiments.Add(exp); + foreach (ExperimentSelectorInfo esi in exp.Options) + { + ExperimentSelectorInfos.Add(esi, exp); + } + } + + public static void Toggle(this ExperimentSelectorInfo exp) + { + if (!ExperimentSelectorInfos.TryGetValue(exp, out ExperimentInfo EI)) return; + if (Settings.Experiments.Any(e => e.Name == EI.Name)) + { + ExperimentJson ej = Settings.Experiments.Where(e => e.Name == EI.Name).First(); + if (EI.Selected == EI.Options.IndexOf(exp)) + { + Settings.Experiments.Remove(ej); + EnabledExperiments.Remove(EI); + EI.Selected = null; + LastExpCount--; + exp.SendTog(false); + } + else + { + EI.Options[EI.Selected!.Value].SendTog(false); + ej.Selected = EI.Options.IndexOf(exp); + EI.Selected = ej.Selected; + exp.SendTog(true); + } + } + else + { + LastExpCount++; + ExperimentJson ej = new() + { + Name = EI.Name, + Selected = EI.Options.IndexOf(exp) + }; + Settings.Experiments.Add(ej); + EI.Selected = ej.Selected; + if (!EnabledExperiments.Contains(EI)) EnabledExperiments.Add(EI); + exp.SendTog(true); + } + Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings); + } + + public static bool IsEnabled(this ExperimentSelectorInfo exp) + { + if (!ExperimentSelectorInfos.TryGetValue(exp, out ExperimentInfo EI)) return false; + if (LastExpCount != Settings.Experiments.Count) + { + //rescan + foreach (ExperimentJson experiment in Settings.Experiments) + { + IEnumerable found = AddedExperiments.Where(e => e.Name == experiment.Name); + ExperimentInfo[] experimentInfos = found as ExperimentInfo[] ?? found.ToArray(); + if (experimentInfos.Count() > 0) + { + if (!EnabledExperiments.Contains(EI)) EnabledExperiments.Add(experimentInfos[0]); + experimentInfos[0].Selected = experiment.Selected; + } + else + { + MissingExperiments.Add(experiment); + } + } + + LastExpCount = Settings.Experiments.Count; + } + + //detect + return EnabledExperiments.Contains(EI) && EI.Selected.HasValue && EI.Options.Count > EI.Selected && + EI.Options[EI.Selected.Value] == exp; + } + + private static Dictionary> TextureResources = new(); + + public static Texture GetTextureResource(this TextureManager tm, string File) + { + if (!TextureResources.ContainsKey(tm)) TextureResources.Add(tm, new()); + if (TextureResources[tm].TryGetValue(File, out Texture? t)) return t; + t = tm.AddTexture(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), + $"Luski.Resources.Textures.{File}")); + TextureResources[tm].Add(File,t); + return t; + } public static void AddBehindObject(this Window w, IRenderObject obj) { @@ -57,7 +160,6 @@ public static class Globals public static bool Download { get; set; } = false; public static API Luski { get; } = new(); public static MainScreenWindow ms; - private static Texture? gac; public static Color4 ToColor4(this Color col) { @@ -66,13 +168,7 @@ public static class Globals public static Texture GetAlphaCircle(this TextureManager tm) { - if (gac is null) - { - gac = tm.AddTexture(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), - "Luski.Resources.Textures.Status.png")); - } - - return gac; + return tm.GetTextureResource("Status.png"); } public static Dictionary UserTextureMap = new(); @@ -144,6 +240,11 @@ public static class Globals return @out; } + public static void SaveSettings(this TResult json, string path, JsonTypeInfo TypeInfo) where TResult : new() + { + File.WriteAllText(path, JsonSerializer.Serialize(json, TypeInfo)); + } + public static string JT { get diff --git a/Luski/Luski.csproj b/Luski/Luski.csproj index a0f927e..1dc1be8 100644 --- a/Luski/Luski.csproj +++ b/Luski/Luski.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 enable enable 1.1.0.1 @@ -19,7 +19,7 @@ - + diff --git a/Luski/LuskiExperiments.cs b/Luski/LuskiExperiments.cs new file mode 100644 index 0000000..f9b94a6 --- /dev/null +++ b/Luski/LuskiExperiments.cs @@ -0,0 +1,78 @@ +using Luski.Classes; + +namespace Luski; + +public static class LuskiExperiments +{ + public static List LuskiExperimentsList = new() + { + Parents.MainServer, + Parents.ThemeEdit, + new() + { + DisplayName = "Server Member List", + Name = "2023_12_member_list", + Options = new() + { + ServerExperiments.MemberList + } + } + }; + + 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 ServerExperiments + { + public static readonly ExperimentSelectorInfo MemberList = new() + { + Name = "Member List", + Description = "Adds a list on the side of a chat that shows members.",RequiresRestart = false + }; + } +} \ No newline at end of file diff --git a/Luski/Program.cs b/Luski/Program.cs index 186f587..07dc05e 100644 --- a/Luski/Program.cs +++ b/Luski/Program.cs @@ -2,42 +2,21 @@ using System.Reflection; using GraphicsManager; using Luski; -using Luski.Clesses; +using Luski.Classes; using Luski.GUI; -using OpenTK.Graphics.OpenGL; -using OpenTK.Mathematics; using OpenTK.Windowing.Common.Input; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using Image = OpenTK.Windowing.Common.Input.Image; -using Rectangle = GraphicsManager.Objects.Rectangle; try { - /*Window w = new(); - Rectangle r, rr; - w.Size = new(1000); - r = new() - { - Location = new(250,250,0), - Size = new(500), - BackgroundColor = Color4.Green - }; - GL.Enable(EnableCap.DepthTest); - // GL.DepthFunc(DepthFunction.Notequal); - rr = new() - { - Location = new(500,500,-1), - Size = new(500), - BackgroundColor = Color4.Blue - }; - w.Controls.Add(rr); - w.Controls.Add(r); - w.StartRender();*/ - - - 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); List> bbb = new(); if (serverlist.Server.Length > 0) @@ -50,15 +29,12 @@ try bbb.Add(Globals.Luski.TryGetPublicServer(out _,server.Domain, server.Version, server.Secure)); break; case true: - Globals.Luski.GetMainServer(server.Domain, server.Version); + if (LuskiExperiments.MainServers.EnableMainServers.IsEnabled()) Globals.Luski.GetMainServer(server.Domain, server.Version); break; } } } - - //var ttttt = GraphicsManager.Tools.GetFamilyList("fc-list ':' family"); - //var ffff = GraphicsManager.Tools.GetFontList($"fc-list ':'family='{ttttt[new Random().Next(0, ttttt.Length)]}' file"); - + Globals.UpdaterSettings = Globals.GetSettings(Path.Combine(Globals.LuskiPath, "UpdaterSettings.json"), UpdaterSettingsContext.Default.UpdaterSettings); //Globals.Luski.LoadedServers.First().CreateAccount("JacobTech", "JacobGuin12173*", "JacobTech", "/home/jacob/Pictures/Logo.png", CancellationToken.None); Task.WaitAll(bbb.ToArray()); diff --git a/Luski/Resources/Textures/RoundedRectangleBottom.png b/Luski/Resources/Textures/RoundedRectangleBottom.png new file mode 100644 index 0000000..8287e08 Binary files /dev/null and b/Luski/Resources/Textures/RoundedRectangleBottom.png differ diff --git a/Luski/Resources/Textures/RoundedRectangleTop.png b/Luski/Resources/Textures/RoundedRectangleTop.png new file mode 100644 index 0000000..bc72e93 Binary files /dev/null and b/Luski/Resources/Textures/RoundedRectangleTop.png differ diff --git a/Luski/Resources/Textures/Textbox.png b/Luski/Resources/Textures/Textbox.png new file mode 100644 index 0000000..67cf086 Binary files /dev/null and b/Luski/Resources/Textures/Textbox.png differ diff --git a/Luski/Resources/Textures/close.png b/Luski/Resources/Textures/close.png new file mode 100644 index 0000000..f65f3de Binary files /dev/null and b/Luski/Resources/Textures/close.png differ diff --git a/Luski/Resources/Textures/person.png b/Luski/Resources/Textures/person.png new file mode 100644 index 0000000..fbe8a19 Binary files /dev/null and b/Luski/Resources/Textures/person.png differ diff --git a/Luski/Resources/Textures/settings.png b/Luski/Resources/Textures/settings.png new file mode 100644 index 0000000..00b7027 Binary files /dev/null and b/Luski/Resources/Textures/settings.png differ