diff --git a/Luski/Classes/Attribs/NumberSelectorAttribute.cs b/Luski/Classes/Attribs/NumberSelectorAttribute.cs index 5509deb..01c1997 100644 --- a/Luski/Classes/Attribs/NumberSelectorAttribute.cs +++ b/Luski/Classes/Attribs/NumberSelectorAttribute.cs @@ -1,14 +1,9 @@ -using System.Numerics; - namespace Luski.Classes.Attribs; [AttributeUsage(AttributeTargets.Property)] -public class NumberSelectorAttribute : Attribute +public class NumberSelectorAttribute(Type PropertyType, bool Percentage = false, string Suffix = "") : Attribute { - public NumberSelectorAttribute(Type propertyType) - { - Kind = propertyType; - } - - public Type Kind { get; init; } + public bool Percentage { get; init; } = Percentage; + public string Suffix { get; init; } = Suffix; + public Type Kind { get; init; } = PropertyType; } \ No newline at end of file diff --git a/Luski/Classes/Settings.cs b/Luski/Classes/Settings.cs index d9ac4a5..c2b1e8d 100644 --- a/Luski/Classes/Settings.cs +++ b/Luski/Classes/Settings.cs @@ -17,7 +17,7 @@ public class Settings [SettingInfo(SettingGroup.AppSettings, SettingsPage.Appearance)] [Shared.GlobalAttributes.DisplayName("App Scale")] [Description("Sets the scale for the app. If disabled, the default system scale will be used.")] - [NumberSelector(typeof(double?))] + [NumberSelector(typeof(double?), true)] [NumberMin(0.25)] [NumberDefault(1)] [NumberMax(2)] @@ -110,10 +110,10 @@ public class Settings [SettingInfo(SettingGroup.AppSettings, SettingsPage.Appearance)] [Shared.GlobalAttributes.DisplayName("Top Time Font Size")] [Description("Sets the px value for the top time font size")] - [NumberSelector(typeof(uint))] + [NumberSelector(typeof(uint), Suffix: "px")] [NumberMin(8)] [NumberDefault(12)] - [NumberMax(20)] + [NumberMax(18)] public uint TopTimeFontPX { get; set; } = 12; [JsonInclude] [JsonPropertyName("role_settings_font_px")] @@ -124,7 +124,7 @@ public class Settings [SettingInfo(SettingGroup.AppSettings, SettingsPage.Appearance)] [Shared.GlobalAttributes.DisplayName("Message Font Size")] [Description("Sets the px value for the message font size")] - [NumberSelector(typeof(uint))] + [NumberSelector(typeof(uint), Suffix: "px")] [NumberMin(12)] [NumberDefault(17)] [NumberMax(24)] diff --git a/Luski/GUI/MainScreen/UI/LuskiControls/NumberSelector.cs b/Luski/GUI/MainScreen/UI/LuskiControls/NumberSelector.cs index 79baf20..e340e5a 100644 --- a/Luski/GUI/MainScreen/UI/LuskiControls/NumberSelector.cs +++ b/Luski/GUI/MainScreen/UI/LuskiControls/NumberSelector.cs @@ -6,6 +6,7 @@ using GraphicsManager.Objects.Core; using Luski.Enums; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.GraphicsLibraryFramework; namespace Luski.GUI.MainScreen.UI.LuskiControls; @@ -40,11 +41,15 @@ public class NumberSelector : UserControl where TNumber : INumber : UserControl where TNumber : INumber= Max) return progressBar.GetParentLocation(Max - Min, IgnoreEnd: true); + if (number <= Min) return progressBar.GetParentLocation(TNumber.Zero, IgnoreEnd: true); return progressBar.GetParentLocation(number - Min, IgnoreEnd: true); } - - public TNumber Default { get; set; } = TNumber.Zero; + + private TNumber Extra = TNumber.Zero; + + public TNumber Default + { + get => _Default; + set + { + if (_Default == value) return; + _Default = value; + if (Percent) L2Default.Text = (value * TNumber.CreateChecked(100))+ "%" + Suffix; + else L2Default.Text = value + Suffix; + int x = GetX(value); + L2Default.SetLocation(x - (L2Default.Size.X/2) + space, L2Default.Location.Y); + DefaltLine.SetLocation(x - (DefaltLine.Size.X/2) + space, DefaltLine.Location.Y); + DefaltLine.ForceDistanceUpdate(this); + L2Default.ForceDistanceUpdate(this); + } + } public TNumber Value { get { - return progressBar.ProgressValue + Min; + return progressBar.ProgressValue + Min - Extra; } set { int i = 0; TNumber tmp = value - Min; - if (progressBar.ProgressValue == tmp) return; AddBlockDraw(); - progressBar.ProgressValue = tmp; - Type tt = typeof(TNumber); - if (tt == typeof(double)) - L2Cursor.Text = Math.Round((double)(object)value, 2) + Suffix; - else if (tt == typeof(float)) - L2Cursor.Text = Math.Round((float)(object)value, 2) + Suffix; + if (value < Min) + { + Extra = Min - value; + progressBar.ProgressValue = TNumber.Zero; + } else - L2Cursor.Text = value.ToString() + Suffix; + { + Extra = TNumber.Zero; + progressBar.ProgressValue = tmp; + } + + Type tt = typeof(TNumber); + + + if (Percent) + { + if (tt == typeof(double)) + L2Cursor.Text = Math.Round((double)(object)(value * TNumber.CreateChecked(100)), 0) + "%" + Suffix; + else if (tt == typeof(float)) + L2Cursor.Text = Math.Round((float)(object)(value * TNumber.CreateChecked(100)), 0) + "%" + Suffix; + else + L2Cursor.Text = (value * TNumber.CreateChecked(100)) + "%" + Suffix; + } + else + { + if (tt == typeof(double)) + L2Cursor.Text = Math.Round((double)(object)value, 2) + Suffix; + else if (tt == typeof(float)) + L2Cursor.Text = Math.Round((float)(object)value, 2) + Suffix; + else + L2Cursor.Text = value.ToString() + Suffix; + } int x = GetX(value); + if (value > Max || value < Min) L2Cursor.Color = Color4.Gold; + else L2Cursor.Color = Color4.White; L2Cursor.SetLocation(x - (L2Cursor.Size.X/2) + space, L2Cursor.Location.Y); Cursor.SetLocation(x - (Cursor.Size.X/2) + space, MaxLine.Location.Y); Cursor.ForceDistanceUpdate(this); L3.Visible = L2Cursor.Location.X + L2Cursor.Size.X < L3.Location.X; L1.Visible = L2Cursor.Location.X > L1.Location.X + L1.Size.X; - L2Default.Visible = value != Default; + L2Cursor.Visible = value != Default; RemoveBlockDraw(); progressBar.UpdateProgress(); if (Loaded && BlockEvents == 0 && ValueChanged is not null) ValueChanged.Invoke(this); @@ -112,15 +167,25 @@ public class NumberSelector : UserControl where TNumber : INumber progressBar = new(); - private Rectangle Cursor = new(), MinLine = new(), MaxLine = new(); - private List ExtraPoints = new(); + private Rectangle Cursor = new(), MinLine = new(), MaxLine = new(), DefaltLine = new(); + private List<(TNumber, Rectangle)> ExtraPoints = new(); private int space = 5; private TNumber _Min = TNumber.Zero, _Default = TNumber.Zero; public Label - L1 = new(Globals.DefaultFont), - L2Default = new(Globals.DefaultFont), - L2Cursor = new(Globals.DefaultFont), - L3 = new(Globals.DefaultFont); + L1 = new(Globals.SliderFont), + L2Default = new(Globals.SliderFont), + L2Cursor = new(Globals.SliderFont), + L3 = new(Globals.SliderFont); + + public bool Percent { get; set; } + + public override void KeyEventChain(KeyboardKeyEventArgs KeyArgs) + { + base.KeyEventChain(KeyArgs); + if (Disabled) return; + if (KeyArgs.Key == Keys.Left && (Value > Min || KeyArgs.Control)) Value--; + else if (KeyArgs.Key == Keys.Right && (Value < Max || KeyArgs.Control)) Value++; + } public NumberSelector() { @@ -151,31 +216,45 @@ public class NumberSelector : UserControl where TNumber : INumber : UserControl where TNumber : INumber Max) return; - ExtraPoints.Add(value); + Rectangle r = new(); + r.Size = MinLine.Size; + r.Location = new(GetX(value) + space - (r.Size.X / 2), MinLine.Location.Y); + r.Anchor = ObjectAnchor.PreventWidthChange; + r.BackgroundColor = MinLine.BackgroundColor; + r.IgnoreHover = true; + r.ForceDistanceUpdate(this); + ExtraPoints.Add(new(value, r)); + Controls.Insert(Controls.IndexOf(MinLine), r); } private byte BlockEvents = 0; @@ -308,6 +395,11 @@ public class NumberSelector : UserControl where TNumber : INumber : UserControl where TNumber : INumber + Globals.AddNumberSlider(this, prop, (uint)PropVal, typeinfo.Suffix, typeinfo.Percentage, b => { prop.SetValue(Globals.Settings, b); Globals.Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings); @@ -82,7 +82,7 @@ public class Generic : PageFlow if (typeinfo.Kind.FullName == typeof(double?).FullName) { double? pv = (double?)PropVal; - Globals.AddNullNumberSlider(this, prop, pv, b => + Globals.AddNullNumberSlider(this, prop, pv, typeinfo.Suffix, typeinfo.Percentage, b => { prop.SetValue(Globals.Settings, b); Globals.Settings.SaveSettings(Path.Combine(Globals.LuskiPath, "Settings.json"), SettingsContext.Default.Settings); diff --git a/Luski/Globals.cs b/Luski/Globals.cs index fe78be7..6c5d64d 100644 --- a/Luski/Globals.cs +++ b/Luski/Globals.cs @@ -299,18 +299,21 @@ public static class Globals return tc; } - public static UserControl AddNumberSlider(IParent parent, string Name, string description, TNumber defaul, TNumber min, TNumber val, TNumber max, Action a) where TNumber : INumber + public static UserControl AddNumberSlider(IParent parent, string Name, string description, string suffix, bool percent, TNumber defaul, TNumber min, TNumber val, TNumber max, Action a) where TNumber : INumber { NumberSelector NumberSelector = new() { - Default = defaul, + Percent = percent, + Suffix = suffix, Min = min, Max = max, + Default = defaul, Value = val, Anchor = ObjectAnchor.Top | ObjectAnchor.Right | ObjectAnchor.Left, BackgroundColor = new(0,0,0,0), Space = 15.ScaleInt() }; + UserControl tc = new() { BackgroundColor = new(0,0,0,0) @@ -354,10 +357,14 @@ public static class Globals }; tc.ForceDistanceUpdate(parent); parent.Controls.Add(tc); + for (TNumber i = max; i > min; i--) + { + NumberSelector.AddPoint(i); + } return tc; } - public static UserControl AddNullNumberSlider(IParent parent, string Name, string description, TNumber defaul, TNumber min, TNumber? val, TNumber max, Action a) where TNumber : struct, INumber + public static UserControl AddNullNumberSlider(IParent parent, string Name, string description, string suffix, bool percent, TNumber defaul, TNumber min, TNumber? val, TNumber max, Action a) where TNumber : struct, INumber { TNumber v = defaul; if (val is not null) v = val.Value; @@ -368,9 +375,11 @@ public static class Globals }; NumberSelector NumberSelector = new() { - Default = defaul, + Percent = percent, + Suffix = suffix, Min = min, Max = max, + Default = defaul, Value = v, Anchor = ObjectAnchor.Top | ObjectAnchor.Right | ObjectAnchor.Left, BackgroundColor = new(0,0,0,0), @@ -468,7 +477,7 @@ public static class Globals AddBool(parent, Name, description,s,a,List); } - public static void AddNumberSlider(IParent parent, PropertyInfo t, TNumber s, Action a) where TNumber : INumber + public static void AddNumberSlider(IParent parent, PropertyInfo t, TNumber s, string suffix, bool percent, Action a) where TNumber : INumber { object[] valueAttributes = t.GetCustomAttributes(typeof(DescriptionAttribute), false); @@ -478,10 +487,10 @@ public static class Globals t.GetCustomAttributes(typeof(Luski.Shared.GlobalAttributes.DisplayNameAttribute), false); if (namevalueAttributes.Length == 0) return; string Name = ((Luski.Shared.GlobalAttributes.DisplayNameAttribute)namevalueAttributes[0]).DisplayName; - _ = AddNumberSlider(parent, Name, description, t.GetAnyAttribute>().Default, t.GetAnyAttribute>().Min, s, t.GetAnyAttribute>().Max,a); + _ = AddNumberSlider(parent, Name, description, suffix, percent, t.GetAnyAttribute>().Default, t.GetAnyAttribute>().Min, s, t.GetAnyAttribute>().Max,a); } - public static void AddNullNumberSlider(IParent parent, PropertyInfo t, TNumber? s, Action a) where TNumber : struct, INumber + public static void AddNullNumberSlider(IParent parent, PropertyInfo t, TNumber? s, string suffix, bool percent, Action a) where TNumber : struct, INumber { object[] valueAttributes = t.GetCustomAttributes(typeof(DescriptionAttribute), false); @@ -491,7 +500,7 @@ public static class Globals t.GetCustomAttributes(typeof(Luski.Shared.GlobalAttributes.DisplayNameAttribute), false); if (namevalueAttributes.Length == 0) return; string Name = ((Luski.Shared.GlobalAttributes.DisplayNameAttribute)namevalueAttributes[0]).DisplayName; - _ = AddNullNumberSlider(parent, Name, description, t.GetAnyAttribute>().Default, t.GetAnyAttribute>().Min, s, t.GetAnyAttribute>().Max,a); + _ = AddNullNumberSlider(parent, Name, description, suffix, percent, t.GetAnyAttribute>().Default, t.GetAnyAttribute>().Min, s, t.GetAnyAttribute>().Max,a); } public static TAttribute GetAnyAttribute(this PropertyInfo t) @@ -720,6 +729,7 @@ public static class Globals public static FontFamily DefaultFontFamly { get; set; } public static FontInteraction DefaultFont { get; set; } + public static FontInteraction SliderFont { get; set; } public static FontInteraction ServerRoleFont { get; set; } public static FontInteraction TopTimeFont { get; set; } public static FontInteraction MessageFont { get; set; } diff --git a/Luski/Luski.csproj b/Luski/Luski.csproj index 56441ab..65279ad 100644 --- a/Luski/Luski.csproj +++ b/Luski/Luski.csproj @@ -22,7 +22,7 @@ - + diff --git a/Luski/New/GUI/RootWindow.cs b/Luski/New/GUI/RootWindow.cs index c6fff8e..12afd94 100644 --- a/Luski/New/GUI/RootWindow.cs +++ b/Luski/New/GUI/RootWindow.cs @@ -87,6 +87,8 @@ public class RootWindow : Window Globals.MessageFont.FontSize = FontSize.Regular; Globals.SmallTimeFont = Globals.DefaultFont.Clone(); Globals.SmallTimeFont.PixelHeight = ((uint)11).ScaleFont(); + Globals.SliderFont = Globals.DefaultFont.Clone(); + Globals.SliderFont.PixelHeight = ((uint)14).ScaleFont(); Globals.LuskiTexture = TextureManager.GetTextureResource("Luski.png"); #endregion