public void OnDragApproachAnimationRequired(int index, GameObject go, Vector2 approachTargetPosition, Action onDone, Action onCancelled)
    {
        var rectTrans = go.GetComponent <RectTransform>();

        animating = true;
        var waitGroup = new WaitGroup(
            () => animating = false
            );

        waitGroup.AddWait(rectTrans);
        IEnumerator approach()
        {
            var count = 0;

            while (true)
            {
                rectTrans.anchoredPosition = rectTrans.anchoredPosition + (approachTargetPosition - rectTrans.anchoredPosition) * 0.5f;
                if (count == 10)
                {
                    onDone();
                    waitGroup.RemoveWait(rectTrans);
                    yield break;
                }
                count++;
                yield return(null);
            }
        }

        StartCoroutine(approach());
    }
    public void OnFlickCancelAnimationRequired(FlickableCorner flickableCorner, Vector2 initialPosition, Action onDone)
    {
        var rectTrans = flickableCorner.GetComponent <RectTransform>();

        animating = true;
        var waitGroup = new WaitGroup(
            () => animating = false
            );

        waitGroup.AddWait(rectTrans);
        IEnumerator cancel()
        {
            var count = 0;

            while (true)
            {
                rectTrans.anchoredPosition = rectTrans.anchoredPosition + (initialPosition - rectTrans.anchoredPosition) * 0.5f;
                flickableCorner.UpdateRelatedCornerPositions();

                if (count == 10)
                {
                    onDone();
                    waitGroup.RemoveWait(rectTrans);
                    yield break;
                }
                count++;
                yield return(null);
            }
        }

        StartCoroutine(cancel());
    }
    public void OnDragBackAnimationRequired(GameObject go, Vector2 initialPosition, Action onDone)
    {
        var rectTrans = go.GetComponent <RectTransform>();

        animating = true;
        var waitGroup = new WaitGroup(
            () => animating = false
            );

        waitGroup.AddWait(rectTrans);
        IEnumerator cancel()
        {
            var count = 0;

            while (true)
            {
                rectTrans.anchoredPosition = rectTrans.anchoredPosition + (initialPosition - rectTrans.anchoredPosition) * 0.5f;
                if (count == 10)
                {
                    onDone();
                    waitGroup.RemoveWait(rectTrans);
                    yield break;
                }
                count++;
                yield return(null);
            }
        }

        StartCoroutine(cancel());
    }
    public void OnDragReachedOnGrid(int index, GameObject go)
    {
        // 表示を更新する
        OnDragApproachingToGrid(index, go);

        var fromIndex = SegOneOfNButtonsCorner.GetIndexOfOne();

        // 変化がないので終了
        if (index == fromIndex)
        {
            return;
        }

        // dragが終わったgridのindexを元に、sequeを選択した状態にする。
        SelectSegue(index);

        // flickableを移動する
        if (FlickableCornersCorner.TryExposureCorners <FlickableCorner>(out var flickableCorners))
        {
            // from to の導出
            var fromFlickableCorner   = flickableCorners[fromIndex];
            var targetFlickableCorner = flickableCorners[index];

            // sequeが操作されたので、flickableCornerの中でフォーカスしてあるものを変更する。
            if (FlickableCorner.TryFindingAutoFlickRoute(fromFlickableCorner, targetFlickableCorner, out var flickDriver))
            {
                // TODO: このへんでdriverを持っておくとおもしろそう。stopしたいので、、

                animating = true;

                var wait = new WaitGroup(
                    () => animating = false
                    );

                wait.AddWait(flickDriver);
                IEnumerator driveCor()
                {
                    while (flickDriver.MoveNext())
                    {
                        yield return(null);
                    }
                    wait.RemoveWait(flickDriver);
                };

                // 開始する
                StartCoroutine(driveCor());
            }
        }
    }
    public void FlickableCornerWillAppear(FlickableCorner flickableCorner)
    {
        // Debug.Log("FlickableCornerWillAppear animating:" + animating);
        var targetIndex = -1;

        switch (flickableCorner.name)
        {
        case "FlickableCorner1":
            targetIndex = 0;
            break;

        case "FlickableCorner2":
            targetIndex = 1;
            break;

        case "FlickableCorner3":
            targetIndex = 2;
            break;

        case "FlickableCorner4":
            targetIndex = 3;
            break;

        default:
            Debug.LogError("unhandled corner:" + flickableCorner);
            break;
        }

        // 該当なし
        if (targetIndex == -1)
        {
            return;
        }

        var currentIndexOfSegue = SegOneOfNButtonsCorner.GetIndexOfOne();

        // 現在既に選択されているindexだった場合、何も起こらない
        if (currentIndexOfSegue == targetIndex)
        {
            return;
        }

        // floatButtonを移動させる
        {
            var dragDriver = draggableDriver(currentIndexOfSegue, targetIndex);

            animating = true;

            var wait = new WaitGroup(
                () => animating = false
                );

            wait.AddWait(dragDriver);
            IEnumerator driveCor()
            {
                while (dragDriver.MoveNext())
                {
                    yield return(null);
                }

                wait.RemoveWait(dragDriver);
            };

            // 開始する
            StartCoroutine(driveCor());
        }

        // 特定のindexのsequeを選択状態にする。
        SelectSegue(targetIndex);
    }
    }                                                                                                 // 何もしない

    public void OnOneOfNChangedToOneByPlayer(GameObject one, GameObject before, GameObject[] all)
    {
        // プレイヤーがUI上のButton1~4のどれかを押したので、flickViewとfloatButtonを移動させる。
        if (FlickableCornersCorner.TryExposureCorners <FlickableCorner>(out var flickableCorners))
        {
            // fromの検出
            var fromIndex = -1;
            switch (before.name)
            {
            case "Button1":
                fromIndex = 0;
                break;

            case "Button2":
                fromIndex = 1;
                break;

            case "Button3":
                fromIndex = 2;
                break;

            case "Button4":
                fromIndex = 3;
                break;

            default:
                Debug.LogError("unhandled:" + one.name);
                return;
            }

            // toの検出
            var toIndex = -1;
            switch (one.name)
            {
            case "Button1":
                toIndex = 0;
                break;

            case "Button2":
                toIndex = 1;
                break;

            case "Button3":
                toIndex = 2;
                break;

            case "Button4":
                toIndex = 3;
                break;

            default:
                Debug.LogError("unhandled:" + one.name);
                return;
            }

            // from to の導出
            var fromFlickableCorner   = flickableCorners[fromIndex];
            var targetFlickableCorner = flickableCorners[toIndex];

            // sequeが操作されたので、flickableCornerの中でフォーカスしてあるものを変更する。
            if (FlickableCorner.TryFindingAutoFlickRoute(fromFlickableCorner, targetFlickableCorner, out var flickDriver))
            {
                // TODO: このへんでdriverを持っておくとおもしろそう。stopしたいので、、

                // draggableをtoIndexに向けて動かす
                var dragDriver = draggableDriver(fromIndex, toIndex);

                animating = true;

                var wait = new WaitGroup(
                    () => animating = false
                    );

                wait.AddWait(flickDriver);
                wait.AddWait(dragDriver);

                IEnumerator flickDriveCor()
                {
                    while (flickDriver.MoveNext())
                    {
                        yield return(null);
                    }
                    wait.RemoveWait(flickDriver);
                };
                IEnumerator dragDriveCor()
                {
                    while (dragDriver.MoveNext())
                    {
                        yield return(null);
                    }
                    wait.RemoveWait(dragDriver);
                };

                // 開始する
                StartCoroutine(flickDriveCor());
                StartCoroutine(dragDriveCor());
            }
        }
    }