public void OnBeginDrag(DraggableAgent agent, PointerEventData eventData)
        {
            switch (state)
            {
            case DragState.INIT:
                // pass.
                break;

            case DragState.RELEASING:
            case DragState.APPROACHING:
                // すでにend中なので無視する
                return;

            case DragState.NONE:
                return;

            default:
                // イレギュラーなので解除
                SetToNone();
                return;
            }

            if (currentAgent == null)
            {
                SetToNone();
                return;
            }

            if (currentAgent != agent)
            {
                Debug.Log("OnBeginDrag currentが切り替わった。");
                SetToNone();
                return;
            }

            // 対象物のサイズとこのオブジェクトのサイズに合わせて移動可能な範囲を出し、deltaを制限する。
            var currentDraggableRect = agent.GetComponent <RectTransform>();

            dragObject = new DragObject(currentRectTransform(), currentDraggableRect, eventData);

            // TODO: 必要があればconstraintを足そう。
            LimitDragValue(eventData, dragObject);

            // 動かす
            Move(dragObject, eventData.position);

            // TODO: 必要であれば書き換える。
            // 保持しているcornerと関連するcornerに対して、willDisappearとwillAppearを通知する。
            // NotifyAppearance(eventData.delta);

            state = DragState.BEGIN;
        }
        public void OnInitializePotentialDrag(DraggableAgent agent, PointerEventData eventData)
        {
            switch (state)
            {
            case DragState.NONE:
                // pass.
                break;

            // 最終アニメーション動作中なので入力を無視する
            case DragState.RELEASING:
            case DragState.APPROACHING:
                return;

            case DragState.INIT:
                // 含まれるボタンを押したりすると発生する。無視していいやつ。
                break;

            default:
                Debug.LogError("OnInitializePotentialDrag unhandled state:" + state);
                SetToNone();
                return;
            }

            if (currentAgent == null)
            {
                // pass.
            }
            else
            {
                SetToNone();
                return;
            }

            // 開始
            state        = DragState.INIT;
            currentAgent = agent;
        }
 private void SetToNone()
 {
     state        = DragState.NONE;
     dragObject   = null;
     currentAgent = null;
 }
        public void OnEndDrag(DraggableAgent agent, PointerEventData eventData)
        {
            // 特定状態以外無視する
            switch (state)
            {
            case DragState.DRAGGING:
                // pass.
                break;

            case DragState.NONE:
                // 無視する
                return;

            case DragState.RELEASING:
            case DragState.APPROACHING:
                // すでにend中なので無視する
                return;

            default:
                Debug.LogError("unhandled state:" + state);
                SetToNone();
                return;
            }

            if (currentAgent == null)
            {
                SetToNone();
                return;
            }

            if (currentAgent != agent)
            {
                Debug.Log("OnEndDrag currentが切り替わった。");
                SetToNone();
                return;
            }

            // 正常にdragの終了に到達した

            /*
             *  gridがある場合、最も近いgridに吸い寄せられる。
             */
            var candidatePointIndex = -1;
            var diff = Vector2.zero;// 差分にすることで最短距離分だけ移動すればいいことにしている。

            if (gridPoints.Any())
            {
                // オブジェクトの中心位置を取得する
                var centerPos = GetLeftTopPosInParent(currentRectTransform(), dragObject.contentRectTrans) + (dragObject.contentRectTrans.sizeDelta / 2);
                var distance  = float.PositiveInfinity;

                for (var i = 0; i < gridPoints.Length; i++)
                {
                    var gridPoint = gridPoints[i];
                    var current   = Vector2.Distance(gridPoint, centerPos);
                    if (current < distance)
                    {
                        // 更新
                        candidatePointIndex = i;
                        diff = gridPoint - centerPos;
                    }
                    else if (current == distance)
                    {
                        // 同じ距離のものが出た場合、先勝ちにする。
                        break;
                    }

                    distance = current;
                }
            }

            // 最も近いgridが発見された
            if (candidatePointIndex != -1)
            {
                // 接近中状態にする。
                state = DragState.APPROACHING;
            }
            else
            {
                // リリース中状態にする
                state = DragState.RELEASING;
            }

            var approachTargetPoint = dragObject.contentRectTrans.anchoredPosition + new Vector2(diff.x, -diff.y);

            // enumeratorを回してアニメーション中状態を処理する
            IEnumerator animationCor()
            {
                while (true)
                {
                    switch (state)
                    {
                    // 終了処理中
                    case DragState.RELEASING:
                        var cancelCor = CancellingCor(candidatePointIndex);
                        while (cancelCor.MoveNext())
                        {
                            yield return(null);
                        }

                        SetToNone();
                        yield break;

                    case DragState.APPROACHING:
                        var cor = ApproachingCor(approachTargetPoint, candidatePointIndex);
                        while (cor.MoveNext())
                        {
                            yield return(null);
                        }

                        SetToNone();
                        yield break;

                    default:
                        // 何もしない
                        break;
                    }

                    yield return(null);
                }
            }

            // animation用のCoroutineを作ってUpdateで回す。
            // こうすることで、不意に画面遷移が発生してもこのGOがなければ事故が発生しないようにする。
            this.animationCor = animationCor();
        }
        public void OnDrag(DraggableAgent agent, PointerEventData eventData)
        {
            // 特定状態以外無視する
            switch (state)
            {
            case DragState.BEGIN:
                state = DragState.DRAGGING;
                // pass.
                break;

            case DragState.DRAGGING:
                // pass.
                break;

            case DragState.NONE:
                // 無視する
                return;

            case DragState.RELEASING:
            case DragState.APPROACHING:
                // すでにend中なので無視する
                return;

            default:
                Debug.LogError("unhandled state:" + state);
                SetToNone();
                return;
            }

            if (currentAgent == null)
            {
                SetToNone();
                return;
            }

            if (currentAgent != agent)
            {
                Debug.Log("OnDrag currentが切り替わった。");
                SetToNone();
                return;
            }

            // TODO: このへんにmouse使ってて画面外みたいなのが必要

            // dragの方向制約処理を行う
            var actualMove = LimitDragValue(eventData, dragObject);

            // 動かす
            Move(dragObject, actualMove);

            if (gridPoints.Any())
            {
                var candidatePointIndex = -1;

                // オブジェクトの中心位置を取得する
                var centerPos = GetLeftTopPosInParent(currentRectTransform(), dragObject.contentRectTrans) + (dragObject.contentRectTrans.sizeDelta / 2);
                var distance  = float.PositiveInfinity;

                for (var i = 0; i < gridPoints.Length; i++)
                {
                    var gridPoint = gridPoints[i];
                    var current   = Vector2.Distance(gridPoint, centerPos);
                    if (current < distance)
                    {
                        // 更新
                        candidatePointIndex = i;
                    }
                    else if (current == distance)
                    {
                        // 同じ距離のものが出た場合、先勝ちにする。
                        break;
                    }

                    distance = current;
                }

                if (candidatePointIndex != -1)
                {
                    // 接近しているものがある場合、listenerへと伝える。
                    listener.OnDragApproachingToGrid(candidatePointIndex, dragObject.contentRectTrans.gameObject);
                }
            }
        }