Firstborn/Assets/RPG Creation Kit/Scripts/UI/ScrollToSelected.cs

89 lines
2.7 KiB
C#
Raw Normal View History

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
[RequireComponent(typeof(ScrollRect))]
public class ScrollToSelected : MonoBehaviour
{
//https://twitter.com/AsherVo/status/1141791964637147136
//https://pastebin.com/HjcktEYv
[Header("Required: Children must have a Y Pivot of 1!")]
public float scrollSpeed = 10f;
ScrollRect m_ScrollRect;
RectTransform m_RectTransform;
RectTransform m_ContentRectTransform;
RectTransform m_SelectedRectTransform;
void Awake()
{
m_ScrollRect = GetComponent<ScrollRect>();
m_RectTransform = GetComponent<RectTransform>();
m_ContentRectTransform = m_ScrollRect.content;
}
void Update()
{
UpdateScrollToSelected();
}
void UpdateScrollToSelected()
{
GameObject selected = EventSystem.current.currentSelectedGameObject;
if (selected == null)
return;
m_SelectedRectTransform = selected.GetComponent<RectTransform>();
float contentHeightDifference = GetContentHeightDifference();
float selectedTop = m_SelectedRectTransform.anchoredPosition.y;
float selectedBottom = selectedTop - m_SelectedRectTransform.rect.height;
float viewportTop = NormalizedToPosition(m_ScrollRect.verticalNormalizedPosition, contentHeightDifference);
float viewportBottom = viewportTop - m_ScrollRect.viewport.rect.height;
if (selectedTop > viewportTop)
{
float goalY = selectedTop;
m_ScrollRect.verticalNormalizedPosition = Mathf.Lerp(
m_ScrollRect.verticalNormalizedPosition,
PositionToNormalized(goalY, contentHeightDifference),
scrollSpeed * Time.deltaTime
);
}
else if (selectedBottom < viewportBottom && !Mathf.Approximately(selectedTop, selectedBottom))
{
float diff = selectedBottom - viewportBottom;
float goalY = viewportTop + diff;
m_ScrollRect.verticalNormalizedPosition = Mathf.Lerp(
m_ScrollRect.verticalNormalizedPosition,
PositionToNormalized(goalY, contentHeightDifference),
scrollSpeed * Time.deltaTime
);
}
}
float GetContentHeightDifference()
{
return m_ContentRectTransform.rect.height - m_RectTransform.rect.height;
}
float NormalizedToPosition(float normPos, float contentHeightDifference)
{
return (normPos - 1.0f) * contentHeightDifference;
}
float PositionToNormalized(float pos, float contentHeightDifference)
{
return (pos / contentHeightDifference) + 1.0f;
}
public bool IsClippingTop()
{
return m_ScrollRect.verticalNormalizedPosition < 1.0f;
}
}