Exemplo n.º 1
0
    /// <summary>
    /// 아직 완전히 넘기지 못한 swipe에 관한 것
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="ratio">0 ~ 1 사이, 1은 완전히 넘긴 것 (그러나 완전히 넘길 때 처리는 다른 곳에서 한다)</param>
    /// <param name="backward">반대 방향으로 swipe하는 경우인지 여부</param>
    public void PartialSwipe(FSNInGameSetting.FlowDirection direction, float ratio)
    {
        if (!CanSwipe)                                                                                                                  // Swipe 불가능한 상태면 리턴
        {
            return;
        }

        var nextshot = m_snapshotTraveler.GetLinkedSnapshot(direction);

        if (nextshot != null)                                                                                                   // * 넘길 수 있는 경우만 처리
        {
            //Debug.Log("Link available");
            var curshot = m_snapshotTraveler.Current;

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

                if (oldLayer.IsEmpty && newLayer.IsEmpty)                                               // * 둘 다 비어있으면 아무것도 하지 않는다
                {
                    continue;
                }

                bool  isBackward = InGameSetting.BackwardFlowDirection == direction;
                float trRatio    = ratio * c_maxSwipeToTransitionRatio;
                module.OldElementOnlyTransition(newLayer, trRatio, isBackward);                 // 트랜지션
            }
        }
    }
Exemplo n.º 2
0
        /// <summary>
        /// 해당 방향의 조건 함수를 실행하여 모두 true일 때만 해당 방향 segment 리턴. 아니면 null
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public Segment CheckAndGetConditionFlow(FSNInGameSetting.FlowDirection dir)
        {
            var condlinks = Flows[(int)dir].ConditionedLinks;

            if (condlinks == null)                                                              // 조건부 링크가 없다면 null
            {
                return(null);
            }

            var engine = FSNEngine.Instance;

            foreach (var link in condlinks)                                             // 링크마다 반복
            {
                Segment foundSeg = link.Linked;                                         // 찾아낸 segment. 일단은 조건을 만족하는 것으로 가정
                foreach (var funcinfo in link.funcinfo)
                {
                    if (!engine.ScriptUnityCallBool(funcinfo.funcname, funcinfo.param))                         // 조건이 하나라도 false가 나왔다면 비교 중단, 찾아낸 것은 null로
                    {
                        foundSeg = null;
                        break;
                    }
                }

                if (foundSeg != null)                                                           // 해당 조건이 모두 만족되었다면 이 segment 리턴
                {
                    return(foundSeg);
                }
            }

            return(null);
        }
Exemplo n.º 3
0
 /// <summary>
 /// 해당 방향으로 움직일 수 있는지 여부. 조건부 점프는 제외된다. (따로 체크해야함)
 /// </summary>
 /// <param name="dir"></param>
 /// <returns></returns>
 public bool CanFlowTo(FSNInGameSetting.FlowDirection dir)
 {
     if (dir == FSNInGameSetting.FlowDirection.None)
     {
         Debug.LogWarning("dir is None??");
         return(false);
     }
     return(Flows[(int)dir].Linked != null);
 }
Exemplo n.º 4
0
        /// <summary>
        /// 해당 방향 스냅샷 구하기
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public FSNSnapshot GetLinkedSnapshot(FSNInGameSetting.FlowDirection dir)
        {
            var linked = GetLinkedToDir(dir);

            if (linked != null)
            {
                return(linked.snapshot);
            }

            return(null);
        }
    static void _addOptions(FSNInGameSetting.FlowDirection dir, FSNScriptSequence.Parser.ICommandGenerateProtocol protocol)
    {
        var data = protocol.GetStateVar(c_key_optionData) as string[][];

        if (data == null)
        {
            Debug.LogError("You can't make options without starting an option sequence.");
        }
        else
        {
            // 0번째 인덱스는 점프할 레이블, 1번째 인덱스는 텍스트
            string text = protocol.parameters.Length > 1? protocol.parameters[1] : "";                  // 텍스트가 지정되지 않았을 때는 빈 문자열로 대체
            data[(int)dir] = new string[2] {
                protocol.parameters[0], text
            };
        }
    }
Exemplo n.º 6
0
        /// <summary>
        /// 스냅샷 단순 연결, 선택지 버전
        /// </summary>
        /// <param name="prev"></param>
        /// <param name="next"></param>
        /// <param name="dir"></param>
        static void LinkSnapshotAsOption(Segment prev, Segment next, FSNInGameSetting.FlowDirection dir, bool isNonTextOption)
        {
            var backDir = FSNInGameSetting.GetOppositeFlowDirection(dir);

            next.BackDirection = backDir;

            prev.SetDirectFlow(dir, next);
            next.SetDirectFlow(backDir, prev);

            if (!isNonTextOption)               // 텍스트가 있는 일반 선택지일 때만
            {
                // FIX : 선택지 분기는 period 세그먼트의 isChaining을 체크하는 부분이 위쪽 UserChoice를 체크하는 조건문에 걸려 실행되지 못함.
                // 선택지 바로 다음에는 LastOption 텍스트를 표시하는 snapshot이 무조건 나온다고 가정하고, 여기서 강제로 chaining을 해준다.
                next.snapshot.NonstopToForward  = true;
                next.snapshot.NonstopToBackward = true;
            }
        }
