【Unity】ダブルタップ・ロングタップ・フリック、ドラッグ移動・回転・拡縮を簡潔に実装できるEventTriggerの拡張メソッド

# 概要
Unity の EventTrigger でダブルタップ・ロングタップ・フリックを扱えるクラス  **EventTriggerAdvance** を作りました。
更に、それを拡張メソッドで簡潔に扱える拡張クラス EventTriggerExtension も作りました。
不具合や改善点等がありましたら、コメントをお願いします。

# 使い方

``` C#
// ダブルクリック
eventTrigger.AddPointerDoubleClickListener((pointerEventData) => {/* 処理 */}, tolerance : 0.5f);
// tolerance : この値より入力が遅いと、無効になります（省略可能）

// ロングタップ
eventTrigger.AddPointerLongPressListener((pointerEventData) => {/* 処理 */}, tooFastToUp : 0.5f);
// tooFastToUp : この値より速く離すと、無効になります（省略可能）

// フリック
eventTrigger.AddPointerFlickListener((pointerEventData, flickAngle) => {/* 処理 */}, float tooShortSqrDistance : 500f, float tooLateToUp : 0.5f, float tooFastToUp : 0f)
// tooShortSqrDistance : この値よりフリック距離の平方根の方が短いと、無効になります（省略可能）
// tooLateToUp : この値より長く押すと、無効になります（省略可能）
// tooFastToUp : この値より速く離すと、無効になります（省略可能）

// ドラッグ移動・回転・拡縮
eventTrigger.AddDragToMoveListener(transform, (pointerEventData, pos) => transform.position = pos);
eventTrigger.AddDragToRotateListener(transform, (pointerEventData, rot) => transform.rotation = Quaternion.Euler(Vector3.forward * rot));
eventTrigger.AddDragToScaleListener(transform, (pointerEventData, scale) => transform.localScale = Vector3.one * scale);
// 1つ目の引数に Camera を追加すると Sprite 向けの処理になります（Camera を省略すると uGUI 向けの処理になります）
```

### FlickAngle
FlickAngle にはフリックした角度の情報が入っており、AddPointerFlickListener の実行時に取得できます。

``` C#
// -180f から 180f の範囲の角度を取得
float angle = flickAngle.angle;
// 0 : 右
// 90 : 上
// -135 : 左下

if (flickAngle.IsRight) Debug.Log("右方向にフリックされた");

// 上記のプロパティの許容角度は±45度です
// 最後に Side が付いているプロパティは、許容角度が±90度になっています
if (flickAngle.IsRightSide) Debug.Log("右側にフリックされた");

// 斜め方向のプロパティ
if (flickAngle.IsTopLeft) Debug.Log("左上方向にフリックされた");

// 角度を指定して判定
if (flickAngle.CompareAngle(angle : 135f, range : 22.5f)) Debug.Log("北北西方向にフリックされた");

// 角度の差を取得
float diff = flickAngle.DiffAngle(angle);
// 角度の差が時計回りなら負の値、反時計回りなら正の値
float signedDiff = flickAngle.SignedDiffAngle(angle);
```

# コード

<details><summary>EventTriggerAdvance.cs</summary><div>

