using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using frame8.Logic.Misc.Other.Extensions;
using frame8.Logic.Misc.Visual.UI;
using frame8.Logic.Misc.Visual.UI.MonoBehaviours;
using Com.ForbiddenByte.OSA.Core;
namespace Com.ForbiddenByte.OSA.Util
{
///
/// Important note: if used with ScrollbarFixer8 (which is true in the most cases,
/// make sure is not too small
///
public class DiscreteScrollbar : MonoBehaviour
{
public RectTransform slotPrefab;
public RectTransform slotsParent;
public UnityIntEvent OnSlotSelected;
public Func getItemsCountFunc;
Scrollbar _Scrollbar;
RectTransform[] slots = new RectTransform[0];
RectTransform _ScrollbarPanelRT;
IScrollRectProxy _ScrollRectProxy;
int _OneIfVert_ZeroIfHor;
const int MAX_COUNT = 100;
bool _UpdatePending;
void Awake()
{
// Get in parent, but ignore self
_ScrollRectProxy = transform.parent.GetComponentInParent();
if (_ScrollRectProxy == null)
throw new OSAException(GetType().Name + ": No IScrollRectProxy component found in parent");
_Scrollbar = GetComponent();
_ScrollbarPanelRT = _Scrollbar.transform as RectTransform;
_OneIfVert_ZeroIfHor = _ScrollRectProxy.IsHorizontal ? 0 : 1;
}
void OnEnable() { _UpdatePending = false; }
public void OnScrollbarSizeChanged()
{
StartCoroutine(UpdateSize());
}
IEnumerator UpdateSize()
{
while (_UpdatePending) // wait for prev request to complete
yield return null;
_UpdatePending = true;
yield return null;
if (getItemsCountFunc == null)
throw new OSAException(GetType().Name + "getItemsCountFunc==null. Please specify a count provider");
_UpdatePending = true;
int count = getItemsCountFunc();
if (count > MAX_COUNT)
throw new OSAException(GetType().Name + ": count is " + count + ". Bigger than MAX_COUNT=" + MAX_COUNT + ". Are you sure you want to use a discrete scrollbar?");
Rebuild(count);
_UpdatePending = false;
}
public void Rebuild(int numSlots)
{
slotPrefab.gameObject.SetActive(true);
// Clear prev
if (slots != null)
foreach (var slot in slots)
Destroy(slot.gameObject);
// Add new
slots = new RectTransform[numSlots];
float sizesCumu = 0;
float slotSize = _ScrollbarPanelRT.rect.size[_OneIfVert_ZeroIfHor] / numSlots; // not using the handle's size because of rounding errors with higher
RectTransform.Edge edgeToInsetFrom = _OneIfVert_ZeroIfHor == 1 ? RectTransform.Edge.Top : RectTransform.Edge.Left;
for (int i = 0; i < numSlots; i++)
{
var slot = (Instantiate(slotPrefab.gameObject) as GameObject).GetComponent();
slots[i] = slot;
slot.SetParent(slotsParent, false);
slot.SetInsetAndSizeFromParentEdgeWithCurrentAnchors(edgeToInsetFrom, sizesCumu, slotSize);
sizesCumu += slotSize;
int copyOfI = i;
slot.GetComponentInChildren