Exemplo n.º 7
0
    /// <summary>
    /// 완전히 넘기는 Swipe 처리
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="transitionStartRatio">트랜지션 애니메이션을 어느 지점부터 시작할지 여부. 0은 처음부터, 1은 종료부분. 기본값은 c_maxSwipeToTransitionRatio</param>
    public void FullSwipe(FSNInGameSetting.FlowDirection direction, float transitionStartRatio = c_maxSwipeToTransitionRatio)
    {
        if (!CanSwipe)                                                                                                                  // Swipe 불가능한 상태면 리턴
        {
            return;
        }

        var nextshot = m_snapshotTraveler.GetLinkedSnapshot(direction);

        if (nextshot != null)                                                                                                   // * 실제로 가능한 경우만 처리
        {
            var curshot = m_snapshotTraveler.Current;

            float transTime = 0f;                                                                                               // 트랜지션 시간

            // FIX : setting에 backward 방향이 등록되어있더라도 DisableBackward 플래그가 서있다면 역방향으로 따지지 않는다.
            bool isBackward = !curshot.DisableBackward && InGameSetting.BackwardFlowDirection == direction;

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

                if (oldLayer.IsEmpty && newLayer.IsEmpty)                                                       // * 둘 다 비어있으면 아무것도 하지 않는다
                {
                    continue;
                }

                float curtt = module.StartTransition(newLayer, nextshot.InGameSetting, transitionStartRatio, isBackward);       // 트랜지션

                if (transTime < curtt)                                                                                          // 제일 긴 트랜지션 시간 추적
                {
                    transTime = curtt;
                }
            }

            m_lastSwipeWasBackward = isBackward;                                                // swipe 방향성 보관해두기 (연결된 snapshot 처리에 사용)
            transTime           += nextshot.AfterSwipeDelay;                                    // swipe 시간에 스냅샷에 지정된 딜레이 시간까지 더하기
            m_swipeAvailableTime = Time.time + transTime;                                       // 현재 시간 + 트랜지션에 걸리는 시간 뒤에 swipe가 가능해짐

            m_snapshotTraveler.TravelTo(direction);                                             // 해당 방향으로 넘기기
            CurrentSession.SnapshotIndex = m_snapshotTraveler.CurrentIndex;                     // Session 정보 업데이트 (스크립트는 변하지 않았으므로 snapshot index만 바꿔주면 된다)
        }
    }
Exemplo n.º 8
0
        /// <summary>
        /// 해당 방향으로 진행하여 현재 상태 바꾸기. 덤으로 해당 snapshot에 지정된 함수들도  호출한다.
        /// </summary>
        /// <param name="dir"></param>
        /// <returns>진행 가능할 경우, 해당 방향의 snapshot. 아니면 null</returns>
        public FSNSnapshot TravelTo(FSNInGameSetting.FlowDirection dir)
        {
            FSNSnapshot next   = null;
            var         linked = GetLinkedToDir(dir);

            if (linked != null)                                                                         // 해당 방향으로 진행 가능한 경우만 변경
            {
                m_current = linked;
                next      = linked.snapshot;

                ExecuteSnapshotFunctions();                                             // 함수 실행

                if (m_current.Type == FlowType.Load)                                    // 스크립트 로딩 이벤트
                {
                    ScriptLoadRequested(m_current.Parameter as string);
                }
            }
            return(next);
        }
Exemplo n.º 9
0
    /// <summary>
    /// 텍스트들을 일정 방향으로 모두 밀어내며 삭제한다.
    /// </summary>
    /// <param name="layer"></param>
    /// <param name="direction"></param>
    private static void ClearTextsToDirection(FSNSnapshot.Layer layer, FSNInGameSetting.FlowDirection direction)
    {
        Vector3 screenHalf = FSNEngine.Instance.ScreenDimension * 0.5f;                                 // 화면 크기 절반
        Vector3 dirVec     = FSNInGameSetting.GetUnitVectorFromFlowDir(direction);                      // 흐름 방향 벡터

        var uidList = layer.UniqueIDList;
        int count   = uidList.Count;

        int[] removeIDList = new int[uidList.Count];
        uidList.CopyTo(removeIDList, 0);

        for (int i = 0; i < count; i++)
        {
            var textElem = layer.GetElement(removeIDList[i]) as SnapshotElems.Text;

            textElem.FinalState.Position = textElem.Position + Vector3.Scale(screenHalf, dirVec);                       // 화면 절반 거리만큼 해당 방향으로 이동
            layer.RemoveElement(removeIDList[i]);
        }
    }
Exemplo n.º 10
0
    /// <summary>
    /// 텍스트 좌표를 가운데로 밀어내기. LastOption이나 가운데 텍스트 옵션 등에서 사용
    /// </summary>
    /// <param name="textpos"></param>
    /// <param name="setting"></param>
    private static void TextPositionToCenter(ref Vector3 textpos, Vector2 textSize, FSNInGameSetting.FlowDirection direction, IInGameSetting setting)
    {
        var oldPos = textpos;

        switch (direction)
        {
        case FSNInGameSetting.FlowDirection.Up:
        case FSNInGameSetting.FlowDirection.Down:
            textpos.y = textSize.y / 2f;
            ApplyCenterTextMargin(ref textpos, setting);
            textpos.x = oldPos.x;
            break;

        case FSNInGameSetting.FlowDirection.Left:
        case FSNInGameSetting.FlowDirection.Right:
            textpos.x = -textSize.x / 2f;
            ApplyCenterTextMargin(ref textpos, setting);
            textpos.y = oldPos.y;
            break;
        }
    }
Exemplo n.º 11
0
    //==============================================================


    /// <summary>
    /// 없는 방향으로 swipe 시도, 시작
    /// </summary>
    /// <param name="direction"></param>
    public void OnTryingSwipeToWrongDirection(FSNInGameSetting.FlowDirection direction)
    {
        SetBusy();                                                                                                      // 움직임이므로 일단 바쁜 상태로

        GameObject orig = null;

        switch (direction)
        {
        case FSNInGameSetting.FlowDirection.Up:
            orig = m_indicatorInvalidUp;
            break;

        case FSNInGameSetting.FlowDirection.Down:
            orig = m_indicatorInvalidDown;
            break;

        case FSNInGameSetting.FlowDirection.Left:
            orig = m_indicatorInvalidLeft;
            break;

        case FSNInGameSetting.FlowDirection.Right:
            orig = m_indicatorInvalidRight;
            break;
        }

        if (orig != null)                                                                                       // swipe 불가 표시 생성
        {
            var newobj    = Instantiate <GameObject>(orig);
            var newtrans  = newobj.transform;
            var origtrans = orig.transform;

            newtrans.SetParent(origtrans.parent);
            newtrans.position = origtrans.position;

            newobj.SetActive(true);
            Destroy(newobj, m_swipeInvalidIndicatorTime);                       // 일정 시간 뒤에는 무조건 제거하도록
        }
    }
