diff --git a/MiraAPI/LocalSettings/ILocalSetting.cs b/MiraAPI/LocalSettings/ILocalSetting.cs index b51a13d..9bc4bbd 100644 --- a/MiraAPI/LocalSettings/ILocalSetting.cs +++ b/MiraAPI/LocalSettings/ILocalSetting.cs @@ -39,4 +39,9 @@ public interface ILocalSetting /// Whether it's the last on the row. /// The created setting's . GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last); + + /// + /// Used to refresh the setting's information, usually for localization. + /// + void RefreshOption(); } diff --git a/MiraAPI/LocalSettings/LocalSettingsTab.cs b/MiraAPI/LocalSettings/LocalSettingsTab.cs index 7fc7e1d..e22f834 100644 --- a/MiraAPI/LocalSettings/LocalSettingsTab.cs +++ b/MiraAPI/LocalSettings/LocalSettingsTab.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using BepInEx.Configuration; using HarmonyLib; +using MiraAPI.LocalSettings.SettingTypes; using MiraAPI.Patches.LocalSettings; using MiraAPI.Translation; using MiraAPI.Utilities; @@ -53,6 +54,11 @@ public abstract class LocalSettingsTab(ConfigFile config) /// public List Settings { get; } = []; + /// + /// Gets a collection of s alongside the locale keys for them. + /// + public Dictionary Labels { get; } = []; + /// /// Gets the list of s. /// @@ -74,12 +80,21 @@ public abstract class LocalSettingsTab(ConfigFile config) } /// - /// Attempts to open the tab. + /// Refreshes setting names upon opening the tab. /// Override for custom behavior. /// public virtual void Open() { - OptionsMenuPatches.Instance?.OpenTabGroup(TabIndex); + foreach (var setting in Settings) + { + setting.RefreshOption(); + } + + foreach (var label in Labels) + { + label.Key.text = + $"{label.Value.Translate()}"; + } } /// @@ -273,7 +288,7 @@ public abstract class LocalSettingsTab(ConfigFile config) return tabButtonObject.gameObject; } - private static void CreateLabel(GameObject template, Transform parent, string text, ref float offset) + private void CreateLabel(GameObject template, Transform parent, string text, ref float offset) { var label = Object.Instantiate(template, parent); label.transform.localPosition = new Vector3(0, 1.85f - offset); @@ -281,6 +296,7 @@ public abstract class LocalSettingsTab(ConfigFile config) label.name = text; var tmp = label.GetComponent(); + Labels.Add(tmp, text); tmp.text = $"{text.Translate()}"; tmp.alignment = TextAlignmentOptions.Center; diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs index ac0f858..e1e0c7b 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs @@ -26,6 +26,10 @@ public class LocalEnumSetting : LocalSettingBase /// public string[] Values { get; } + private SpriteRenderer _highlight { get; set; } + + private TextMeshPro _btnText { get; set; } + /// /// Initializes a new instance of the class. /// @@ -54,6 +58,7 @@ public class LocalEnumSetting : LocalSettingBase { var button = Object.Instantiate(toggle, parent).GetComponent(); var tmp = button.transform.FindChild("Text_TMP").GetComponent(); + _btnText = tmp; var rollover = button.GetComponent(); tmp.GetComponent().Destroy(); button.gameObject.SetActive(true); @@ -63,6 +68,7 @@ public class LocalEnumSetting : LocalSettingBase var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent(); if (highlight != null) { + _highlight = highlight; highlight.color = Tab!.TabAppearance.EnumHoverColor; highlight.gameObject.SetActive(false); } @@ -125,9 +131,19 @@ public class LocalEnumSetting : LocalSettingBase return button.gameObject; } + /// + public override void RefreshOption() + { + _btnText.text = GetValueText(); + if (_highlight) + { + _highlight.gameObject.SetActive(false); + } + } + /// protected override string GetValueText() { - return $"{Name.Translate()}: {Values[GetValue()]}"; + return $"{Name.Translate()}: {Values[GetValue()].Translate()}"; } } diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs index 75d1fde..f37ea80 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs @@ -35,6 +35,10 @@ public class LocalNumberSetting : LocalSettingBase /// public MiraNumberSuffixes SuffixType { get; } + private SpriteRenderer _highlight { get; set; } + + private TextMeshPro _btnText { get; set; } + /// /// Initializes a new instance of the class. /// @@ -65,6 +69,7 @@ public class LocalNumberSetting : LocalSettingBase { var button = Object.Instantiate(toggle, parent).GetComponent(); var tmp = button.transform.FindChild("Text_TMP").GetComponent(); + _btnText = tmp; var rollover = button.GetComponent(); tmp.GetComponent().Destroy(); button.gameObject.SetActive(true); @@ -74,6 +79,7 @@ public class LocalNumberSetting : LocalSettingBase var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent(); if (highlight != null) { + _highlight = highlight; highlight.color = Tab!.TabAppearance.NumberHoverColor; highlight.gameObject.SetActive(false); } @@ -136,6 +142,16 @@ public class LocalNumberSetting : LocalSettingBase return button.gameObject; } + /// + public override void RefreshOption() + { + _btnText.text = GetValueText(); + if (_highlight) + { + _highlight.gameObject.SetActive(false); + } + } + /// protected override string GetValueText() { diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs index d7c2c64..e26f6ce 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs @@ -54,6 +54,9 @@ public abstract class LocalSettingBase : ILocalSetting /// The created setting. public abstract GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last); + /// + public abstract void RefreshOption(); + /// /// Returns the formated string to use in the text of the setting. /// diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs index eb59cce..2a90bfd 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs @@ -40,6 +40,8 @@ public class LocalSliderSetting : LocalSettingBase /// public MiraNumberSuffixes SuffixType { get; } + private SlideBar _slider { get; set; } + /// /// Initializes a new instance of the class. /// @@ -71,6 +73,7 @@ public class LocalSliderSetting : LocalSettingBase 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(); + _slider = newSlider; 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(); @@ -105,6 +108,12 @@ public class LocalSliderSetting : LocalSettingBase return newSlider.gameObject; } + /// + public override void RefreshOption() + { + _slider.Title.text = GetValueText(); + } + /// protected override string GetValueText() { diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs index 3cb02e3..f28b6db 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs @@ -15,6 +15,8 @@ namespace MiraAPI.LocalSettings.SettingTypes; /// public class LocalToggleSetting : LocalSettingBase { + private ToggleButtonBehaviour _toggle { get; set; } + /// /// Initializes a new instance of the class. /// @@ -32,6 +34,7 @@ public class LocalToggleSetting : LocalSettingBase 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(); + _toggle = toggleObject; var tmp = toggleObject.transform.FindChild("Text_TMP").GetComponent(); var passiveButton = toggleObject.GetComponent(); var rollover = toggleObject.GetComponent(); @@ -86,4 +89,11 @@ public class LocalToggleSetting : LocalSettingBase return toggleObject.gameObject; } + + /// + public override void RefreshOption() + { + _toggle.UpdateText(GetValue()); + _toggle.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor; + } } diff --git a/MiraAPI/Patches/LocalSettings/OptionsMenuPatches.cs b/MiraAPI/Patches/LocalSettings/OptionsMenuPatches.cs index a8cab15..75edd5e 100644 --- a/MiraAPI/Patches/LocalSettings/OptionsMenuPatches.cs +++ b/MiraAPI/Patches/LocalSettings/OptionsMenuPatches.cs @@ -213,6 +213,8 @@ public static class OptionsMenuPatches if (background != null) background.color = tab.TabAppearance.TabColor; + + tab.Open(); } private static void CustomClose(LocalSettingsTab tab) { diff --git a/MiraAPI/Translation/MiraLocaleManager.cs b/MiraAPI/Translation/MiraLocaleManager.cs index 9f9bfd7..a34f22f 100644 --- a/MiraAPI/Translation/MiraLocaleManager.cs +++ b/MiraAPI/Translation/MiraLocaleManager.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Xml; +using MiraAPI.Utilities; using Reactor.Localization.Utilities; using UnityEngine; @@ -97,7 +98,22 @@ public static class MiraLocaleManager var callingAssembly = Assembly.GetCallingAssembly(); var dir = GetModLangDir(modGuid); - LoadInternalStrings(callingAssembly, modGuid, dir); + LoadInternalStrings(callingAssembly, callingAssembly.GetName().Name!, modGuid, dir); + } + + /// + /// Registers translations for a mod. Copies embedded XML to mira_languages/{modGuid}/ on first run, + /// then loads all XML files from that directory into memory. + /// Call once per mod during plugin Load(). + /// + /// The mod GUID (e.g., "mira.example"). + /// The mod's root namespace (e.g., "mira.api"). + public static void Register(string modGuid, string internalName) + { + var callingAssembly = Assembly.GetCallingAssembly(); + var dir = GetModLangDir(modGuid); + + LoadInternalStrings(callingAssembly, internalName, modGuid, dir); } /// @@ -194,7 +210,7 @@ public static class MiraLocaleManager return newString; } - private static void LoadInternalStrings(Assembly assembly, string modGuid, string dir) + private static void LoadInternalStrings(Assembly assembly, string internalName, string modGuid, string dir) { Directory.CreateDirectory(dir); @@ -203,8 +219,9 @@ public static class MiraLocaleManager Locale[modGuid] = []; } - var resourcePrefix = $"{assembly.GetName().Name}.Resources.Locale."; + var resourcePrefix = $"{internalName}.Resources.Locale."; + var atLeastOneLoaded = false; foreach (var locale in LangList) { using var resourceStream = @@ -221,7 +238,8 @@ public static class MiraLocaleManager { var dict = ParseXmlFile(xmlContent); Locale[modGuid][locale.Key] = dict; - Info($"Loaded {locale.Key} translation for mod {modGuid} ({dict.Count} keys)"); + Info($"Loaded {locale.Key.ToDisplayString()} translation for mod {modGuid} ({dict.Count} keys)"); + atLeastOneLoaded = true; } catch (Exception e) { @@ -229,6 +247,11 @@ public static class MiraLocaleManager } } + if (!atLeastOneLoaded) + { + Error($"No internal strings were found for {internalName}!"); + } + if (!Locale.TryGetValue(modGuid, out _)) { Locale[modGuid] = []; @@ -247,11 +270,11 @@ public static class MiraLocaleManager { var dict = ParseXmlFile(filePath); Locale[modGuid][lang] = dict; - Info($"Loaded {lang} translation for mod {modGuid} ({dict.Count} keys)"); + Info($"Loaded external {lang.ToDisplayString()} translation for mod {modGuid} ({dict.Count} keys)"); } catch (Exception e) { - Error($"Failed to load translation {filePath}: {e.Message}"); + Error($"Failed to load external translation {filePath}: {e.Message}"); } } }