Exemple #1
0
        public virtual async Task <TResult> NavigateAsPopupAsync <TResult>(SceneArgs args, IProgress <float> progress = null)
        {
            var resultRequirementId  = Guid.NewGuid();
            var taskCompletionSource = new TaskCompletionSource <object>();

            if (!this._taskCompletionSourcesByResultRequirementId.TryAdd(resultRequirementId, taskCompletionSource))
            {
                this._logger.LogException(new NavigationFailureException("シーンをテーブルに追加できませんでした"));
                return(default(TResult));
            }

            var activateResult = await NavigateCoreAsync(args, NavigationOption.Popup, progress);

            // ここでダメな場合は既にActivateAsyncでエラーを吐いてるハズ
            if (activateResult == null)
            {
                return(default(TResult));
            }

            activateResult.ActivatedScene.ResultRequirementId = resultRequirementId;

            var result = await taskCompletionSource.Task;

            if (!(result is TResult))
            {
                this._logger.LogException(new NavigationFailureException($"戻り値の型は{typeof(TResult)}を期待しましたが、{result.GetType()}が返されました"));
                return(default(TResult));
            }

            return((TResult)result);
        }
Exemple #2
0
        private async Task <ActivationResult> LoadAsync(SceneArgs args, NavigationOption option = NavigationOption.None, IProgress <float> progress = null)
        {
            var asyncOperation = SceneManager.LoadSceneAsync(args.SceneName, LoadSceneMode.Additive);

            progress?.Report(0f);
            while (!asyncOperation.isDone)
            {
                progress?.Report(asyncOperation.progress);
                await Task.Delay(TimeSpan.FromSeconds(Time.fixedDeltaTime));
            }
            progress?.Report(1f);

            var result = Activate(args, option);

            // ここに来たという事は新規
            result.TransitionMode |= TransitionMode.New;

            if (!this._scenesByName.TryAdd(args.SceneName, result.ActivatedScene))
            {
                this._logger.LogException(new NavigationFailureException("シーンをテーブルに追加できませんでした"));
                return(null);
            }

            // ロード時にCanvasの調整をする
            if (this._canvasCustomizer != null)
            {
                this._canvasCustomizer.Customize(result.ActivatedScene.RootCanvas);
            }

            return(result);
        }
Exemple #3
0
        public virtual Task NavigateAsync(SceneArgs args, IProgress <float> progress = null)
        {
            // 結果を待ってるシーンがあるならダメ
            if (this._taskCompletionSourcesByResultRequirementId.Count > 0)
            {
                this._logger.LogException(new NavigationFailureException("結果を待っているシーンがあります"));
                return(Task.CompletedTask);
            }

            return(NavigateCoreAsync(args, NavigationOption.Push, progress));
        }
Exemple #4
0
        private async Task UnloadAsync(SceneArgs args, IProgress <float> progress = null)
        {
            var asyncOperation = SceneManager.UnloadSceneAsync(args.SceneName);

            progress?.Report(0f);
            while (!asyncOperation.isDone)
            {
                progress?.Report(asyncOperation.progress);
                await Task.Delay(TimeSpan.FromSeconds(Time.fixedDeltaTime));
            }
            progress?.Report(1f);

            var removedScene = default(INavigatableScene);

            if (!this._scenesByName.TryRemove(args.SceneName, out removedScene))
            {
                this._logger.LogException(new NavigationFailureException("シーンをテーブルから削除できませんでした"));
            }
        }