Exemplo n.º 12
0
        /// <summary>
        /// 캐싱된 조건부 링크 등등을 종합해서 해당 방향으로 링크되는 Segment를 구한다. 없을 경우 null
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        private FSNSnapshotSequence.Segment GetLinkedToDir(FSNInGameSetting.FlowDirection dir)
        {
            if (dir != FSNInGameSetting.FlowDirection.None)
            {
                var condlink = m_cachedConditionLinks[(int)dir];                        // 조건부 링크 구하기
                if (condlink != null)
                {
                    return(condlink);
                }
            }
            else
            {
                Debug.LogWarning("dir is None??");
            }

            if (m_current.CanFlowTo(dir))                                                       // 일반 링크 구하기
            {
                return(m_current.GetLinked(dir));
            }
            else
            {
                return(null);                                                                                   // 링크 없음
            }
        }
Exemplo n.º 13
0
    /// <summary>
    /// Layer 안에 들어있는 텍스트들을 특정 방향으로 모두 밀어낸다. 알파값도 변경. 수명이 다 된 것은 제거 처리.
    /// </summary>
    /// <param name="layer">변경할 레이어 (이미 복제된 상태여야함)</param>
    /// <param name="direction"></param>
    /// <param name="newTextSize"></param>
    private static void PushTextsToDirection(FSNSnapshot.Layer layer, FSNInGameSetting.FlowDirection direction, Vector2 newTextSize, float paraSpacing = 0)
    {
        Vector2    dirVec      = FSNInGameSetting.GetUnitVectorFromFlowDir(direction);
        List <int> UIDtoRemove = new List <int>();              // 삭제 리스트

        foreach (var uId in layer.UniqueIDList)
        {
            var textElem = layer.GetElement(uId) as SnapshotElems.Text;
            int elemAge  = textElem.ChainedParentCount;

            // 텍스트의 종류에 따라서 다른 룰을 적용한다.

            if (textElem.type == SnapshotElems.Text.Type.Normal)                                                        // ** 일반 텍스트
            {
                Vector3 transVec = Vector2.Scale(newTextSize, dirVec);                                                  // 이동할 벡터 양
                if (elemAge > 0)
                {
                    transVec += (Vector3)(dirVec * paraSpacing);                                                                        // 최초에 등장한 이후엔 문단 간격도 적용
                }
                if (elemAge < c_textLife)                                                                                               // 텍스트가 아직 살아있어야하는 경우
                {
                    textElem.Alpha    = (float)(c_textLife - elemAge) / (float)c_textLife;
                    textElem.Position = textElem.Position + transVec;
                    CopyCurrentToFinal(textElem);                                                                                               // 임시 FinalState
                }
                else
                {                                                                                                                                                               // 텍스트가 죽어야하는 경우
                    textElem.FinalState.Position = textElem.Position + transVec;
                    UIDtoRemove.Add(uId);
                }
            }
            else
            {                                                                                                 // ** 기타 (선택지 관련 텍스트)
                int killAge = textElem.type == SnapshotElems.Text.Type.OptionTexts? 1 : 2;                    //(선택한 텍스트는 1턴 더 살아있어야 하므로)

                if (elemAge == killAge)                                                                       // 없어지는 타이밍
                {
                    // NOTE : 현재 구조상의 문제로 인해 분기점 이후 바로 없어지는 오브젝트의 FinalState를 여러개 둘 수 없음.
                    // 따라서 분기점 이후에도 한번은 오브젝트를 살려놓은 뒤 안보이게만 하고 다음번에 없애는 식으로.

                    Vector2 halfScreen = FSNEngine.Instance.ScreenDimension / 2f;
                    Vector3 transVec   = Vector2.Scale(dirVec, halfScreen);

                    textElem.Position = textElem.Position + transVec;
                    textElem.Alpha    = 0f;

                    // TODO : Alpha를 0으로 하는 것 이외에 실제로 visible을 끌 수 있는 방법이 있다면 사용하도록 한다. 지금도 딱히 문제는 없긴 한데...
                }
                else if (elemAge == killAge + 1)                                                                                                // 원래 없어져야했던 타이밍이 지나고 나서 실제로 없앤다.
                {
                    UIDtoRemove.Add(uId);
                }
            }
        }

        int rmvCount = UIDtoRemove.Count;

        for (int i = 0; i < rmvCount; i++)                                                                                                      // 삭제 리스트 처리
        {
            layer.RemoveElement(UIDtoRemove[i]);
        }
    }
Exemplo n.º 14
0
 public void SetConditionFlow(FSNInGameSetting.FlowDirection dir, Segment.FlowInfo.ConditionLink [] links)
 {
     Flows[(int)dir].ConditionedLinks = links;
 }
