From c15ba69533cd191f2b956452d37c465ce58bcaa8 Mon Sep 17 00:00:00 2001 From: XtraCube <72575280+XtraCube@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:37:10 -0400 Subject: [PATCH] Options management cleanup + fixes --- MiraAPI/GameOptions/IModdedOption.cs | 2 +- MiraAPI/GameOptions/ModdedOptionsManager.cs | 23 +++--- .../GameOptions/OptionTypes/ModdedOption.cs | 8 +-- MiraAPI/MiraAPI.csproj | 1 + .../Patches/Options/GameOptionsMenuPatch.cs | 67 +++++++++++------- .../Patches/Options/RoleSettingMenuPatches.cs | 4 +- MiraAPI/Patches/Roles/NameTagPatch.cs | 2 - MiraAPI/PluginLoading/MiraPluginManager.cs | 12 +++- MiraAPI/Resources/Empty.png | Bin 0 -> 6349 bytes MiraAPI/Utilities/Assets/MiraAssets.cs | 2 +- MiraAPI/Utilities/Extensions.cs | 2 +- 11 files changed, 73 insertions(+), 50 deletions(-) create mode 100644 MiraAPI/Resources/Empty.png diff --git a/MiraAPI/GameOptions/IModdedOption.cs b/MiraAPI/GameOptions/IModdedOption.cs index 232cf5a..a041cc7 100644 --- a/MiraAPI/GameOptions/IModdedOption.cs +++ b/MiraAPI/GameOptions/IModdedOption.cs @@ -9,7 +9,7 @@ public interface IModdedOption { public uint Id { get; } public BaseGameSetting Data { get; } - public IModdedOptionGroup Group { get; set; } + public bool HasGroup { get; set; } public IMiraPlugin ParentMod { get; set; } public Type AdvancedRole { get; set; } public OptionBehaviour OptionBehaviour { get; protected set; } diff --git a/MiraAPI/GameOptions/ModdedOptionsManager.cs b/MiraAPI/GameOptions/ModdedOptionsManager.cs index 0d8e15f..88228a7 100644 --- a/MiraAPI/GameOptions/ModdedOptionsManager.cs +++ b/MiraAPI/GameOptions/ModdedOptionsManager.cs @@ -12,12 +12,16 @@ namespace MiraAPI.GameOptions; public class ModdedOptionsManager { - public static readonly Dictionary ModdedOptions = new(); - public static readonly List Options = []; - public static readonly List Groups = []; private static readonly Dictionary OptionAttributes = new(); - public static readonly Dictionary OriginalTypes = new(); - public static uint NextId = 1; + + public static readonly Dictionary ModdedOptions = new(); + public static readonly Dictionary> GroupedOptions = new(); + + public static readonly List Groups = []; + public static readonly Dictionary TypeToGroup = new(); + + public static uint NextId => _nextId++; + private static uint _nextId = 1; public static IModdedOption RegisterOption(Type type, ModdedOptionAttribute attribute, PropertyInfo property) { @@ -50,11 +54,12 @@ public class ModdedOptionsManager OptionAttributes.Add(property, attribute); - if (OriginalTypes.ContainsKey(type)) + if (TypeToGroup.ContainsKey(type)) { - Logger.Error($"Grouping {attribute.Title} with {OriginalTypes[type].GroupName}"); - result.Group = OriginalTypes[type]; - result.AdvancedRole = OriginalTypes[type].AdvancedRole; + Logger.Error($"Grouping {attribute.Title} with {TypeToGroup[type].GroupName}"); + GroupedOptions[TypeToGroup[type]].Add(result); + result.HasGroup = true; + result.AdvancedRole = TypeToGroup[type].AdvancedRole; } } diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs index 386cc7c..3021cd1 100644 --- a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs +++ b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs @@ -4,7 +4,6 @@ using Reactor.Localization.Utilities; using System; using MiraAPI.Networking; using Reactor.Networking.Rpc; -using Reactor.Utilities; using UnityEngine; namespace MiraAPI.GameOptions.OptionTypes; @@ -13,6 +12,8 @@ public abstract class ModdedOption : IModdedOption { public uint Id { get; } public BaseGameSetting Data { get; protected init; } + public bool HasGroup { get; set; } = false; + public IMiraPlugin ParentMod { get; set; } = null; public T Value { get; protected set; } public T DefaultValue { get; init; } public Action ChangedEvent { get; set; } @@ -21,8 +22,6 @@ public abstract class ModdedOption : IModdedOption public Func Visible { get; set; } public Type AdvancedRole { get; set; } public OptionBehaviour OptionBehaviour { get; set; } - public IModdedOptionGroup Group { get; set; } = null; - public IMiraPlugin ParentMod { get; set; } = null; protected ModdedOption(string title, T defaultValue, Type roleType) : this() { @@ -40,8 +39,7 @@ public abstract class ModdedOption : IModdedOption private ModdedOption() { - Id = ModdedOptionsManager.NextId++; - ModdedOptionsManager.Options.Add(this); + Id = ModdedOptionsManager.NextId; ModdedOptionsManager.ModdedOptions.Add(Id, this); } diff --git a/MiraAPI/MiraAPI.csproj b/MiraAPI/MiraAPI.csproj index aad0751..0de367f 100644 --- a/MiraAPI/MiraAPI.csproj +++ b/MiraAPI/MiraAPI.csproj @@ -22,6 +22,7 @@ + diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs index 20e1d96..580add3 100644 --- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs +++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs @@ -22,7 +22,10 @@ public static class GameOptionsMenuPatch __instance.MapPicker.gameObject.SetActive(false); float num = 2.1f; - foreach (IModdedOptionGroup group in GameSettingMenuPatches.SelectedMod.OptionGroups) + + var filteredGroups = GameSettingMenuPatches.SelectedMod.OptionGroups.Where(x => x.AdvancedRole is null); + + foreach (IModdedOptionGroup group in filteredGroups) { CategoryHeaderMasked categoryHeaderMasked = Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer); categoryHeaderMasked.SetHeader(CustomStringName.CreateAndRegister(group.GroupName), 20); @@ -35,7 +38,7 @@ public static class GameOptionsMenuPatch categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, num, -2f); num -= 0.63f; - foreach (var opt in ModdedOptionsManager.Options.Where(opt => opt.Group is not null && opt.AdvancedRole is null && opt.Group.GroupName == group.GroupName)) + foreach (var opt in ModdedOptionsManager.GroupedOptions[group]) { OptionBehaviour newOpt = opt.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.settingsContainer); newOpt.transform.localPosition = new Vector3(0.952f, num, -2f); @@ -62,36 +65,46 @@ public static class GameOptionsMenuPatch } } - CategoryHeaderMasked ungroupedHeader = Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer); - ungroupedHeader.SetHeader(CustomStringName.CreateAndRegister("Ungrouped Options"), 20); - ungroupedHeader.transform.localScale = Vector3.one * 0.63f; - ungroupedHeader.transform.localPosition = new Vector3(-0.903f, num, -2f); + var filteredOptions = GameSettingMenuPatches.SelectedMod.Options.Where(x => x.AdvancedRole is null && !x.HasGroup).ToList(); - num -= 0.63f; - - foreach (var opt in ModdedOptionsManager.Options.Where(opt => opt.Group is null && opt.AdvancedRole is null)) + if (filteredOptions.Count > 0) { - OptionBehaviour newOpt = opt.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.settingsContainer); - newOpt.transform.localPosition = new Vector3(0.952f, num, -2f); - newOpt.SetClickMask(__instance.ButtonClickMask); - newOpt.SetUpFromData(newOpt.data, 20); - SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren(true); - for (int i = 0; i < componentsInChildren.Length; i++) + CategoryHeaderMasked ungroupedHeader = Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, + Quaternion.identity, __instance.settingsContainer); + ungroupedHeader.SetHeader(CustomStringName.CreateAndRegister("Ungrouped Options"), 20); + ungroupedHeader.transform.localScale = Vector3.one * 0.63f; + ungroupedHeader.transform.localPosition = new Vector3(-0.903f, num, -2f); + + num -= 0.63f; + + + foreach (var opt in filteredOptions) { - componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20); + OptionBehaviour newOpt = opt.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, + __instance.stringOptionOrigin, __instance.settingsContainer); + newOpt.transform.localPosition = new Vector3(0.952f, num, -2f); + newOpt.SetClickMask(__instance.ButtonClickMask); + newOpt.SetUpFromData(newOpt.data, 20); + + SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren(true); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20); + } + + foreach (TextMeshPro textMeshPro in newOpt.GetComponentsInChildren(true)) + { + textMeshPro.fontMaterial.SetFloat(ShaderID.StencilComp, 3f); + textMeshPro.fontMaterial.SetFloat(ShaderID.Stencil, 20); + } + + __instance.Children.Add(newOpt); + + num -= 0.45f; + + newOpt.Initialize(); } - foreach (TextMeshPro textMeshPro in newOpt.GetComponentsInChildren(true)) - { - textMeshPro.fontMaterial.SetFloat(ShaderID.StencilComp, 3f); - textMeshPro.fontMaterial.SetFloat(ShaderID.Stencil, 20); - } - - __instance.Children.Add(newOpt); - - num -= 0.45f; - - newOpt.Initialize(); } __instance.scrollBar.SetYBoundsMax(-num - 1.65f); diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs index ff62645..4bd63e7 100644 --- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs @@ -139,8 +139,10 @@ public static class RoleSettingMenuPatches __instance.advancedSettingChildren.Clear(); float num = -0.872f; - foreach (var option in GameSettingMenuPatches.SelectedMod.Options.Where(option => option.AdvancedRole != null && option.AdvancedRole == role.GetType())) + foreach (var option in GameSettingMenuPatches.SelectedMod.Options) { + if (option.AdvancedRole is not null && option.AdvancedRole != role.GetType()) continue; + OptionBehaviour newOpt = option.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.AdvancedRolesSettings.transform); newOpt.transform.localPosition = new Vector3(2.17f, num, -2f); newOpt.SetClickMask(__instance.ButtonClickMask); diff --git a/MiraAPI/Patches/Roles/NameTagPatch.cs b/MiraAPI/Patches/Roles/NameTagPatch.cs index 3566416..929ccaf 100644 --- a/MiraAPI/Patches/Roles/NameTagPatch.cs +++ b/MiraAPI/Patches/Roles/NameTagPatch.cs @@ -1,6 +1,4 @@ using HarmonyLib; -using MiraAPI.GameModes; -using MiraAPI.GameOptions; using UnityEngine; namespace MiraAPI.Patches.Roles; diff --git a/MiraAPI/PluginLoading/MiraPluginManager.cs b/MiraAPI/PluginLoading/MiraPluginManager.cs index 6ac174e..17235bd 100644 --- a/MiraAPI/PluginLoading/MiraPluginManager.cs +++ b/MiraAPI/PluginLoading/MiraPluginManager.cs @@ -74,9 +74,11 @@ public class MiraPluginManager if (typeof(IModdedOptionGroup).IsAssignableFrom(type)) { IModdedOptionGroup group = (IModdedOptionGroup)Activator.CreateInstance(type); + if (group == null) continue; ModdedOptionsManager.Groups.Add(group); - ModdedOptionsManager.OriginalTypes.Add(type, group); + ModdedOptionsManager.TypeToGroup.Add(type, group); + ModdedOptionsManager.GroupedOptions.Add(group, []); pluginInfo.OptionGroups.Add(group); foreach (var property in type.GetProperties()) @@ -84,9 +86,13 @@ public class MiraPluginManager if (typeof(IModdedOption).IsAssignableFrom(property.PropertyType)) { IModdedOption option = (IModdedOption)property.GetValue(group); - group.Options.Add(option); - option.Group = group; + if (option == null) continue; + + option.HasGroup = true; option.AdvancedRole = group.AdvancedRole; + + ModdedOptionsManager.GroupedOptions[group].Add(option); + pluginInfo.Options.Add(option); } } } diff --git a/MiraAPI/Resources/Empty.png b/MiraAPI/Resources/Empty.png new file mode 100644 index 0000000000000000000000000000000000000000..478b531a69b64666a507ee45a95312a2369cba6c GIT binary patch literal 6349 zcmeHIe@qi+7(Nshgs|Y;gt)~Whr%+_-nIPf*^`vE+D_V3TBXPUukE!xZF}9_RSFTu z*u?BdqUZ!6n30V|+}w=QC2TM!*_?|bCc4ExbO~FGbJ0d2+t`K%_uUmrS%=x*p>MNl?ug_s8T5d3>nuH;K{Hoz~u@qqCRvK z=Va+1Pcs2n@JTwD5KkZoz~R}*{K1&>05_98&;bpTK~y2f(0Fpt%kT{6Wfm}r!3l;` zn4ZgF-ZcV}K<8=q0(1dMpaZQg&HuBZjL4cD?1$x}M82t|5r)OcCdNg(oBorm!V3j5 z9?u5l;UanR|L|ji;{rPx6e!I{Ml@%mWqb?^f&)1eiowo7My=MuGH%)jFs^E21#Hx7 zOBAY-5}8u25V^v;;TAef`RqE{PX#zoV+5kW%A$GC!8HrQ;{8_8Uf`0bQ{i=Sqo4Fp z)wGNE#`&8=Dye`c5fa|X7ZM76OMnJ1s}zG2t?Y9cfs`uIxT|UsAfa_&wOCNNf#!II zZ4!^7{bZ$HiteIYA1yW#42$K2lTP7&0tvE=E99hHVhF%p6y+E<-$=5Q#seyeKs0VQ z4I*uVEkaMhN?0kMl{RM5=%s+Wf4yd0$)Gc#p+axZ#->ISqF0NAxM2Y7qGw>pfN6!s z#ueDa1|AgvrNn}9cK+lkD+DFILW816ClQgqdLV9kZTfu`fD4`pW&dAa(L$iuO-w^%S4j zyXoMTAD`I&)pgaG_P#rh_f&sJd>G*-lSfQ{e^6Ui_F9r^?CfNE*DcS3V_mJo;JdUe zXsF>JD1C*nlAxa6YzSIDYSd|L;oitdQWBuF9+*CPH&yuXNk2&eNdZX#NdZX#NdZX# zNdZX#NdZX#NdZX#Nr6SJK opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour)); + return ModdedOptionsManager.ModdedOptions.Values.Any(opt => opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour)); } public static Color DarkenColor(this Color color)