-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScroller.cs
More file actions
134 lines (111 loc) · 4.5 KB
/
Scroller.cs
File metadata and controls
134 lines (111 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Ricimon.ScrollSnap
{
public class Scroller
{
public event Action<Vector2> ScrollPositionUpdate;
public enum ScrollState
{
NotScrolling,
WillStartScrolling,
ScrollingWithInertia,
ScrollingBackInBounds,
Snapping,
}
public ScrollState State { get; private set; } = ScrollState.NotScrolling;
public bool ContentInBounds { get; set; }
private const float MINIMUM_VELOCITY = 1f;
private DirectionalScrollSnap _scrollSnap;
private IInterpolator _interpolator;
private float _scrollTotalDuration;
private float _scrollTotalDurationReciprocal;
private float _scrollDurationLeft;
private Vector2 _scrollStartPosition;
private Vector2 _scrollTargetPosition;
private Vector2 _movementDelta;
public Scroller(DirectionalScrollSnap scrollSnap)
{
_scrollSnap = scrollSnap;
}
public void StopScroll()
{
State = ScrollState.NotScrolling;
}
public void StartScroll(Vector2 startPosition, Vector2 targetPosition, float duration, IInterpolator interpolator)
{
if (interpolator == null)
{
interpolator = new ViscousFluidInterpolator();
}
State = ScrollState.Snapping;
_interpolator = interpolator;
_scrollTotalDuration = _scrollDurationLeft = duration;
_scrollTotalDurationReciprocal = 1 / duration;
_scrollStartPosition = startPosition;
_scrollTargetPosition = targetPosition;
_movementDelta = targetPosition - startPosition;
//if (ContentInBounds)
//{
// State = ScrollState.WillStartScrolling;
//}
//else
//{
// State = ScrollState.ScrollingBackInBounds;
//}
}
public void Tick()
{
switch(State)
{
case ScrollState.Snapping:
_scrollDurationLeft = Mathf.Max(
_scrollDurationLeft - (_scrollSnap.affectedByTimeScaling ? Time.deltaTime : Time.unscaledDeltaTime),
0f);
float x = _interpolator.GetInterpolation((_scrollTotalDuration - _scrollDurationLeft) * _scrollTotalDurationReciprocal);
ScrollPositionUpdate?.Invoke(_scrollStartPosition + (x * _movementDelta));
if (_scrollDurationLeft == 0)
{
State = ScrollState.NotScrolling;
}
break;
case ScrollState.WillStartScrolling:
State = ScrollState.ScrollingWithInertia;
goto case ScrollState.ScrollingWithInertia;
case ScrollState.ScrollingWithInertia:
if (!ContentInBounds)
{
goto case ScrollState.ScrollingBackInBounds;
}
if (!_scrollSnap.inertia)
{
State = ScrollState.Snapping;
goto case ScrollState.Snapping;
}
else
{
float deltaTime = _scrollSnap.affectedByTimeScaling ? Time.deltaTime : Time.unscaledDeltaTime;
Vector2 decayedVelocity = _scrollSnap.velocity * Mathf.Pow(_scrollSnap.decelerationRate, deltaTime);
//Debug.Log($"Decayed vel: {decayedVelocity.ToString("F6")}");
if (Mathf.Abs(decayedVelocity.x) < MINIMUM_VELOCITY &&
Mathf.Abs(decayedVelocity.y) < MINIMUM_VELOCITY)
{
State = ScrollState.NotScrolling;
break;
}
Vector2 endPosition = _scrollSnap.contentPosition + decayedVelocity * deltaTime;
ScrollPositionUpdate?.Invoke(endPosition);
}
break;
case ScrollState.ScrollingBackInBounds:
ScrollPositionUpdate?.Invoke(_scrollSnap.contentPosition);
break;
}
}
public static implicit operator bool(Scroller exists)
{
return exists != null;
}
}
}