Exemplo n.º 15
0
    /// <summary>
    /// swipe 변위 보내기
    /// </summary>
    public void Swipe(FSNInGameSetting.FlowDirection direction, float distance)
    {
        if (m_enginePause)                      // 엔진 일시정지시에는 이벤트 처리를 받지 않는다.
        {
            return;
        }

        m_swippedAnyway = true;                                                                                 // 어쨌든 swipe를 하긴 했음. release 하더라도 메뉴 토글은 콜하지 않도록

        if (!m_swipeCompleted && m_seqEngine.CanSwipe)                                                          // swipe 가능한 상태
        {
            var engine = FSNEngine.Instance;

            m_swipeDirection = direction;                                                                                       // 민 방향을 보관해둔다

            var dirvalid = m_seqEngine.SwipeDirectionAvailable(direction);
            if (dirvalid)                                                                                                                       // 밀 수 있는 방향일 때
            {
                float weight  = engine.InGameSetting.SwipeWeight;
                float maxdist = (direction == FSNInGameSetting.FlowDirection.Left || direction == FSNInGameSetting.FlowDirection.Right)?
                                engine.ScreenXSize : engine.ScreenYSize;                                                // 해당 방향으로 최대한 밀 수 있는 거리

                float fullDist      = weight * maxdist;
                float curSwipeRatio = Mathf.Pow(distance / fullDist, 0.5f);                             // 드래그할 때 약간 저항을 주기 위해
                if (curSwipeRatio < 1.0f)                                                               // 아직 덜 밀었을 때
                {
                    //m_seqEngine.PartialSwipe(direction, curSwipeRatio * c_partialSwipeLimit);// Partial swipe
                    m_seqEngine.PartialSwipe(direction, curSwipeRatio);                                         // Partial swipe
                    m_swipeRatio = curSwipeRatio;


                    if (!m_swipeEventSent || m_swipeEventSentWasWrongDir)                               // 아직 이벤트를 보낸 적이 없거나 잘못된 방향으로 이벤트를 보냈을 경우
                    {
                        ExecuteSwipeEvent((obj, param) =>
                        {
                            obj.OnTryingSwipe(direction);                                                                       // 옳은 방향으로 swipe 이벤트
                        });

                        m_swipeEventSent            = true;
                        m_swipeEventSentWasWrongDir = false;
                    }
                }
                else if (!m_swipeCompleted)                                                             // 완전히 밀었을 때, 아직 이전에 완전히 밀지는 않았을 경우
                {
                    m_seqEngine.FullSwipe(direction, c_partialSwipeLimit);                              // Full swipe
                    m_swipeRatio     = 0;
                    m_swipeCompleted = true;

                    ExecuteSwipeEvent(
                        (obj, param) =>
                    {
                        obj.OnTryingSwipe(direction);                                                                           // swipe완료 이벤트
                    });
                }
            }
            else
            {                                                                                           // 밀 수 없는 방향일 때
                if (!m_swipeEventSent || !m_swipeEventSentWasWrongDir)                                  // 아직 이벤트를 보낸 적이 없거나 올바른 방향으로 이벤트를 보냈을 경우
                {
                    ExecuteSwipeEvent((obj, param) =>
                    {
                        obj.OnTryingSwipeToWrongDirection(direction);                                           // 잘못된 방향으로 swipe 이벤트
                    });

                    m_swipeEventSent            = true;
                    m_swipeEventSentWasWrongDir = true;
                }
            }
        }
    }
Exemplo n.º 16
0
 /// <summary>
 /// 없는 방향으로 swipe 시도하다가 중단함
 /// </summary>
 /// <param name="direction"></param>
 public void OnReleaseSwipeToWrongDirection(FSNInGameSetting.FlowDirection direction)
 {
     StartCoroutine(CheckIdle());            // 조건이 완전히 성립할 때까지 계속 Idle 체크
 }
Exemplo n.º 17
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="direction"></param>
 public void OnCompleteSwipe(FSNInGameSetting.FlowDirection direction)
 {
     StartCoroutine(CheckIdle());            // 조건이 완전히 성립할 때까지 계속 Idle 체크
 }
