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