Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using UnityEngine.UI;
- using System.Collections;
- using System.Collections.Generic;
- // EXTENDS BaseMenuGrid class, it basically only enables elements that fit
- // on the screen and disables everything else to save on UI rendering times.
- // USAGE
- // simply inherit after this class rather than BaseMenuGrid and it will take effect
- // HIERARCHY LAYOUT
- // video showing compatible UI hierarchy layout: https://www.youtube.com/watch?v=lUun2xW6FJ4
- public class OptimizedMenuGrid : BaseMenuGrid {
- //*** ATTRIBUTES ***//
- [Header("[ Settings ]")]
- [SerializeField]
- private Direction gridDirection; // is this a horizontal or vertical grid? Double direction not supported
- // INTERNAL
- private List<RectTransform> cachedGridElements = new List<RectTransform>();
- // CONSTANTS
- private const int ADDITIONAL_GRID_COUNT = 2;
- //*** PROPERTIES ***//
- // SETTINGS
- private Direction GridDirection {
- get {return gridDirection;}
- }
- // CACHED REFERENCES
- protected RectTransform LayoutListGroup {
- get {return TargetScrollRect != null ? TargetScrollRect.content : null;}
- }
- protected List<RectTransform> CachedGridElements {
- get {return cachedGridElements;}
- }
- protected ScrollRect TargetScrollRect {get; set;}
- protected RectTransform ScrollWindow {get; set;}
- protected ContentSizeFitter TargetSizeFitter {get; set;}
- protected LayoutElement TargetLayoutElement {get; set;}
- protected LayoutGroup TargetLayoutGroup {get; set;}
- // VARIABLES
- private float GridSpacing {get; set;}
- private float GridElementSize {get; set;}
- private float ScrollWindowSize {get; set;}
- private int MaxGridDisplayCount {get; set;}
- private int CurrentGridOffsetIndex {get; set;}
- // not a property due to ref
- private Coroutine DisableComponentsCoroutine;
- //*** METHODS - PUBLIC ***//
- public override void SetUpGridElement (GameObject element)
- {
- element.transform.SetParent(TargetGrid);
- element.transform.localScale = Vector3.one;
- CachedGridElements.Add(element.GetComponent<RectTransform>());
- // element.SetActive(CachedGridElements.Count <= MaxGridDisplayCount);
- element.SetActive(true);
- }
- public override void ClearGrid ()
- {
- base.ClearGrid();
- CachedGridElements.Clear();
- EnableLayoutComponents();
- ExecuteRunMethodOnEndOfFrame(ref DisableComponentsCoroutine, DisableLayoutComponents);
- ExecuteRunMethodOnEndOfFrame(UpdateVisibleGridElements);
- }
- //*** METHODS - PROTECTED ***//
- protected override void Awake ()
- {
- base.Awake();
- CacheReferences();
- }
- protected override void Start ()
- {
- base.Start();
- }
- protected override void Update ()
- {
- base.Update();
- HandleReusableGridElements();
- }
- protected override void OnDestroy ()
- {
- base.OnDestroy();
- }
- //*** METHODS - PRIVATE ***//
- private void HandleReusableGridElements ()
- {
- // check main references
- bool referencesAreIncorrect = (TargetScrollRect == null || LayoutListGroup == null || ScrollWindow == null);
- if (referencesAreIncorrect == true || CachedGridElements.Count < MaxGridDisplayCount)
- {
- return;
- }
- // depending on selected scroll direction get current offset
- int lastIndex = (int)Mathf.Clamp(CurrentGridOffsetIndex + MaxGridDisplayCount, 0, CachedGridElements.Count - 1);
- float firstOffset = GetElementOffset(CachedGridElements[CurrentGridOffsetIndex]);
- float lastOffset = GetElementOffset(CachedGridElements[lastIndex]);
- firstOffset *= (GridDirection == Direction.HORIZONTAL) ? -1f : 1f;
- lastOffset *= (GridDirection == Direction.HORIZONTAL) ? -1f : 1f;
- // swap elements when enough offset is given
- if (lastOffset < -GridElementSize * 2f && CurrentGridOffsetIndex > 0)
- {
- MoveOffsetIndexInDirection(-1);
- UpdateVisibleGridElements();
- }
- else if (firstOffset > GridElementSize * 2f && CurrentGridOffsetIndex < CachedGridElements.Count - MaxGridDisplayCount)
- {
- MoveOffsetIndexInDirection(1);
- UpdateVisibleGridElements();
- }
- }
- private void MoveOffsetIndexInDirection (int direction)
- {
- CurrentGridOffsetIndex += direction;
- }
- private void UpdateVisibleGridElements ()
- {
- for (int i = 0; i < CachedGridElements.Count; i++)
- {
- bool isActive = (i >= CurrentGridOffsetIndex) && (i < CurrentGridOffsetIndex + MaxGridDisplayCount);
- CachedGridElements[i].gameObject.SetActive(isActive);
- }
- }
- private void EnableLayoutComponents ()
- {
- TargetSizeFitter.enabled = true;
- TargetLayoutGroup.enabled = true;
- }
- private void DisableLayoutComponents ()
- {
- TargetSizeFitter.enabled = false;
- TargetLayoutGroup.enabled = false;
- AdjustGridSize();
- }
- private void CacheReferences ()
- {
- TargetScrollRect = TargetGrid.GetComponentInParent<ScrollRect>();
- ScrollWindow = TargetScrollRect.GetComponent<RectTransform>();
- TargetSizeFitter = TargetGrid.GetComponent<ContentSizeFitter>();
- TargetLayoutElement = GridElement.GetComponent<LayoutElement>();
- TargetLayoutGroup = TargetGrid.GetComponent<LayoutGroup>();
- GridSpacing =
- (GridDirection == Direction.HORIZONTAL) ?
- ((HorizontalLayoutGroup)TargetLayoutGroup).spacing :
- ((VerticalLayoutGroup)TargetLayoutGroup).spacing;
- GridElementSize =
- (GridDirection == Direction.HORIZONTAL) ?
- TargetLayoutElement.preferredWidth :
- TargetLayoutElement.preferredHeight;
- ScrollWindowSize =
- (GridDirection == Direction.HORIZONTAL) ?
- ScrollWindow.rect.width :
- ScrollWindow.rect.height;
- MaxGridDisplayCount = GetMaxGridDisplayCount();
- }
- private void AdjustGridSize ()
- {
- // calculate grid length
- float lenght =
- CachedGridElements.Count * GridElementSize +
- (CachedGridElements.Count - 1) * GridSpacing;
- lenght = Mathf.Clamp(lenght, 0, Mathf.Infinity);
- // set new size depending on grid direction
- Vector2 newSize = TargetGrid.sizeDelta;
- if (GridDirection == Direction.HORIZONTAL)
- {
- newSize.x = lenght;
- }
- else
- {
- newSize.y = lenght;
- }
- // apply final size
- TargetGrid.sizeDelta = newSize;
- }
- private int GetMaxGridDisplayCount ()
- {
- float overallLength = 0;
- int maxCount = 0;
- while (overallLength < ScrollWindowSize)
- {
- maxCount++;
- overallLength = maxCount * (GridElementSize + GridSpacing);
- }
- return maxCount + ADDITIONAL_GRID_COUNT;
- }
- private float GetElementOffset (RectTransform selection)
- {
- switch (GridDirection)
- {
- case Direction.VERTICAL:
- return GetVerticalElementOffset(selection);
- case Direction.HORIZONTAL:
- return GetHorizontalElementOffset(selection);
- default:
- return 0.0f;
- }
- }
- private float GetVerticalElementOffset (RectTransform selection)
- {
- // move the current scroll rect to correct position
- float selectionPosition = -selection.anchoredPosition.y;
- float elementHeight = selection.rect.height;
- float maskHeight = ScrollWindow.rect.height;
- float listAnchorPosition = LayoutListGroup.anchoredPosition.y;
- // get the element offset value depending on the cursor move direction
- float offlimitsValue = GetScrollOffset(selectionPosition, listAnchorPosition, elementHeight, maskHeight);
- // return offlimitsValue / LayoutListGroup.rect.height;
- return offlimitsValue;
- }
- private float GetHorizontalElementOffset (RectTransform selection)
- {
- // move the current scroll rect to correct position
- float selectionPosition = selection.anchoredPosition.x;
- float elementWidth = selection.rect.width;
- float maskWidth = ScrollWindow.rect.width;
- float listAnchorPosition = -LayoutListGroup.anchoredPosition.x;
- // get the element offset value depending on the cursor move direction
- float offlimitsValue = -GetScrollOffset(selectionPosition, listAnchorPosition, elementWidth, maskWidth);
- // return offlimitsValue / LayoutListGroup.rect.width;
- return offlimitsValue;
- }
- private float GetScrollOffset (float position, float listAnchorPosition, float targetLength, float maskLength)
- {
- if (position < listAnchorPosition)
- {
- return listAnchorPosition - position;
- }
- else if (position + targetLength > listAnchorPosition + maskLength)
- {
- return (listAnchorPosition + maskLength) - (position + targetLength);
- }
- return 0;
- }
- //*** ENUMS ***//
- public enum Direction
- {
- VERTICAL,
- HORIZONTAL
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment