Add settings size modifications

This commit is contained in:
AlchlcDvl committed 2025-03-22 00:04:39 -04:00
1 parent 5eba77dba9
commit 94bb5a7a37
10 files changed
+248 -47

No files matched your search

+10
View File
@@ -78,4 +78,14 @@ public interface IModdedOption
/// </summary>
/// <param name="data">The NetData's byte array.</param>
void HandleNetData(byte[] data);
/// <summary>
/// Changes the scales and positions of the option if it's attached to the game options menu.
/// </summary>
void ChangeGameSetting();
/// <summary>
/// Changes the scales and positions of the option if it's attached to the roles settings menu.
/// </summary>
void ChangeRoleSetting();
}
@@ -35,10 +35,7 @@ public class ModdedEnumOption : ModdedOption<int>
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = (values is null
? Enum.GetNames(enumType)
: values)
.Select(CustomStringName.CreateAndRegister).ToArray();
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Value;
}
@@ -51,6 +48,10 @@ public class ModdedEnumOption : ModdedOption<int>
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
// Changing the button text to make them more distinct from number options
stringOption.MinusBtn.ChangeButtonText("<");
stringOption.PlusBtn.ChangeButtonText(">");
// SetUpFromData method doesn't work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
@@ -61,6 +62,32 @@ public class ModdedEnumOption : ModdedOption<int>
return stringOption;
}
/// <inheritdoc />
public override void ChangeGameSetting()
{
var stringOption = OptionBehaviour as StringOption;
stringOption!.MinusBtn.transform.localPosition += new Vector3(0.6f, 0f, 0f);
stringOption.PlusBtn.transform.localPosition += new Vector3(1.5f, 0f, 0f);
// The value box itself becomes the button
stringOption.PlusBtn.gameObject.SetActive(false);
stringOption.MinusBtn.gameObject.SetActive(false);
var background = stringOption.transform.GetChild(0);
background.localPosition += new Vector3(-0.8f, 0f, 0f);
background.localScale += new Vector3(1f, 0f, 0f);
var title = stringOption.TitleText;
title.transform.localPosition = new(-2.0466f, 0f, -2.9968f);
title.GetComponent<RectTransform>().sizeDelta = new(5.8f, 0.458f);
title.fontSize = 2.9f; // Why is it different for string options??
var valueBox = stringOption.transform.GetChild(5);
valueBox.localPosition += new Vector3(1.05f, 0f, 0f);
valueBox.localScale += new Vector3(0.2f, 0f, 0f);
}
/// <inheritdoc />
public override float GetFloatData()
{
@@ -126,10 +153,7 @@ public class ModdedEnumOption<T> : ModdedOption<T> where T : struct, Enum
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = (values is null
? Enum.GetNames<T>()
: values)
.Select(CustomStringName.CreateAndRegister).ToArray();
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Convert.ToInt32(Value, NumberFormatInfo.InvariantInfo);
}
@@ -142,6 +166,10 @@ public class ModdedEnumOption<T> : ModdedOption<T> where T : struct, Enum
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Action<OptionBehaviour>)ValueChanged;
// Changing the button text to make them more distinct from number options
stringOption.MinusBtn.ChangeButtonText("<");
stringOption.PlusBtn.ChangeButtonText(">");
// SetUpFromData method doesn't work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
@@ -152,6 +180,32 @@ public class ModdedEnumOption<T> : ModdedOption<T> where T : struct, Enum
return stringOption;
}
/// <inheritdoc />
public override void ChangeGameSetting()
{
var stringOption = OptionBehaviour as StringOption;
stringOption!.MinusBtn.transform.localPosition += new Vector3(0.6f, 0f, 0f);
stringOption.PlusBtn.transform.localPosition += new Vector3(1.5f, 0f, 0f);
// The value box itself becomes the button
stringOption.PlusBtn.gameObject.SetActive(false);
stringOption.MinusBtn.gameObject.SetActive(false);
var background = stringOption.transform.GetChild(0);
background.localPosition += new Vector3(-0.8f, 0f, 0f);
background.localScale += new Vector3(1f, 0f, 0f);
var title = stringOption.TitleText;
title.transform.localPosition = new(-2.0466f, 0f, -2.9968f);
title.GetComponent<RectTransform>().sizeDelta = new(5.8f, 0.458f);
title.fontSize = 2.9f; // Why is it different for string options??
var valueBox = stringOption.transform.GetChild(5);
valueBox.localPosition += new Vector3(1.05f, 0f, 0f);
valueBox.localScale += new Vector3(0.2f, 0f, 0f);
}
/// <inheritdoc />
public override float GetFloatData()
{
@@ -1,11 +1,15 @@
using AmongUs.GameOptions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Modules;
using MiraAPI.Networking;
using Reactor.Localization.Utilities;
using Reactor.Utilities;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Extensions;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -15,7 +19,7 @@ namespace MiraAPI.GameOptions.OptionTypes;
/// An option for selecting an enum value.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> where T : struct, Enum
public class ModdedMultiSelectOption<T> : ModdedOption<T> where T : struct, Enum
{
/// <summary>
/// Gets the string values of the enum.
@@ -32,6 +36,11 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
/// </summary>
public T None { get; }
/// <summary>
/// Gets the list of buttons that relate to the current instance.
/// </summary>
public List<MonoBehaviour> Buttons { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ModdedMultiSelectOption{T}"/> class.
/// </summary>
@@ -40,35 +49,25 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
/// <param name="all">The all value.</param>
/// <param name="none">The none value.</param>
/// <param name="values">An option list of string values to use in place of the enum name.</param>
/// <exception cref="ArgumentException">The enum type doesn't have the flags attribute.</exception>
public ModdedMultiSelectOption(string title, T defaultValue, T all, T none, string[]? values = null) : base(title, defaultValue)
{
var tType = typeof(T);
if (tType.GetCustomAttribute<FlagsAttribute>() == null)
throw new ArgumentException($"{tType.Name} is not a flag enum type");
Values = values ?? Enum.GetNames<T>();
All = all;
None = none;
Data = ScriptableObject.CreateInstance<MultiSelectGameSetting>();
Buttons = [];
var data = (MultiSelectGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = (values ?? Enum.GetNames<T>()).Select(CustomStringName.CreateAndRegister).ToArray();
}
/// <inheritdoc />
public override void BindConfig()
{
var entry = ParentMod?.GetConfigFile().Bind(ConfigDefinition, DefaultValue.ToString());
if (entry != null)
{
try
{
Value = new MultiSelectValue<T>([.. entry.Value.Split(",").Select(x => Enum.Parse<T>(x.Trim()))]);
}
catch (Exception e)
{
Value = DefaultValue;
Logger<MiraApiPlugin>.Error($"Failed to bind config for {Title}: {e.Message}");
}
}
data.OptionName = Int32OptionNames.Invalid;
data.Type = global::OptionTypes.MultipleChoice; // How nice of the game to provide an enum value themselves
data.EnumNames = []; // We don't initialise the translation here, we just add one as and when needed
}
/// <inheritdoc />
@@ -79,9 +78,23 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Action<OptionBehaviour>)ValueChanged;
var toggle = Object.Instantiate(toggleOpt.GetComponentInChildren<PassiveButton>(), stringOption.transform);
toggle.name = "Button";
toggle.transform.DestroyChildren();
toggle.OverrideOnClickListeners(ToggleButtons);
var box = toggle.GetComponent<BoxCollider2D>();
var prevColliderSize = box.size;
prevColliderSize.x *= 4.97f;
box.size = prevColliderSize;
var rend = stringOption.transform.GetChild(5).GetComponent<SpriteRenderer>();
toggle.OverrideOnMouseOverListeners(() => rend.color = Buttons.Count > 0 ? Color.white : MiraAssets.AcceptedTeal);
toggle.OverrideOnMouseOutListeners(() => rend.color = Buttons.Count > 0 ? MiraAssets.AcceptedTeal : Color.white);
// SetUpFromData method doesn't work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
stringOption.Values = (Data as MultiSelectGameSetting)?.EnumNames?.Values?.ToArray() ?? new Il2CppStructArray<StringNames>(0);
stringOption.Value = Convert.ToInt32(Value, NumberFormatInfo.InvariantInfo);
OptionBehaviour = stringOption;
@@ -89,6 +102,40 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
return stringOption;
}
/// <inheritdoc />
public override void ChangeGameSetting()
{
var stringOption = OptionBehaviour as StringOption;
// The value box itself becomes the button
stringOption!.PlusBtn.gameObject.SetActive(false);
stringOption.MinusBtn.gameObject.SetActive(false);
var background = stringOption.transform.GetChild(0);
background.localPosition += new Vector3(-0.8f, 0f, 0f);
background.localScale += new Vector3(1f, 0f, 0f);
var title = stringOption.TitleText;
title.transform.localPosition = new(-2.0466f, 0f, -2.9968f);
title.GetComponent<RectTransform>().sizeDelta = new(5.8f, 0.458f);
title.fontSize = 2.9f; // Why is it different for string options??
var valueBox = stringOption.transform.GetChild(5);
valueBox.localPosition += new Vector3(1.05f, 0f, 0f);
valueBox.localScale += new Vector3(0.2f, 0f, 0f);
}
private void ToggleButtons()
{
if (Buttons.Count > 0)
{
Buttons.ForEach(x => x.gameObject.Destroy());
return;
}
// TODO: Implement this
}
/// <inheritdoc />
public override float GetFloatData()
{
@@ -98,23 +145,23 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
/// <inheritdoc />
public override NetData GetNetData()
{
return new NetData(Id, Value.ToBytes());
return new NetData(Id, EnumSerializer.EnumToBytes(Value));
}
/// <inheritdoc />
public override void HandleNetData(byte[] data)
{
SetValue(MultiSelectValue<T>.FromBytes(data));
SetValue(EnumSerializer.EnumFromBytes<T>(data, 0));
}
/// <inheritdoc />
public override MultiSelectValue<T> GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
public override T GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return []; // TODO: Add implementation
return Enum.Parse<T>(optionBehaviour.GetInt().ToString(NumberFormatInfo.InvariantInfo));
}
/// <inheritdoc />
protected override void OnValueChanged(MultiSelectValue<T> newValue)
protected override void OnValueChanged(T newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data!.GetValueString(Convert.ToInt32(newValue, NumberFormatInfo.InvariantInfo)), false);
if (!OptionBehaviour)
@@ -112,6 +112,27 @@ public class ModdedNumberOption : ModdedOption<float>
return numberOption;
}
/// <inheritdoc />
public override void ChangeGameSetting()
{
var numberOption = OptionBehaviour as NumberOption;
numberOption!.PlusBtn.transform.localPosition += new Vector3(0.6f, 0f, 0f);
numberOption.MinusBtn.transform.localPosition += new Vector3(1.5f, 0f, 0f);
var background = numberOption.transform.GetChild(0);
background.localPosition += new Vector3(-0.8f, 0f, 0f);
background.localScale += new Vector3(1f, 0f, 0f);
var title = numberOption.TitleText;
title.transform.localPosition = new(-2.0466f, 0f, -2.9968f);
title.GetComponent<RectTransform>().sizeDelta = new(5.8f, 0.458f);
var valueBox = numberOption.transform.GetChild(5);
valueBox.localPosition += new Vector3(1.05f, 0f, 0f);
valueBox.localScale += new Vector3(0.2f, 0f, 0f);
}
/// <inheritdoc />
public override float GetFloatData()
{
@@ -142,7 +163,7 @@ public class ModdedNumberOption : ModdedOption<float>
Value = Mathf.Clamp(newValue, Min, Max);
HudManager.Instance.Notifier.AddSettingsChangeMessage(
StringName,
Data.GetValueString(Value),
Data!.GetValueString(Value),
false);
if (OptionBehaviour is NumberOption opt)
@@ -139,6 +139,15 @@ public abstract class ModdedOption<T> : IModdedOption where T : struct
StringOption stringOpt,
Transform container);
/// <inheritdoc />
public abstract void ChangeGameSetting();
/// <inheritdoc />
public virtual void ChangeRoleSetting()
{
// TODO: Implement this as an abstract
}
/// <summary>
/// Binds the option to the configuration file of the parent mod, if available.
/// </summary>
@@ -41,6 +41,21 @@ public class ModdedToggleOption : ModdedOption<bool>
return toggleOption;
}
/// <inheritdoc />
public override void ChangeGameSetting()
{
var toggleOption = OptionBehaviour as ToggleOption;
toggleOption!.transform.GetChild(1).localPosition += new Vector3(2.2f, 0f, 0f); // Checkbox
var title = toggleOption.TitleText;
title.transform.localPosition = new(-2.0466f, 0f, -2.9968f);
title.GetComponent<RectTransform>().sizeDelta = new(5.8f, 0.458f);
var background = toggleOption.transform.GetChild(2);
background.localPosition += new Vector3(-0.8f, 0f, 0f);
background.localScale += new Vector3(1f, 0f, 0f);
}
/// <inheritdoc />
public override float GetFloatData()
{
+4 -8
View File
@@ -1,7 +1,9 @@
// TODO: Remove later before completing the pr
#pragma warning disable
using System;
using System.Collections.Generic;
using AmongUs.GameOptions;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Reactor.Utilities.Attributes;
@@ -10,14 +12,8 @@ namespace MiraAPI.Modules;
[RegisterInIl2Cpp, Serializable]
public class MultiSelectGameSetting : BaseGameSetting
{
public MultiSelectGameSetting() => Type = OptionTypes.MultipleChoice; // How nice of the game to provide an enum value themselves
public override string GetValueString(float value)
{
return TranslationController.Instance.GetString(default(StringNames), null, null);
}
public Int32OptionNames OptionName;
public Dictionary<int, StringNames> EnumNames;
public Il2CppStructArray<StringNames> Values;
public override string GetValueString(float value) => TranslationController.Instance.GetString(EnumNames[(int)value]);
}
@@ -226,6 +226,8 @@ public static class GameOptionsMenuPatch
menu.stringOptionOrigin,
menu.settingsContainer));
group.Options.ForEach(x => x.ChangeGameSetting());
foreach (var newOpt in options)
{
newOpt.SetClickMask(menu.ButtonClickMask);
@@ -325,6 +325,7 @@ public static class RoleSettingMenuPatches
newOpt.transform.localPosition = new Vector3(hasImage ? 2.17f : 1.1f, num, -2f);
newOpt.SetClickMask(__instance.ButtonClickMask);
option.ChangeRoleSetting();
SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren<SpriteRenderer>(true);
foreach (var renderer in componentsInChildren)
+46
View File
@@ -431,4 +431,50 @@ public static class Helpers
items.Do(x => result += $"{separator}{x}");
return result[separator.Length..];
}
/// <summary>
/// Shorthand helper for overriding the on click listeners for PassiveButton.
/// </summary>
/// <param name="passive">The PassiveButton being modified.</param>
/// <param name="action">The action that's replacing the original listeners.</param>
public static void OverrideOnClickListeners(this PassiveButton passive, Action action)
{
if (!passive)
return;
passive.OnClick?.RemoveAllListeners();
passive.OnClick = new();
passive.OnClick.AddListener(action);
passive.enabled = true;
}
/// <summary>
/// Shorthand helper for overriding the on mouse over listeners for PassiveButton.
/// </summary>
/// <inheritdoc cref="OverrideOnClickListeners"/>
public static void OverrideOnMouseOverListeners(this PassiveButton passive, Action action)
{
if (!passive)
return;
passive.OnMouseOver?.RemoveAllListeners();
passive.OnMouseOver = new();
passive.OnMouseOver.AddListener(action);
passive.enabled = true;
}
/// <summary>
/// Shorthand helper for overriding the on mouse out listeners for PassiveButton.
/// </summary>
/// <inheritdoc cref="OverrideOnClickListeners"/>
public static void OverrideOnMouseOutListeners(this PassiveButton passive, Action action)
{
if (!passive)
return;
passive.OnMouseOut?.RemoveAllListeners();
passive.OnMouseOut = new();
passive.OnMouseOut.AddListener(action);
passive.enabled = true;
}
}