namespace UIWidgets
{
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
///
/// ScrollRect events.
///
[AddComponentMenu("UI/New UI Widgets/Helpers/ScrollRect Events")]
[RequireComponent(typeof(ScrollRect))]
public class ScrollRectEvents : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
///
/// Pull thresholds.
///
[Serializable]
public struct PullThreshold : IEquatable
{
///
/// Up.
///
public float Up;
///
/// Down.
///
public float Down;
///
/// Left.
///
public float Left;
///
/// Right.
///
public float Right;
///
/// Initializes a new instance of the struct.
///
/// Up.
/// Down.
/// Left.
/// Right.
public PullThreshold(float up = 50f, float down = 50f, float left = 50f, float right = 50f)
{
Up = up;
Down = down;
Left = left;
Right = right;
}
///
/// Determines whether the specified object is equal to the current object.
///
/// The object to compare with the current object.
/// true if the specified object is equal to the current object; otherwise, false.
public override bool Equals(object obj)
{
if (obj is PullThreshold)
{
return Equals((PullThreshold)obj);
}
return false;
}
///
/// Determines whether the specified object is equal to the current object.
///
/// The object to compare with the current object.
/// true if the specified object is equal to the current object; otherwise, false.
public bool Equals(PullThreshold other)
{
return Up == other.Up && Down == other.Down && Left == other.Left && Right == other.Right;
}
///
/// Hash function.
///
/// A hash code for the current object.
public override int GetHashCode()
{
return Up.GetHashCode() ^ Down.GetHashCode() ^ Left.GetHashCode() ^ Right.GetHashCode();
}
///
/// Compare specified instances.
///
/// Left instance.
/// Right instances.
/// true if the instances are equal; otherwise, false.
public static bool operator ==(PullThreshold left, PullThreshold right)
{
return left.Equals(right);
}
///
/// Compare specified instances.
///
/// Left instance.
/// Right instances.
/// true if the instances are now equal; otherwise, false.
public static bool operator !=(PullThreshold left, PullThreshold right)
{
return !left.Equals(right);
}
}
///
/// Pull directions.
///
public enum PullDirection
{
///
/// None.
///
None = 0,
///
/// Up.
///
Up = 1,
///
/// Down.
///
Down = 2,
///
/// Left.
///
Left = 3,
///
/// Right.
///
Right = 4,
}
///
/// Pull event.
///
[Serializable]
public class PullEvent : UnityEvent
{
}
///
/// Pull event.
///
[Serializable]
public class PullingEvent : UnityEvent
{
}
///
/// The required pull distance to raise events.
///
[SerializeField]
[Obsolete("Replaced with Thresholds.")]
[HideInInspector]
public float RequiredMovement = 50f;
///
/// Thresholds.
///
[SerializeField]
public PullThreshold Thresholds;
///
/// OnPulling event.
///
[SerializeField]
public PullingEvent OnPulling = new PullingEvent();
///
/// OnPull event.
///
[SerializeField]
public PullEvent OnPull = new PullEvent();
///
/// Event raised when drag distance is equal or more than RequiredMovement.
///
[SerializeField]
public PullEvent OnPullAllowed = new PullEvent();
///
/// Event raised when drag distance is less than RequiredMovement after OnPullValid was called.
///
[SerializeField]
public PullEvent OnPullCancel = new PullEvent();
///
/// OnPullUp event.
///
[SerializeField]
public UnityEvent OnPullUp = new UnityEvent();
///
/// OnPullDown event.
///
[SerializeField]
public UnityEvent OnPullDown = new UnityEvent();
///
/// OnPullLeft event.
///
[SerializeField]
public UnityEvent OnPullLeft = new UnityEvent();
///
/// OnPullRight event.
///
[SerializeField]
public UnityEvent OnPullRight = new UnityEvent();
ScrollRect scrollRect;
///
/// Gets the ScrollRect.
///
/// ScrollRect.
public ScrollRect ScrollRect
{
get
{
if (scrollRect == null)
{
scrollRect = GetComponent();
}
return scrollRect;
}
}
PullDirection pullDirection = PullDirection.None;
bool isPullValid;
///
/// Called by a BaseInputModule before a drag is started.
///
/// Event data.
public virtual void OnBeginDrag(PointerEventData eventData)
{
ResetDrag();
}
///
/// Called by a BaseInputModule when a drag is ended.
///
/// Event data.
public virtual void OnEndDrag(PointerEventData eventData)
{
if (isPullValid)
{
OnPull.Invoke(pullDirection);
switch (pullDirection)
{
case PullDirection.Up:
OnPullUp.Invoke();
break;
case PullDirection.Down:
OnPullDown.Invoke();
break;
case PullDirection.Left:
OnPullLeft.Invoke();
break;
case PullDirection.Right:
OnPullRight.Invoke();
break;
case PullDirection.None:
break;
default:
Debug.LogWarning(string.Format("Unsupported pull direction: {0}", EnumHelper.ToString(pullDirection)));
break;
}
}
ResetDrag();
}
///
/// Resets the drag values.
///
protected virtual void ResetDrag()
{
pullDirection = PullDirection.None;
isPullValid = false;
}
///
/// Pull distance.
///
public float PullDistance
{
get;
protected set;
}
///
/// When dragging is occurring this will be called every time the cursor is moved.
///
/// Event data.
public virtual void OnDrag(PointerEventData eventData)
{
var size = (ScrollRect.transform as RectTransform).rect.size;
var max_x = Mathf.Max(0f, ScrollRect.content.rect.width - size.x);
var max_y = Mathf.Max(0f, ScrollRect.content.rect.height - size.y);
var valid_distance = false;
if (ScrollRect.content.anchoredPosition.y < 0f)
{
PullDistance = -ScrollRect.content.anchoredPosition.y;
valid_distance = PullDistance >= Thresholds.Up;
pullDirection = PullDirection.Up;
}
else if (ScrollRect.content.anchoredPosition.y > max_y)
{
PullDistance = ScrollRect.content.anchoredPosition.y - max_y;
valid_distance = PullDistance >= Thresholds.Down;
pullDirection = PullDirection.Down;
}
else if (ScrollRect.content.anchoredPosition.x < 0f)
{
PullDistance = -ScrollRect.content.anchoredPosition.x;
valid_distance = PullDistance >= Thresholds.Left;
pullDirection = PullDirection.Left;
}
else if (ScrollRect.content.anchoredPosition.x > max_x)
{
PullDistance = ScrollRect.content.anchoredPosition.x - max_x;
valid_distance = PullDistance >= Thresholds.Right;
pullDirection = PullDirection.Right;
}
else
{
PullDistance = 0f;
}
OnPulling.Invoke(this, pullDirection);
if (valid_distance)
{
if (!isPullValid)
{
OnPullAllowed.Invoke(pullDirection);
isPullValid = true;
}
}
else
{
if (isPullValid)
{
OnPullCancel.Invoke(pullDirection);
isPullValid = false;
pullDirection = PullDirection.None;
}
}
}
[SerializeField]
[HideInInspector]
int version = 0;
#if UNITY_EDITOR
///
/// Validate this instance.
///
protected virtual void OnValidate()
{
Upgrade();
}
#endif
///
/// Upgrade this instance.
///
protected virtual void Upgrade()
{
if (version == 0)
{
#pragma warning disable 0618
Thresholds = new PullThreshold(RequiredMovement, RequiredMovement, RequiredMovement, RequiredMovement);
#pragma warning restore 0618
version = 1;
}
}
}
}