diff --git a/MiraAPI.Example/ExampleLocalSetings.cs b/MiraAPI.Example/ExampleLocalSetings.cs index fb07869..fcbc455 100644 --- a/MiraAPI.Example/ExampleLocalSetings.cs +++ b/MiraAPI.Example/ExampleLocalSetings.cs @@ -1,6 +1,7 @@ using BepInEx.Configuration; using MiraAPI.LocalSettings; using MiraAPI.LocalSettings.Attributes; +using MiraAPI.Utilities; using Reactor.Utilities; namespace MiraAPI.Example; @@ -9,6 +10,9 @@ public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Mira Example"; + [LocalSettingFloat(min: 0, max: 15, suffixType: MiraNumberSuffixes.Multiplier, roundValue: false)] + public ConfigEntry ExampleFloatEntry { get; private set; } = config.Bind("General", "Example Float Setting", 50f); + [LocalSettingToggle] public ConfigEntry PlayStartupSound { get; private set; } = config.Bind("Audio", "Play Startup Sound", true); @@ -38,4 +42,12 @@ public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config) [LocalSettingToggle] public ConfigEntry EnableHardMode { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false); + [LocalSettingToggle] + public ConfigEntry EnableHardMode2 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false); + [LocalSettingToggle] + public ConfigEntry EnableHardMode3 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false); + [LocalSettingToggle] + public ConfigEntry EnableHardMode4 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false); + [LocalSettingToggle] + public ConfigEntry EnableHardMode5 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false); } diff --git a/MiraAPI/LocalSettings/Attributes/LocalSettingFloatAttribute.cs b/MiraAPI/LocalSettings/Attributes/LocalSettingFloatAttribute.cs new file mode 100644 index 0000000..1414ad8 --- /dev/null +++ b/MiraAPI/LocalSettings/Attributes/LocalSettingFloatAttribute.cs @@ -0,0 +1,28 @@ +using System; +using BepInEx.Configuration; +using MiraAPI.LocalSettings.SettingTypes; +using MiraAPI.Utilities; +using UnityEngine; + +namespace MiraAPI.LocalSettings.Attributes; + +/// +/// Creates a float and binds it with the config entry. +/// +[AttributeUsage(AttributeTargets.Property)] +public class LocalSettingFloatAttribute( + string? name = null, + float min = 0, + float max = 100, + string? description = null, + string? formatString = null, + bool roundValue = true, + MiraNumberSuffixes suffixType = MiraNumberSuffixes.None + ) : LocalSettingAttribute(name, description) +{ + /// + internal override LocalSettingFloat CreateSetting(Type tab, ConfigEntryBase configEntryBase) + { + return new LocalSettingFloat(tab, configEntryBase, name, description, new FloatRange(min, max), suffixType, formatString, roundValue); + } +} diff --git a/MiraAPI/LocalSettings/LocalSettingsTab.cs b/MiraAPI/LocalSettings/LocalSettingsTab.cs index a7e2ea7..f6bb88c 100644 --- a/MiraAPI/LocalSettings/LocalSettingsTab.cs +++ b/MiraAPI/LocalSettings/LocalSettingsTab.cs @@ -112,12 +112,19 @@ public abstract class LocalSettingsTab(ConfigFile config) ref contentOrder, contentIndex == pair.Value.Count); - obj!.GetComponentsInChildren().Do(x => + obj!.GetComponentsInChildren(true).Do(x => { x.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; x.sortingOrder = 150; x.sortingLayerName = "Default"; }); + + obj!.GetComponentsInChildren(true).Do(x => + { + x.sortingOrder = 151; + x.sortingLayerName = "Default"; + }); + obj.GetComponentsInChildren().Do(x => { x.ClickMask = OptionsMenuPatches.MaskCollider; }); contentIndex++; diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSettingFloat.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSettingFloat.cs new file mode 100644 index 0000000..ca5781a --- /dev/null +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSettingFloat.cs @@ -0,0 +1,127 @@ +using System; +using System.Globalization; +using BepInEx.Configuration; +using MiraAPI.Utilities; +using Reactor.Localization.Utilities; +using Reactor.Utilities.Extensions; +using TMPro; +using UnityEngine; +using UnityEngine.Events; +using Object = UnityEngine.Object; + +namespace MiraAPI.LocalSettings.SettingTypes; + +/// +/// Local setting class for toggles. +/// +public class LocalSettingFloat : LocalSettingBase +{ + /// + /// Gets the color of the slider. + /// + public Color SliderColor { get; } + + /// + /// Gets the range of the slider. + /// + public FloatRange SliderRange { get; } + + /// + /// Gets a format for the text to use to format the number. + /// + public string FormatString { get; } + + /// + /// Gets a value indicating whether the value should be rounded. + /// + public bool RoundValue { get; } + + /// + /// Gets the suffix for the number value. + /// + public MiraNumberSuffixes SuffixType { get; } + + /// + /// Initializes a new instance of the class. + /// + /// /// Tab that the toggle belongs to. + /// The binded config entry. + /// The name of the setting. Defaults to ConfigEntry key. + /// The desription of the setting. No description by default. + /// Gets the suffix for the number value. + /// Gets a format for the text to use to format the number. + /// Gets the color of the slider. + /// Gets the range of the slider. + /// Gets whether the value should be rounded. + public LocalSettingFloat( + Type tab, + ConfigEntryBase configEntry, + string? name = null, + string? description = null, + FloatRange? sliderRange = null, + MiraNumberSuffixes? suffixType = null, + string? formatString = null, + bool roundValue = true) + : base(tab, configEntry, name, description) + { + SliderColor = Palette.AcceptedGreen; + SuffixType = suffixType ?? MiraNumberSuffixes.None; + SliderRange = sliderRange ?? new FloatRange(0, 100); + RoundValue = roundValue; + FormatString = formatString ?? "0.0"; + } + + /// + public override GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last) + { + var newSlider = Object.Instantiate(slider, parent).GetComponent(); + var rollover = newSlider.GetComponent(); + newSlider.Title = newSlider.transform.FindChild("Text_TMP").GetComponent(); // Why the hell slider has a title property that is not even assigned??? + newSlider.Title.GetComponent().Destroy(); + newSlider.gameObject.SetActive(true); + + if (order == 2) + offset += 0.5f; + + newSlider.Bar.transform.localPosition = new Vector3(2.85f, 0, 0); + newSlider.transform.localPosition = new Vector3(-2.12f, 1.85f - offset, -7); + newSlider.name = Name; + newSlider.Range = new FloatRange(-1.5f, 1.5f); + newSlider.SetValue(Mathf.InverseLerp(SliderRange.min, SliderRange.max, GetValue())); + rollover.OverColor = SliderColor; + newSlider.Title.transform.localPosition = new Vector3(0.5f, 0, -1f); + newSlider.Title.horizontalAlignment = HorizontalAlignmentOptions.Right; + newSlider.Title.text = GetValueText(); + + newSlider.OnValueChange.AddListener((UnityAction)(() => + { + SetValue(RoundValue + ? Mathf.Round(Mathf.Lerp(SliderRange.min, SliderRange.max, newSlider.Value)) + : Mathf.Lerp(SliderRange.min, SliderRange.max, newSlider.Value)); + + newSlider.Title.text = GetValueText(); + })); + + order = 1; + offset += 0.5f; + return newSlider.gameObject; + } + + private string FormatValue(float value) + { + return SuffixType switch + { + MiraNumberSuffixes.None => value.ToString(FormatString, NumberFormatInfo.InvariantInfo), + MiraNumberSuffixes.Multiplier => value.ToString(FormatString, NumberFormatInfo.InvariantInfo) + "x", + MiraNumberSuffixes.Percent => value.ToString(FormatString, NumberFormatInfo.InvariantInfo) + "%", + _ => TranslationController.Instance.GetString( + StringNames.GameSecondsAbbrev, + (Il2CppSystem.Object[])[value.ToString(FormatString, CultureInfo.InvariantCulture)]), + }; + } + private string GetValueText() + { + var value = GetValue(); + return $"{Name}: {FormatValue(value)} / {FormatValue(SliderRange.max)}"; + } +} diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSettingToggle.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSettingToggle.cs index fa36333..0624345 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalSettingToggle.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSettingToggle.cs @@ -54,6 +54,7 @@ public class LocalSettingToggle : LocalSettingBase ToggleActiveColor = toggleActiveColor ?? Palette.AcceptedGreen; } + /// public override GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last) { var toggleObject = Object.Instantiate(toggle, parent).GetComponent(); @@ -65,11 +66,11 @@ public class LocalSettingToggle : LocalSettingBase if (last && order == 1) { // Toggle in the middle - toggleObject.transform.localPosition = new Vector3(0, 1.85f - offset); + toggleObject.transform.localPosition = new Vector3(0, 1.85f - offset, -7); } else { - toggleObject.transform.localPosition = new Vector3(order == 1 ? -1.185f : 1.185f, 1.85f - offset); + toggleObject.transform.localPosition = new Vector3(order == 1 ? -1.185f : 1.185f, 1.85f - offset, -7); } toggleObject.BaseText = CustomStringName.CreateAndRegister(Name);