Exemplo n.º 18
0
        /// <summary>
        /// FSNSequence 해석. 분기마다 builderState를 복제해야 하므로 새로 호출된다.
        /// </summary>
        /// <param name="builderState"></param>
        /// <param name="snapshotSeq">이번 콜에서 생성할 시퀀스 이전의 스냅샷 인덱스</param>
        /// <param name="bs"></param>
        /// <param name="linkToLast">이 메서드를 호출하기 바로 이전의 Snapshot에 연결할지 여부. 기본은 true. 선택지 등등에서 false로 해줘야함</param>
        /// <returns>이번 콜에서 생성한 시퀀스들 중 제일 첫번째 것. 다른 시퀀스 흐름과 연결할 때 사용 가능</returns>
        static Segment ProcessSnapshotBuild(State bs, FSNSnapshotSequence snapshotSeq, int prevSnapshotIndex, bool linkToLast = true)
        {
            ModuleCallQueue moduleCalls = new ModuleCallQueue();

            Segment     sseg;                                                                                                                   // 새로 생성할 Segment/Snapshot
            FSNSnapshot sshot;

            NewSnapshot(out sseg, out sshot);

            var firstSeg    = sseg;                                                             // 최초 스냅샷
            var prevCallSeg = snapshotSeq.Get(prevSnapshotIndex);                               // 이번에 생성할 시퀀스의 이전 스냅샷

            var lastSeg = prevCallSeg;                                                          // 바로 이전에 처리한 스냅샷 (최초 루프시에는 실행 이전의 마지막 스냅샷과 동일)

            List <Segments.Control>     jumpSegs  = new List <Segments.Control>();              // 점프(goto, SwipeOption 등) 세그먼트가 등장했을 경우 여기에 보관된다
            List <Segment.CallFuncInfo> funcCalls = new List <Segment.CallFuncInfo>();          // 함수 콜이 있을 경우 여기에 먼저 누적하고 period때 한번에 처리한다

            float snapshotDelay = 0f;                                                           // 스냅샷에 적용할 지연 시간 (/기다리기 커맨드)

            //

            // 처음 시작할 때는 무조건 모든 객체들을 Hard-Clone한다 (분기점에서 Initial/Final 스테이트 독립을 하기 위해)

            moduleCalls.CatchupPreviousLayerState(prevCallSeg.snapshot);                        // 기존의 유효한 Layer들을 활성화 (안그러면 모듈 콜을 누락해버림)
            moduleCalls.AddAllModuleCall(new Segments.HardClone(), bs.settings);


            // 스크립트 Sequence가 끝나거나 특정 명령을 만날 때까지 반복

            bool keepProcess = true;

            while (keepProcess)
            {
                var curSeg = bs.sequence[bs.segIndex];                                          // 현재 명령어 (Sequence 세그먼트)
                FSNDebug.currentProcessingScriptLine = curSeg.scriptLineNumber;                 // 디버깅 정보 세팅 (줄 번호)

                switch (curSeg.type)                                                            // 명령어 타입 체크 후 분기
                {
                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Setting:                                                                    // ** 세팅
                {
                    var settingSeg = curSeg as Segments.Setting;

                    if (settingSeg.settingMethod == Segments.Setting.SettingMethod.Pop)                         // * 세팅 pop
                    {
                        if (bs.settings.ParentChain != null)
                        {
                            bs.settings = bs.settings.ParentChain;
                        }
                        else
                        {
                            Debug.LogError("Cannot pop settings anymore - there is no settings pushed");
                        }
                    }
                    else
                    {
                        if (settingSeg.settingMethod == Segments.Setting.SettingMethod.Push)                            // * Push일 경우에는 새 Chain을 생성한다
                        {
                            bs.settings = new FSNInGameSetting.Chain(bs.settings);
                        }

                        foreach (var settingPair in settingSeg.RawSettingTable)                         // Setting 설정
                        {
                            bs.settings.SetPropertyByString(settingPair.Key, settingPair.Value);
                        }
                    }

                    bs.SetSettingDirty();                                                                                               // 세팅 변경됨 플래그 올리기
                }
                break;

                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Text:                                                               // ** 텍스트
                {
                    var module = FSNEngine.Instance.GetModule(FSNEngine.ModuleType.Text) as IFSNProcessModule;

                    moduleCalls.AddCall(module, curSeg, bs.FrozenSetting);                              // 해당 명령 저장
                }
                break;

                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Object:                                                             // ** 오브젝트 (이미지 등)
                {
                    var objSeg = curSeg as Segments.Object;
                    var module = FSNEngine.Instance.GetModuleByLayerID(objSeg.layerID) as IFSNProcessModule;

                    moduleCalls.AddCall(module, objSeg, bs.FrozenSetting);
                }
                break;

                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Label:                                                              // ** 레이블
                {
                    //var labelSeg		= curSeg as Segments.Label;
                    // 현재 이 시점에서는 labelSeg로 하는 일이 없다...
                    //Debug.Log("Label : " + labelSeg.labelName);
                }
                break;

                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Control:                                                    // ** 엔진 컨트롤
                {
                    var controlSeg = curSeg as Segments.Control;

                    switch (controlSeg.controlType)                                                                             // 종류에 따라 처리
                    {
                    case Segments.Control.ControlType.Block:
                        keepProcess = false;                                            // 블로킹 - 이 분기에서는 해석 종료
                        break;

                    case Segments.Control.ControlType.SwipeOption:
                        sseg.Type = FlowType.UserChoice;                                                                        // 스냅샷 세그먼트 종류 변경 (유저 선택으로)

                        jumpSegs.Add(controlSeg);                                                                               // 점프 명령어로 보관해두고 나중에 처리한다.

                        break;

                    case Segments.Control.ControlType.Goto:
                    case Segments.Control.ControlType.ReverseGoto:
                    case Segments.Control.ControlType.ConditionJump:
                        jumpSegs.Add(controlSeg);                                                                                       // 점프 명령어로 보관해두고 나중에 처리한다.
                        break;

                    case Segments.Control.ControlType.Clear:                                                            // 모든 모듈에 clear를 보낸다
                        moduleCalls.AddAllModuleCall(controlSeg, bs.FrozenSetting);
                        break;

                    case Segments.Control.ControlType.Oneway:
                        sseg.OneWay = true;
                        break;

                    case Segments.Control.ControlType.ForceBack:
                        sseg.snapshot.ForceBackward = true;
                        break;

                    case Segments.Control.ControlType.Load:
                        sseg.Type      = FlowType.Load;
                        sseg.Parameter = controlSeg.GetLoadScriptData();                                        // 스냅샷 세그먼트의 parameter에 스크립트 파일명 보관
                        break;

                    case Segments.Control.ControlType.UnityCall:                                                // 함수콜
                    {
                        var callinfo = new Segment.CallFuncInfo();
                        controlSeg.GetUnityCallData(out callinfo.funcname, out callinfo.param);
                        funcCalls.Add(callinfo);
                    }
                    break;

                    case Segments.Control.ControlType.Delay:                                                            // 딜레이
                        snapshotDelay = controlSeg.GetDelay();                                                          // 지연 시간을 미리 지정해둔다
                        break;
                    }
                }
                break;

                //////////////////////////////////////////////////////////////
                case FSNScriptSequence.Segment.Type.Period:                                                             // ** Period : 현재까지 누적한 call을 실행하는 개념으로 사용중
                {
                    var periodSeg = curSeg as Segments.Period;

                    // 다음 snapshot을 위해 현재 진행 방향의 반대방향으로 FlowDirection 정해놓기
                    bs.settings.BackwardFlowDirection = FSNInGameSetting.GetOppositeFlowDirection(bs.settings.CurrentFlowDirection);
                    bs.SetSettingDirty();

                    sshot.InGameSetting = bs.FrozenSetting;                                                     // 현재까지의 세팅 적용 (굳힌거 사용)

                    moduleCalls.ProcessCall(lastSeg.snapshot, sshot);                                           // 지금까지 모인 모듈 콜 집행하기

                    if (linkToLast)                                                                             // 이전 스냅샷에 붙여야하는경우
                    {
                        LinkSnapshots(lastSeg, sseg);

                        if (bs.prevPeriodWasChain)                                                                                      // 이전 period가 chaining이었다면, 역방향 chaining 걸기
                        {
                            sseg.snapshot.NonstopToBackward = true;
                            bs.prevPeriodWasChain           = false;                                                            // (플래그 해제)
                        }

                        if (periodSeg.isChaining)                                                                                       // Chaining 옵션이 켜져있을 경우
                        {
                            sseg.snapshot.NonstopToForward = true;
                            bs.prevPeriodWasChain          = true;                                                              // (chaining 상태 기록)
                        }
                    }
                    else
                    {
                        linkToLast = true;                              // FIX : linkToLast는 맨 첫번째 스냅샷에만 해당하는 파라미터임. 두번째는 꺼준다
                    }

                    sseg.FunctionCalls = funcCalls.ToArray();                                                           // 쌓인 함수콜 리스트를 배열로 변환하여 세팅
                    funcCalls.Clear();

                    snapshotSeq.Add(sseg);                                                                                              // 현재 스냅샷을 시퀀스에 추가
                    //

                    sseg.snapshot.AfterSwipeDelay = snapshotDelay;                                              // 현재 지정된 딜레이를 적용.
                    snapshotDelay = 0f;
                    //


                    // Condition 링크 임시 보관소 - 나중에 한번에 특정 방향으로 몰아넣는다
                    FSNInGameSetting.FlowDirection        conditionLinkDir      = FSNInGameSetting.FlowDirection.None;
                    FSNInGameSetting.FlowDirection        conditionLinkBackDir  = FSNInGameSetting.FlowDirection.None;
                    List <Segment.FlowInfo.ConditionLink> conditionLinks        = null;
                    Dictionary <string, Segment>          conditionLinkSegCache = new Dictionary <string, Segment>();           // 조건부 점프시, 중복되는 점프는 이전 것을 사용하게

                    foreach (var jumpSeg in jumpSegs)                                                                           // * 점프 세그먼트가 있을 경우 처리
                    {
                        // NOTE : 현재 Label은 Soft만 구현한다.

                        if (jumpSeg.controlType == Segments.Control.ControlType.SwipeOption)                                    // *** 선택지
                        {
                            bool isNonTextOption = jumpSeg.IsNonTextOption();
                            for (int i = 0; i < 4; i++)                                                                                                                         // 모든 방향마다 처리
                            {
                                var    dir   = (FSNInGameSetting.FlowDirection)i;
                                string label = jumpSeg.GetLabelFromSwipeOptionData(dir);
                                if (!string.IsNullOrEmpty(label))                                                                                                       // 라벨이 지정된 경우만 처리(= 해당 방향으로 분기가 있을 때만)
                                {
                                    // FIX : 만약 해당 선택지 방향이 원래의 역방향에 해당하는 것이었다면, 역방향을 None으로 재설정한다. (역방향 오버라이드 지원)
                                    if (dir == sseg.BackDirection)
                                    {
                                        sseg.BackDirection            = FSNInGameSetting.FlowDirection.None;
                                        sseg.snapshot.DisableBackward = true;                                           // 역방향 비활성화
                                    }

                                    int labelIndex = bs.sequence.GetIndexOfLabel(label);
                                    var labelSeg   = bs.sequence.GetSegment(labelIndex) as Segments.Label;

                                    if (labelSeg.labelType == Segments.Label.LabelType.Soft)                                                    // * SOFT 라벨로 점프
                                    {
                                        if (labelIndex < bs.segIndex)                                                                           // SOFT 라벨은 거슬러올라갈 수 없다.
                                        {
                                            Debug.LogError("Cannot jump to previous soft label");
                                        }

                                        var clonnedState = bs.Clone();                                                                                  // 상태 복제
                                        clonnedState.segIndex = labelIndex;                                                                             // 라벨 인덱스 세팅
                                        clonnedState.settings.CurrentFlowDirection  = dir;                                                              // 진행 방향 세팅 - 선택지 방향으로 진행 방향을 강제 세팅한다
                                        clonnedState.settings.BackwardFlowDirection = FSNInGameSetting.GetOppositeFlowDirection(dir);

                                        var newSeg = ProcessSnapshotBuild(clonnedState, snapshotSeq, sseg.Index, false);                        // 새 분기 해석하기. 이전 스냅샷에 바로 붙이지 않는다.
                                        LinkSnapshotAsOption(sseg, newSeg, dir, isNonTextOption);                                               // 선택지로 연결하기
                                    }
                                    else
                                    {                                                                                                                                                                   // * HARD 라벨로 점프
                                        Debug.LogError("Not implemented");
                                    }
                                }
                            }
                        }
                        else if (jumpSeg.controlType == Segments.Control.ControlType.Goto)                                              // *** GOTO
                        {
                            string label      = jumpSeg.GetGotoLabel();
                            int    labelIndex = bs.sequence.GetIndexOfLabel(label);
                            var    labelSeg   = bs.sequence.GetSegment(labelIndex) as Segments.Label;

                            if (labelSeg.labelType == Segments.Label.LabelType.Soft)                                                            // * SOFT 라벨로 점프
                            {
                                if (labelIndex < bs.segIndex)                                                                                   // SOFT 라벨은 거슬러올라갈 수 없다.
                                {
                                    Debug.LogError("Cannot jump to previous soft label");
                                }

                                var clonnedState = bs.Clone();                                                                          // 상태 복제
                                clonnedState.segIndex = labelIndex;                                                                     // 라벨 인덱스 세팅

                                ProcessSnapshotBuild(clonnedState, snapshotSeq, sseg.Index);                                            // 새 분기 해석하기

                                // SOFT 라벨로 점프하는 경우엔 사실상 이 분기점으로 다시 되돌아올 일이 생기지 않는다.
                                // 추가 스크립트 해석을 중단한다.
                                keepProcess = false;
                            }
                            else
                            {                                                                                                                                                                           // * HARD 라벨로 점프
                                Debug.LogError("Not implemented");
                            }
                        }
                        else if (jumpSeg.controlType == Segments.Control.ControlType.ReverseGoto)                               // ** ReverseGoto
                        {
                            string label      = jumpSeg.GetReverseGotoLabel();
                            int    labelIndex = bs.sequence.GetIndexOfLabel(label);
                            var    labelSeg   = bs.sequence.GetSegment(labelIndex) as Segments.Label;

                            if (labelSeg.labelType == Segments.Label.LabelType.Soft)                                                            // * SOFT 라벨로 점프
                            {
                                if (labelIndex < bs.segIndex)                                                                                   // SOFT 라벨은 거슬러올라갈 수 없다.
                                {
                                    Debug.LogError("Cannot jump to previous soft label");
                                }

                                var clonnedState = bs.Clone();                                                                                                  // 상태 복제
                                clonnedState.segIndex = labelIndex;                                                                                             // 라벨 인덱스 세팅

                                // 진행 방향을 역방향으로 세팅
                                clonnedState.settings.CurrentFlowDirection  = FSNInGameSetting.GetOppositeFlowDirection(clonnedState.settings.CurrentFlowDirection);
                                clonnedState.settings.BackwardFlowDirection = FSNInGameSetting.GetOppositeFlowDirection(clonnedState.settings.BackwardFlowDirection);

                                // 가장 마지막 세그먼트를 잠시동안만 UserChoice로 변경해서 새 스냅샷시퀀스를 정방향에 붙이지 못하게 막는다.
                                // 생성한 스냅샷을 역방향에 직접 붙여줘야하기 때문.
                                // 좀 Hacky한 방법이라서 변경이 필요할지도.

                                var newSeg = ProcessSnapshotBuild(clonnedState, snapshotSeq, sseg.Index, false); // 새 분기 해석한 후 레퍼런스 받기. 링크는 하지 않음

                                LinkSnapshotsReverseOverride(sseg, newSeg);                                      //붙이기

                                sseg.snapshot.DisableBackward = true;                                            // 역방향 비활성화
                            }
                            else
                            {                                                                                                                                                                           // * HARD 라벨로 점프
                                Debug.LogError("Not implemented");
                            }
                        }
                        else if (jumpSeg.controlType == Segments.Control.ControlType.ConditionJump)                             // ** 조건부 점프
                        {
                            string    funcname;
                            string [] param;
                            string    label      = jumpSeg.GetConditionJumpLabel();
                            int       labelIndex = bs.sequence.GetIndexOfLabel(label);
                            var       labelSeg   = bs.sequence.GetSegment(labelIndex) as Segments.Label;

                            if (labelSeg.labelType == Segments.Label.LabelType.Soft)                                                            // * SOFT 라벨로 점프
                            {
                                if (labelIndex < bs.segIndex)                                                                                   // SOFT 라벨은 거슬러올라갈 수 없다.
                                {
                                    Debug.LogError("Cannot jump to previous soft label");
                                }

                                Segment newSeg;
                                if (!conditionLinkSegCache.TryGetValue(label, out newSeg))                                                      // 이전에 캐싱된 것이 없을 때만 새로 해석한다.
                                {
                                    var clonnedState = bs.Clone();                                                                              // 상태 복제
                                    clonnedState.segIndex = labelIndex;                                                                         // 라벨 인덱스 세팅

                                    // 가장 마지막 세그먼트를 잠시동안만 UserChoice로 변경해서 새 스냅샷시퀀스를 정방향에 붙이지 못하게 막는다.
                                    // 생성한 스냅샷을 역방향에 직접 붙여줘야하기 때문.
                                    // 좀 Hacky한 방법이라서 변경이 필요할지도.

                                    newSeg = ProcessSnapshotBuild(clonnedState, snapshotSeq, sseg.Index, false);                                                // 새 분기 해석한 후 레퍼런스 받기. 링크는 하지 않음

                                    conditionLinkSegCache[label] = newSeg;                                                                                      // 캐싱해두기
                                }

                                // Note : 현재 스크립트 스펙 상, 한 스냅샷 안에서 Condition Link은 한쪽 방향으로밖에 나올 수 없다.
                                // 따라서 방향 구분 없이 리스트 하나에 모두 모아둔 후, 기록해둔 방향에 모두 집어넣는다.

                                conditionLinkDir     = newSeg.snapshot.InGameSetting.CurrentFlowDirection;
                                conditionLinkBackDir = newSeg.snapshot.InGameSetting.BackwardFlowDirection;

                                // 만약 일반 링크가 등장하지 않아 방향이 설정되지 않을 때를 대비해서 세팅
                                if (sseg.FlowDirection == FSNInGameSetting.FlowDirection.None)
                                {
                                    sseg.FlowDirection = conditionLinkDir;
                                }
                                if (newSeg.BackDirection == FSNInGameSetting.FlowDirection.None)
                                {
                                    newSeg.BackDirection = conditionLinkBackDir;
                                }

                                List <Segment.CallFuncInfo> callfuncs = new List <Segment.CallFuncInfo>();
                                while (jumpSeg.DequeueConditionJumpData(out funcname, out param))                                                       // AND 조건으로 묶인 모든 condition 읽기
                                {
                                    callfuncs.Add(new Segment.CallFuncInfo()
                                        {
                                            funcname = funcname, param = param
                                        });
                                }
                                if (conditionLinks == null)
                                {
                                    conditionLinks = new List <Segment.FlowInfo.ConditionLink>();
                                }
                                conditionLinks.Add(new Segment.FlowInfo.ConditionLink()
                                    {
                                        funcinfo = callfuncs.ToArray(), Linked = newSeg
                                    });

                                if (!newSeg.OneWay)
                                {
                                    newSeg.SetDirectFlow(conditionLinkBackDir, sseg);                                                                                   // 역방향 설정
                                }
                            }
                            else
                            {                                                                                                                                                                           // * HARD 라벨로 점프
                                Debug.LogError("Not implemented");
                            }
                        }
                        else
                        {
                            Debug.LogError("Unknown or not-yet-implemented jump statement!");
                        }
                    }
                    jumpSegs.Clear();

                    if (conditionLinks != null)                                                                                         // 모아뒀던 조건부 점프 한번에 세팅
                    {
                        sseg.SetConditionFlow(conditionLinkDir, conditionLinks.ToArray());
                    }

                    lastSeg = sseg;
                    NewSnapshot(out sseg, out sshot);                                                                           // 새 스냅샷 인스턴스 준비
                }
                break;

                /////////////////////////////////////////////////////////////
                default:
                    Debug.LogError("?????????");
                    break;
                }


                //
                bs.segIndex++;                                                                                          // 다음 명령어 인덱스

                if (bs.segIndex >= bs.sequence.Length)                                                                  // * Sequence 가 끝났다면 루프 종료
                {
                    keepProcess = false;
                }
            }

            return(firstSeg);
        }
