enum and int options and lots of other stuff i forgot

This commit is contained in:
xChipseq committed 2025-09-01 21:54:13 +02:00
1 parent 04d5e72caa
commit 57bab258e5
22 files changed
+708 -183

No files matched your search

+35 -1
View File
@@ -3,14 +3,22 @@ using MiraAPI.LocalSettings;
using MiraAPI.LocalSettings.Attributes;
using MiraAPI.Utilities;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.Example;
public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config)
{
public override string TabName => "Mira Example";
public override LocalSettingTabAppearance TabAppearance => new()
{
TabColor = Color.cyan,
ToggleActiveColor = Color.blue,
ToggleInactiveColor = Color.red,
SliderHoverColor = Color.magenta,
};
[LocalSettingFloat(min: 0, max: 15, suffixType: MiraNumberSuffixes.Multiplier, roundValue: false)]
[LocalSliderSetting(min: 0, max: 15, suffixType: MiraNumberSuffixes.Multiplier)]
public ConfigEntry<float> ExampleFloatEntry { get; private set; } = config.Bind("General", "Example Float Setting", 50f);
[LocalSettingToggle]
@@ -50,4 +58,30 @@ public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config)
public ConfigEntry<bool> EnableHardMode4 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false);
[LocalSettingToggle]
public ConfigEntry<bool> EnableHardMode5 { get; private set; } = config.Bind("Gameplay", "Enable Hard Mode", false);
[LocalNumberSetting]
public ConfigEntry<int> NumberExample { get; private set; } = config.Bind("Gameplay", "Number of cheeseburgers", 3);
[LocalEnumSetting]
public ConfigEntry<ExampleSettingEnum> EnumExample { get; private set; } = config.Bind("Gameplay", "Anything else", ExampleSettingEnum.Fries);
}
public enum ExampleSettingEnum
{
Fries,
OnionRings,
ChickenNuggets,
Gun,
}
public class Tab1(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab2(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab4(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab3(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab5(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab6(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab7(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab8(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab9(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab10(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
public class Tab11(ConfigFile config) : LocalSettingsTab(config) { public override string TabName => "Tab"; public override LocalSettingTabAppearance TabAppearance => new(); }
@@ -0,0 +1,24 @@
using System;
using BepInEx.Configuration;
using MiraAPI.LocalSettings.SettingTypes;
namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Creates an enum setting for the <see cref="ConfigEntry{T}"/>.
/// </summary>
/// <param name="names">Optional custom enum names.</param>
/// <inheritdoc/>
[AttributeUsage(AttributeTargets.Property)]
public class LocalEnumSettingAttribute(
string? name = null,
string? description = null,
string[]? names = null
) : LocalSettingAttribute(name, description)
{
/// <inheritdoc/>
internal override LocalEnumSetting CreateSetting(Type tab, ConfigEntryBase configEntryBase)
{
return new LocalEnumSetting(tab, configEntryBase, configEntryBase.SettingType, name, description, names);
}
}
@@ -0,0 +1,33 @@
using System;
using BepInEx.Configuration;
using MiraAPI.LocalSettings.SettingTypes;
using MiraAPI.Utilities;
namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Creates a number setting for the <see cref="ConfigEntry{T}"/>.
/// </summary>
/// <param name="min">Minimum range.</param>
/// <param name="max">Maximum range.</param>
/// <param name="increment">Increment per use.</param>
/// <param name="suffixType">Suffix for the value.</param>
/// <param name="formatString">Format string used when formating.</param>
/// <inheritdoc/>
[AttributeUsage(AttributeTargets.Property)]
public class LocalNumberSettingAttribute(
string? name = null,
string? description = null,
int min = 1,
int max = 5,
int increment = 1,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None,
string? formatString = null
) : LocalSettingAttribute(name, description)
{
/// <inheritdoc/>
internal override LocalNumberSetting CreateSetting(Type tab, ConfigEntryBase configEntryBase)
{
return new LocalNumberSetting(tab, configEntryBase, name, description, new IntRange(min, max), increment, suffixType, formatString);
}
}
@@ -6,10 +6,13 @@ namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Base class for all local settings attributes.
/// </summary>
/// <param name="name">The name of the setting. Defaults to entry key.</param>
/// <param name="description">The description of the setting. Defalts to entry description.</param>
[AttributeUsage(AttributeTargets.Property)]
public abstract class LocalSettingAttribute(
string? name = null,
string? description = null) : Attribute
string? description = null
) : Attribute
{
/// <summary>
/// Returns the created setting object.
@@ -1,28 +0,0 @@
using System;
using BepInEx.Configuration;
using MiraAPI.LocalSettings.SettingTypes;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Creates a float and binds it with the config entry.
/// </summary>
[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)
{
/// <inheritdoc/>
internal override LocalSettingFloat CreateSetting(Type tab, ConfigEntryBase configEntryBase)
{
return new LocalSettingFloat(tab, configEntryBase, name, description, new FloatRange(min, max), suffixType, formatString, roundValue);
}
}
@@ -1,13 +1,13 @@
using System;
using BepInEx.Configuration;
using MiraAPI.LocalSettings.SettingTypes;
using UnityEngine;
namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Creates a toggle and binds it with the config entry.
/// Creates a toggle setting for the <see cref="ConfigEntry{T}"/>.
/// </summary>
/// <inheritdoc/>
[AttributeUsage(AttributeTargets.Property)]
public class LocalSettingToggleAttribute(
string? name = null,
@@ -15,8 +15,8 @@ public class LocalSettingToggleAttribute(
) : LocalSettingAttribute(name, description)
{
/// <inheritdoc/>
internal override LocalSettingToggle CreateSetting(Type tab, ConfigEntryBase configEntryBase)
internal override LocalToggleSetting CreateSetting(Type tab, ConfigEntryBase configEntryBase)
{
return new LocalSettingToggle(tab, configEntryBase, name, description);
return new LocalToggleSetting(tab, configEntryBase, name, description);
}
}
@@ -0,0 +1,32 @@
using System;
using BepInEx.Configuration;
using MiraAPI.LocalSettings.SettingTypes;
using MiraAPI.Utilities;
namespace MiraAPI.LocalSettings.Attributes;
/// <summary>
/// Creates a slider setting for the <see cref="ConfigEntry{T}"/>.
/// </summary>
/// <inheritdoc/>
/// <param name="min">Minimum range.</param>
/// <param name="max">Maximum range.</param>
/// <param name="roundValue">Should the value be rounded.</param>
/// <param name="suffixType">Suffix for the value.</param>
[AttributeUsage(AttributeTargets.Property)]
public class LocalSliderSettingAttribute(
string? name = null,
float min = 0,
float max = 100,
string? description = null,
string? formatString = null,
bool roundValue = false,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None
) : LocalSettingAttribute(name, description)
{
/// <inheritdoc/>
internal override LocalSliderSetting CreateSetting(Type tab, ConfigEntryBase configEntryBase)
{
return new LocalSliderSetting(tab, configEntryBase, name, description, new FloatRange(min, max), suffixType, formatString, roundValue);
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ using UnityEngine;
namespace MiraAPI.LocalSettings;
/// <summary>
/// Interface for all local settings
/// Interface for all local settings.
/// </summary>
public interface ILocalSetting
{
@@ -29,7 +29,7 @@ public interface ILocalSetting
ConfigEntryBase ConfigEntry { get; }
/// <summary>
/// Used to create the setting
/// Used to create the setting.
/// </summary>
/// <param name="toggle">Toggle template.</param>
/// <param name="slider">Slider template.</param>
+25 -43
View File
@@ -4,7 +4,6 @@ using BepInEx.Configuration;
using HarmonyLib;
using MiraAPI.Patches.LocalSettings;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -14,39 +13,29 @@ using Object = UnityEngine.Object;
namespace MiraAPI.LocalSettings;
/// <summary>
/// Represents a local settings tab. Gets a button by default
/// Represents a local settings tab. Gets a button by default.
/// </summary>
public abstract class LocalSettingsTab(ConfigFile config)
{
/// <summary>
/// Gets the name of the tab
/// Gets the name of the tab.
/// </summary>
public abstract string TabName { get; }
/// <summary>
/// Gets the tab button icon.
/// Gets the tab appearance.
/// </summary>
public virtual LoadableAsset<Sprite>? TabIcon => null;
/// <summary>
/// Gets the color of the tab button.
/// </summary>
public virtual Color TabColor => Color.white;
/// <summary>
/// Gets the color of the tab button when hovered.
/// </summary>
public Color TabHoverColor => Palette.AcceptedGreen;
/// <summary>
/// Gets the color of the tab button when active.
/// </summary>
public virtual Color TabActiveColor => Palette.AcceptedGreen;
public virtual LocalSettingTabAppearance TabAppearance { get; } = new();
/// <summary>
/// Gets a value indicating whether a button should be created for the tab.
/// </summary>
protected virtual bool ShouldCreateButton => true;
public virtual bool ShouldCreateButton => true;
/// <summary>
/// Gets a value indicating whether the tab should have category labels.
/// </summary>
protected virtual bool ShouldCreateLabels => true;
/// <summary>
/// Gets the mod's config file. Automatically found in the plugin loader.
@@ -57,13 +46,8 @@ public abstract class LocalSettingsTab(ConfigFile config)
internal List<ILocalSetting> Settings { get; } = [];
private Scroller? Scroller { get; set; }
internal GameObject? CreateTab(OptionsMenuBehaviour instance, ref int tabIdx, ref float offset)
internal GameObject CreateTab(OptionsMenuBehaviour instance)
{
if (ShouldCreateButton)
{
CreateTabButton(instance, ref tabIdx, ref offset);
}
var tab = Object.Instantiate(instance.transform.FindChild("GeneralTab").gameObject, instance.transform);
tab.name = $"{TabName}Tab";
tab.transform.DestroyChildren();
@@ -100,7 +84,10 @@ public abstract class LocalSettingsTab(ConfigFile config)
foreach (var pair in entriesByGroup)
{
CreateLabel(generalLabel, Scroller.Inner, pair.Key, ref contentOffset);
if (ShouldCreateLabels)
{
CreateLabel(generalLabel, Scroller.Inner, pair.Key, ref contentOffset);
}
foreach (var setting in pair.Value)
{
@@ -119,7 +106,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
x.sortingLayerName = "Default";
});
obj!.GetComponentsInChildren<MeshRenderer>(true).Do(x =>
obj.GetComponentsInChildren<MeshRenderer>(true).Do(x =>
{
x.sortingOrder = 151;
x.sortingLayerName = "Default";
@@ -137,13 +124,13 @@ public abstract class LocalSettingsTab(ConfigFile config)
return tab;
}
private void CreateTabButton(OptionsMenuBehaviour instance, ref int tabIdx, ref float offset)
internal GameObject CreateTabButton(OptionsMenuBehaviour instance, ref int tabIdx, ref float offset)
{
var tabButtonObject = Object.Instantiate(instance.Tabs[0], instance.transform);
tabButtonObject.name = $"{TabName} Button";
tabButtonObject.transform.localPosition = new Vector3(2.4f, 2.1f - offset, 5.5f);
tabButtonObject.transform.localScale = new Vector3(1.25f, 1.25f, 1);
tabButtonObject.Button.color = TabColor;
tabButtonObject.Button.color = TabAppearance.TabButtonColor;
TabButton = tabButtonObject;
var tabButtonText = tabButtonObject.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
@@ -155,18 +142,18 @@ public abstract class LocalSettingsTab(ConfigFile config)
var tabButton = tabButtonObject.GetComponent<PassiveButton>();
var rollover = tabButtonObject.Rollover;
rollover.OverColor = TabColor;
rollover.OutColor = TabColor;
rollover.OverColor = TabAppearance.TabButtonHoverColor;
rollover.OutColor = TabAppearance.TabButtonColor;
SpriteRenderer? tabButtonRend = null;
if (TabIcon != null)
if (TabAppearance.TabIcon != null)
{
tabButtonRend = new GameObject("sprite").AddComponent<SpriteRenderer>();
tabButtonRend.gameObject.layer = 5; // ui layer
tabButtonRend.transform.SetParent(tabButtonObject.transform);
tabButtonRend.transform.localPosition = new Vector3(0.5f, 0, -2);
tabButtonRend.transform.localScale = new Vector3(0.2f, 0.2f, 1);
tabButtonRend.sprite = TabIcon.LoadAsset();
tabButtonRend.sprite = TabAppearance.TabIcon.LoadAsset();
tabButtonText.gameObject.SetActive(false);
}
@@ -176,8 +163,6 @@ public abstract class LocalSettingsTab(ConfigFile config)
tabButton.OnMouseOver.AddListener((UnityAction)(() =>
{
tabButton.transform.localPosition = new Vector3(3.55f, 2.1f - tabOffset, 5.5f);
tabButtonObject.Button.color = TabHoverColor;
tabButtonObject.Rollover.OutColor = TabHoverColor;
tabButtonText.gameObject.SetActive(true);
tabButtonText.transform.localPosition = new Vector3(-0.024f, 0, 0);
tabButtonText.maxVisibleCharacters = int.MaxValue;
@@ -188,8 +173,8 @@ public abstract class LocalSettingsTab(ConfigFile config)
{
if (!tabButtonObject.Content.gameObject.activeSelf)
{
tabButtonObject.Button.color = TabColor;
tabButtonObject.Rollover.OutColor = TabColor;
//tabButtonObject.Button.color = TabColor;
//tabButtonObject.Rollover.OutColor = TabColor;
}
tabButton.transform.localPosition = new Vector3(2.4f, 2.1f - tabOffset, 5.5f);
@@ -205,8 +190,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
tabButtonText.text = $"<b>{GetShortName(TabName)}</b>";
}));
offset += 0.6f;
tabIdx++;
return tabButtonObject.gameObject;
}
private static void CreateLabel(GameObject template, Transform parent, string text, ref float offset)
@@ -227,7 +211,6 @@ public abstract class LocalSettingsTab(ConfigFile config)
offset += 0.5f;
}
private static string GetShortName(string name)
{
var shortName = string.Empty;
@@ -235,4 +218,3 @@ public abstract class LocalSettingsTab(ConfigFile config)
return shortName;
}
}
@@ -0,0 +1,81 @@
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.LocalSettings;
/// <summary>
/// Struct for modyfing tab apparance.
/// Defines how the settings look.
/// </summary>
public record struct LocalSettingTabAppearance()
{
/// <summary>
/// Gets or sets main color of the tab.
/// </summary>
public Color TabColor { get; set; } = Color.white;
/// <summary>
/// Gets or sets tab button icon. No icon by default.
/// </summary>
public LoadableAsset<Sprite>? TabIcon { get; set; }
/// <summary>
/// Gets or sets color of the tab button.
/// </summary>
public Color TabButtonColor { get; set; } = Color.white;
/// <summary>
/// Gets or sets hover color of the tab button.
/// </summary>
public Color TabButtonHoverColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets active color of the tab button.
/// </summary>
public Color TabButtonActiveColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets hover color of toggles.
/// </summary>
public Color ToggleHoverColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets active color of toggles.
/// </summary>
public Color ToggleActiveColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets inactive color of toggles.
/// </summary>
public Color ToggleInactiveColor { get; set; } = Color.red;
/// <summary>
/// Gets or sets color of number buttons.
/// </summary>
public Color NumberColor { get; set; } = Color.white;
/// <summary>
/// Gets or sets hover color of number buttons.
/// </summary>
public Color NumberHoverColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets color of sliders.
/// </summary>
public Color SliderColor { get; set; } = Color.white;
/// <summary>
/// Gets or sets hover color of sliders.
/// </summary>
public Color SliderHoverColor { get; set; } = Palette.AcceptedGreen;
/// <summary>
/// Gets or sets color of enum buttons.
/// </summary>
public Color EnumColor { get; set; } = Color.white;
/// <summary>
/// Gets or sets hover color of enum buttons.
/// </summary>
public Color EnumHoverColor { get; set; } = Palette.AcceptedGreen;
}
@@ -1,7 +1,6 @@
using System.Linq;
using MiraAPI.LocalSettings;
namespace MiraAPI.GameOptions;
namespace MiraAPI.LocalSettings;
/// <summary>
/// Singleton for local settings tabs.
@@ -0,0 +1,126 @@
using System;
using BepInEx.Configuration;
using MiraAPI.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using Object = UnityEngine.Object;
namespace MiraAPI.LocalSettings.SettingTypes;
/// <summary>
/// Local setting class for enums.
/// </summary>
public class LocalEnumSetting : LocalSettingBase<int>
{
/// <summary>
/// Gets the enum type of the setting.
/// </summary>
public Type EnumType { get; }
/// <summary>
/// Gets the enum values.
/// </summary>
public string[] Values { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalEnumSetting"/> class.
/// </summary>
/// <inheritdoc/>
/// <param name="enumType">The enum type.</param>
/// <param name="values">The optional values array to replace the enum names.</param>
public LocalEnumSetting(
Type tab,
ConfigEntryBase configEntry,
Type enumType,
string? name = null,
string? description = null,
string[]? values = null)
: base(tab, configEntry, name, description)
{
EnumType = enumType;
Values = values ?? Enum.GetNames(EnumType);
}
/// <inheritdoc />
public override GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
{
var button = Object.Instantiate(toggle, parent).GetComponent<PassiveButton>();
var tmp = button.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
var rollover = button.GetComponent<ButtonRolloverHandler>();
tmp.GetComponent<TextTranslatorTMP>().Destroy();
button.gameObject.SetActive(true);
var toggleComp = button.GetComponent<ToggleButtonBehaviour>();
var background = toggleComp.Background;
var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent<SpriteRenderer>();
if (highlight != null)
{
highlight.color = Tab!.TabAppearance.EnumHoverColor;
}
toggleComp.Destroy();
if (last && order == 1)
{
// Button in the middle
button.transform.localPosition = new Vector3(0, 1.85f - offset, -7);
}
else
{
button.transform.localPosition = new Vector3(order == 1 ? -1.185f : 1.185f, 1.85f - offset, -7);
}
tmp.text = GetValueText();
button.name = Name;
button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent();
rollover.OutColor = Tab!.TabAppearance.EnumColor;
rollover.OverColor = Tab!.TabAppearance.EnumHoverColor;
background.color = Tab!.TabAppearance.EnumColor;
button.OnClick.AddListener((UnityAction)(() =>
{
int value = GetValue();
value++;
if (value >= Values.Length)
{
value = 0;
}
SetValue(value);
tmp.text = GetValueText();
}));
button.OnMouseOver.AddListener((UnityAction)(() =>
{
if (!Description.IsNullOrWhiteSpace())
{
tmp.text = Description;
}
highlight?.gameObject.SetActive(true);
}));
button.OnMouseOut.AddListener((UnityAction)(() =>
{
tmp.text = GetValueText();
highlight?.gameObject.SetActive(false);
}));
Helpers.DivideSize(button.gameObject, 1.1f);
order++;
if (order > 2 && !last)
{
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
return button.gameObject;
}
/// <inheritdoc/>
protected override string GetValueText()
{
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name}: <b>{Values[GetValue()]}</font></b>";
}
}
@@ -0,0 +1,144 @@
using System;
using BepInEx.Configuration;
using MiraAPI.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using Object = UnityEngine.Object;
namespace MiraAPI.LocalSettings.SettingTypes;
/// <summary>
/// Local setting class for numbers.
/// </summary>
public class LocalNumberSetting : LocalSettingBase<int>
{
/// <summary>
/// Gets the range of the button.
/// </summary>
public IntRange NumberRange { get; }
/// <summary>
/// Gets the increment of the value when button is pressed.
/// </summary>
public int Increment { get; }
/// <summary>
/// Gets a format for the text to use to format the number.
/// </summary>
public string FormatString { get; }
/// <summary>
/// Gets the suffix for the number value.
/// </summary>
public MiraNumberSuffixes SuffixType { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalNumberSetting"/> class.
/// </summary>
/// <inheritdoc/>
/// <param name="numberRange">The value range.</param>
/// <param name="increment">The increment per click.</param>
/// <param name="suffixType">The suffix used for formating.</param>
/// <param name="formatString">The format string used for formating.</param>
public LocalNumberSetting(
Type tab,
ConfigEntryBase configEntry,
string? name = null,
string? description = null,
IntRange? numberRange = null,
int? increment = null,
MiraNumberSuffixes? suffixType = null,
string? formatString = null)
: base(tab, configEntry, name, description)
{
SuffixType = suffixType ?? MiraNumberSuffixes.None;
NumberRange = numberRange ?? new IntRange(1, 5);
Increment = increment ?? 1;
FormatString = formatString ?? "0";
}
/// <inheritdoc />
public override GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
{
var button = Object.Instantiate(toggle, parent).GetComponent<PassiveButton>();
var tmp = button.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
var rollover = button.GetComponent<ButtonRolloverHandler>();
tmp.GetComponent<TextTranslatorTMP>().Destroy();
button.gameObject.SetActive(true);
var toggleComp = button.GetComponent<ToggleButtonBehaviour>();
var background = toggleComp.Background;
var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent<SpriteRenderer>();
if (highlight != null)
{
highlight.color = Tab!.TabAppearance.NumberHoverColor;
}
toggleComp.Destroy();
if (last && order == 1)
{
// Button in the middle
button.transform.localPosition = new Vector3(0, 1.85f - offset, -7);
}
else
{
button.transform.localPosition = new Vector3(order == 1 ? -1.185f : 1.185f, 1.85f - offset, -7);
}
tmp.text = GetValueText();
button.name = Name;
button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent();
rollover.OutColor = Tab!.TabAppearance.NumberColor;
rollover.OverColor = Tab!.TabAppearance.NumberHoverColor;
background.color = Tab!.TabAppearance.NumberColor;
button.OnClick.AddListener((UnityAction)(() =>
{
int value = GetValue();
value += Increment;
if (value > NumberRange.max)
{
value = NumberRange.min;
}
SetValue(value);
tmp.text = GetValueText();
}));
button.OnMouseOver.AddListener((UnityAction)(() =>
{
if (!Description.IsNullOrWhiteSpace())
{
tmp.text = Description;
}
highlight?.gameObject.SetActive(true);
}));
button.OnMouseOut.AddListener((UnityAction)(() =>
{
tmp.text = GetValueText();
highlight?.gameObject.SetActive(false);
}));
Helpers.DivideSize(button.gameObject, 1.1f);
order++;
if (order > 2 && !last)
{
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
return button.gameObject;
}
/// <inheritdoc/>
protected override string GetValueText()
{
var value = GetValue();
var formated = Helpers.FormatValue(value, SuffixType, FormatString);
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name}: <b>{formated}</font></b>";
}
}
@@ -1,6 +1,6 @@
using System;
using System.Linq;
using BepInEx.Configuration;
using TMPro;
using UnityEngine;
namespace MiraAPI.LocalSettings.SettingTypes;
@@ -20,6 +20,8 @@ public abstract class LocalSettingBase<T> : ILocalSetting
/// <inheritdoc />
public ConfigEntryBase ConfigEntry { get; }
internal LocalSettingsTab? Tab => LocalSettingsManager.Tabs.FirstOrDefault(x => x.Settings.Contains(this));
/// <summary>
/// Initializes a new instance of the <see cref="LocalSettingBase{T}"/> class.
/// </summary>
@@ -32,7 +34,6 @@ public abstract class LocalSettingBase<T> : ILocalSetting
ConfigEntry = configEntry;
Name = name ?? ConfigEntry.Definition.Key;
Description = description ?? ConfigEntry.Description.Description;
LocalSettingsManager.TypeToTab[tab].Settings.Add(this);
}
@@ -40,7 +41,16 @@ public abstract class LocalSettingBase<T> : ILocalSetting
/// Creates an instance of the setting.
/// </summary>
/// <returns>The created setting.</returns>
public abstract GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last);
public abstract GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last);
/// <summary>
/// Returns the formated string to use in the text of the setting.
/// </summary>
/// <returns>The value text.</returns>
protected virtual string GetValueText()
{
return GetValue()?.ToString() ?? string.Empty;
}
/// <summary>
/// Gets the value of the config entry, casted to the setting type.
@@ -52,7 +62,7 @@ public abstract class LocalSettingBase<T> : ILocalSetting
}
/// <summary>
/// Sets the value of the config entry
/// Sets the value of the config entry.
/// </summary>
/// <param name="value">The value to set to.</param>
public void SetValue(T value)
@@ -1,8 +1,6 @@
using System;
using System.Globalization;
using BepInEx.Configuration;
using MiraAPI.Utilities;
using Reactor.Localization.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -12,15 +10,10 @@ using Object = UnityEngine.Object;
namespace MiraAPI.LocalSettings.SettingTypes;
/// <summary>
/// Local setting class for toggles.
/// Local setting class for sliders.
/// </summary>
public class LocalSettingFloat : LocalSettingBase<float>
public class LocalSliderSetting : LocalSettingBase<float>
{
/// <summary>
/// Gets the color of the slider.
/// </summary>
public Color SliderColor { get; }
/// <summary>
/// Gets the range of the slider.
/// </summary>
@@ -42,18 +35,14 @@ public class LocalSettingFloat : LocalSettingBase<float>
public MiraNumberSuffixes SuffixType { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalSettingFloat"/> class.
/// Initializes a new instance of the <see cref="LocalSliderSetting"/> class.
/// </summary>
/// /// <param name="tab">Tab that the toggle belongs to.</param>
/// <param name="configEntry">The binded config entry.</param>
/// <param name="name">The name of the setting. Defaults to ConfigEntry key.</param>
/// <param name="description">The desription of the setting. No description by default.</param>
/// <param name="suffixType">Gets the suffix for the number value.</param>
/// <param name="formatString">Gets a format for the text to use to format the number.</param>
/// <param name="sliderColor">Gets the color of the slider.</param>
/// <param name="sliderRange">Gets the range of the slider.</param>
/// <param name="roundValue">Gets whether the value should be rounded.</param>
public LocalSettingFloat(
/// <inheritdoc/>
/// <param name="sliderRange">The value range.</param>
/// <param name="suffixType">The suffix used for formating.</param>
/// <param name="formatString">The format string used for formating.</param>
/// <param name="roundValue">Should the value be rounded.</param>
public LocalSliderSetting(
Type tab,
ConfigEntryBase configEntry,
string? name = null,
@@ -61,10 +50,9 @@ public class LocalSettingFloat : LocalSettingBase<float>
FloatRange? sliderRange = null,
MiraNumberSuffixes? suffixType = null,
string? formatString = null,
bool roundValue = true)
bool roundValue = false)
: base(tab, configEntry, name, description)
{
SliderColor = Palette.AcceptedGreen;
SuffixType = suffixType ?? MiraNumberSuffixes.None;
SliderRange = sliderRange ?? new FloatRange(0, 100);
RoundValue = roundValue;
@@ -72,13 +60,14 @@ public class LocalSettingFloat : LocalSettingBase<float>
}
/// <inheritdoc />
public override GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
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<SlideBar>();
var rollover = newSlider.GetComponent<ButtonRolloverHandler>();
newSlider.Title = newSlider.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>(); // Why the hell slider has a title property that is not even assigned???
newSlider.Title.GetComponent<TextTranslatorTMP>().Destroy();
newSlider.gameObject.SetActive(true);
newSlider.Bar.color = Tab!.TabAppearance.SliderColor;
if (order == 2)
offset += 0.5f;
@@ -88,7 +77,8 @@ public class LocalSettingFloat : LocalSettingBase<float>
newSlider.name = Name;
newSlider.Range = new FloatRange(-1.5f, 1.5f);
newSlider.SetValue(Mathf.InverseLerp(SliderRange.min, SliderRange.max, GetValue()));
rollover.OverColor = SliderColor;
rollover.OutColor = Tab!.TabAppearance.SliderColor;
rollover.OverColor = Tab!.TabAppearance.SliderHoverColor;
newSlider.Title.transform.localPosition = new Vector3(0.5f, 0, -1f);
newSlider.Title.horizontalAlignment = HorizontalAlignmentOptions.Right;
newSlider.Title.text = GetValueText();
@@ -107,21 +97,12 @@ public class LocalSettingFloat : LocalSettingBase<float>
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()
/// <inheritdoc/>
protected override string GetValueText()
{
var value = GetValue();
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name}: <b>{FormatValue(value)} / {FormatValue(SliderRange.max)}</font></b>";
var formated = Helpers.FormatValue(value, SuffixType, FormatString);
var maxFormated = Helpers.FormatValue(SliderRange.max, SuffixType, FormatString);
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name}: <b>{formated} / {maxFormated}</font></b>";
}
}
@@ -12,50 +12,23 @@ namespace MiraAPI.LocalSettings.SettingTypes;
/// <summary>
/// Local setting class for toggles.
/// </summary>
public class LocalSettingToggle : LocalSettingBase<bool>
public class LocalToggleSetting : LocalSettingBase<bool>
{
/// <summary>
/// Gets the color of the toggle.
/// Initializes a new instance of the <see cref="LocalToggleSetting"/> class.
/// </summary>
public Color ToggleColor { get; }
/// <summary>
/// Gets the color of the toggle when hovered.
/// </summary>
public Color ToggleHoverColor { get; }
/// <summary>
/// Gets the color of the toggle when enabled.
/// </summary>
public Color ToggleActiveColor { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalSettingToggle"/> class.
/// </summary>
/// /// <param name="tab">Tab that the toggle belongs to.</param>
/// <param name="configEntry">The binded config entry.</param>
/// <param name="name">The name of the setting. Defaults to ConfigEntry key.</param>
/// <param name="description">The desription of the setting. No description by default.</param>
/// <param name="toggleColor">The color of the toggle.</param>
/// <param name="toggleHoverColor">The hover color of the toggle.</param>
/// <param name="toggleActiveColor">The active color of the toggle.</param>
public LocalSettingToggle(
/// <inheritdoc/>
public LocalToggleSetting(
Type tab,
ConfigEntryBase configEntry,
string? name = null,
string? description = null,
Color? toggleColor = null,
Color? toggleHoverColor = null,
Color? toggleActiveColor = null)
: base(tab, configEntry, name, description)
string? description = null
) : base(tab, configEntry, name, description)
{
ToggleColor = toggleColor ?? Color.white;
ToggleHoverColor = toggleHoverColor ?? Palette.AcceptedGreen;
ToggleActiveColor = toggleActiveColor ?? Palette.AcceptedGreen;
}
/// <inheritdoc />
public override GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
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<ToggleButtonBehaviour>();
var tmp = toggleObject.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
@@ -76,15 +49,15 @@ public class LocalSettingToggle : LocalSettingBase<bool>
toggleObject.BaseText = CustomStringName.CreateAndRegister(Name);
toggleObject.UpdateText(GetValue());
toggleObject.name = Name;
toggleObject.Background.color = GetValue() ? ToggleActiveColor : ToggleColor;
toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor;
passiveButton.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent();
rollover.OverColor = ToggleHoverColor;
rollover.OverColor = Tab!.TabAppearance.ToggleHoverColor;
passiveButton.OnClick.AddListener((UnityAction)(() =>
{
SetValue(!GetValue());
toggleObject.UpdateText(GetValue());
toggleObject.Background.color = GetValue() ? ToggleActiveColor : ToggleColor;
toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor;
}));
passiveButton.OnMouseOver.AddListener((UnityAction)(() =>
{
@@ -96,7 +69,7 @@ public class LocalSettingToggle : LocalSettingBase<bool>
passiveButton.OnMouseOut.AddListener((UnityAction)(() =>
{
toggleObject.UpdateText(GetValue());
toggleObject.Background.color = GetValue() ? ToggleActiveColor : ToggleColor;
toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor;
}));
Helpers.DivideSize(toggleObject.gameObject, 1.1f);
+5 -1
View File
@@ -23,7 +23,11 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
public override string TabName => "Mira API";
/// <inheritdoc />
public override LoadableAsset<Sprite>? TabIcon => MiraAssets.SettingsIcon;
public override LocalSettingTabAppearance TabAppearance => new()
{
TabButtonHoverColor = MiraApiPlugin.MiraColor,
TabIcon = MiraAssets.SettingsIcon,
};
/// <summary>
/// Gets whether the modifiers hud should be on the left side of the screen (under roles/task tab). Recommended for streamers.
+1 -1
View File
@@ -4,7 +4,7 @@ using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.GameOptions;
using MiraAPI.LocalSettings;
using MiraAPI.Modifiers.ModifierDisplay;
using MiraAPI.Modifiers.Types;
using MiraAPI.Patches.Roles;
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.GameOptions;
using MiraAPI.Patches.Roles;
using MiraAPI.LocalSettings;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.Extensions;
using TMPro;
@@ -2,11 +2,12 @@
using System.Linq;
using HarmonyLib;
using MiraAPI.LocalSettings;
using Reactor.Localization.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace MiraAPI.Patches.LocalSettings;
@@ -14,6 +15,11 @@ namespace MiraAPI.Patches.LocalSettings;
public static class OptionsMenuPatches
{
internal static BoxCollider2D MaskCollider;
private static SpriteRenderer? background;
private static int currentPage = 1;
private static Dictionary<int, List<GameObject>> tabButtons = new();
/// <summary>
/// Creates the tabs and their content
/// </summary>
@@ -28,6 +34,8 @@ public static class OptionsMenuPatches
__instance.transform.FindChild("Tint").SetLocalZ(5.6f);
}
background = __instance.Background;
var maskObj = new GameObject
{
layer = 5,
@@ -54,16 +62,101 @@ public static class OptionsMenuPatches
MaskCollider.isTrigger = true;
MaskCollider.enabled = true;
currentPage = 1;
tabButtons.Clear();
float yOffset = 0;
var i = 0;
int i = 0;
int tabIdx = 0;
int page = 1;
foreach (var settings in LocalSettingsManager.Tabs)
{
settings.CreateTab(__instance, ref i, ref yOffset);
var tab = settings.CreateTab(__instance);
if (settings.ShouldCreateButton)
{
var button = settings.CreateTabButton(__instance, ref tabIdx, ref yOffset);
button.GetComponent<TabGroup>().Content = tab;
button.SetActive(page == currentPage);
if (!tabButtons.TryGetValue(page, out var list))
{
tabButtons.Add(page, new());
list = tabButtons[page];
}
list.Add(button);
yOffset += 0.6f;
tabIdx++;
i++;
}
if (i > 7)
{
i = 0;
yOffset = 0;
page++;
}
}
void ChangePage(int increase)
{
currentPage += increase;
if (currentPage > tabButtons.Count)
{
currentPage = 1;
}
if (currentPage < 1)
{
currentPage = tabButtons.Count;
}
}
// Create page buttons
// TODO: In-game menu has no close button. I tried making one from scratch but failed. Add one later plz
if (tabButtons.Count <= 1)
{
return;
}
var nextButton = Object.Instantiate(__instance.BackButton, __instance.transform).GetComponent<PassiveButton>();
nextButton.transform.localPosition = new Vector3(3.2f, 2.6f, -10);
nextButton.transform.localScale = new Vector2(0.25f, 0.25f);
var nextRend = nextButton.GetComponent<SpriteRenderer>();
nextRend.sprite = MiraAssets.NextButton.LoadAsset();
nextButton.gameObject.GetComponent<CloseButtonConsoleBehaviour>().DestroyImmediate();
var nextRollover = nextButton.gameObject.AddComponent<ButtonRolloverHandler>();
nextRollover.Target = nextRend;
nextRollover.OverColor = Palette.AcceptedGreen;
nextButton.OnClick = new Button.ButtonClickedEvent();
nextButton.OnClick.AddListener(
(UnityAction)(() =>
{
ChangePage(1);
UpdatePages();
}));
var backButton = Object.Instantiate(__instance.BackButton, __instance.transform).GetComponent<PassiveButton>();
backButton.transform.localPosition = new Vector3(2.9f, 2.6f, -10);
backButton.transform.localScale = new Vector2(0.25f, 0.25f);
var backRend = backButton.GetComponent<SpriteRenderer>();
backRend.sprite = MiraAssets.NextButton.LoadAsset();
backRend.flipX = true;
backButton.gameObject.GetComponent<CloseButtonConsoleBehaviour>().DestroyImmediate();
var backRollover = backButton.gameObject.AddComponent<ButtonRolloverHandler>();
backRollover.Target = backRend;
backRollover.OverColor = Palette.AcceptedGreen;
backButton.OnClick = new Button.ButtonClickedEvent();
backButton.OnClick.AddListener(
(UnityAction)(() =>
{
ChangePage(-1);
UpdatePages();
}));
}
/// <summary>
/// Modifies how opening tabs is handled for the custom ones to work
/// Modifies how opening tabs is handled for the custom ones to work.
/// </summary>
[HarmonyPrefix]
[HarmonyPatch(nameof(OptionsMenuBehaviour.OpenTabGroup))]
@@ -72,7 +165,8 @@ public static class OptionsMenuPatches
__instance.Tabs.ToList().ForEach(x => x.Close()); // Close all vanilla tabs
LocalSettingsManager.Tabs.ForEach(CustomClose); // Close all mod tabs
if (index >= 10) // Tabs with index 10 and above are the mod settings tabs
// Tabs with index 10 and above are the mod settings tabs
if (index >= 10)
{
CustomOpen(LocalSettingsManager.Tabs[index - 10]);
return false;
@@ -82,35 +176,51 @@ public static class OptionsMenuPatches
}
/// <summary>
/// Makes the custom tabs close when opening the options menu
/// Makes the custom tabs close when opening the options menu and reset pages.
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(nameof(OptionsMenuBehaviour.Open))]
public static void OpenPostfix(OptionsMenuBehaviour __instance)
{
LocalSettingsManager.Tabs.ForEach(CustomClose);
currentPage = 1;
UpdatePages();
}
private static void UpdatePages()
{
foreach (var pages in tabButtons)
{
pages.Value.Do(x => x.SetActive(pages.Key == currentPage));
}
}
private static void CustomOpen(LocalSettingsTab tab)
{
if (tab.TabButton?.Button)
tab.TabButton!.Button.color = tab.TabHoverColor;
tab.TabButton!.Button.color = tab.TabAppearance.TabButtonHoverColor;
if (tab.TabButton?.Rollover)
tab.TabButton!.Rollover.OutColor = tab.TabHoverColor;
tab.TabButton!.Rollover.OutColor = tab.TabAppearance.TabButtonHoverColor;
if (tab.TabButton?.Content)
tab.TabButton!.Content.SetActive(true);
if (background != null)
background.color = tab.TabAppearance.TabColor;
}
private static void CustomClose(LocalSettingsTab tab)
{
if (tab.TabButton?.Button)
tab.TabButton!.Button.color = tab.TabColor;
tab.TabButton!.Button.color = tab.TabAppearance.TabButtonColor;
if (tab.TabButton?.Rollover)
tab.TabButton!.Rollover.OutColor = tab.TabColor;
tab.TabButton!.Rollover.OutColor = tab.TabAppearance.TabButtonColor;
if (tab.TabButton?.Content)
tab.TabButton!.Content.SetActive(false);
if (background != null)
background.color = Color.white;
}
}
@@ -7,14 +7,15 @@ namespace MiraAPI.Patches.LocalSettings;
public static class ToggleBehaviourPatch
{
/// <summary>
/// ResetText was inlined ofc
/// ResetText was inlined ofc.
/// Skill issue
/// </summary>
[HarmonyPrefix]
[HarmonyPatch(nameof(ToggleButtonBehaviour.UpdateText))]
public static bool ResetTextPrefix(ToggleButtonBehaviour __instance, bool on)
public static bool UpdateTextPrefix(ToggleButtonBehaviour __instance, bool on)
{
__instance.onState = on;
var color = on ? new Color(0f, 1f, 0.16470589f, 1f) : Color.white;
__instance.onState = on;
__instance.Background.color = color;
// Used to mask the text
@@ -22,7 +23,6 @@ public static class ToggleBehaviourPatch
__instance.Text.text = $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">" +
$"{DestroyableSingleton<TranslationController>.Instance.GetString(__instance.BaseText)}: <b>" +
$"{DestroyableSingleton<TranslationController>.Instance.GetString(__instance.onState ? StringNames.SettingsOn : StringNames.SettingsOff)}</b></font>";
__instance.Text.sortingOrder = 151;
__instance.Text.renderer.sortingLayerName = "Default";
__instance.Text.renderer.sortingOrder = 151;
+20
View File
@@ -496,4 +496,24 @@ public static class Helpers
}
return KeyboardKeyCode.None;
}
/// <summary>
/// Returns the formated value using the specified suffix and format string.
/// </summary>
/// <param name="value">The value to format.</param>
/// <param name="suffix">The suffix to add.</param>
/// <param name="formatString">The format string to use to format.</param>
/// <returns>The formated value.</returns>
public static string FormatValue(float value, MiraNumberSuffixes suffix = MiraNumberSuffixes.None, string formatString = "0.0")
{
return suffix 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)]),
};
}
}