コード例 #1
0
    /// <summary>
    /// ノベル処理開始
    /// </summary>
    public void Execute(NovelCommand.SharedData data = null, NovelCommand.SharedVariable variable = null)
    {
        if (variable == null)
        {
            variable = new NovelCommand.SharedVariable()
            {
                index        = 0,
                handles      = new Dictionary <string, GameObject>(),
                values       = new Dictionary <string, string>(),
                groupValues  = new Dictionary <string, string>(),
                groupHistory = new Queue <NovelHistory.GroupData>(),
            };
        }

        if (data == null)
        {
            data = new NovelCommand.SharedData()
            {
                data   = novelData,
                system = this,
                view   = GetComponent <NovelView>(),
            };
        }

        if (executer == null)
        {
            executer = new NovelExecuter(novelData, commandTypeDic);
        }

        StartCoroutine(RunCoroutine(data, variable));
    }
コード例 #2
0
    /// <summary>
    /// ノベルコマンドDo処理コルーチン
    /// </summary>
    private IEnumerator RunCoroutine(NovelCommand.SharedData data, NovelCommand.SharedVariable variable)
    {
        yield return(executer.SetupCoroutine(data));

        yield return(executer.RunCoroutine(variable, data.data.commands.Count));

        yield break;
    }
コード例 #3
0
    /// <summary>
    /// 履歴追加
    /// </summary>
    public void Add(NovelCommand.SharedData data, NovelCommand.SharedVariable variable, NovelCommand.NovelCommandInterface commandInstance)
    {
        // 履歴追加
        histories.Insert(0, new HistoryData()
        {
            historyID = GetCurrentHistoryID() + 1,
            index     = variable.index,
            command   = commandInstance,
        });

        // 初回データを用意(TextClear時に履歴追加したい為)
        if (logs.Count <= 0)
        {
            logs.Insert(0, new LogData());
            logs[0].historyID = 0;
        }

        // コマンドID毎に処理
        var commandData = data.info_.NovelInfoList[variable.index];

        switch (commandData.id)
        {
        case (int)NovelCommandType.NameWrite:
        {
            logs[0].name += variable.FindValue(commandData.parameters[0]);
        }
        break;

        case (int)NovelCommandType.NameClear:
        {
            logs[0].name = "";
        }
        break;

        case (int)NovelCommandType.TextWrite:
        {
            logs[0].text += variable.FindValue(commandData.parameters[0]);
        }
        break;

        case (int)NovelCommandType.TextClear:
        {
            if (MaxHistoryCount <= logs.Count)
            {
                // 古い順で履歴の削除
                var log = logs[MaxHistoryCount - 1];
                logs.RemoveAt(MaxHistoryCount - 1);
                histories.RemoveAll(d => d.historyID <= log.historyID);
                //groups.RemoveAll(d => d.historyID <= log.historyID);

                // groupsはGroup/GrouopEndコマンドの巻き戻しがある為徐々に増えていきます。
                // 古いデータを消す為の処理をコメントアウトしていますが、この処理は正しく動作しません。
                // GroupコマンドはUndoの際に開始位置を把握する為、単純に古いhistoryIDを消すとGroupのPush/Popが壊れます。
                // GroupEndコマンドを消さないとGroupコマンドは消せません。
                // この辺りは都合により未実装なので、執筆者githubより最新版をご確認ください。
            }

            // 履歴を残すべきデータがあるかどうか確認
            if (!string.IsNullOrEmpty(logs[0].name) ||
                !string.IsNullOrEmpty(logs[0].text))
            {
                logs.Insert(0, new LogData()
                    {
                        // historyIDはTextClear時の履歴リストの番号
                        historyID = histories[0].historyID,
                        // 名前は前回のものを引き継ぐ
                        name = logs[0].name,
                        text = "",
                    });
            }
        }
        break;
        }
    }
コード例 #4
0
    /// <summary>
    /// セットアップコルーチン
    /// Include, Import, Groupコマンドの必要情報を集めます
    /// </summary>
    public IEnumerator SetupCoroutine(NovelCommand.SharedData data)
    {
        if (data == null)
        {
            yield break;
        }

        sharedData               = data;
        sharedData.meta          = new NovelMetaData();
        sharedData.meta.groupDic = new Dictionary <string, NovelMetaData.GroupData>();

        // セットアップ用に専用の変数を用意
        // indexはRunCoroutine時とは別物である為(開始位置に関わらずSetupは全部見る)
        var variable = new NovelCommand.SharedVariable()
        {
            values  = new Dictionary <string, string>(),
            handles = new Dictionary <string, UnityEngine.GameObject>(),
            index   = 0,
        };

        // セットアップが必要なコマンド
        var setupIDs = new int[] {
            (int)NovelCommandType.Include,
            (int)NovelCommandType.Import,
            (int)NovelCommandType.Group,
        };

        while (variable.index < novelData.NovelInfoList.Count)
        {
            // 次に処理するコマンドデータ
            // 各コマンドはここから引数を取得します
            sharedData.model_ = novelData.NovelInfoList[variable.index];

            // セットアップが必要なコマンドのみ実行
            if (sharedData.model_.id.IsAny(setupIDs))
            {
                // コマンドデータのIDから型を取得
                Type commandType;
                if (commandTypeDic.TryGetValue(sharedData.model_.id, out commandType))
                {
                    // 型からインスタンスを生成
                    // このインスタンスはUndoを簡易的に行う為のものです
                    command = Activator.CreateInstance(commandType) as NovelCommand.NovelCommandInterface;

                    // 必ず1フレーム消費するので、これだとシビアなタイミングがまずい
                    //yield return command.Do(sharedData, sharedVariable);

                    // 同フレームで処理できるように自分でコルーチンを回す
                    var coroutine = command.Do(sharedData, variable);
                    while (coroutine.MoveNext())
                    {
                        if (coroutine.Current != null)
                        {
                            // 何かしらが返ってきたら同フレームを保証する必要はなさそう
                            var nestCoroutine = coroutine.Current as IEnumerator;
                            if (nestCoroutine != null)
                            {
                                yield return(nestCoroutine);
                            }
                        }

                        yield return(null);
                    }
                }
            }

            variable.index++;
        }

        yield break;
    }