|
using UnityEngine; |
|
using System.Collections; |
|
using Holoville.HOTween; |
|
|
|
namespace FS.Handlers |
|
{ |
|
public class FSScrollController : MonoBehaviour { |
|
|
|
public float contentOverflowY = 0f; |
|
public float contentHeight = 0f; |
|
public float viewHeight = 0f; |
|
public float inertiaDuration = 0.95f; |
|
|
|
private Vector3 scrollPosition; |
|
private float scrollVelocity = 0f; |
|
private float timeTouchPhaseEnded = 0f; |
|
private float elasticSpringBackTime = 0.5f; |
|
static private float SCROLL_RESISTANCE_COEFFICIENT = 8f; |
|
|
|
private void setupBounds(){ |
|
// create a default viewHeight, unless it is provided for us externally. |
|
if (viewHeight == 0f) { |
|
viewHeight = (Camera.main.orthographicSize * 2); |
|
} |
|
|
|
// create a default contentHeight, unless it is provided for us externally. |
|
if (contentHeight == 0f) { |
|
contentHeight = viewHeight; |
|
} |
|
|
|
// contentOverflowY is calculated by subtracting the viewheight from the content height. |
|
// this leaves us with the amount we need to be able to move the view. |
|
if (contentOverflowY == 0f) { |
|
contentOverflowY = contentHeight - viewHeight; |
|
} |
|
|
|
// Finally, if our overflow is less than the viewHeight, we get strange scrolling |
|
// behavior, since it snaps the bottom of the content to the bottom of the view. |
|
if (contentOverflowY < 0) { |
|
contentOverflowY = 0; |
|
} |
|
} |
|
|
|
public void Reset() { |
|
// create a default viewHeight, unless it is provided for us externally. |
|
viewHeight = 0f; |
|
contentHeight = 0f; |
|
contentOverflowY = 0f; |
|
} |
|
|
|
public bool ScrollController(){ |
|
|
|
bool scrolling = false; |
|
setupBounds(); |
|
|
|
scrollPosition = this.gameObject.transform.position; |
|
|
|
// Support the computer scrollwheel |
|
float scroll = Input.GetAxis("Mouse ScrollWheel"); |
|
if (0f != scroll) { |
|
scrollPosition = this.gameObject.transform.position; |
|
scrollPosition += Vector3.down * scroll * 400f; |
|
|
|
this.gameObject.transform.position = scrollPosition; |
|
SpringToEdge(); |
|
|
|
// We are scrolling with the mouse scrollwheel, |
|
// so we don't need to execute any more code here. |
|
return true; |
|
} |
|
|
|
if (Input.touchCount < 1) { |
|
if ( scrollVelocity != 0.0f ) { |
|
// slow down over time |
|
float t = (Time.time - timeTouchPhaseEnded) / inertiaDuration; |
|
float frameVelocity = Mathf.Lerp(scrollVelocity, 0f, t); |
|
scrollPosition.y += (frameVelocity * Time.deltaTime); |
|
|
|
// We finish after the time is up. |
|
if (t >= inertiaDuration) scrollVelocity = 0.0f; |
|
|
|
SpringToEdge(); |
|
this.gameObject.transform.position = scrollPosition; |
|
} |
|
return false; |
|
} |
|
|
|
Touch touch = Input.touches[0]; |
|
float drag; |
|
if (touch.phase == TouchPhase.Began){ |
|
scrollVelocity = 0.0f; |
|
scrolling = true; |
|
} else if (touch.phase == TouchPhase.Moved) { |
|
float velocity; |
|
// Figure out where we are starting from: |
|
drag = scrollPosition.y; |
|
|
|
// Add scroll resistance if we are past the bounds of the screen |
|
// AKA elastic scrolling - doesn't work quite right. |
|
// With micro-movements of the fingers, we get to a place where we |
|
// start working our way back to the start. |
|
if(scrollPosition.y < 0) |
|
drag -= drag/SCROLL_RESISTANCE_COEFFICIENT; |
|
else if(scrollPosition.y > contentOverflowY) |
|
drag -= SCROLL_RESISTANCE_COEFFICIENT; |
|
|
|
drag += touch.deltaPosition.y; |
|
scrollPosition.y = drag; |
|
|
|
|
|
// Impart momentum to the scrolled view, using the velocity of the finger |
|
// to compute the momentum of the scroll. |
|
velocity = (touch.deltaPosition.y / touch.deltaTime); |
|
|
|
// Moving average filter to get rid of wild variations... |
|
scrollVelocity = 0.8f * velocity + 0.2f * scrollVelocity; |
|
|
|
// If we move past a certain threshold, then we are scrolling |
|
// otherwise, we are possibly trying to tap. This allows us |
|
// to detect when we are just trying to push a button. |
|
scrolling = (Mathf.Abs(touch.deltaPosition.y) >= 3.0f) ? true : false; |
|
} else if (touch.phase == TouchPhase.Ended) { |
|
|
|
// track the time we ended so we can compute when to stop the scroll. |
|
timeTouchPhaseEnded = Time.time; |
|
|
|
// Add the elastic bounce to the end if we're past bounds. |
|
SpringToEdge(); |
|
scrolling = false; |
|
} |
|
|
|
this.gameObject.transform.position = scrollPosition; |
|
|
|
return scrolling; |
|
} |
|
|
|
private void SpringToEdge() { |
|
TweenParms parms = new TweenParms(); |
|
|
|
if(scrollPosition.y < 0) { |
|
scrollVelocity = 0f; |
|
parms.Prop("position", new Vector3(scrollPosition.x, 0, scrollPosition.z)); // Position tween |
|
parms.Ease(EaseType.EaseOutCubic); // Easing type |
|
HOTween.To(this.gameObject.transform, elasticSpringBackTime, parms); |
|
return; |
|
} |
|
|
|
if(scrollPosition.y > contentOverflowY) { |
|
scrollVelocity = 0f; |
|
parms.Prop("position", new Vector3(scrollPosition.x, contentOverflowY,scrollPosition.z)); // Position tween |
|
parms.Ease(EaseType.EaseOutCubic); // Easing type |
|
HOTween.To(this.gameObject.transform, elasticSpringBackTime, parms); |
|
return; |
|
} |
|
} |
|
} |
|
} |
I do not, unfortunately. I know that the guy who took over the project after me made some major improvements to this code, but I don't think he open sourced those changes.