Files
project-reset/Assets/Plugins/LiveWatchLite/Scripts/Editor/Utilities/ScrollbarGUI.cs
2025-08-31 18:14:07 -04:00

103 lines
3.3 KiB
C#

using System;
using UnityEngine;
namespace Ingvar.LiveWatch.Editor
{
[Serializable]
public class ScrollbarGUI
{
public bool AllowStickToLast;
public bool IsHorizontal;
public Rect ScrollRect;
public float Size;
public float StartValue;
public float EndValue;
public float ScrollValue;
public float ScrollValueNormalized => EndValue - Size <= 0 ? 0 : ScrollValue / (EndValue - Size);
public bool IsStickingToLast { get; set; }
public ScrollbarGUI(bool isHorizontal)
{
IsHorizontal = isHorizontal;
IsStickingToLast = false;
}
public void Prepare(Rect scrollRect, float size, float startValue, float endValue)
{
ScrollRect = scrollRect;
Size = size;
StartValue = startValue;
EndValue = endValue;
}
public void DrawPlaceholder()
{
if (Event.current.type == EventType.Repaint)
{
var style = new GUIStyle(GUI.skin.horizontalScrollbar);
style.Draw(ScrollRect, false, false, false, false);
}
}
public void Draw()
{
if (EndValue <= Size)
{
ScrollValue = 0;
return;
}
if (IsStickingToLast)
ScrollValue = EndValue - Size;
var scrollValueBefore = ScrollValue;
ScrollValue = IsHorizontal
? GUI.HorizontalScrollbar(ScrollRect, ScrollValue, Size, StartValue, EndValue)
: GUI.VerticalScrollbar(ScrollRect, ScrollValue, Size, StartValue, EndValue);
var scrollValueAfter = ScrollValue;
if (AllowStickToLast && !IsStickingToLast && scrollValueBefore < scrollValueAfter &&
ScrollValueNormalized >= 0.99f)
{
IsStickingToLast = true;
}
else if (IsStickingToLast && scrollValueAfter < scrollValueBefore)
{
IsStickingToLast = false;
}
}
public void SetNormalizedPosition(float normPos, float normAnchor = 0.5f)
{
normPos = Mathf.Clamp01(normPos);
normAnchor = Mathf.Clamp01(normAnchor);
ScrollValue = Mathf.Lerp(StartValue, EndValue, normPos);
ScrollValue = Mathf.Clamp(ScrollValue - Size * normAnchor, 0, EndValue - Size);
}
public void ScrollToValue(float value, float normAnchor = 0.5f)
{
ScrollValue = Mathf.Clamp(
value - Mathf.Clamp01(normAnchor) * Size,
0,
EndValue - Size);
}
public void ResizeRelativeToPointer(float pointerPosition, float resizeFactor)
{
var normAnchor = IsHorizontal
? Mathf.InverseLerp(ScrollRect.xMin, ScrollRect.xMax, pointerPosition)
: Mathf.InverseLerp(ScrollRect.yMin, ScrollRect.yMax, pointerPosition);
var newScrollPos = resizeFactor * (ScrollValue + Size * normAnchor);
EndValue *= resizeFactor;
ScrollToValue(newScrollPos, normAnchor);
}
}
}