``` EventTriggerAdvance.cs
using System;
using UnityEngine;

namespace UnityEngine.EventSystems
{
    public static class EventTriggerAdvance
    {
        /// <summary>
        /// Execute when double-clicked.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="tolerance">If the double-click time is longer than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerDoubleClickListener(EventTrigger trigger, Action<PointerEventData> action, float tolerance = 0.75f)
        {
            byte stage = 0;
            double time = 0, subTime = 0;

            // PointerDown
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerDown;
            entry.callback.AddListener((eventData) =>
            {

                if (stage == 2 && Time.unscaledTimeAsDouble - time < tolerance)
                {
                    stage = 3;
                    subTime = Time.unscaledTimeAsDouble;
                    return;
                }
                stage = 1;
                time = Time.unscaledTimeAsDouble;
            });
            trigger.triggers.Add(entry);

            //PointerUp
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerUp;
            entry.callback.AddListener((eventData) =>
            {
                if (stage == 1)
                {
                    if (Time.unscaledTimeAsDouble - time < tolerance) stage = 2;
                    else stage = 0;
                }
                else if (stage == 3)
                {
                    if (Time.unscaledTimeAsDouble - time < tolerance)
                    {
                        stage = 0;
                        action?.Invoke(eventData as PointerEventData);
                        return;
                    }
                    stage = 2;
                    time = subTime;
                }
                else
                {
                    stage = 0;
                }
            });
            trigger.triggers.Add(entry);

            /*
            // If you enable this code, the double-click decision will be strict. 
            // PointerExit
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerExit;
            entry.callback.AddListener((eventData) =>
            {
                stage = 0;
                first = double.NegativeInfinity;
                second = double.NegativeInfinity;
            });
            trigger.triggers.Add(entry);
            // */

            return entry;
        }

        /// <summary>
        /// Execute when long pressed.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="tooFastToUp">If the tap interval is longer than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerLongPressListener(EventTrigger trigger, Action<PointerEventData> action, float tooFastToUp = 0.5f)
        {
            double time = 0;

            // PointerDown
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerDown;
            entry.callback.AddListener((eventData) =>
            {
                time = Time.unscaledTimeAsDouble;
            });
            trigger.triggers.Add(entry);

            // PointerUp
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerUp;
            entry.callback.AddListener((eventData) =>
            {
                double duration = Time.unscaledTimeAsDouble - time;
                if (duration >= tooFastToUp) action?.Invoke(eventData as PointerEventData);
            });
            trigger.triggers.Add(entry);

            // PointerExit
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerExit;
            entry.callback.AddListener((eventData) =>
            {
                time = double.MinValue;
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        /// <summary>
        /// Execute when flicked.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="tooShortSqrDistance">If the flick sqrt distance is shorter than this value, it will be disabled.</param>
        /// <param name="tooLateToUp">If the flick time is slower than this value, it will be disabled.</param>
        /// <param name="tooFastToUp">If the flick interval is faster than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerFlickListener(EventTrigger trigger, Action<PointerEventData, FlickAngle> action, float tooShortSqrDistance = 500f, float tooLateToUp = 0.5f, float tooFastToUp = 0f)
        {
            double time = 0;

            // PointerDown
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerDown;
            entry.callback.AddListener((eventData) =>
            {
                time = Time.unscaledTimeAsDouble;
            });
            trigger.triggers.Add(entry);

            // PointerUp
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.PointerUp;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                if ((data.position - data.pressPosition).sqrMagnitude >= tooShortSqrDistance)
                {
                    float duration = (float)(Time.unscaledTimeAsDouble - time);
                    if (duration >= tooFastToUp && duration <= tooLateToUp)
                    {
                        action?.Invoke(data, new FlickAngle(data.position, data.pressPosition));
                    }
                }
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        #region Drag to transform

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can move it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToMoveListenerUI(EventTrigger trigger, Transform transform, Action<PointerEventData, Vector2> action = null)
        {
            Vector2 beginPos = Vector2.zero;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                beginPos = transform.position;
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                action?.Invoke(data, beginPos + data.position - data.pressPosition);
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can rotate it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToRotateListenerUI(EventTrigger trigger, Transform transform, Action<PointerEventData, float> action = null)
        {
            Vector2 beginVector = Vector2.zero;
            float beginAngle = 0f;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                beginAngle = transform.rotation.eulerAngles.z;
                beginVector = (Vector2)transform.position - data.pressPosition;
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                Vector2 deltaPos = data.position - data.pressPosition;
                action?.Invoke(data, beginAngle + Vector2.SignedAngle(beginVector, beginVector - deltaPos));
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can scale it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToScaleListenerUI(EventTrigger trigger, Transform transform, Action<PointerEventData, float> action = null)
        {
            float dividedBeginMagnitude = 0f;
            float beginScale = 1f;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                beginScale = transform.localScale.z;
                dividedBeginMagnitude = 1f / Mathf.Max(0.0000001f, ((Vector2)transform.position - data.pressPosition).magnitude);
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                action?.Invoke(data, beginScale * ((Vector2)transform.position - data.position).magnitude * dividedBeginMagnitude);
            });
            trigger.triggers.Add(entry);

            return entry;
        }



        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can move it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToMoveListenerSprite(EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, Vector2> action = null)
        {
            Vector3 beginScreenPos = Vector2.zero;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                Vector3 tempPos = camera.WorldToScreenPoint(transform.position);
                tempPos.z = transform.position.z;
                beginScreenPos = tempPos;
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                Vector3 deltaPos = data.position - data.pressPosition;
                deltaPos.z = beginScreenPos.z;
                action?.Invoke(data, camera.ScreenToWorldPoint(beginScreenPos + deltaPos));
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can rotate it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToRotateListenerSprite(EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, float> action = null)
        {
            Vector2 beginVector = Vector2.zero;
            float beginAngle = 0f;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                beginAngle = transform.rotation.eulerAngles.z;
                beginVector = (Vector2)camera.WorldToScreenPoint(transform.position) - data.pressPosition;
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                Vector2 deltaPos = data.position - data.pressPosition;
                action?.Invoke(data, beginAngle + Vector2.SignedAngle(beginVector, beginVector - deltaPos));
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can scale it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToScaleListenerSprite(EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, float> action = null)
        {
            float dividedBeginMagnitude = 0f;
            float beginScale = 1f;

            // BeginDrag
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.BeginDrag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                beginScale = transform.localScale.z;
                dividedBeginMagnitude = 1f / Mathf.Max(0.0000001f, ((Vector2)camera.WorldToScreenPoint(transform.position) - data.pressPosition).magnitude);
            });
            trigger.triggers.Add(entry);

            // Drag
            entry = new EventTrigger.Entry();
            entry.eventID = EventTriggerType.Drag;
            entry.callback.AddListener((eventData) =>
            {
                PointerEventData data = eventData as PointerEventData;
                action?.Invoke(data, beginScale * ((Vector2)camera.WorldToScreenPoint(transform.position) - data.position).magnitude * dividedBeginMagnitude);
            });
            trigger.triggers.Add(entry);

            return entry;
        }

        #endregion
    }
}
```