Exemplo n.º 19
0
        /// <summary>
        /// SwipeOption일 때, 방향에 따른 진행 라벨 구하기
        /// </summary>
        /// <param name="dir"></param>
        public string GetLabelFromSwipeOptionData(FSNInGameSetting.FlowDirection dir)
        {
            var data = CheckOptionData <SwipeOptionData>(ControlType.SwipeOption);

            return(data.m_dirLabelDict[(int)dir]);
        }
Exemplo n.º 20
0
        /// <summary>
        /// SwipeOption일 때, 방향에 따른 진행 라벨 추가
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="label"></param>
        public void SetSwipeOptionData(FSNInGameSetting.FlowDirection dir, string label)
        {
            var data = CheckOptionData <SwipeOptionData>(ControlType.SwipeOption);

            data.m_dirLabelDict[(int)dir] = label;
        }
Exemplo n.º 21
0
 /// <summary>
 /// 특정 방향으로 진행 가능한지 여부
 /// </summary>
 /// <param name="direction"></param>
 /// <returns></returns>
 public bool SwipeDirectionAvailable(FSNInGameSetting.FlowDirection direction)
 {
     return(CanSwipe && m_snapshotTraveler.GetLinkedSnapshot(direction) != null);
 }
Exemplo n.º 22
0
        //=======================================================================

        public Segment()
        {
            Flows         = new FlowInfo[4];
            FlowDirection = FSNInGameSetting.FlowDirection.None;
            BackDirection = FSNInGameSetting.FlowDirection.None;
        }
