ProjectDDD/Assets/Plugins/Pixel Crushers/Common/Scripts/UI/UIScrollbarEnabler.cs

108 lines
4.1 KiB (Stored with Git LFS)
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
using System.Collections;
namespace PixelCrushers
{
/// <summary>
/// Enables a scrollbar only if the content is larger than the scroll rect. This component only
/// only shows or hides the scrollbar when the component is enabled or when CheckScrollbar is invoked.
/// </summary>
[AddComponentMenu("")] // Use wrapper.
public class UIScrollbarEnabler : MonoBehaviour
{
[Tooltip("The scroll rect.")]
[UnityEngine.Serialization.FormerlySerializedAs("container")]
public UnityEngine.UI.ScrollRect scrollRect = null;
[Tooltip("The content inside the scroll rect. The scrollbar will be enabled if the content is taller than the scroll rect.")]
[UnityEngine.Serialization.FormerlySerializedAs("content")]
public RectTransform scrollContent = null;
[Tooltip("The scrollbar to enable or disable. If scroll rect doesn't have a scrollbar, just scrolls scroll rect.")]
public UnityEngine.UI.Scrollbar scrollbar = null;
[Tooltip("Scroll smoothly instead of jumping to reset value.")]
public bool smoothScroll = false;
public float smoothScrollSpeed = 5;
protected bool m_started = false;
protected bool m_checking = false;
protected RectTransform m_scrollRectTransform = null;
protected virtual void Start()
{
m_started = true;
CheckScrollbar();
}
public virtual void OnEnable()
{
if (m_started) CheckScrollbar();
}
public virtual void OnDisable()
{
m_checking = false;
}
public virtual void CheckScrollbar()
{
if (m_checking || scrollRect == null || scrollContent == null || !gameObject.activeInHierarchy || !enabled) return;
StopAllCoroutines();
StartCoroutine(CheckScrollbarAfterUIUpdate(false, 0));
}
public virtual void CheckScrollbarWithResetValue(float value)
{
if (m_checking || scrollRect == null || scrollContent == null || !gameObject.activeInHierarchy || !enabled) return;
StopAllCoroutines();
StartCoroutine(CheckScrollbarAfterUIUpdate(true, value));
}
protected virtual IEnumerator CheckScrollbarAfterUIUpdate(bool useResetValue, float resetValue)
{
m_checking = true;
yield return null;
if (scrollbar != null)
{
scrollbar.gameObject.SetActive(scrollContent.rect.height > scrollRect.GetComponent<RectTransform>().rect.height);
}
m_checking = false;
yield return null;
if (useResetValue)
{
if (smoothScroll)
{
var contentHeight = scrollContent.rect.height;
if (m_scrollRectTransform == null) m_scrollRectTransform = scrollRect.GetComponent<RectTransform>();
var scrollRectHeight = m_scrollRectTransform.rect.height;
var needToScroll = contentHeight > scrollRectHeight;
if (needToScroll)
{
var ratio = scrollRectHeight / contentHeight;
var timeout = Time.time + 10f; // Avoid infinite loops by maxing out at 10 seconds.
while (scrollRect.verticalNormalizedPosition > 0.01f && Time.time < timeout)
{
var newPos = scrollRect.verticalNormalizedPosition - smoothScrollSpeed * Time.deltaTime * ratio;
scrollRect.verticalNormalizedPosition = Mathf.Max(0, newPos);
yield return null;
}
}
scrollRect.verticalNormalizedPosition = 0;
}
else
{
if (scrollbar != null) scrollbar.value = resetValue;
scrollRect.verticalNormalizedPosition = resetValue;
}
}
}
}
}