</div></details>

<details><summary>FlickAngle.cs</summary><div>

``` FlickAngle.cs
namespace UnityEngine.EventSystems
{
    public class FlickAngle
    {
        public readonly float angle;

        public FlickAngle(Vector2 position, Vector2 pressPosition)
        {
            angle = Vector2.SignedAngle(Vector2.right, position - pressPosition);
        }

        /// <summary>
        /// Compare if the angle is within range.
        /// </summary>
        /// <param name="angle">Between -180 and 180<br/>Right:0<br/>Top:90<br/>Left:180<br/>Bottom:-90</param>
        /// <param name="range">Between 0 and 180</param>
        public bool CompareAngle(float angle, float range)
        {
            return DiffAngle(angle) <= range;
        }

        /// <summary>
        /// Return the difference in angle.
        /// </summary>
        /// <param name="angle">Between -180 and 180</param>
        /// <returns>Angle difference</returns>
        public float DiffAngle(float angle)
        {
            float dist = Mathf.Repeat(this.angle - angle + 360f, 360f);
            if (dist > 180f) return 360f - dist;
            return dist;
        }

        /// <summary>
        /// Return the difference in signed angle.
        /// </summary>
        /// <param name="angle">Between -180 and 180</param>
        /// <returns>Signed angle difference</returns>
        public float SignedDiffAngle(float angle)
        {
            float dist = Mathf.Repeat(this.angle - angle + 360f, 360f);
            dist = dist > 180f ? 360f - dist : dist;

            if ((this.angle - angle >= 0f
                    && this.angle - angle <= 180f)
                || (this.angle - angle <= -180f
                    && this.angle - angle >= -360f))
            {
                return dist;
            }
            return -dist;
        }

        public bool IsRightSide { get { return Mathf.Abs(angle) < 90f; } }
        public bool IsTopSide { get { return angle >= 0f; } }
        public bool IsLeftSide { get { return !IsRightSide; } }
        public bool IsBottomSide { get { return !IsTopSide; } }
        public bool IsTopRightSide { get { return Mathf.Abs(angle - 45f) < 90f; } }
        public bool IsTopLeftSide { get { return CompareAngle(135f, 90f); } }
        public bool IsBottomRightSide { get { return Mathf.Abs(angle + 45f) < 90f; } }
        public bool IsBottomLeftSide { get { return CompareAngle(-135f, 90f); } }

        public bool IsRight { get { return Mathf.Abs(angle) < 45f; } }
        public bool IsTop { get { return angle >= 45f && angle < 135f; } }
        public bool IsBottom { get { return angle < -45f && angle >= -135f; } }
        public bool IsLeft { get { return Mathf.Abs(angle) > 135f; } }
        public bool IsTopRight { get { return IsTopSide && IsRightSide; } }
        public bool IsTopLeft { get { return IsTopSide && IsLeftSide; } }
        public bool IsBottomRight { get { return IsBottomSide && IsRightSide; } }
        public bool IsBottomLeft { get { return IsBottomSide && IsLeftSide; } }
    }
}
```