Exemplo n.º 23
0
 /// <summary>
 /// 해당 방향의 Segment 구하기
 /// </summary>
 /// <param name="dir"></param>
 /// <returns></returns>
 public Segment GetLinked(FSNInGameSetting.FlowDirection dir)
 {
     return(Flows[(int)dir].Linked);
 }
Exemplo n.º 24
0
 public void SetDirectFlow(FSNInGameSetting.FlowDirection dir, Segment linked)
 {
     Flows[(int)dir].Linked = linked;
 }
Exemplo n.º 25
0
 /// <summary>
 /// 있는 방향으로 swipe 시도, 시작
 /// </summary>
 /// <param name="direction"></param>
 public void OnTryingSwipe(FSNInGameSetting.FlowDirection direction)
 {
     SetBusy();
 }
Exemplo n.º 26
0
        public FSNSnapshot snapshot; // 스냅샷 (본체)

        #endregion Fields

        #region Constructors

        //=======================================================================
        public Segment()
        {
            Flows			= new FlowInfo[4];
            FlowDirection	= FSNInGameSetting.FlowDirection.None;
            BackDirection	= FSNInGameSetting.FlowDirection.None;
        }
Exemplo n.º 27
0
    /// <summary>
    /// swipe 변위 보내기
    /// </summary>
    public void Swipe(FSNInGameSetting.FlowDirection direction, float distance)
    {
        if (m_enginePause)		// 엔진 일시정지시에는 이벤트 처리를 받지 않는다.
            return;

        m_swippedAnyway		= true;												// 어쨌든 swipe를 하긴 했음. release 하더라도 메뉴 토글은 콜하지 않도록

        if(!m_swipeCompleted && m_seqEngine.CanSwipe)							// swipe 가능한 상태
        {
            var engine		= FSNEngine.Instance;

            m_swipeDirection= direction;										// 민 방향을 보관해둔다

            var dirvalid	= m_seqEngine.SwipeDirectionAvailable(direction);
            if (dirvalid)														// 밀 수 있는 방향일 때
            {
                float weight	= engine.InGameSetting.SwipeWeight;
                float maxdist	= (direction == FSNInGameSetting.FlowDirection.Left || direction == FSNInGameSetting.FlowDirection.Right)?
                                    engine.ScreenXSize : engine.ScreenYSize;	// 해당 방향으로 최대한 밀 수 있는 거리

                float fullDist		= weight * maxdist;
                float curSwipeRatio	= Mathf.Pow(distance / fullDist, 0.5f);		// 드래그할 때 약간 저항을 주기 위해
                if (curSwipeRatio < 1.0f)										// 아직 덜 밀었을 때
                {
                    //m_seqEngine.PartialSwipe(direction, curSwipeRatio * c_partialSwipeLimit);// Partial swipe
                    m_seqEngine.PartialSwipe(direction,curSwipeRatio);			// Partial swipe
                    m_swipeRatio	= curSwipeRatio;

                    if (!m_swipeEventSent || m_swipeEventSentWasWrongDir)		// 아직 이벤트를 보낸 적이 없거나 잘못된 방향으로 이벤트를 보냈을 경우
                    {
                        ExecuteSwipeEvent((obj, param) =>
                            {
                                obj.OnTryingSwipe(direction);					// 옳은 방향으로 swipe 이벤트
                            });

                        m_swipeEventSent			= true;
                        m_swipeEventSentWasWrongDir	= false;
                    }
                }
                else if(!m_swipeCompleted)										// 완전히 밀었을 때, 아직 이전에 완전히 밀지는 않았을 경우
                {
                    m_seqEngine.FullSwipe(direction, c_partialSwipeLimit);		// Full swipe
                    m_swipeRatio	= 0;
                    m_swipeCompleted = true;

                    ExecuteSwipeEvent(
                        (obj, param) =>
                        {
                            obj.OnTryingSwipe(direction);						// swipe완료 이벤트
                        });
                }
            }
            else
            {																	// 밀 수 없는 방향일 때

                if (!m_swipeEventSent || !m_swipeEventSentWasWrongDir)			// 아직 이벤트를 보낸 적이 없거나 올바른 방향으로 이벤트를 보냈을 경우
                {
                    ExecuteSwipeEvent((obj, param) =>
                        {
                            obj.OnTryingSwipeToWrongDirection(direction);		// 잘못된 방향으로 swipe 이벤트
                        });

                    m_swipeEventSent			= true;
                    m_swipeEventSentWasWrongDir	= true;
                }
            }
        }
    }