Exemple #5
0
        private ActivationResult Activate(SceneArgs args, NavigationOption option = NavigationOption.None)
        {
            var result = new ActivationResult();

            if (this._currentScene != null)
            {
                var currentUnityScene = SceneManager.GetSceneByName(this._currentScene.SceneArgs.SceneName);
                if (!currentUnityScene.isLoaded)
                {
                    this._logger.LogException(new NavigationFailureException("無効なシーンが設定されています"));
                    return(null);
                }

                result.DisactivatedScene = this._currentScene;
            }

            // シーンマネージャの方から次のSceneを取得
            var nextUnityScene = SceneManager.GetSceneByName(args.SceneName);

            if (!nextUnityScene.isLoaded)
            {
                this._logger.LogException(new NavigationFailureException("シーンの読み込みに失敗しました"));
                return(null);
            }
            if (nextUnityScene.rootCount != 1)
            {
                this._logger.LogException(new NavigationFailureException("シーンのRootObjectが複数あります"));
                return(null);
            }

            // SceneからINavigatableSceneを取得
            var rootObjects = nextUnityScene.GetRootGameObjects();

            if (rootObjects.Length == 0)
            {
                this._logger.LogException(new NavigationFailureException("RootObjectが存在しません"));
            }
            if (rootObjects.Length > 1)
            {
                this._logger.LogException(new NavigationFailureException("RootObjectが複数あります"));
            }

            var containsCanvases = rootObjects[0].GetComponentsInChildren <Canvas>();

            if (containsCanvases.Length == 0)
            {
                this._logger.LogException(new NavigationFailureException("Canvasが見つかりませんでした"));
                return(null);
            }

            var sceneBases = rootObjects[0].GetComponents <SceneBase>();

            if (sceneBases.Length == 0)
            {
                this._logger.LogException(new NavigationFailureException("SceneBaseコンポーネントがRootObjectに存在しません"));
                return(null);
            }
            if (sceneBases.Length > 1)
            {
                this._logger.LogException(new NavigationFailureException("SceneBaseコンポーネントが複数あります"));
                return(null);
            }

            // 進む場合、新しいシーンは非表示にしておく
            if (!option.HasFlag(NavigationOption.Pop))
            {
                rootObjects[0].SetActive(false);
            }

            // 次のシーンに諸々引数を渡す
            var nextScene = sceneBases[0] as INavigatableScene;

            nextScene.SetRootCanvas(containsCanvases[0]);
            nextScene.SceneArgs = args;
            nextScene.SetNavigator(this);
            nextScene.SetLogger(this._logger);
            if (this._currentScene != null)
            {
                nextScene.SetParentSceneArgs(this._currentScene.SceneArgs);
            }

            // 進む場合、ソートを整える
            if (!option.HasFlag(NavigationOption.Pop))
            {
                if (this._currentScene != null)
                {
                    nextScene.RootCanvas.sortingOrder = this._canvasOrderArranger.GetOrder(this._currentScene.RootCanvas.sortingOrder, option);
                }
                else
                {
                    nextScene.RootCanvas.sortingOrder = this._canvasOrderArranger.InitialOrder;
                }
            }

            // 次のシーンにnextSceneを設定
            this._currentScene = result.ActivatedScene = nextScene;

            // TransitionModeの調整
            if (option.HasFlag(NavigationOption.Override))
            {
                result.TransitionMode |= TransitionMode.KeepCurrent;
            }
            if (option.HasFlag(NavigationOption.Pop))
            {
                result.TransitionMode |= TransitionMode.Back;
            }

            return(result);
        }
Exemple #6
0
        private async Task <ActivationResult> NavigateCoreAsync(SceneArgs args, NavigationOption option = NavigationOption.None, IProgress <float> progress = null)
        {
            var loadingDisplay = this._loadingDisplaySelector != null?this._loadingDisplaysByOption.GetOrAdd((int)option, this._loadingDisplaySelector.SelectDisplay(option)) : null;

            if (loadingDisplay != null)
            {
                loadingDisplay.Show();
            }

            ActivationResult activationResult;

            if (this._scenesByName.ContainsKey(args.SceneName))
            {
                // 既にInitialize済みのSceneであればActivateするだけでOK
                activationResult = Activate(args, option);
            }
            else
            {
                activationResult = await LoadAsync(args, option, progress);
            }
            // ここでダメな場合は既にActivateAsyncでエラーを吐いてるハズ
            if (activationResult == null || activationResult.ActivatedScene == null)
            {
                return(null);
            }

            if (option.HasFlag(NavigationOption.Push))
            {
                // 新しいシーンをスタックに積む
                this._navigateHistoryStack.Push(new NavigationStackElement()
                {
                    SceneName = args.SceneName, TransitionMode = activationResult.TransitionMode
                });
            }

            // 新しいシーンをリセットする
            await activationResult.ActivatedScene.ResetAsync(args, activationResult.TransitionMode);

            // 新規シーンなら初期化する
            if (activationResult.TransitionMode.HasFlag(TransitionMode.New))
            {
                activationResult.ActivatedScene.Initialize();
            }

            // 新規シーンに入る
            activationResult.ActivatedScene.RootObject.SetActive(true);
            await activationResult.ActivatedScene.EnterAsync(activationResult.TransitionMode);

            // 入ったらイベント発火
            if (this.OnNavigatedAsync != null)
            {
                await this.OnNavigatedAsync(activationResult.ActivatedScene, activationResult.DisactivatedScene, activationResult.TransitionMode);
            }

            // 古いシーンから出る
            if (activationResult.DisactivatedScene != null)
            {
                await activationResult.DisactivatedScene.LeaveAsync(activationResult.TransitionMode);

                // 上に乗せるフラグが無ければ非アクティブ化
                if (!option.HasFlag(NavigationOption.Override))
                {
                    activationResult.DisactivatedScene.RootObject.SetActive(false);
                }

                // Popするならアンロードも行う
                if (option.HasFlag(NavigationOption.Pop))
                {
                    // 古いシーンをスタックから抜いてアンロード
                    var popObject = default(NavigationStackElement);
                    this._navigateHistoryStack.TryPop(out popObject);
                    await UnloadAsync(activationResult.DisactivatedScene.SceneArgs, progress);
                }
            }

            if (loadingDisplay != null)
            {
                loadingDisplay.Hide();
            }

            return(activationResult);
        }
Exemple #7
0
 public virtual async Task ResetAsync(SceneArgs args, TransitionMode mode)
 {
 }
Exemple #8
0
 void INavigatableScene.SetParentSceneArgs(SceneArgs args)
 {
     this.ParentSceneArgs = args;
 }