</div></details>

<details><summary>EventTriggerExtension.cs</summary><div>

``` EventTriggerExtension.cs
using System;

namespace UnityEngine.EventSystems
{
    public static class EventTriggerExtension
    {
        public static EventTrigger.Entry AddListener(this EventTrigger trigger, EventTriggerType type, Action<BaseEventData> action)
        {
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = type;
            entry.callback.AddListener((eventData) => action.Invoke(eventData));
            trigger.triggers.Add(entry);
            return entry;
        }
        public static EventTrigger.Entry AddPointerListener(this EventTrigger trigger, EventTriggerType type, Action<PointerEventData> action)
        {
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = type;
            entry.callback.AddListener(eventData => action?.Invoke(eventData as PointerEventData));
            trigger.triggers.Add(entry);
            return entry;
        }
        public static EventTrigger.Entry AddAxisListener(this EventTrigger trigger, EventTriggerType type, Action<AxisEventData> action)
        {
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = type;
            entry.callback.AddListener(eventData => action?.Invoke(eventData as AxisEventData));
            trigger.triggers.Add(entry);
            return entry;
        }
        public static EventTrigger.Entry AddListener<T>(
                this EventTrigger trigger,
                EventTriggerType type,
                Action<T> action) where T : BaseEventData
        {
            EventTrigger.Entry entry = new EventTrigger.Entry();
            entry.eventID = type;
            entry.callback.AddListener(eventData => action?.Invoke(eventData as T));
            trigger.triggers.Add(entry);
            return entry;
        }
        public static bool RemoveListener(this EventTrigger trigger, EventTrigger.Entry entry)
        {
            if (trigger != null && entry != null && trigger.triggers.Contains(entry))
            {
                trigger.triggers.Remove(entry);
                return true;
            }
            return false;
        }

        #region PointerEventData
        public static EventTrigger.Entry AddPointerClickListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.PointerClick, action);
        public static EventTrigger.Entry AddPointerDownListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.PointerDown, action);
        public static EventTrigger.Entry AddPointerUpListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.PointerUp, action);
        public static EventTrigger.Entry AddPointerEnterListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.PointerEnter, action);
        public static EventTrigger.Entry AddPointerExitListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.PointerExit, action);
        public static EventTrigger.Entry AddBeginDragListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.BeginDrag, action);
        public static EventTrigger.Entry AddDragListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.Drag, action);
        public static EventTrigger.Entry AddEndDragListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.EndDrag, action);
        public static EventTrigger.Entry AddDropListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.Drop, action);
        public static EventTrigger.Entry AddScrollListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.Scroll, action);
        public static EventTrigger.Entry AddInitializePotentialDragListener(this EventTrigger trigger, Action<PointerEventData> action)
            => AddPointerListener(trigger, EventTriggerType.InitializePotentialDrag, action);
        #endregion

        #region BaseEventData
        public static EventTrigger.Entry AddUpdateSelectedListener(this EventTrigger trigger, Action<BaseEventData> action)
            => AddListener(trigger, EventTriggerType.UpdateSelected, action);
        public static EventTrigger.Entry AddSelectListener(this EventTrigger trigger, Action<BaseEventData> action)
            => AddListener(trigger, EventTriggerType.Select, action);
        public static EventTrigger.Entry AddDeselectListener(this EventTrigger trigger, Action<BaseEventData> action)
            => AddListener(trigger, EventTriggerType.Deselect, action);
        public static EventTrigger.Entry AddSubmitListener(this EventTrigger trigger, Action<BaseEventData> action)
            => AddListener(trigger, EventTriggerType.Submit, action);
        public static EventTrigger.Entry AddCancelListener(this EventTrigger trigger, Action<BaseEventData> action)
            => AddListener(trigger, EventTriggerType.Cancel, action);
        #endregion

        #region AxisEventData
        public static EventTrigger.Entry AddMoveListener(this EventTrigger trigger, Action<AxisEventData> action)
            => AddAxisListener(trigger, EventTriggerType.Move, action);
        #endregion

        #region PointerEventData(Advance)

        /// <summary>
        /// Execute when long pressed.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="interval">If the tap interval is longer than this value, it will be disabled.</param>
        /// <param name="tooLateToUp">If the tap is slower than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerLongPressListener(this EventTrigger trigger, Action<PointerEventData> action, float tooFastToUp = 0.5f)
        {
            return EventTriggerAdvance.AddPointerLongPressListener(trigger, action, tooFastToUp);
        }

        /// <summary>
        /// Execute when double-clicked.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="tolerance">If the tap interval is longer than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerDoubleClickListener(this EventTrigger trigger, Action<PointerEventData> action, float tolerance = 0.75f)
        {
            return EventTriggerAdvance.AddPointerDoubleClickListener(trigger, action, tolerance);
        }
        /// <summary>
        /// Execute when flicked.
        /// </summary>
        /// <param name="trigger">EventTrigger</param>
        /// <param name="tooShortSqrDistance">If the flick sqrt distance is shorter than this value, it will be disabled.</param>
        /// <param name="tooFastToUp">If the tap interval is longer than this value, it will be disabled.</param>
        /// <param name="tooLateToUp">If the tap is slower than this value, it will be disabled.</param>
        /// <returns>Entry</returns>
        public static EventTrigger.Entry AddPointerFlickListener(this EventTrigger trigger, Action<PointerEventData, FlickAngle> action, float tooShortSqrDistance = 500f, float tooLateToUp = 0.5f, float tooFastToUp = 0f)
        {
            return EventTriggerAdvance.AddPointerFlickListener(trigger, action, tooShortSqrDistance, tooLateToUp, tooFastToUp);
        }

        #region Drag to transform

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can move it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToMoveListener(this EventTrigger trigger, Transform transform, Action<PointerEventData, Vector2> action)
        {
            return EventTriggerAdvance.AddDragToMoveListenerUI(trigger, transform, action);
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can rotate it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToRotateListener(this EventTrigger trigger, Transform transform, Action<PointerEventData, float> action)
        {
            return EventTriggerAdvance.AddDragToRotateListenerUI(trigger, transform, action);
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can scale it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToScaleListener(this EventTrigger trigger, Transform transform, Action<PointerEventData, float> action)
        {
            return EventTriggerAdvance.AddDragToScaleListenerUI(trigger, transform, action);
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can move it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToMoveListener(this EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, Vector2> action)
        {
            return EventTriggerAdvance.AddDragToMoveListenerSprite(trigger, camera, transform, action);
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can rotate it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToRotateListener(this EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, float> action)
        {
            return EventTriggerAdvance.AddDragToRotateListenerSprite(trigger, camera, transform, action);
        }

        /// <summary>
        /// By assigning the return value of the Action, Vector2, to Transform, can scale it by dragging.
        /// </summary>
        public static EventTrigger.Entry AddDragToScaleListener(this EventTrigger trigger, Camera camera, Transform transform, Action<PointerEventData, float> action)
        {
            return EventTriggerAdvance.AddDragToScaleListenerSprite(trigger, camera, transform, action);
        }
        #endregion

        #endregion
    }
}
```

</div></details>