r2mods/ilspy_dump/ror2_csproj/RoR2.UI/AllyCardManager.cs

426 lines
11 KiB
C#
Raw Normal View History

2024-10-04 07:26:37 +00:00
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using HG;
using UnityEngine;
using UnityEngine.UI;
namespace RoR2.UI;
[RequireComponent(typeof(RectTransform))]
public class AllyCardManager : MonoBehaviour, ILayoutGroup, ILayoutController
{
private struct SourceInfo
{
public readonly GameObject gameObject;
public readonly TeamComponent teamComponent;
public readonly CharacterMaster master;
public SourceInfo(GameObject gameObject)
{
bool flag = gameObject;
this.gameObject = gameObject;
teamComponent = (flag ? gameObject.GetComponent<TeamComponent>() : null);
CharacterBody characterBody = (flag ? gameObject.GetComponent<CharacterBody>() : null);
master = (characterBody ? characterBody.master : null);
}
}
private struct DisplayElement
{
public CharacterMaster master;
public bool shouldIndent;
public int priority;
}
private class DisplayElementComparer : IComparer<DisplayElement>
{
public static DisplayElementComparer instance = new DisplayElementComparer();
public int Compare(DisplayElement a, DisplayElement b)
{
int num = a.priority - b.priority;
if (num == 0)
{
num = (int)(a.master.netId.Value - b.master.netId.Value);
}
return num;
}
private DisplayElementComparer()
{
}
}
private struct CharacterData
{
public readonly CharacterMaster master;
public readonly CharacterMaster leaderMaster;
private readonly int masterInstanceId;
private readonly int leaderMasterInstanceId;
public readonly bool isMinion;
public readonly bool isPlayer;
public CharacterData(CharacterMaster master)
{
this.master = master;
leaderMaster = master.minionOwnership.ownerMaster;
isMinion = leaderMaster;
isPlayer = master.playerCharacterMasterController;
masterInstanceId = master.gameObject.GetInstanceID();
leaderMasterInstanceId = (isMinion ? leaderMaster.gameObject.GetInstanceID() : 0);
}
public bool Equals(in CharacterData other)
{
if (masterInstanceId == other.masterInstanceId && leaderMasterInstanceId == other.leaderMasterInstanceId && isMinion == other.isMinion)
{
return isPlayer == other.isPlayer;
}
return false;
}
}
private class CharacterDataSet
{
private CharacterData[] buffer = new CharacterData[128];
private int _count;
public int count => _count;
public ref CharacterData this[int i] => ref buffer[i];
public bool Equals(CharacterDataSet other)
{
if (other == null)
{
return false;
}
if (_count != other._count)
{
return false;
}
for (int i = 0; i < _count; i++)
{
if (!buffer[i].Equals(in other.buffer[i]))
{
return false;
}
}
return true;
}
public void Clear()
{
Array.Clear(buffer, 0, _count);
_count = 0;
}
public void Add(ref CharacterData element)
{
ArrayUtils.ArrayAppend(ref buffer, ref _count, in element);
}
public void CopyFrom(CharacterDataSet src)
{
int num = _count - src._count;
if (num > 0)
{
Array.Clear(buffer, src._count, num);
}
ArrayUtils.EnsureCapacity(ref buffer, src.buffer.Length);
_count = src.count;
Array.Copy(src.buffer, buffer, _count);
}
}
private static class CharacterDataSetPool
{
private static readonly Stack<CharacterDataSet> pool = new Stack<CharacterDataSet>();
public static CharacterDataSet Request()
{
if (pool.Count == 0)
{
return new CharacterDataSet();
}
return pool.Pop();
}
public static void Return(ref CharacterDataSet characterDataSet)
{
characterDataSet.Clear();
pool.Push(characterDataSet);
}
}
public float indentWidth = 16f;
private SourceInfo currentSource;
private UIElementAllocator<AllyCardController> cardAllocator;
private RectTransform rectTransform;
private bool needsRefresh;
private DisplayElement[] displayElements = Array.Empty<DisplayElement>();
private int displayElementCount;
private CharacterDataSet currentCharacterData;
private float updateTimer;
private const float updateDelay = 0f;
public GameObject sourceGameObject
{
get
{
return currentSource.gameObject;
}
set
{
if ((object)currentSource.gameObject != value)
{
currentSource = new SourceInfo(value);
OnSourceChanged();
}
}
}
private void OnCardCreated(int index, AllyCardController element)
{
Vector2 anchorMin = element.rectTransform.anchorMin;
anchorMin.x = 0f;
anchorMin.y = 1f;
element.rectTransform.anchorMin = anchorMin;
anchorMin = element.rectTransform.anchorMax;
anchorMin.x = 1f;
anchorMin.y = 1f;
element.rectTransform.anchorMax = anchorMin;
}
private void OnSourceChanged()
{
needsRefresh = true;
}
private TeamIndex FindTargetTeam()
{
TeamIndex result = TeamIndex.None;
TeamComponent teamComponent = currentSource.teamComponent;
if ((bool)teamComponent)
{
result = teamComponent.teamIndex;
}
return result;
}
private void SetCharacterData(CharacterDataSet newCharacterData)
{
if (!newCharacterData.Equals(currentCharacterData))
{
currentCharacterData.CopyFrom(newCharacterData);
BuildFromCharacterData(currentCharacterData);
}
}
private void PopulateCharacterDataSet(CharacterDataSet characterDataSet)
{
TeamIndex teamIndex = FindTargetTeam();
ReadOnlyCollection<CharacterMaster> readOnlyInstancesList = CharacterMaster.readOnlyInstancesList;
for (int i = 0; i < readOnlyInstancesList.Count; i++)
{
CharacterMaster characterMaster = readOnlyInstancesList[i];
if (characterMaster.teamIndex == teamIndex)
{
CharacterBody body = characterMaster.GetBody();
if ((!body || !body.teamComponent || !body.teamComponent.hideAllyCardDisplay) && (!characterMaster.playerCharacterMasterController || (bool)characterMaster.playerCharacterMasterController.networkUser) && (object)currentSource.master != characterMaster)
{
CharacterData element = new CharacterData(characterMaster);
characterDataSet.Add(ref element);
}
}
}
}
private void BuildFromCharacterData(CharacterDataSet characterDataSet)
{
if (characterDataSet.count < displayElementCount)
{
Array.Clear(displayElements, characterDataSet.count, displayElementCount - characterDataSet.count);
}
displayElementCount = characterDataSet.count;
ArrayUtils.EnsureCapacity(ref displayElements, displayElementCount);
int i = 0;
for (int count = characterDataSet.count; i < count; i++)
{
ref CharacterData reference = ref characterDataSet[i];
displayElements[i] = new DisplayElement
{
master = reference.master,
priority = -1
};
}
int num = 0;
int j = 0;
for (int count2 = characterDataSet.count; j < count2; j++)
{
if (characterDataSet[j].isPlayer)
{
displayElements[j].priority = num;
num += 2;
}
}
int k = 0;
for (int count3 = characterDataSet.count; k < count3; k++)
{
if (!characterDataSet[k].isMinion)
{
ref DisplayElement reference2 = ref displayElements[k];
if (reference2.priority == -1)
{
reference2.priority = num;
num += 2;
}
}
}
int l = 0;
for (int count4 = characterDataSet.count; l < count4; l++)
{
ref CharacterData reference3 = ref characterDataSet[l];
if (!reference3.isMinion)
{
continue;
}
ref DisplayElement reference4 = ref displayElements[l];
if (reference4.priority == -1)
{
int num2 = FindIndexForMaster(reference3.leaderMaster);
if (num2 != -1)
{
reference4.priority = displayElements[num2].priority + 1;
reference4.shouldIndent = true;
}
}
}
int m = 0;
for (int count5 = characterDataSet.count; m < count5; m++)
{
ref DisplayElement reference5 = ref displayElements[m];
if (reference5.priority == -1)
{
reference5.priority = num;
num += 2;
}
}
Array.Sort(displayElements, 0, comparer: DisplayElementComparer.instance, length: displayElementCount);
cardAllocator.AllocateElements(displayElementCount);
for (int n = 0; n < displayElementCount; n++)
{
ref DisplayElement reference6 = ref displayElements[n];
AllyCardController allyCardController = cardAllocator.elements[n];
allyCardController.sourceMaster = reference6.master;
allyCardController.shouldIndent = reference6.shouldIndent;
}
ArrayUtils.Clear(displayElements, ref displayElementCount);
int FindIndexForMaster(CharacterMaster master)
{
for (int num3 = 0; num3 < displayElementCount; num3++)
{
if ((object)master == displayElements[num3].master)
{
return num3;
}
}
return -1;
}
}
private void Awake()
{
cardAllocator = new UIElementAllocator<AllyCardController>((RectTransform)base.transform, LegacyResourcesAPI.Load<GameObject>("Prefabs/UI/AllyCard"));
rectTransform = (RectTransform)base.transform;
UIElementAllocator<AllyCardController> uIElementAllocator = cardAllocator;
uIElementAllocator.onCreateElement = (UIElementAllocator<AllyCardController>.ElementOperationDelegate)Delegate.Combine(uIElementAllocator.onCreateElement, new UIElementAllocator<AllyCardController>.ElementOperationDelegate(OnCardCreated));
}
private void Update()
{
updateTimer -= Time.deltaTime;
if (updateTimer <= 0f)
{
updateTimer = 0f;
CharacterDataSet characterDataSet = CharacterDataSetPool.Request();
PopulateCharacterDataSet(characterDataSet);
SetCharacterData(characterDataSet);
CharacterDataSetPool.Return(ref characterDataSet);
}
}
private void OnEnable()
{
needsRefresh = true;
currentCharacterData = CharacterDataSetPool.Request();
}
private void OnDisable()
{
CharacterDataSetPool.Return(ref currentCharacterData);
}
public void SetLayoutHorizontal()
{
if (cardAllocator != null)
{
ReadOnlyCollection<AllyCardController> elements = cardAllocator.elements;
int i = 0;
for (int count = elements.Count; i < count; i++)
{
AllyCardController allyCardController = elements[i];
RectTransform obj = allyCardController.rectTransform;
Vector2 offsetMin = obj.offsetMin;
offsetMin.x = (allyCardController.shouldIndent ? indentWidth : 0f);
obj.offsetMin = offsetMin;
offsetMin = obj.offsetMax;
offsetMin.x = 0f;
obj.offsetMax = offsetMin;
}
}
}
public void SetLayoutVertical()
{
if (cardAllocator != null)
{
ReadOnlyCollection<AllyCardController> elements = cardAllocator.elements;
float b = this.rectTransform.rect.height / (float)elements.Count;
float num = 0f;
int i = 0;
for (int count = elements.Count; i < count; i++)
{
AllyCardController allyCardController = elements[i];
RectTransform rectTransform = allyCardController.rectTransform;
float preferredHeight = allyCardController.layoutElement.preferredHeight;
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferredHeight);
Vector2 anchoredPosition = rectTransform.anchoredPosition;
anchoredPosition.y = num;
rectTransform.anchoredPosition = anchoredPosition;
num -= Mathf.Min(preferredHeight, b);
}
}
}
}