Esempio n. 1
0
    //-----------------------------------------------------------------

    /// <summary>
    /// 세션 로드
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    public static FSNSession Load(string filepath)
    {
        var newsession = new FSNSession();

        var        rawdata = FSNUtils.LoadTextData(filepath);
        JSONObject json    = JSONObject.Create(rawdata);

        if (json != null)
        {
            // Script 관련
            newsession.ScriptName    = json[c_field_scriptName].str;
            newsession.ScriptHashKey = json[c_field_scriptHash].str;
            newsession.SnapshotIndex = (int)json[c_field_snapshotIndex].n;

            // 플래그 테이블
            var flagtable = json[c_field_flagTable];
            foreach (var key in flagtable.keys)
            {
                newsession.SetFlagValue(key, flagtable[key].b, true);
            }

            // 값 테이블
            var valuetable = json[c_field_valueTable];
            foreach (var key in valuetable.keys)
            {
                newsession.SetNumberValue(key, valuetable[key].n, true);
            }
        }
        else
        {
            Debug.LogErrorFormat("[FSNSession] error loading session file : {0}", filepath);
        }

        return(newsession);
    }
Esempio n. 2
0
    /// <summary>
    /// 세션 저장
    /// </summary>
    /// <param name="session"></param>
    /// <param name="filepath"></param>
    public static void Save(FSNSession session, string filepath, string saveTitle = "")
    {
        {
            var json = new JSONObject(JSONObject.Type.OBJECT);

            // Script 관련
            json.AddField(c_field_scriptName, session.ScriptName);
            json.AddField(c_field_scriptHash, session.ScriptHashKey);
            json.AddField(c_field_snapshotIndex, session.SnapshotIndex);

            // 세이브 정보
            json.AddField(c_field_saveDateTime, FSNUtils.GenerateCurrentDateAndTimeString());
            json.AddField(c_field_saveTitle, saveTitle);

            // 플래그 테이블
            var flagtable = new JSONObject(JSONObject.Type.OBJECT);
            json.AddField(c_field_flagTable, flagtable);
            foreach (var pair in session.m_flagTable)
            {
                flagtable.AddField(pair.Key, pair.Value);
            }

            // 값 테이블
            var valuetable = new JSONObject(JSONObject.Type.OBJECT);
            json.AddField(c_field_valueTable, valuetable);
            foreach (var pair in session.m_valueTable)
            {
                valuetable.AddField(pair.Key, pair.Value);
            }

            FSNUtils.SaveTextData(filepath, json.Print());
        }
    }
Esempio n. 3
0
    /// <summary>
    /// 매칭되는 세이브 파일을 세팅하고 파일 정보를 읽어서 표시
    /// </summary>
    /// <param name="path"></param>
    public void SetSaveFile(string path)
    {
        m_savefilePath = path;
        m_saveinfo     = FSNSession.GetSaveFileInfo(path);

        var title = !string.IsNullOrEmpty(m_saveinfo.title)? m_saveinfo.title : "(제목 없음)";
        var text  = string.Format("{0}\n{1}", title, m_saveinfo.saveDateTime);

        m_text.text = text;
    }
Esempio n. 4
0
    /// <summary>
    /// 세션 (세이브 파일) 로드
    /// </summary>
    /// <param name="filepath"></param>
    public void LoadSession(string filepath)
    {
        foreach (var module in m_moduleRefDict.Values)                  // 로딩 직전의 이벤트 호출
        {
            module.OnBeforeLoadSession();
        }

        var session = FSNSession.Load(filepath);

        m_seqEngine.LoadFromSession(session);
    }
