Compare commits

..
16 Commits
21 changed files with 214 additions and 85 deletions

No files matched your search

+6
View File
@@ -105,5 +105,11 @@ dotnet_diagnostic.S1244.severity = none
# S2325: Methods and properties that don't access instance data should be static
dotnet_diagnostic.S2325.severity = none
# CA1710: Identifiers should have correct suffix
dotnet_diagnostic.CA1710.severity = silent
# CA1010: Generic interface should also be implemented
dotnet_diagnostic.CA1010.severity = silent
# IDE0005: Using directive is unnecessary.
dotnet_diagnostic.IDE0005.severity = warning
@@ -15,7 +15,7 @@ namespace MiraAPI.GameOptions.Attributes;
public class ModdedEnumOptionListAttribute(string title, Type enumType, string[]? values = null)
: ModdedOptionListAttribute(title)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedEnumOption>(
value.Count, idx => new(GetFormattedTitle(idx), (int)(value[idx] ?? 0), enumType, values));
@@ -25,14 +25,14 @@ public class ModdedEnumOptionListAttribute(string title, Type enumType, string[]
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedEnumOption;
var opt = HolderOptionList?.ElementAt(idx) as ModdedEnumOption;
opt?.SetValue((int)value);
}
/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedEnumOption opt
return HolderOptionList?.ElementAt(idx) is ModdedEnumOption opt
? Enum.ToObject(enumType, opt.Value)
: throw new InvalidOperationException($"HolderOption for option \"{GetFormattedTitle(idx)}\" with EnumType {enumType.FullName} is not a ModdedEnumOption");
}
@@ -49,7 +49,7 @@ public class ModdedEnumOptionListAttribute<T>(string title, string[]? values = n
: ModdedOptionListAttribute(title)
where T : struct, Enum
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedEnumOption<T>>(
value.Count, idx => new(GetFormattedTitle(idx), (T)(value[idx] ?? 0), values));
@@ -59,14 +59,14 @@ public class ModdedEnumOptionListAttribute<T>(string title, string[]? values = n
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedEnumOption<T>;
var opt = HolderOptionList?.ElementAt(idx) as ModdedEnumOption<T>;
opt?.SetValue((T)value);
}
/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedEnumOption<T> opt
return HolderOptionList?.ElementAt(idx) is ModdedEnumOption<T> opt
? opt.Value
: throw new InvalidOperationException($"HolderOption for option \"{GetFormattedTitle(idx)}\" with EnumType {typeof(T).FullName} is not a ModdedEnumOption<{typeof(T).FullName}>");
}
@@ -53,7 +53,7 @@ public class ModdedNumberOptionListAttribute(
{
}
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
return new ModdedOptionList<ModdedNumberOption>(value.Count, idx =>
{
@@ -81,7 +81,7 @@ public class ModdedNumberOptionListAttribute(
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
if (HolderOptionList?[idx] is not ModdedNumberOption opt)
if (HolderOptionList?.ElementAt(idx) is not ModdedNumberOption opt)
return;
var final = value switch
@@ -95,7 +95,7 @@ public class ModdedNumberOptionListAttribute(
/// <inheritdoc />
public override object GetValue(int idx)
{
if (HolderOptionList?[idx] is not ModdedNumberOption opt)
if (HolderOptionList?.ElementAt(idx) is not ModdedNumberOption opt)
throw new InvalidOperationException($"HolderOption for option \"{GetFormattedTitle(idx)}\" is not a ModdedNumberOption");
var value = opt.Value;
@@ -14,7 +14,7 @@ namespace MiraAPI.GameOptions.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public abstract class ModdedOptionListAttribute(string title) : PropertyOptionAttribute
{
internal IModdedOptionList? HolderOptionList { get; set; }
internal IBaseModdedOptionList? HolderOptionList { get; set; }
internal IList? Value { get; set; }
internal Type ValueType { get; set; }
@@ -68,7 +68,7 @@ public abstract class ModdedOptionListAttribute(string title) : PropertyOptionAt
/// <returns>The value of the option as an object.</returns>
public abstract object GetValue(int idx);
internal abstract IModdedOptionList? CreateOptionList(IList value, PropertyInfo property);
internal abstract IBaseModdedOptionList? CreateOptionList(IList value, PropertyInfo property);
/// <summary>
/// Gets the <see cref="Title"/> formatted with the option's index.
@@ -16,7 +16,7 @@ public class ModdedPlayerOptionListAttribute(
bool allowNone = true)
: ModdedOptionListAttribute(title)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
return new ModdedOptionList<ModdedPlayerOption>(value.Count, idx =>
{
@@ -27,7 +27,7 @@ public class ModdedPlayerOptionListAttribute(
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
if (HolderOptionList?[idx] is not ModdedPlayerOption opt)
if (HolderOptionList?.ElementAt(idx) is not ModdedPlayerOption opt)
return;
var final = value switch
@@ -41,7 +41,7 @@ public class ModdedPlayerOptionListAttribute(
/// <inheritdoc />
public override object GetValue(int idx)
{
if (HolderOptionList?[idx] is not ModdedPlayerOption opt)
if (HolderOptionList?.ElementAt(idx) is not ModdedPlayerOption opt)
throw new InvalidOperationException($"HolderOption for option \"{GetFormattedTitle(idx)}\" is not a ModdedPlayerOption");
if (ValueType == typeof(int))
@@ -17,7 +17,7 @@ public class ModdedStringOptionListAttribute(
string[] values)
: ModdedOptionListAttribute(title)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
return new ModdedOptionList<ModdedStringOption>(value.Count, idx =>
{
@@ -28,14 +28,14 @@ public class ModdedStringOptionListAttribute(
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedStringOption;
var opt = HolderOptionList?.ElementAt(idx) as ModdedStringOption;
opt?.SetValue((string)value);
}
/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedStringOption opt
return HolderOptionList?.ElementAt(idx) is ModdedStringOption opt
? opt.Value
: throw new InvalidOperationException($"HolderOption for option \"{GetFormattedTitle(idx)}\" is not a ModdedStringOption");
}
@@ -27,7 +27,7 @@ public class ModdedToggleOptionListAttribute(
{
}
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
internal override IBaseModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedToggleOption>(
value.Count, idx => new(GetFormattedTitle(idx), (bool)(value[idx] ?? false), on, off));
@@ -37,14 +37,14 @@ public class ModdedToggleOptionListAttribute(
/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedToggleOption;
var opt = HolderOptionList?.ElementAt(idx) as ModdedToggleOption;
opt?.SetValue((bool)value);
}
/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedToggleOption opt
return HolderOptionList?.ElementAt(idx) is ModdedToggleOption opt
? opt.Value
: throw new InvalidOperationException($"Holder option for {GetFormattedTitle(idx)} is not a ModdedToggleOption.");
}
+27 -8
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BepInEx.Configuration;
using MiraAPI.Networking;
@@ -143,9 +144,11 @@ public interface IModdedOption
}
/// <summary>
/// Interface for list of modded options.
/// Base interface for list of modded options.
/// <para/>
/// Do not implement directly, implement <see cref="IModdedOptionList"/> or <see cref="IModdedOptionList{T}"/> instead.
/// </summary>
public interface IModdedOptionList : IReadOnlyList<IModdedOption>
public interface IBaseModdedOptionList : IEnumerable
{
/// <summary>
/// Gets the function to name the keys of the individual options in the configuration file.
@@ -153,18 +156,34 @@ public interface IModdedOptionList : IReadOnlyList<IModdedOption>
/// Return <see langword="null"/> to use the default of the property's name with its index appended.
/// </summary>
Func<int, string>? ConfigName { get; init; }
/// <inheritdoc cref="IReadOnlyCollection{T}.Count"/>
int Count { get; }
/// <inheritdoc cref="System.Linq.Enumerable.ElementAt{TSource}(IEnumerable{TSource}, int)"/>
IModdedOption ElementAt(int index);
}
/// <summary>
/// Interface for list of modded options.
/// </summary>
public interface IModdedOptionList : IBaseModdedOptionList, IReadOnlyList<IModdedOption>
{
IModdedOption IBaseModdedOptionList.ElementAt(int index)
{
return this[index];
}
}
/// <summary>
/// Interface for list of <typeparamref name="T"/> options.
/// </summary>
/// <typeparam name="T">The type of <see cref="IModdedOption"/>.</typeparam>
public interface IModdedOptionList<out T> : IModdedOptionList
public interface IModdedOptionList<out T> : IBaseModdedOptionList, IReadOnlyList<T>
where T : IModdedOption
{
/// <inheritdoc cref="IReadOnlyList{T}.this[int]"/>
new T this[int index] { get; }
/// <inheritdoc cref="IEnumerable{T}.GetEnumerator"/>
new IEnumerator<T> GetEnumerator();
IModdedOption IBaseModdedOptionList.ElementAt(int index)
{
return this[index];
}
}
+3 -3
View File
@@ -217,7 +217,7 @@ public static class ModdedOptionsManager
return;
}
if (property.GetValue(group) is not IModdedOptionList optionList)
if (property.GetValue(group) is not IBaseModdedOptionList optionList)
{
Error($"Failed to get option list for {property.Name}");
return;
@@ -227,7 +227,7 @@ public static class ModdedOptionsManager
for (var i = 0; i < optionList.Count; i++)
{
RegisterOption(optionList[i], group, configName(i), pluginInfo);
RegisterOption(optionList.ElementAt(i), group, configName(i), pluginInfo);
}
}
@@ -324,7 +324,7 @@ public static class ModdedOptionsManager
for (var i = 0; i < optionList.Count; i++)
{
var option = optionList[i];
var option = optionList.ElementAt(i);
if (visibilityFactory != null)
option.Visible = (Func<bool>)(visibilityFactory(i) ?? DelegateUtilities.AlwaysTrue);
@@ -62,13 +62,4 @@ public class ModdedOptionList<T> : IModdedOptionList<T>
{
return Options.GetEnumerator();
}
/// <inheritdoc cref="IEnumerable{T}.GetEnumerator"/>
IEnumerator<IModdedOption> IEnumerable<IModdedOption>.GetEnumerator()
{
return ((IEnumerable<IModdedOption>)Options).GetEnumerator();
}
/// <inheritdoc cref="IReadOnlyList{T}.this"/>
IModdedOption IReadOnlyList<IModdedOption>.this[int index] => this[index];
}
+4
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using MiraAPI.Patches.Stubs;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using UnityEngine;
using UnityEngine.Events;
@@ -106,6 +107,7 @@ public abstract class CustomMultiSelectMenu<TEntry> : CustomPhoneMenu<CustomMult
protected void Begin(IEnumerable<TEntry> entries, Action<List<TEntry>?> onClick, int totalSelections, bool shouldConfirm, bool canRepeat = false)
{
MinigameStubs.Begin(Component, null);
MeetingVoteAreaVisibility.HideNameplates(Component);
this.totalSelections = totalSelections;
this.shouldConfirm = shouldConfirm;
@@ -116,6 +118,7 @@ public abstract class CustomMultiSelectMenu<TEntry> : CustomPhoneMenu<CustomMult
back.OnClick.AddListener((UnityAction)(() =>
{
selectedEntries.Clear();
MeetingVoteAreaVisibility.Restore(Component);
onClick(null);
}));
@@ -177,6 +180,7 @@ public abstract class CustomMultiSelectMenu<TEntry> : CustomPhoneMenu<CustomMult
}
selectedEntries.Add(menuEntry);
MeetingVoteAreaVisibility.Restore(Component);
// Add choice to list of selections
if (selectedEntries.Count <= totalSelections)
+1
View File
@@ -387,6 +387,7 @@ public abstract class CustomPaginableMenu : CustomPhoneMenu<CustomPaginableMenu.
protected void Begin(Action registerEntryPanels)
{
MinigameStubs.Begin(Component, null);
MeetingVoteAreaVisibility.HideNameplates(Component);
searchText = string.Empty;
currentPage = 0;
+2
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AmongUs.GameOptions;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.Extensions;
@@ -21,6 +22,7 @@ public class CustomPhoneMenuComponent(IntPtr cppPtr) : Minigame(cppPtr)
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")]
private void OnDisable()
{
MeetingVoteAreaVisibility.Restore(this);
if (ControllerManager.Instance)
{
ControllerManager.Instance.CloseOverlayMenu(name);
+20 -2
View File
@@ -74,6 +74,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
protected int TabIndex => LocalSettingsManager.Tabs.IndexOf(this) + 10;
private Scroller? Scroller { get; set; }
private float MaxScroll { get; set; }
/// <summary>
/// Invoked when an option value is changed.
@@ -106,6 +107,17 @@ public abstract class LocalSettingsTab(ConfigFile config)
}
}
internal void RefreshScrollBounds()
{
if (Scroller == null)
{
return;
}
Scroller.SetBounds(new FloatRange(0, MaxScroll), new FloatRange(0, 0));
Scroller.ScrollToTop();
}
/// <summary>
/// Creates the tab <see cref="GameObject"/> and it's content.
/// </summary>
@@ -118,11 +130,13 @@ public abstract class LocalSettingsTab(ConfigFile config)
tab.transform.DestroyChildren();
tab.gameObject.SetActive(false);
if (Scroller == null)
if (Scroller == null || Scroller.transform.parent != tab.transform)
{
Scroller = Helpers.CreateScroller(tab.transform, OptionsMenuPatches.MaskCollider);
}
Labels.Clear();
if (TabButton != null)
{
TabButton.Content = tab.gameObject;
@@ -216,7 +230,11 @@ public abstract class LocalSettingsTab(ConfigFile config)
contentIndex++;
}
Scroller.SetBounds(new FloatRange(0, (Settings.Count + Buttons.Count) * 0.5f - 5f), new FloatRange(0, 0));
const float visibleHeight = 5f;
const float extraPadding = 0.25f;
var itemRange = (Settings.Count + Buttons.Count) * 0.5f - visibleHeight;
var offsetRange = contentOffset - visibleHeight + extraPadding;
MaxScroll = Mathf.Max(0f, itemRange, offsetRange);
return tab;
}
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.LocalSettings;
@@ -183,7 +185,9 @@ public static class OptionsMenuPatches
// Tabs with index 10 and above are the mod settings tabs
if (index >= 10)
{
CustomOpen(LocalSettingsManager.AvailableTabs[index - 10]);
var tab = LocalSettingsManager.AvailableTabs[index - 10];
CustomOpen(tab);
__instance.StartCoroutine(RefreshScrollBoundsAfterOpen(__instance, tab).WrapToIl2Cpp());
return false;
}
@@ -229,6 +233,16 @@ public static class OptionsMenuPatches
tab.Open();
}
private static IEnumerator RefreshScrollBoundsAfterOpen(OptionsMenuBehaviour menu, LocalSettingsTab tab)
{
yield return new WaitForEndOfFrame();
if (menu && tab.TabButton?.Content && tab.TabButton.Content.activeInHierarchy)
{
tab.RefreshScrollBounds();
}
}
private static void CustomClose(LocalSettingsTab tab)
{
if (tab.TabButton?.Button)
@@ -362,6 +362,7 @@ public static class RoleSettingMenuPatches
}
roleMenu.SetScrollBounds();
roleMenu.scrollBar.ScrollToTop();
_quotaTabCoroutine = null;
}
+9
View File
@@ -279,6 +279,8 @@ public static class RoleGuidePatches
MapBehaviour.Instance.Close();
}
MeetingVoteAreaVisibility.HideNameplates(__instance);
if (HudManager.InstanceExists)
{
ConsoleJoystick.SetMode_MenuAdditive();
@@ -390,6 +392,13 @@ public static class RoleGuidePatches
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(MatchInfoGuide), nameof(MatchInfoGuide.Close))]
private static void ClosePostfix(MatchInfoGuide __instance)
{
MeetingVoteAreaVisibility.Restore(__instance);
}
private static void SetUpTabGrids(MatchInfoTabPos position)
{
tabButtonContainer.startCorner = GridLayoutGroup.Corner.UpperLeft;
@@ -106,6 +106,7 @@ internal static class MeetingHudPatches
[HarmonyPatch(nameof(MeetingHud.OnDestroy))]
public static void OnDestroyPatch(MeetingHud __instance)
{
MeetingVoteAreaVisibility.RestoreAll();
MiraEventManager.InvokeEvent(new EndMeetingEvent(__instance));
}
@@ -113,6 +114,7 @@ internal static class MeetingHudPatches
[HarmonyPatch(nameof(MeetingHud.VotingComplete))]
public static void VotingCompletePatch(MeetingHud __instance)
{
MeetingVoteAreaVisibility.RestoreAll();
foreach (var meetingAbility in MeetingButtonManager.UntargetedButtons.Where(x => x.Enabled(PlayerControl.LocalPlayer.Data.Role) &&
(x.DisableUponVoting || x.HideUponWrapUp)))
{
+2 -2
View File
@@ -238,7 +238,7 @@ public sealed class MiraPluginManager
continue;
}
if (property.PropertyType.IsAssignableTo(typeof(IModdedOptionList)))
if (property.PropertyType.IsAssignableTo(typeof(IBaseModdedOptionList)))
{
ModdedOptionsManager.RegisterPropertyOptionList(type, property, pluginInfo);
continue;
@@ -259,7 +259,7 @@ public sealed class MiraPluginManager
}
foreach (var field in type.GetFields()
.Where(f => f.FieldType.IsAssignableTo(typeof(IModdedOption)) || f.FieldType.IsAssignableTo(typeof(IModdedOptionList))))
.Where(f => f.FieldType.IsAssignableTo(typeof(IModdedOption)) || f.FieldType.IsAssignableTo(typeof(IBaseModdedOptionList))))
{
Error($"{field.Name} is a field, not a property. Use properties for options.");
}
+27 -39
View File
@@ -936,7 +936,7 @@ public static class Helpers
{
const float contentTop = 0.95f;
const float horizontalOffset = -0.2f;
const float headerContentGap = 0.2f;
const float groupHeaderContentGap = 0.05f;
const int contentSortingOrder = 151;
columns = Mathf.Clamp(columns, 1, 6);
@@ -1024,7 +1024,7 @@ public static class Helpers
groupColumns[group] = i % columns;
bandHeights[band] = Mathf.Max(
bandHeights[band],
rowPitch * (groupedSettings[i].Count() + 1) + headerContentGap + 0.25f);
rowPitch * (groupedSettings[i].Count() + 1) + groupHeaderContentGap + 0.25f);
}
var bandOffset = 0f;
@@ -1040,7 +1040,6 @@ public static class Helpers
}
}
var contentBottom = float.PositiveInfinity;
var previousGroup = (AbstractOptionGroup?)null;
var rowIndex = 0;
var column = 0;
@@ -1089,12 +1088,12 @@ public static class Helpers
if (headerSource)
{
const float headerScale = 0.46f;
const float groupHeaderScale = 0.42f;
var headerWidth = groupsAsColumns
? columnWidth / headerScale
: (columns * columnWidth + (columns - 1) * columnGap) / headerScale;
? columnWidth / groupHeaderScale
: (columns * columnWidth + (columns - 1) * columnGap) / groupHeaderScale;
var header = Object.Instantiate(headerSource!, page.transform, false);
header.transform.localScale = Vector3.one * headerScale;
header.transform.localScale = Vector3.one * groupHeaderScale;
if (groupsAsColumns)
{
var totalWidth = columns * columnWidth + (columns - 1) * columnGap;
@@ -1155,12 +1154,6 @@ public static class Helpers
renderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask;
renderer.material.SetInt(PlayerMaterial.MaskLayer, 50);
renderer.sortingOrder = contentSortingOrder;
if (renderer.enabled && renderer.sprite)
{
contentBottom = Mathf.Min(
contentBottom,
inner.InverseTransformPoint(renderer.bounds.min).y);
}
}
foreach (var text in header.GetComponentsInChildren<TextMeshPro>(true))
@@ -1171,9 +1164,6 @@ public static class Helpers
if (text.enabled)
{
text.ForceMeshUpdate();
contentBottom = Mathf.Min(
contentBottom,
inner.InverseTransformPoint(text.bounds.min).y);
}
}
@@ -1191,7 +1181,7 @@ public static class Helpers
horizontalOffset;
var centerY = groupsAsColumns && settings[i].Group is { } rowGroup
? contentTop - groupTopOffsets[rowGroup] -
(rowPitch * (groupRows[rowGroup] + 1)) - headerContentGap - (rowHeight / 2f)
(rowPitch * (groupRows[rowGroup] + 1)) - groupHeaderContentGap - (rowHeight / 2f)
: contentTop - (rowHeight / 2f) - (rowIndex * rowPitch) - groupSpacing;
var row = Object.Instantiate(rowPrefab, page.transform);
row.enabled = false;
@@ -1238,27 +1228,6 @@ public static class Helpers
renderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask;
renderer.material.SetInt(PlayerMaterial.MaskLayer, 50);
renderer.sortingOrder = contentSortingOrder;
if (renderer.enabled &&
renderer.sprite &&
renderer.transform != row.PlusBtn.transform &&
!renderer.transform.IsChildOf(row.PlusBtn.transform) &&
renderer.transform != row.MinusBtn.transform &&
!renderer.transform.IsChildOf(row.MinusBtn.transform))
{
contentBottom = Mathf.Min(
contentBottom,
inner.InverseTransformPoint(renderer.bounds.min).y);
}
}
foreach (var text in row.GetComponentsInChildren<TextMeshPro>(true))
{
if (text.enabled)
{
contentBottom = Mathf.Min(
contentBottom,
inner.InverseTransformPoint(text.bounds.min).y);
}
}
row.gameObject.SetActive(true);
@@ -1277,6 +1246,26 @@ public static class Helpers
}
}
page.SetActive(true);
var contentBottom = float.PositiveInfinity;
foreach (var text in page.GetComponentsInChildren<TextMeshPro>(true))
{
if (text.enabled && text.gameObject.activeInHierarchy)
{
text.ForceMeshUpdate();
}
}
foreach (var renderer in page.GetComponentsInChildren<Renderer>(true))
{
if (renderer.enabled && renderer.gameObject.activeInHierarchy)
{
contentBottom = Mathf.Min(
contentBottom,
inner.InverseTransformPoint(renderer.bounds.min).y);
}
}
var maskArea = parent.transform.FindChild("MaskArea")?.GetComponent<SpriteRenderer>();
var maskBottom = maskArea
? inner.InverseTransformPoint(maskArea!.bounds.min).y
@@ -1288,7 +1277,6 @@ public static class Helpers
? contentOverflow + 0.05f
: 0f;
parent.SetYBoundsMax(Mathf.Clamp(scrollRange, 0f, 999f));
page.SetActive(true);
return page;
}
@@ -0,0 +1,74 @@
using System.Collections.Generic;
using UnityEngine;
namespace MiraAPI.Utilities;
internal static class MeetingVoteAreaVisibility
{
private static readonly Dictionary<Renderer, bool> originalRendererStates = [];
private static readonly HashSet<int> activeOwners = [];
internal static void HideNameplates(UnityEngine.Object owner)
{
var meetingHud = MeetingHud.Instance;
if (!owner ||
!meetingHud ||
meetingHud.state is not (MeetingHud.MeetingStates.Discussion or
MeetingHud.MeetingStates.NotVoted or
MeetingHud.MeetingStates.Voted))
{
return;
}
activeOwners.Add(owner.GetInstanceID());
foreach (var playerVoteArea in meetingHud.playerStates)
{
if (!playerVoteArea)
{
continue;
}
var buttons = playerVoteArea.Buttons;
foreach (var renderer in playerVoteArea.GetComponentsInChildren<Renderer>(true))
{
if (!renderer ||
(buttons &&
(renderer.transform == buttons.transform || renderer.transform.IsChildOf(buttons.transform))))
{
continue;
}
if (!originalRendererStates.ContainsKey(renderer))
{
originalRendererStates.Add(renderer, renderer.enabled);
}
renderer.enabled = false;
}
}
}
internal static void Restore(UnityEngine.Object owner)
{
if (!owner || !activeOwners.Remove(owner.GetInstanceID()) || activeOwners.Count > 0)
{
return;
}
RestoreAll();
}
internal static void RestoreAll()
{
activeOwners.Clear();
foreach (var rendererState in originalRendererStates)
{
if (rendererState.Key)
{
rendererState.Key.enabled = rendererState.Value;
}
}
originalRendererStates.Clear();
}
}