89 lines
2.7 KiB
C#
89 lines
2.7 KiB
C#
|
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;
|
||
|
}
|
||
|
}
|