Esempio n. 5
0
        //---------------------------------------------------------------------------------------

        /// <summary>
        /// 헤더 정보 먼저 처리
        /// </summary>
        /// <param name="scriptData"></param>
        /// <param name="session"></param>
        static void ProcessHeaders(string scriptData, FSNScriptSequence sequence, FSNSession session)
        {
            var    strstream  = new System.IO.StringReader(scriptData);
            string line       = null;
            int    linenumber = 0;                        // 줄 번호

            while ((line = strstream.ReadLine()) != null) // 줄 단위로 읽는다.
            {
                linenumber++;
                FSNDebug.currentProcessingScriptLine = linenumber;                       // 디버깅 정보 설정

                if (line.Length > 0 && line.Substring(0, 1) == c_token_PreProcessor)     // 프리프로세서 기호에만 반응한다
                {
                    var commandAndParam = line.Substring(1).Split(c_whiteSpaceArray, 2); // 명령어 파라미터 구분
                    var command         = commandAndParam[0];
                    var paramStr        = commandAndParam.Length > 1? commandAndParam[1] : "";

                    // 아직까지는 header 커맨드밖에 없으므로 간단하게 if로만 체크한다. 더 늘어나면 리팩토링이 필요해질듯...
                    if (command == "헤더" || command == "header")
                    {
                        sequence.Header.FromAsset(paramStr.Trim());
                    }
                    else
                    {
                        Debug.LogErrorFormat("[FSNSequence] line {0} : unknown preprocessor command {1}", linenumber, command);
                    }
                }
            }

            // 읽어들인 헤더 정보를 바탕으로 플래그/변수 기본값들 세팅하기 (선언되어있지 않은 경우에만)

            foreach (var pair in sequence.Header.FlagDeclarations)                    // 플래그 선언
            {
                if (!session.FlagIsDeclared(pair.Key))                                // 아직 선언되지 않은 경우만 세팅
                {
                    bool value = string.IsNullOrEmpty(pair.Value)?
                                 false : FSNUtils.StringToValue <bool>(pair.Value);                 // 초기값까지 선언한 경우 값 해독, 아니면 기본값 false
                    session.SetFlagValue(pair.Key, value, true);
                }
            }

            foreach (var pair in sequence.Header.ValueDeclarations)                   // 값 선언
            {
                if (!session.ValueIsDeclared(pair.Key))                               // 아직 선언되지 않은 경우만 세팅
                {
                    float value = string.IsNullOrEmpty(pair.Value)?
                                  0 : FSNUtils.StringToValue <float>(pair.Value);                   // 초기값까지 선언한 경우 값 해독, 아니면 기본값 false
                    session.SetNumberValue(pair.Key, value, true);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Asset에 포함된 텍스트 파일에서 스크립트를 읽는다
        /// </summary>
        /// <returns></returns>
        public static FSNScriptSequence FromAsset(string assetPath, FSNSession session)
        {
            FSNDebug.currentProcessingScript = assetPath;               // 디버깅 정보 세팅

            var textfile = Resources.Load <TextAsset>(assetPath);

            if (textfile == null)
            {
                Debug.LogErrorFormat("[FSNSequence] Cannot open script asset : {0}", assetPath);
            }
            var sequence = FromString(textfile.text, session);

            sequence.OriginalScriptPath = assetPath;                    // 경로를 기록해둔다
            return(sequence);
        }
Esempio n. 7
0
    /// <summary>
    /// Session에 기록된 값을 통해 스크립트 상태 로딩
    /// </summary>
    /// <param name="session"></param>
    /// <returns>정상적으로 로드했다면 true, 만약 스크립트 버전이 달라서 첫 번재 snapshot부터 보여줘야하는 경우 false</returns>
    public bool LoadFromSession(FSNSession session)
    {
        bool fullSuccess = false;

        CurrentSession = session;                                                                // 로딩시의 세션 정보를 사용하도록 지정
        FSNEngine.Instance.RunScript(session.ScriptName, FSNEngine.ExecuteType.LoadFromSession); // 스크립트 로드

        if (m_snapshotSeq.ScriptHashKey == session.ScriptHashKey)                                // 저장 당시의 hashkey가 일치한다면, 저장 당시의 snapshot index로 점프
        {
            m_snapshotTraveler.JumpToIndex(session.SnapshotIndex);
            m_snapshotTraveler.ExecuteSnapshotFunctions();                                              // 함수 실행이 자동으로 되지 않으므로, 수동으로 호출
            fullSuccess = true;

            // 실제로 트랜지션

            var   curshot   = m_snapshotTraveler.Current;
            float transTime = 0f;                                                                       // 트랜지션 시간

            foreach (var module in m_layerModules.Values)                                               // 현재 로드된 모든 LayerModule 에 맞는 레이어를 찾아 각각 처리한다
            {
                int layerID  = module.LayerID;
                var newLayer = curshot.GetLayer(layerID) ?? FSNSnapshot.Layer.Empty;

                // 로딩 직후의 상황이므로 이전 화면과는 어떤 연관성도 없는 것으로 간주, 빈 레이어도 강제로 트랜지션을 걸어준다.

                float curtt = module.StartTransition(newLayer, curshot.InGameSetting, 0, false);                        // 트랜지션

                if (transTime < curtt)                                                                                  // 제일 긴 트랜지션 시간 추적
                {
                    transTime = curtt;
                }
            }
            m_lastSwipeWasBackward = false;                                                             // swipe 방향성, 정방향으로 취급하기
            m_swipeAvailableTime   = Time.time + transTime;                                             // 현재 시간 + 트랜지션에 걸리는 시간 뒤에 swipe가 가능해짐
        }
        else
        {
            Debug.LogWarningFormat("[FSNSequenceEngine] Script version differs ({0}), so started from the begining", session.ScriptName);
        }

        return(fullSuccess);
    }
Esempio n. 8
0
    public void PopulateList()
    {
        SortedList <long, FSNSaveListUIItem> sortList = new SortedList <long, FSNSaveListUIItem>();

        var fileList = FSNSession.GetSaveFileList();                                                                    // 파일 목록 읽어오기
        int count    = fileList.Length;

        for (int i = 0; i < count; i++)                                                         // 리스트 항목 생성
        {
            var newitemgo = Instantiate <GameObject>(m_itemOriginal.gameObject);                // 게임 오브젝트 복제
            newitemgo.SetActive(true);
            newitemgo.transform.SetParent(m_gridTransform, false);

            var newitem = newitemgo.GetComponent <FSNSaveListUIItem>();                                         // 컴포넌트 찾기
            newitem.SetSaveFile(fileList[i]);                                                                   // 세이브 파일 지정하기
            m_allItems.Add(newitem);

            sortList.Add(newitem.DateTime.Ticks, newitem);                                              // 소팅 리스트에 집어넣기

            newitem.GetComponent <Toggle>().onValueChanged.AddListener(OnItemValueChanged);             // 이벤트 추가
        }

        int sortlistcount = sortList.Count;

        foreach (var item in sortList.Values)                                                                                   // 역순으로 아이템 순서 맞추기
        {
            item.transform.SetSiblingIndex(sortlistcount--);
        }

        if (m_saveMode)                                                                                         // 저장 모드일 경우, 새 세이브 슬롯도 추가
        {
            m_newSaveItem.gameObject.SetActive(true);                                                           // 활성화하기
            m_newSaveItem.transform.SetAsFirstSibling();                                                        // 순서 맞추기 (제일 위로)

            var toggleComp = m_newSaveItem.GetComponent <Toggle>();                                             // 이벤트 추가
            var onChanged  = toggleComp.onValueChanged;
            onChanged.RemoveAllListeners();
            onChanged.AddListener(OnItemValueChanged);

            m_allItems.Add(m_newSaveItem);                                                                                              // 똑같이 아이템 리스트에 추가
        }
    }
Esempio n. 9
0
        //---------------------------------------------------------------------------------------
        /// <summary>
        /// 헤더 정보 먼저 처리
        /// </summary>
        /// <param name="scriptData"></param>
        /// <param name="session"></param>
        static void ProcessHeaders(string scriptData, FSNScriptSequence sequence, FSNSession session)
        {
            var strstream	= new System.IO.StringReader(scriptData);
            string line		= null;
            int linenumber	= 0;    // 줄 번호

            while ((line = strstream.ReadLine()) != null)               // 줄 단위로 읽는다.
            {
                linenumber++;
                FSNDebug.currentProcessingScriptLine    = linenumber;   // 디버깅 정보 설정

                if (line.Length > 0 && line.Substring(0,1) == c_token_PreProcessor)		// 프리프로세서 기호에만 반응한다
                {
                    var commandAndParam = line.Substring(1).Split(c_whiteSpaceArray, 2);            // 명령어 파라미터 구분
                    var command         = commandAndParam[0];
                    var paramStr        = commandAndParam.Length > 1? commandAndParam[1] : "";

                    // 아직까지는 header 커맨드밖에 없으므로 간단하게 if로만 체크한다. 더 늘어나면 리팩토링이 필요해질듯...
                    if (command == "헤더" || command == "header")
                    {
                        sequence.Header.FromAsset(paramStr.Trim());
                    }
                    else
                    {
                        Debug.LogErrorFormat("[FSNSequence] line {0} : unknown preprocessor command {1}", linenumber, command);
                    }
                }
            }

            // 읽어들인 헤더 정보를 바탕으로 플래그/변수 기본값들 세팅하기 (선언되어있지 않은 경우에만)

            foreach (var pair in sequence.Header.FlagDeclarations)        // 플래그 선언
            {
                if (!session.FlagIsDeclared(pair.Key))                          // 아직 선언되지 않은 경우만 세팅
                {
                    bool value  = string.IsNullOrEmpty(pair.Value)?
                        false : FSNUtils.StringToValue<bool>(pair.Value);   // 초기값까지 선언한 경우 값 해독, 아니면 기본값 false
                    session.SetFlagValue(pair.Key, value, true);
                }
            }

            foreach (var pair in sequence.Header.ValueDeclarations)       // 값 선언
            {
                if (!session.ValueIsDeclared(pair.Key))                         // 아직 선언되지 않은 경우만 세팅
                {
                    float value = string.IsNullOrEmpty(pair.Value)?
                        0 : FSNUtils.StringToValue<float>(pair.Value);      // 초기값까지 선언한 경우 값 해독, 아니면 기본값 false
                    session.SetNumberValue(pair.Key, value, true);
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// 문자열으로 스크립트 파싱
        /// </summary>
        /// <param name="scriptData"></param>
        /// <returns></returns>
        public static FSNScriptSequence FromString(string scriptData, FSNSession session)
        {
            // 디버깅 세션 세팅
            FSNDebug.currentRuntimeStage = FSNDebug.RuntimeStage.Compile;

            var sequence				= new FSNScriptSequence();
            sequence.OriginalScriptPath	= "(string)";
            sequence.ScriptHashKey		= GenerateHashKeyFromScript(scriptData);    // 해시키 생성해두기 (세이브 파일과 스크립트 파일 버전 체크용)

            // ===== FIRST PASS : 헤더 파일 먼저 해석 ==================================

            ProcessHeaders(scriptData, sequence, session);

            // ===== SECOND PASS : 나머지 스크립트 요소들 해석 =========================
            var strstream               = new System.IO.StringReader(scriptData);

            // 스크립트 해석 상태값들
            CommandGenerateProtocol protocol	= new CommandGenerateProtocol();

            // flags
            Segments.Period	periodSeg			= null;				// Period 세그먼트. 먼저 만들어놓고 있다가 적당한 때에 삽입한다. (스크립트와 실제 세그먼트 순서가 다르기 때문)
            bool			textMultilineMode	= false;			// 텍스트 여러줄 처리중인지 (//)
            string			multilineText		= "";				// 멀티라인 모드에서, 텍스트 처리중일 때
            //

            // ** 스크립트 로드 후 첫번째 스냅샷에서 다시 이전으로 돌아가는 것은 불가능하므로, 맨 처음에 oneway 컨트롤 세그먼트를 추가해준다
            var onewayAtFirstSeg			= new Segments.Control();
            onewayAtFirstSeg.controlType	= Segments.Control.ControlType.Oneway;
            var onewaySegInfo				= new FSNScriptSequence.Parser.GeneratedSegmentInfo()
            {
                newSeg	= onewayAtFirstSeg
            };
            protocol.PushSegment(onewaySegInfo);
            //

            string line		= null;
            int linenumber	= 0;	// 줄 번호
            while ((line = strstream.ReadLine()) != null)				// 줄 단위로 읽는다.
            {
                line		= sequence.Header.Macros.Replace(line);		// 정적 매크로 치환

                linenumber++;
                FSNDebug.currentProcessingScriptLine	= linenumber;	// 디버깅 정보 설정

                if (!textMultilineMode && line.Length == 0)				// * 빈 줄은 스루. 단 여러줄 텍스트 모드일 경우 빈 줄에서는 여러줄 모드를 끝내게 한다.
                    continue;

                if (line.EndsWith(c_token_LineConcat))					// * 여러줄 텍스트로 지정된 경우, 자동으로 여러줄 모드로. 해당 라인 붙이기
                {
                    textMultilineMode	= true;

                    if (multilineText.Length > 0)						// 이미 쌓여있는 텍스트가 있다면 공백 추가
                        multilineText	+= "\n";
                    multilineText		+= line.Substring(0, line.Length - c_token_LineConcat.Length);
                }
                else
                {
                    var pretoken		= line.Length > 0? line.Substring(0, 1) : "";
                    switch (pretoken)										// 앞쪽 토큰으로 명령 구분
                    {
                        case c_token_Comment:								// * 주석
                            // 스루. 뭐 왜 뭐 주석인데 뭐
                            break;

                        case c_token_PreProcessor:							// * 전처리 구문
                            // 프리프로세서는 첫번째 패스에서 처리함.
                            break;

                        case c_token_Command:								// * 명령
                            {
                                var commandAndParam	= line.Substring(1).Split(c_whiteSpaceArray, 2);			// 명령어 파라미터 구분
                                var command			= commandAndParam[0];
                                var paramStr		= commandAndParam.Length > 1? commandAndParam[1] : "";

                                CommandSegmentGenerateFunc genfunc = null;
                                s_aliasToSegFunction.TryGetValue(command, out genfunc);
                                if(genfunc == null)																// 등록된 명령어인지 체크
                                {
                                    Debug.LogError("Unknown command : " + command);
                                }
                                else
                                {
                                    protocol.parameters	= ParseParameters(paramStr);
                                    genfunc(protocol);
                                }
                            }
                            break;

                        case c_token_HardLabel:								// * hard label
                            {
                                var labelSeg		= new Segments.Label();
                                labelSeg.labelName	= line.Substring(1);
                                labelSeg.labelType	= Segments.Label.LabelType.Hard;

                                var segInfo				= new GeneratedSegmentInfo();
                                segInfo.newSeg			= labelSeg;
                                segInfo.usePrevPeriod	= true;				// Label 전에 period로 다 출력해야함
                                segInfo.selfPeriod		= false;
                                protocol.PushSegment(segInfo);
                            }
                            break;

                        case c_token_SoftLabel:								// * soft label
                            {
                                var labelSeg		= new Segments.Label();
                                labelSeg.labelName	= line.Substring(1);
                                labelSeg.labelType	= Segments.Label.LabelType.Soft;

                                var segInfo				= new GeneratedSegmentInfo();
                                segInfo.newSeg			= labelSeg;
                                segInfo.usePrevPeriod	= true;				// Label 전에 period로 다 출력해야함
                                segInfo.selfPeriod		= false;
                                protocol.PushSegment(segInfo);
                            }
                            break;

                        case c_token_Period:								// * period
                            if (line.Length == 1)							// . 한글자일 때 - 일반 period
                            {
                                if(periodSeg != null)						// * 이미 period 명령어가 대기중일 때, 기존 명령어를 먼저 처리한다
                                {
                                    sequence.m_segments.Add(periodSeg);
                                }
                                periodSeg	= new Segments.Period();
                            }
                            else if(line.Length == 2 && line[1].ToString() == c_token_Period)	// .. 으로 두 글자일 때 - 연결 period, 만약 period가 이전에 등장했다면 연결으로 변경
                            {
                                Segments.Period lastPeriodseg;

                                if(periodSeg != null)											// 처리 안된 period가 있을 경우, 이것을 chaining으로 변경해준다
                                {
                                    lastPeriodseg	= periodSeg;
                                }
                                else if((lastPeriodseg = sequence.m_segments[sequence.m_segments.Count - 1] as Segments.Period)
                                                .type == Segment.Type.Period)					// 아닐 경우, 가장 마지막으로 추가된 세그먼트가 period를 chaining으로 변경한다
                                {
                                    //
                                }
                                else
                                {																// 그도 아닐 경우 새로 period 생성
                                    periodSeg		= new Segments.Period();
                                    lastPeriodseg	= periodSeg;
                                }

                                lastPeriodseg.isChaining	= true;								// 선택한 period에 chaining속성 부여
                            }
                            else
                            {
                                Debug.LogError("invalid command... is it a period command?");
                            }
                            break;

                        case c_token_ForceText:
                        default:											// * 아무 토큰도 없음 : 텍스트
                            {
                                if (line.Length > 0 && line[0].ToString() == c_token_ForceText)	// 만약 강제 텍스트 토큰 (~) 이 붙어있었다면, 해당 토큰 제거
                                    line	= line.Substring(1);

                                multilineText		+= multilineText.Length > 0? "\n" + line : line;
                                var textSeg			= new Segments.Text();
                                textSeg.text		= multilineText;
                                textSeg.textType	= Segments.Text.TextType.Normal;

                                multilineText		= "";	// 멀티라인 텍스트 보관되어있던 것을 초기화
                                textMultilineMode	= false;

                                var segInfo				= new GeneratedSegmentInfo();
                                segInfo.newSeg			= textSeg;
                                segInfo.usePrevPeriod	= true;	// 출력 명령어임
                                segInfo.selfPeriod		= true;	// 스스로 period를 포함함
                                protocol.PushSegment(segInfo);
                            }
                            break;
                    }

                    GeneratedSegmentInfo newSegInfo	= null;
                    while ((newSegInfo = protocol.PullSegment()) != null)	// 새로 생성된 시퀀스 모두 처리
                    {
                        if (newSegInfo.usePrevPeriod && periodSeg != null)	// * 선행 period를 먼저 처리해야하는 상황
                        {
                            periodSeg.scriptLineNumber		= linenumber;	// 줄번호 기록?
                            sequence.m_segments.Add(periodSeg);
                            periodSeg	= null;
                        }

                        newSegInfo.newSeg.scriptLineNumber	= linenumber;	// 줄번호 기록
                        sequence.m_segments.Add(newSegInfo.newSeg);			// 시퀀스 추가
                        if (newSegInfo.newSeg.type == Segment.Type.Label)	// 라벨일 경우 등록
                            sequence.RegisterLabelSegment();

                        if(newSegInfo.selfPeriod)							// * 방금 추가된 세그먼트가 period를 포함하는 개념이라면, period 대기시켜놓기
                        {
                            periodSeg	= new Segments.Period();
                        }
                    }
                }
            }

            if(periodSeg != null)											// 끝날 때까지 처리되지 않은 period가 있다면 여기서 추가해준다
            {
                periodSeg.scriptLineNumber		= linenumber;				// 줄번호 기록?
                sequence.m_segments.Add(periodSeg);
                periodSeg = null;
            }

            // 디버깅 세션 세팅
            FSNDebug.currentRuntimeStage = FSNDebug.RuntimeStage.Runtime;

            return sequence;
        }
Esempio n. 11
0
        /// <summary>
        /// Asset에 포함된 텍스트 파일에서 스크립트를 읽는다
        /// </summary>
        /// <returns></returns>
        public static FSNScriptSequence FromAsset(string assetPath, FSNSession session)
        {
            FSNDebug.currentProcessingScript = assetPath;	// 디버깅 정보 세팅

            var textfile	= Resources.Load<TextAsset>(assetPath);
            if (textfile == null)
            {
                Debug.LogErrorFormat("[FSNSequence] Cannot open script asset : {0}", assetPath);
            }
            var sequence	= FromString(textfile.text, session);
            sequence.OriginalScriptPath	= assetPath;	// 경로를 기록해둔다
            return sequence;
        }
Esempio n. 12
0
        /// <summary>
        /// 문자열으로 스크립트 파싱
        /// </summary>
        /// <param name="scriptData"></param>
        /// <returns></returns>
        public static FSNScriptSequence FromString(string scriptData, FSNSession session)
        {
            // 디버깅 세션 세팅
            FSNDebug.currentRuntimeStage = FSNDebug.RuntimeStage.Compile;

            var sequence = new FSNScriptSequence();

            sequence.OriginalScriptPath = "(string)";
            sequence.ScriptHashKey      = GenerateHashKeyFromScript(scriptData);                    // 해시키 생성해두기 (세이브 파일과 스크립트 파일 버전 체크용)

            // ===== FIRST PASS : 헤더 파일 먼저 해석 ==================================

            ProcessHeaders(scriptData, sequence, session);


            // ===== SECOND PASS : 나머지 스크립트 요소들 해석 =========================
            var strstream = new System.IO.StringReader(scriptData);

            // 스크립트 해석 상태값들
            CommandGenerateProtocol protocol = new CommandGenerateProtocol();

            // flags
            Segments.Period periodSeg         = null;                                                   // Period 세그먼트. 먼저 만들어놓고 있다가 적당한 때에 삽입한다. (스크립트와 실제 세그먼트 순서가 다르기 때문)
            bool            textMultilineMode = false;                                                  // 텍스트 여러줄 처리중인지 (//)
            string          multilineText     = "";                                                     // 멀티라인 모드에서, 텍스트 처리중일 때
            //

            // ** 스크립트 로드 후 첫번째 스냅샷에서 다시 이전으로 돌아가는 것은 불가능하므로, 맨 처음에 oneway 컨트롤 세그먼트를 추가해준다
            var onewayAtFirstSeg = new Segments.Control();

            onewayAtFirstSeg.controlType = Segments.Control.ControlType.Oneway;
            var onewaySegInfo = new FSNScriptSequence.Parser.GeneratedSegmentInfo()
            {
                newSeg = onewayAtFirstSeg
            };

            protocol.PushSegment(onewaySegInfo);
            //

            string line       = null;
            int    linenumber = 0;                           // 줄 번호

            while ((line = strstream.ReadLine()) != null)    // 줄 단위로 읽는다.
            {
                line = sequence.Header.Macros.Replace(line); // 정적 매크로 치환

                linenumber++;
                FSNDebug.currentProcessingScriptLine = linenumber;                      // 디버깅 정보 설정

                if (!textMultilineMode && line.Length == 0)                             // * 빈 줄은 스루. 단 여러줄 텍스트 모드일 경우 빈 줄에서는 여러줄 모드를 끝내게 한다.
                {
                    continue;
                }

                if (line.EndsWith(c_token_LineConcat))                                                  // * 여러줄 텍스트로 지정된 경우, 자동으로 여러줄 모드로. 해당 라인 붙이기
                {
                    textMultilineMode = true;

                    if (multilineText.Length > 0)                                                               // 이미 쌓여있는 텍스트가 있다면 공백 추가
                    {
                        multilineText += "\n";
                    }
                    multilineText += line.Substring(0, line.Length - c_token_LineConcat.Length);
                }
                else
                {
                    var pretoken = line.Length > 0? line.Substring(0, 1) : "";
                    switch (pretoken)                                                                                           // 앞쪽 토큰으로 명령 구분
                    {
                    case c_token_Comment:                                                                                       // * 주석
                        // 스루. 뭐 왜 뭐 주석인데 뭐
                        break;

                    case c_token_PreProcessor:                                                                                  // * 전처리 구문
                        // 프리프로세서는 첫번째 패스에서 처리함.
                        break;

                    case c_token_Command:                                                                                       // * 명령
                    {
                        var commandAndParam = line.Substring(1).Split(c_whiteSpaceArray, 2);                                    // 명령어 파라미터 구분
                        var command         = commandAndParam[0];
                        var paramStr        = commandAndParam.Length > 1? commandAndParam[1] : "";

                        CommandSegmentGenerateFunc genfunc = null;
                        s_aliasToSegFunction.TryGetValue(command, out genfunc);
                        if (genfunc == null)                                                                                                                                                                    // 등록된 명령어인지 체크
                        {
                            Debug.LogError("Unknown command : " + command);
                        }
                        else
                        {
                            protocol.parameters = ParseParameters(paramStr);
                            genfunc(protocol);
                        }
                    }
                    break;

                    case c_token_HardLabel:                                                                                     // * hard label
                    {
                        var labelSeg = new Segments.Label();
                        labelSeg.labelName = line.Substring(1);
                        labelSeg.labelType = Segments.Label.LabelType.Hard;

                        var segInfo = new GeneratedSegmentInfo();
                        segInfo.newSeg        = labelSeg;
                        segInfo.usePrevPeriod = true;                                                                   // Label 전에 period로 다 출력해야함
                        segInfo.selfPeriod    = false;
                        protocol.PushSegment(segInfo);
                    }
                    break;

                    case c_token_SoftLabel:                                                                                     // * soft label
                    {
                        var labelSeg = new Segments.Label();
                        labelSeg.labelName = line.Substring(1);
                        labelSeg.labelType = Segments.Label.LabelType.Soft;

                        var segInfo = new GeneratedSegmentInfo();
                        segInfo.newSeg        = labelSeg;
                        segInfo.usePrevPeriod = true;                                                                   // Label 전에 period로 다 출력해야함
                        segInfo.selfPeriod    = false;
                        protocol.PushSegment(segInfo);
                    }
                    break;

                    case c_token_Period:                                                                                        // * period
                        if (line.Length == 1)                                                                                   // . 한글자일 때 - 일반 period
                        {
                            if (periodSeg != null)                                                                              // * 이미 period 명령어가 대기중일 때, 기존 명령어를 먼저 처리한다
                            {
                                sequence.m_segments.Add(periodSeg);
                            }
                            periodSeg = new Segments.Period();
                        }
                        else if (line.Length == 2 && line[1].ToString() == c_token_Period)                                      // .. 으로 두 글자일 때 - 연결 period, 만약 period가 이전에 등장했다면 연결으로 변경
                        {
                            Segments.Period lastPeriodseg;

                            if (periodSeg != null)                                                                                                                      // 처리 안된 period가 있을 경우, 이것을 chaining으로 변경해준다
                            {
                                lastPeriodseg = periodSeg;
                            }
                            else if ((lastPeriodseg = sequence.m_segments[sequence.m_segments.Count - 1] as Segments.Period)
                                     .type == Segment.Type.Period)                                                                                              // 아닐 경우, 가장 마지막으로 추가된 세그먼트가 period를 chaining으로 변경한다
                            {
                                //
                            }
                            else
                            {                                                                                                                                                                   // 그도 아닐 경우 새로 period 생성
                                periodSeg     = new Segments.Period();
                                lastPeriodseg = periodSeg;
                            }

                            lastPeriodseg.isChaining = true;                                                                                                    // 선택한 period에 chaining속성 부여
                        }
                        else
                        {
                            Debug.LogError("invalid command... is it a period command?");
                        }
                        break;

                    case c_token_ForceText:
                    default:                                                                                                    // * 아무 토큰도 없음 : 텍스트
                    {
                        if (line.Length > 0 && line[0].ToString() == c_token_ForceText)                                         // 만약 강제 텍스트 토큰 (~) 이 붙어있었다면, 해당 토큰 제거
                        {
                            line = line.Substring(1);
                        }

                        multilineText += multilineText.Length > 0? "\n" + line : line;
                        var textSeg = new Segments.Text();
                        textSeg.text     = multilineText;
                        textSeg.textType = Segments.Text.TextType.Normal;

                        multilineText     = "";                                                 // 멀티라인 텍스트 보관되어있던 것을 초기화
                        textMultilineMode = false;

                        var segInfo = new GeneratedSegmentInfo();
                        segInfo.newSeg        = textSeg;
                        segInfo.usePrevPeriod = true;                                           // 출력 명령어임
                        segInfo.selfPeriod    = true;                                           // 스스로 period를 포함함
                        protocol.PushSegment(segInfo);
                    }
                    break;
                    }

                    GeneratedSegmentInfo newSegInfo = null;
                    while ((newSegInfo = protocol.PullSegment()) != null)                       // 새로 생성된 시퀀스 모두 처리
                    {
                        if (newSegInfo.usePrevPeriod && periodSeg != null)                      // * 선행 period를 먼저 처리해야하는 상황
                        {
                            periodSeg.scriptLineNumber = linenumber;                            // 줄번호 기록?
                            sequence.m_segments.Add(periodSeg);
                            periodSeg = null;
                        }

                        newSegInfo.newSeg.scriptLineNumber = linenumber;                                // 줄번호 기록
                        sequence.m_segments.Add(newSegInfo.newSeg);                                     // 시퀀스 추가
                        if (newSegInfo.newSeg.type == Segment.Type.Label)                               // 라벨일 경우 등록
                        {
                            sequence.RegisterLabelSegment();
                        }

                        if (newSegInfo.selfPeriod)                                                                              // * 방금 추가된 세그먼트가 period를 포함하는 개념이라면, period 대기시켜놓기
                        {
                            periodSeg = new Segments.Period();
                        }
                    }
                }
            }

            if (periodSeg != null)                                                                              // 끝날 때까지 처리되지 않은 period가 있다면 여기서 추가해준다
            {
                periodSeg.scriptLineNumber = linenumber;                                                        // 줄번호 기록?
                sequence.m_segments.Add(periodSeg);
                periodSeg = null;
            }

            // 디버깅 세션 세팅
            FSNDebug.currentRuntimeStage = FSNDebug.RuntimeStage.Runtime;

            return(sequence);
        }
Esempio n. 13
0
 /// <summary>
 /// 새 게임시 Session 오브젝트를 준비한다.
 /// </summary>
 public void PrepareNewSession()
 {
     CurrentSession = new FSNSession();
 }
Esempio n. 14
0
    /// <summary>
    /// 세션 저장
    /// </summary>
    /// <param name="session"></param>
    /// <param name="filepath"></param>
    public static void Save(FSNSession session, string filepath, string saveTitle = "")
    {
        {
            var json		= new JSONObject(JSONObject.Type.OBJECT);

            // Script 관련
            json.AddField(c_field_scriptName, session.ScriptName);
            json.AddField(c_field_scriptHash, session.ScriptHashKey);
            json.AddField(c_field_snapshotIndex, session.SnapshotIndex);

            // 세이브 정보
            json.AddField(c_field_saveDateTime, FSNUtils.GenerateCurrentDateAndTimeString());
            json.AddField(c_field_saveTitle, saveTitle);

            // 플래그 테이블
            var flagtable	= new JSONObject(JSONObject.Type.OBJECT);
            json.AddField(c_field_flagTable, flagtable);
            foreach(var pair in session.m_flagTable)
            {
                flagtable.AddField(pair.Key, pair.Value);
            }

            // 값 테이블
            var valuetable	= new JSONObject(JSONObject.Type.OBJECT);
            json.AddField(c_field_valueTable, valuetable);
            foreach(var pair in session.m_valueTable)
            {
                valuetable.AddField(pair.Key, pair.Value);
            }

            FSNUtils.SaveTextData(filepath, json.Print());
        }
    }
Esempio n. 15
0
    //-----------------------------------------------------------------
    /// <summary>
    /// 세션 로드
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    public static FSNSession Load(string filepath)
    {
        var newsession		= new FSNSession();

        var rawdata			= FSNUtils.LoadTextData(filepath);
        JSONObject json		= JSONObject.Create(rawdata);

        if (json != null)
        {
            // Script 관련
            newsession.ScriptName		= json[c_field_scriptName].str;
            newsession.ScriptHashKey	= json[c_field_scriptHash].str;
            newsession.SnapshotIndex	= (int)json[c_field_snapshotIndex].n;

            // 플래그 테이블
            var flagtable				= json[c_field_flagTable];
            foreach(var key in flagtable.keys)
            {
                newsession.SetFlagValue(key, flagtable[key].b, true);
            }

            // 값 테이블
            var valuetable				= json[c_field_valueTable];
            foreach(var key in valuetable.keys)
            {
                newsession.SetNumberValue(key, valuetable[key].n, true);
            }
        }
        else
        {
            Debug.LogErrorFormat("[FSNSession] error loading session file : {0}", filepath);
        }

        return newsession;
    }
Esempio n. 16
0
 /// <summary>
 /// 세션 (세이브 파일) 저장
 /// </summary>
 /// <param name="filepath"></param>
 public void SaveSession(string filepath, string memo = "")
 {
     m_seqEngine.SaveToCurrentSession();
     FSNSession.Save(m_seqEngine.CurrentSession, filepath, memo);
 }