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

411 lines
9.0 KiB
C#

using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace RoR2.UI;
[RequireComponent(typeof(RectTransform))]
public class ItemInventoryDisplay : UIBehaviour, ILayoutElement
{
private struct LayoutValues
{
public float width;
public float height;
public float iconSize;
public int iconsPerRow;
public float rowWidth;
public int rowCount;
public Vector3 iconLocalScale;
public Vector3 topLeftCorner;
}
private RectTransform rectTransform;
public GameObject itemIconPrefab;
[FormerlySerializedAs("iconWidth")]
public float itemIconPrefabWidth = 64f;
public float maxIconWidth = 64f;
public float maxHeight = 128f;
public float verticalMargin = 8f;
[SerializeField]
[HideInInspector]
private List<ItemIcon> itemIcons;
private ItemIndex[] itemOrder;
private int itemOrderCount;
private int[] itemStacks;
private float currentIconScale = 1f;
private float previousWidth;
private bool updateRequestPending;
[SerializeField]
private UnityEvent onItemClicked;
private Inventory inventory;
private bool inventoryWasValid;
private MPEventSystemLocator eventSystemLocator;
private bool isUninitialized => (object)rectTransform == null;
public MPEventSystem eventSystem => eventSystemLocator.eventSystem;
public float minWidth => preferredWidth;
public float preferredWidth => rectTransform.rect.width;
public float flexibleWidth => 0f;
public float minHeight => preferredHeight;
public float preferredHeight { get; set; }
public float flexibleHeight => 0f;
public int layoutPriority => 0;
public void SetSubscribedInventory([CanBeNull] Inventory newInventory)
{
if ((object)inventory != newInventory || (bool)inventory != inventoryWasValid)
{
if ((object)inventory != null)
{
inventory.onInventoryChanged -= OnInventoryChanged;
inventory = null;
}
inventory = newInventory;
inventoryWasValid = inventory;
if ((bool)inventory)
{
inventory.onInventoryChanged += OnInventoryChanged;
}
OnInventoryChanged();
}
}
private void OnInventoryChanged()
{
if (base.isActiveAndEnabled)
{
if ((bool)inventory)
{
inventory.WriteItemStacks(itemStacks);
inventory.itemAcquisitionOrder.CopyTo(itemOrder);
itemOrderCount = inventory.itemAcquisitionOrder.Count;
}
else
{
Array.Clear(itemStacks, 0, itemStacks.Length);
itemOrderCount = 0;
}
RequestUpdateDisplay();
}
}
public int GetTotalVisibleItemCount()
{
int num = 0;
for (int i = 0; i < itemStacks.Length; i++)
{
if (ItemIsVisible((ItemIndex)i))
{
num += itemStacks[i];
}
}
return num;
}
private static bool ItemIsVisible(ItemIndex itemIndex)
{
ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
if (itemDef != null)
{
return !itemDef.hidden;
}
return false;
}
private void AllocateIcons(int desiredItemCount)
{
if (desiredItemCount != itemIcons.Count)
{
while (itemIcons.Count > desiredItemCount)
{
UnityEngine.Object.Destroy(itemIcons[itemIcons.Count - 1].gameObject);
itemIcons.RemoveAt(itemIcons.Count - 1);
}
CalculateLayoutValues(out var v, desiredItemCount);
while (itemIcons.Count < desiredItemCount)
{
ItemIcon component = UnityEngine.Object.Instantiate(itemIconPrefab, rectTransform).GetComponent<ItemIcon>();
itemIcons.Add(component);
component.OnItemClicked = (Action)Delegate.Combine(component.OnItemClicked, (Action)delegate
{
onItemClicked?.Invoke();
});
LayoutIndividualIcon(in v, itemIcons.Count - 1);
}
}
OnIconCountChanged();
}
private float CalculateIconScale(int iconCount)
{
int num = (int)rectTransform.rect.width;
int num2 = (int)maxHeight;
int num3 = (int)itemIconPrefabWidth;
int num4 = num3;
int num5 = num3 / 8;
int num6 = Math.Max(num / num4, 1);
int num7 = HGMath.IntDivCeil(iconCount, num6);
while (num4 * num7 > num2)
{
num6++;
num4 = Math.Min(num / num6, num3);
num7 = HGMath.IntDivCeil(iconCount, num6);
if (num4 <= num5)
{
num4 = num5;
break;
}
}
num4 = Math.Min(num4, (int)maxIconWidth);
return (float)num4 / (float)num3;
}
private void OnIconCountChanged()
{
float num = CalculateIconScale(itemIcons.Count);
if (num != currentIconScale)
{
currentIconScale = num;
OnIconScaleChanged();
}
}
private void OnIconScaleChanged()
{
LayoutAllIcons();
}
private void CalculateLayoutValues(out LayoutValues v, int iconCount)
{
float num = CalculateIconScale(itemIcons.Count);
Rect rect = rectTransform.rect;
v.width = rect.width;
v.iconSize = itemIconPrefabWidth * num;
v.iconsPerRow = Math.Max((int)v.width / (int)v.iconSize, 1);
v.rowWidth = (float)v.iconsPerRow * v.iconSize;
float num2 = (v.width - v.rowWidth) * 0.5f;
v.rowCount = HGMath.IntDivCeil(itemIcons.Count, v.iconsPerRow);
v.iconLocalScale = new Vector3(num, num, 1f);
v.topLeftCorner = new Vector3(rect.xMin + num2, rect.yMax - verticalMargin);
v.height = v.iconSize * (float)v.rowCount + verticalMargin * 2f;
}
private void LayoutAllIcons()
{
CalculateLayoutValues(out var v, itemIcons.Count);
int num = itemIcons.Count - (v.rowCount - 1) * v.iconsPerRow;
int i = 0;
int num2 = 0;
for (; i < v.rowCount; i++)
{
Vector3 topLeftCorner = v.topLeftCorner;
topLeftCorner.y += (float)i * (0f - v.iconSize);
int num3 = v.iconsPerRow;
if (i == v.rowCount - 1)
{
num3 = num;
}
int num4 = 0;
while (num4 < num3)
{
RectTransform obj = itemIcons[num2].rectTransform;
obj.localScale = v.iconLocalScale;
obj.localPosition = topLeftCorner;
topLeftCorner.x += v.iconSize;
num4++;
num2++;
}
}
}
private void LayoutIndividualIcon(in LayoutValues layoutValues, int i)
{
int num = i / layoutValues.iconsPerRow;
int num2 = i - num * layoutValues.iconsPerRow;
Vector3 topLeftCorner = layoutValues.topLeftCorner;
topLeftCorner.x += (float)num2 * layoutValues.iconSize;
topLeftCorner.y += (float)num * (0f - layoutValues.iconSize);
RectTransform obj = itemIcons[i].rectTransform;
obj.localPosition = topLeftCorner;
obj.localScale = layoutValues.iconLocalScale;
}
private void CacheComponents()
{
rectTransform = (RectTransform)base.transform;
}
protected override void Awake()
{
base.Awake();
CacheComponents();
itemStacks = ItemCatalog.RequestItemStackArray();
itemOrder = ItemCatalog.RequestItemOrderBuffer();
eventSystemLocator = GetComponent<MPEventSystemLocator>();
}
protected override void OnDestroy()
{
SetSubscribedInventory(null);
ItemCatalog.ReturnItemStackArray(itemStacks);
itemStacks = null;
ItemCatalog.ReturnItemOrderBuffer(itemOrder);
itemOrder = null;
base.OnDestroy();
}
protected override void OnEnable()
{
base.OnEnable();
if ((bool)inventory)
{
OnInventoryChanged();
}
RequestUpdateDisplay();
LayoutAllIcons();
}
private void RequestUpdateDisplay()
{
if (!updateRequestPending)
{
updateRequestPending = true;
RoR2Application.onNextUpdate += UpdateDisplay;
}
}
public void UpdateDisplay()
{
updateRequestPending = false;
if (!this || !base.isActiveAndEnabled)
{
return;
}
ItemIndex[] array = ItemCatalog.RequestItemOrderBuffer();
int num = 0;
for (int i = 0; i < itemOrderCount; i++)
{
if (ItemIsVisible(itemOrder[i]))
{
array[num++] = itemOrder[i];
}
}
AllocateIcons(num);
for (int j = 0; j < num; j++)
{
ItemIndex itemIndex = array[j];
itemIcons[j].SetItemIndex(itemIndex, itemStacks[(int)itemIndex]);
}
ItemCatalog.ReturnItemOrderBuffer(array);
}
public void SetItems(List<ItemIndex> newItemOrder, int[] newItemStacks)
{
itemOrderCount = newItemOrder.Count;
for (int i = 0; i < itemOrderCount; i++)
{
itemOrder[i] = newItemOrder[i];
}
Array.Copy(newItemStacks, itemStacks, itemStacks.Length);
RequestUpdateDisplay();
}
public void SetItems(ItemIndex[] newItemOrder, int newItemOrderCount, int[] newItemStacks)
{
itemOrderCount = newItemOrderCount;
Array.Copy(newItemOrder, itemOrder, itemOrderCount);
Array.Copy(newItemStacks, itemStacks, itemStacks.Length);
RequestUpdateDisplay();
}
public void ResetItems()
{
itemOrderCount = 0;
Array.Clear(itemStacks, 0, itemStacks.Length);
RequestUpdateDisplay();
}
protected override void OnRectTransformDimensionsChange()
{
base.OnRectTransformDimensionsChange();
if ((bool)rectTransform)
{
float width = rectTransform.rect.width;
if (width != previousWidth)
{
previousWidth = width;
LayoutAllIcons();
}
}
}
public void CalculateLayoutInputHorizontal()
{
}
public void CalculateLayoutInputVertical()
{
if (!isUninitialized)
{
CalculateLayoutValues(out var v, itemIcons.Count);
preferredHeight = v.height;
}
}
protected void OnValidate()
{
CacheComponents();
}
public bool SelectFirstItemIcon()
{
if (itemIcons.Count > 0)
{
eventSystem.SetSelectedObject(itemIcons[0].gameObject);
return true;
}
return false;
}
public int GetItemCount()
{
return itemOrderCount;
}
}