Exemplo n.º 28
0
    //=================================================================

    /// <summary>
    /// 가운데가 아닌 텍스트의 위치를 여백에 따라 보정
    /// </summary>
    /// <param name="textpos"></param>
    /// <param name="flow"></param>
    private static void ApplySideTextMargin(ref Vector3 textpos, IInGameSetting setting, FSNInGameSetting.FlowDirection flow)
    {
        //float xoffset	= setting.TextMarginLeft - setting.TextMarginRight;
        float yoffset = setting.TextMarginBottom - setting.TextMarginTop;

        // 해당 사이드에서 여백만큼 떨어트리기
        switch (flow)
        {
        case FSNInGameSetting.FlowDirection.Up:
            textpos.y += setting.TextMarginBottom;
            textpos.x += setting.TextMarginLeft;
            break;

        case FSNInGameSetting.FlowDirection.Down:
            textpos.y -= setting.TextMarginTop;
            textpos.x += setting.TextMarginLeft;
            break;

        case FSNInGameSetting.FlowDirection.Left:
            textpos.x -= setting.TextMarginRight;
            textpos.y += yoffset;
            break;

        case FSNInGameSetting.FlowDirection.Right:
            textpos.x += setting.TextMarginLeft;
            textpos.y += yoffset;
            break;
        }
    }