using System; using System.Collections.Generic; using System.Collections.ObjectModel; using HG; using RoR2.UI; using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; using UnityEngine.UI; namespace RoR2; [RequireComponent(typeof(MPEventSystemLocator))] public class CharacterSelectBarController : MonoBehaviour { public struct SurvivorPickInfo { public LocalUser localUser; public SurvivorDef pickedSurvivor; } [Serializable] public class SurvivorPickInfoUnityEvent : UnityEvent { } [Header("Prefabs")] public GameObject choiceButtonPrefab; public GameObject fillButtonPrefab; [ShowFieldObsolete] [Obsolete("No longer used.", false)] public GameObject WIPButtonPrefab; [Header("Required References")] [FormerlySerializedAs("gridLayoutGroup")] public GridLayoutGroup iconContainerGrid; [Header("Events")] public SurvivorPickInfoUnityEvent onSurvivorPicked; public MPEventSystemLocator eventSystemLocator; private UIElementAllocator survivorIconControllers; private UIElementAllocator fillerIcons; private LocalUser currentLocalUser; [Obsolete("Use iconContainerGrid instead", false)] public ref GridLayoutGroup gridLayoutGroup => ref iconContainerGrid; public SurvivorIconController pickedIcon { get; private set; } private bool isEclipseRun { get { if ((bool)PreGameController.instance) { return PreGameController.instance.gameModeIndex == GameModeCatalog.FindGameModeIndex("EclipseRun"); } return false; } } private void Awake() { eventSystemLocator = GetComponent(); survivorIconControllers = new UIElementAllocator((RectTransform)iconContainerGrid.transform, choiceButtonPrefab); survivorIconControllers.onCreateElement = OnCreateSurvivorIcon; fillerIcons = new UIElementAllocator((RectTransform)iconContainerGrid.transform, fillButtonPrefab); } private void LateUpdate() { EnforceValidChoice(); } private void OnEnable() { eventSystemLocator.onEventSystemDiscovered += OnEventSystemDiscovered; if ((bool)eventSystemLocator.eventSystem) { OnEventSystemDiscovered(eventSystemLocator.eventSystem); } } private void OnDisable() { eventSystemLocator.onEventSystemDiscovered -= OnEventSystemDiscovered; } public void ApplyPickToPickerSurvivorPreference(SurvivorPickInfo survivorPickInfo) { if (survivorPickInfo.localUser != null) { survivorPickInfo.localUser.userProfile.SetSurvivorPreference(survivorPickInfo.pickedSurvivor); } } public void ApplyPickToEclipseSurvivorPreference(SurvivorPickInfo survivorPickInfo) { } private void OnEventSystemDiscovered(MPEventSystem eventSystem) { currentLocalUser = eventSystem.localUser; Build(); SurvivorDef localUserExistingSurvivorPreference = GetLocalUserExistingSurvivorPreference(); PickIconBySurvivorDef(localUserExistingSurvivorPreference); } private void OnCreateSurvivorIcon(int index, SurvivorIconController survivorIconController) { survivorIconController.characterSelectBarController = this; survivorIconController.hgButton.onClick.AddListener(delegate { PickIcon(survivorIconController); }); } private int FindIconIndexForSurvivorDef(SurvivorDef survivorDef) { ReadOnlyCollection elements = survivorIconControllers.elements; for (int i = 0; i < elements.Count; i++) { if ((object)elements[i].survivorDef == survivorDef) { return i; } } return -1; } private int FindIconIndex(SurvivorIconController survivorIconController) { ReadOnlyCollection elements = survivorIconControllers.elements; for (int i = 0; i < elements.Count; i++) { if ((object)elements[i] == survivorIconController) { return i; } } return -1; } private void PickIconBySurvivorDef(SurvivorDef survivorDef) { int num = FindIconIndexForSurvivorDef(survivorDef); if (num >= 0) { PickIcon(survivorIconControllers.elements[num]); } } private void PickIcon(SurvivorIconController newPickedIcon) { if ((object)pickedIcon != newPickedIcon) { pickedIcon = newPickedIcon; onSurvivorPicked?.Invoke(new SurvivorPickInfo { localUser = currentLocalUser, pickedSurvivor = newPickedIcon.survivorDef }); Util.PlaySound("Kill_SelectScreen", base.gameObject); } } private bool ShouldDisplaySurvivor(SurvivorDef survivorDef) { if ((bool)survivorDef && !survivorDef.hidden) { return survivorDef.CheckUserHasRequiredEntitlement(currentLocalUser); } return false; } private SurvivorDef GetLocalUserExistingSurvivorPreference() { return currentLocalUser?.userProfile.GetSurvivorPreference(); } public void Build() { List list = new List(); foreach (SurvivorDef orderedSurvivorDef in SurvivorCatalog.orderedSurvivorDefs) { if (ShouldDisplaySurvivor(orderedSurvivorDef)) { list.Add(orderedSurvivorDef); } } int count = list.Count; int desiredCount = Math.Max(CalcGridCellCount(count, iconContainerGrid.constraintCount) - count, 0); survivorIconControllers.AllocateElements(count); fillerIcons.AllocateElements(desiredCount); fillerIcons.MoveElementsToContainerEnd(); ReadOnlyCollection elements = survivorIconControllers.elements; for (int i = 0; i < count; i++) { SurvivorDef survivorDef = list[i]; SurvivorIconController survivorIconController = elements[i]; survivorIconController.survivorDef = survivorDef; survivorIconController.hgButton.defaultFallbackButton = i == 0; if (count > 1) { int num = 0; int num2 = 0; if (i == 0) { num = count - 1; num2 = i + 1; } else if (i == count - 1) { num = i - 1; num2 = 0; } else { num = i - 1; num2 = i + 1; } UnityEngine.UI.Navigation navigation = survivorIconController.hgButton.navigation; navigation.mode = UnityEngine.UI.Navigation.Mode.Explicit; navigation.selectOnLeft = elements[num].hgButton; navigation.selectOnRight = elements[num2].hgButton; if (i - iconContainerGrid.constraintCount >= 0) { navigation.selectOnUp = elements[i - iconContainerGrid.constraintCount].hgButton; } if (i + iconContainerGrid.constraintCount < count) { navigation.selectOnDown = elements[i + iconContainerGrid.constraintCount].hgButton; } survivorIconController.hgButton.navigation = navigation; } } } private static int CalcGridCellCount(int elementCount, int gridFixedDimensionLength) { return (int)Mathf.Ceil((float)elementCount / (float)gridFixedDimensionLength) * gridFixedDimensionLength; } private void EnforceValidChoice() { int num = FindIconIndex(pickedIcon); if ((bool)pickedIcon && pickedIcon.survivorIsAvailable) { return; } int num2 = -1; ReadOnlyCollection elements = survivorIconControllers.elements; while (num2 < elements.Count) { int num3 = num + num2; if (0 <= num3 && num3 < elements.Count) { SurvivorIconController survivorIconController = elements[num3]; if (survivorIconController.survivorIsAvailable) { PickIcon(survivorIconController); break; } } if (num2 >= 0) { num2++; } num2 = -num2; } } }