//======================================================================== /// <summary> /// 오브젝트 생성 커맨드 처리 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> void CreateElement(SegT segment, FSNSnapshot.Layer layer) { { int uid; if (FindUIDFromLookupDict(segment.objectName, out uid, layer)) // 이미 해당 이름으로 오브젝트가 존재한다면 에러 { Debug.LogError("there is already a SnapshotElem named " + segment.objectName); } } var newElem = new ElemT(); newElem.Alpha = 1; newElem.Color = Color.white; newElem.TransitionTime = 1; SetElemBySegProperties(newElem, segment); // 세팅하기 newElem.MakeItUnique(); var initialState = newElem.InitialState as ElemT; // Inital State 기본값 주기 - 시작 세팅에서 알파만 0 initialState.Alpha = 0; initialState.TransitionTime = 1; SetElemBySegProperties(initialState, segment); AutoSetFinalState(newElem, false); // Final State 임시로 세팅 newElem.motionState = SnapshotElems.ObjectBase <ElemT> .State.MotionKey; // Key로 지정 layer.AddElement(newElem); AddToLookupDict(segment.objectName, newElem, layer); // 오브젝트 이름 등록 OnCreateElement(segment, layer, newElem); // 추가 동작 실행 }
protected override void OnCreateElement(Segments.Image segment, FSNSnapshot.Layer layer, SnapshotElems.Image elemCreated) { base.OnCreateElement(segment, layer, elemCreated); if (segment.combinedImgPath != null) // 조합 이미지를 사용하는 경우 { var combimg = FSNResourceCache.Load <FSNCombinedImage>(FSNResourceCache.Category.Script, segment.combinedImgPath); if (combimg == null) { Debug.LogErrorFormat("조합 이미지 파일을 열 수 없습니다. : {0}", segment.texturePath); } elemCreated.combimg = combimg; // 실행 순서 문제 때문에 initial/finalstate의 텍스쳐를 직접 세팅해줘야함 (initial state가 이미 초기화된 상태, 값이 자동으로 복사되지 않음) elemCreated.InitialState.combimg = combimg; elemCreated.FinalState.combimg = combimg; } else { // 일반 텍스쳐를 사용하는 경우 var texture = FSNResourceCache.Load <Texture2D>(FSNResourceCache.Category.Script, segment.texturePath); if (texture == null) { Debug.LogErrorFormat("텍스쳐 파일을 열 수 없습니다. : {0}", segment.texturePath); } elemCreated.texture = texture; // 실행 순서 문제 때문에 initial/finalstate의 텍스쳐를 직접 세팅해줘야함 (initial state가 이미 초기화된 상태, 값이 자동으로 복사되지 않음) elemCreated.InitialState.texture = texture; elemCreated.FinalState.texture = texture; } var pivotVec = Segments.Image.ConvertPivotPresetToVector(segment.pivot); elemCreated.pivot = pivotVec; elemCreated.InitialState.pivot = pivotVec; elemCreated.FinalState.pivot = pivotVec; }
// 트랜지션 관련 /// <summary> /// 타겟 레이어 비교. 이전에 비교한 레이어라면 캐싱된 것을 사용, 새로운 타겟이라면 캐시 업데이트. /// </summary> /// <param name="target"></param> void UpdateTargetLayerDiff(FSNSnapshot.Layer target) { if (m_lastTargetLayerRef != target) { m_lastTargetLayerDiff = m_curLayerRef.CompareAndReturnElements(target); m_lastTargetLayerRef = target; } }
protected override void OnSetElement(LibSequentia.ScriptSegment segment, FSNSnapshot.Layer layer, LibSequentia.SnapshotElement elemToSet) { //base.OnSetElement(segment, layer, elemToSet); var elem = elemToSet as LibSequentia.SnapshotElement; elem.CountUpScriptProgress(); // 진행 방향을 알 수 있도록 }
protected override void OnCreateElement(LibSequentia.ScriptSegment segment, FSNSnapshot.Layer layer, LibSequentia.SnapshotElement elemCreated) { //base.OnCreateElement(segment, layer, elemCreated); var elem = elemCreated as LibSequentia.SnapshotElement; elem.CountUpScriptProgress(); // 진행 방향을 알 수 있도록 elem.InitialState.SetNegativeProgress(); }
static void RemoveFromLookupDict(string name, FSNSnapshot.Layer layer) { var nameDict = layer.GetCustomData(c_customDataName) as Dictionary <string, int>; if (nameDict == null) { nameDict = new Dictionary <string, int>(); layer.SetCustomData(c_customDataName, nameDict); } nameDict.Remove(name); }
protected override void OnCreateElement(Segments.GObject segment, FSNSnapshot.Layer layer, SnapshotElems.GObject elemCreated) { base.OnCreateElement(segment, layer, elemCreated); var prefab = FSNResourceCache.Load <GameObject>(FSNResourceCache.Category.Script, segment.prefabPath); if (prefab == null) { Debug.LogErrorFormat("프리팹을 열 수 없습니다. : {0}", segment.prefabPath); } elemCreated.prefab = prefab; elemCreated.InitialState.prefab = prefab; // 실행 순서 문제 때문에 initial/finalstate의 프리팹을 직접 세팅해줘야함 elemCreated.FinalState.prefab = prefab; }
protected override void OnCreateElement(Segments.Sound segment, FSNSnapshot.Layer layer, SnapshotElems.Sound elemCreated) { base.OnCreateElement(segment, layer, elemCreated); var clip = FSNResourceCache.Load <AudioClip>(FSNResourceCache.Category.Script, segment.clipPath); elemCreated.clip = clip; elemCreated.InitialState.clip = clip; // 실행 순서 문제 때문에 initial/finalstate의 텍스쳐를 직접 세팅해줘야함 elemCreated.FinalState.clip = clip; elemCreated.looping = segment.looping; elemCreated.InitialState.looping = segment.looping; elemCreated.FinalState.looping = segment.looping; }
/// <summary> /// 오브젝트 초기 세팅 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> void SetElementInitial(SegT segment, FSNSnapshot.Layer layer) { int uid; if (!FindUIDFromLookupDict(segment.objectName, out uid, layer)) // 이름으로 uid 찾기 { Debug.LogError("cannot find SnapshotElem named " + segment.objectName); } var elem = layer.GetElement(uid) as ElemT; SetElemBySegProperties(elem.InitialState as ElemT, segment); // 설정값들 세팅 OnSetElementInitial(segment, layer, elem); // 추가동작 }
/// <summary> /// 오브젝트 파괴 세팅 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> void SetElementFinal(SegT segment, FSNSnapshot.Layer layer) { int uid; if (!FindUIDFromLookupDict(segment.objectName, out uid, layer)) // 이름으로 uid 찾기 { Debug.LogError("cannot find SnapshotElem named " + segment.objectName); } var elem = layer.GetElement(uid) as ElemT; AutoSetFinalState(elem); // Final State가 하나도 세팅되지 않은 경우, 기본값부터 세팅 SetElemBySegProperties(elem.FinalState as ElemT, segment); // 마지막 설정값들 세팅 OnSetElementFinal(segment, layer, elem); // 추가 동작 }
public override void ProcessCustomElementCommand(Segments.Sound segment, FSNSnapshot.Layer layer) { //base.ProcessCustomElementCommand(segment, layer); // One-Shot 사운드에 대한 처리 // 레이어에 one-shot 사운드 리스트가 없다면 생성 var oneshotSounds = layer.GetCustomData(c_oneshotSoundData) as List <Segments.Sound>; if (oneshotSounds == null) { oneshotSounds = new List <Segments.Sound>(); layer.SetCustomData(c_oneshotSoundData, oneshotSounds); } oneshotSounds.Add(segment); // 세그먼트채로 집어넣는다. }
/// <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]); } }
//================================================================= public override FSNSnapshot.Layer GenerateNextLayerImage(FSNSnapshot.Layer curLayer, params FSNProcessModuleCallParam[] callParams) { FSNSnapshot.Layer newLayer = curLayer.Clone(); foreach (var callParam in callParams) { if (callParam.segment.type == FSNScriptSequence.Segment.Type.Text) // ** 텍스트 세그먼트 처리 ** { var textSeg = callParam.segment as Segments.Text; // 타입 변환 switch (textSeg.textType) // * 텍스트 종류에 따라 처리 분기 { case Segments.Text.TextType.Normal: AddNormalText(newLayer, textSeg, callParam.setting); break; case Segments.Text.TextType.Clear: ClearTextsToDirection(newLayer, callParam.setting.CurrentFlowDirection); break; case Segments.Text.TextType.Options: ClearTextsToDirection(newLayer, callParam.setting.CurrentFlowDirection); // 선택지 텍스트는 clear를 먼저 한 뒤에 표시 ShowOptionTexts(newLayer, textSeg, callParam.setting); break; case Segments.Text.TextType.LastOption: AddLastOptionText(newLayer, textSeg, callParam.setting); break; } } else if (callParam.segment.type == FSNScriptSequence.Segment.Type.Control && (callParam.segment as Segments.Control).controlType == Segments.Control.ControlType.Clear) // Clear 명령에 반응 { ClearTextsToDirection(newLayer, callParam.setting.CurrentFlowDirection); } else if (callParam.segment.type == FSNScriptSequence.Segment.Type.HardClone) // 레이어 Hard-Clone { newLayer.MakeAllElemsHardClone(); } } return(newLayer); }
static bool AddToLookupDict(string name, ElemT elem, FSNSnapshot.Layer layer) { var nameDict = layer.GetCustomData(c_customDataName) as Dictionary <string, int>; if (nameDict == null) { nameDict = new Dictionary <string, int>(); layer.SetCustomData(c_customDataName, nameDict); } if (nameDict.ContainsKey(name)) { return(false); } else { nameDict[name] = elem.UniqueID; return(true); } }
/// <summary> /// 오브젝트 세팅 커맨드 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> void SetElement(SegT segment, FSNSnapshot.Layer layer) { int uid; if (!FindUIDFromLookupDict(segment.objectName, out uid, layer)) // 이름으로 uid 찾기 { Debug.LogError("cannot find SnapshotElem named " + segment.objectName); } var elem = layer.GetElement(uid) as ElemT; SetElemBySegProperties(elem, segment); // 설정값들 세팅 elem.motionState = SnapshotElems.ObjectBase <ElemT> .State.MotionKey; AutoSetFinalState(elem, false); // Final State가 세팅되지 않은 객체에 한해서만 Final State를 임시로 계속 만들어주기 CalculateStates(elem); // 지금까지 좌표값들 보간 OnSetElement(segment, layer, elem); // 추가 동작 }
/// <summary> /// 오브젝트 이름으로 UID 찾기 /// </summary> /// <param name="name"></param> /// <param name="uid"></param> /// <returns></returns> protected static bool FindUIDFromLookupDict(string name, out int uid, FSNSnapshot.Layer layer) { var nameDict = layer.GetCustomData(c_customDataName) as Dictionary <string, int>; if (nameDict == null) { nameDict = new Dictionary <string, int>(); layer.SetCustomData(c_customDataName, nameDict); } if (!nameDict.ContainsKey(name)) { uid = 0; return(false); } else { uid = nameDict[name]; return(true); } }
/// <summary> /// 현재 존재하는 오브젝트들만 toLayer 의 상태에 맞춰 트랜지션. (자동재생 아님) /// 다음으로 넘기기 위해 Swipe하는 도중에 화면에 보여지는 상태. /// </summary> /// <param name="toLayer"></param> /// <param name="ratio">트랜지션 비율. 0 : 현재 상태 그대로, 1 : 완전히 toLayer 상태로</param> /// <param name="backward">진행 반대 방향으로 swipe를 한 경우에는 false</param> public void OldElementOnlyTransition(FSNSnapshot.Layer toLayer, float ratio, bool backward) { UpdateTargetLayerDiff(toLayer); // 비교 업데이트 // *** 유지되는 오브젝트들 IterateMatchingUIDs((int uId) => { m_objectDict[uId].TransitionWith(toLayer.GetElement(uId) as ElmT, ratio); }); // *** 다음에 사라지는 오브젝트들 IterateOnlyInThisUIDs((int uId) => { var currentElem = toLayer.GetRemovedElementOrNull(uId) // (정방향) 다음 레이어에 지워지는 해당 오브젝트에 관한 정보가 있다면 얻어오고 ?? m_curLayerRef.GetElement(uId); // 아니면 현재 레이어의 해당 오브젝트를 얻는다 var finalElem = (!backward)? currentElem.GenericFinalState // 정방향일 경우 마지막 스테이트로 움직인 뒤 소멸, : currentElem.GenericInitialState; // 역방향일 경우 최초 스테이트로 움직인 뒤 소멸해야한다. m_objectDict[uId].TransitionWith(finalElem as ElmT, ratio); }); }
/// <summary> /// 오브젝트 삭제 커맨드 처리 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> void RemoveElement(SegT segment, FSNSnapshot.Layer layer) { int uid; if (!FindUIDFromLookupDict(segment.objectName, out uid, layer)) // 이름으로 uid 찾기 { Debug.LogError("cannot find SnapshotElem named " + segment.objectName); } var elem = layer.GetElement(uid) as ElemT; AutoSetFinalState(elem); // Final State가 하나도 세팅되지 않은 경우, 기본값부터 세팅 SetElemBySegProperties(elem, segment); // 마지막 설정값들 세팅 elem.motionState = SnapshotElems.ObjectBase <ElemT> .State.MotionKey; OnRemoveElement(segment, layer, elem); // 추가 동작 실행 CalculateStates(elem); // 지금까지 좌표값들 보간 RemoveFromLookupDict(segment.objectName, layer); // 제거 layer.RemoveElement(uid); }
protected override void OnLayerTransitionStart(FSNSnapshot.Layer toLayer) { //base.OnLayerTransitionStart(toLayer); var oneshotSounds = toLayer.GetCustomData(c_oneshotSoundData) as List <Segments.Sound>; if (oneshotSounds != null) // one-shot sound가 있는 경우에만, 트랜지션 시작시에 사운드 재생 { foreach (var sound in oneshotSounds) // 사운드마다 게임 오브젝트, 오디오소스 생성 등등... { var clip = FSNResourceCache.Load <AudioClip>(FSNResourceCache.Category.Script, sound.clipPath); var go = new GameObject("Sound oneshot"); go.transform.SetParent(ObjectRoot, false); var source = go.AddComponent <AudioSource>(); source.volume = sound.volume; source.panStereo = sound.panning; source.PlayOneShot(clip); Destroy(go, clip.length + 0.1f); // 오디오 재생 길이만큼만 게임 오브젝트 유지 } } }
private void AddLastOptionText(FSNSnapshot.Layer layer, Segments.Text textSeg, IInGameSetting setting) { // TODO : 상하좌우 여백, 정렬 등도 따져야함 // NOTE : 선택한 방향은 setting 쪽에 설정되어 오는 것으로... SnapshotElems.Text optionText = null; foreach (var elem in layer.Elements) // * 이전 레이어를 전부 뒤져서 진행 방향이 같은 선택지 텍스트를 찾아온다 { var textElem = elem as SnapshotElems.Text; if (textElem.type == SnapshotElems.Text.Type.OptionTexts && textElem.optionDir == setting.CurrentFlowDirection) { optionText = textElem; break; } } if (optionText != null) // * 찾은 경우에 한해서... { // 텍스트를 새로 만드는 것이 아니라 기존 것을 변경한다. // PushTextsToDirection 에서는 이 시점의 LastOption텍스트는 건들지 않는다. var textSize = CalculateTextSize(optionText.text, setting); var posToCenter = optionText.Position; TextPositionToCenter(ref posToCenter, textSize, optionText.optionDir, setting); // 중앙 위치 맞추기 optionText.Position = posToCenter; optionText.type = SnapshotElems.Text.Type.LastOption; // LastOption 타입으로 변경 CopyCurrentToFinal(optionText); // 임시 FinalState PushTextsToDirection(layer, setting.CurrentFlowDirection, Vector2.zero); // 기존 텍스트 일괄적으로 해당 방향으로 밀기 (내부 조건체크에 따라 LastOption은 이 타이밍에는 제외된다) } else { Debug.LogError("cannot find option text to direction : " + setting.CurrentFlowDirection.ToString()); } }
/// <summary> /// 오브젝트 생성 커맨드, 추가 처리 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> /// <param name="elemCreated"></param> protected virtual void OnCreateElement(SegT segment, FSNSnapshot.Layer layer, ElemT elemCreated) { }
/// <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]); } }
/// <summary> /// 오브젝트 삭제 커맨드, 추가 처리 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> /// <param name="elemToBeRemoved"></param> protected virtual void OnRemoveElement(SegT segment, FSNSnapshot.Layer layer, ElemT elemToBeRemoved) { }
/// <summary> /// 특정 레이어로 트랜지션하는 애니메이션이 시작될 때 호출됨 /// </summary> /// <param name="toLayer"></param> protected virtual void OnLayerTransitionStart(FSNSnapshot.Layer toLayer) { }
/// <summary> /// 트랜지션 애니메이션 시작. /// </summary> /// <param name="toLayer"></param> /// <param name="startRatioForOlds">기존 오브젝트들은 해당 비율부터 애니메이션 시작</param> /// <param name="backward">진행 반대 방향으로 swipe를 한 경우에는 false</param> /// <returns>트랜지션이 모두 끝나는데 걸리는 시간</returns> public float StartTransition(FSNSnapshot.Layer toLayer, IInGameSetting nextSetting, float startRatioForOlds, bool backward) { UpdateTargetLayerDiff(toLayer); // 비교 업데이트 float longestDuration = 0f; // 트랜지션 중 제일 오래걸리는 것의 시간 // *** 유지되는 오브젝트들 IterateMatchingUIDs((int uId) => { var elem = toLayer.GetElement(uId) as ElmT; float trTime = elem.TransitionTime / nextSetting.TransitionSpeedRatio; // 전환속도 비율 적용 m_objectDict[uId].DoTransition(elem, startRatioForOlds, trTime, false); if (longestDuration < trTime) { longestDuration = trTime; // 제일 긴 트랜지션 시간 추적하기 } }); // *** 다음에 사라지는 오브젝트들 IterateOnlyInThisUIDs((int uId) => { var currentElem = m_curLayerRef.GetElement(uId); // 다음 레이어에 없어질 현재 레이어 객체 var refelem = toLayer.GetRemovedElementOrNull(uId) // (정방향) 다음 레이어에 지워지는 해당 오브젝트에 관한 정보가 있다면 이것을 사용 ?? currentElem; // 아니면 현재 레이어의 해당 오브젝트를 사용하여 finalState를 구한다 var finalElem = (!backward)? refelem.GenericFinalState // 정방향일 경우 마지막 스테이트로 움직인 뒤 소멸, : refelem.GenericInitialState; // 역방향일 경우 최초 스테이트로 움직인 뒤 소멸해야한다. float trTime = finalElem.TransitionTime / nextSetting.TransitionSpeedRatio; // 전환속도 비율 적용 m_objectDict[uId].DoTransition(finalElem as ElmT, startRatioForOlds, trTime, true); if (longestDuration < trTime) { longestDuration = trTime; // 제일 긴 트랜지션 시간 추적하기 } }); // *** 다음에 처음 등장하는 오브젝트들 IterateOnlyInOtherUIDs((int uId) => { var currentElem = toLayer.GetElement(uId); // 다음 레이어의 해당 객체 var refelem = m_curLayerRef.GetRemovedElementOrNull(uId) // (역방향) 현재 레이어에 지워진 오브젝트의 정보가 있다면 그것을 사용, ?? currentElem; // 아니면 다음 레이어의 오브젝트를 참조해서 InitialState를 구한다 var initialElem = backward? refelem.GenericFinalState : refelem.GenericInitialState; // 역방향이면 finalState, 정방향이면 InitialState 로 초기세팅한다 float trTime = initialElem.TransitionTime / nextSetting.TransitionSpeedRatio; // 현재 상태로 transition하지만 시간값은 최초 상태값에 지정된 걸 사용한다. var newobj = AddNewLayerObject(initialElem as ElmT, nextSetting); newobj.DoTransition(currentElem as ElmT, 0, trTime, false); if (longestDuration < trTime) { longestDuration = trTime; // 제일 긴 트랜지션 시간 추적하기 } }); // NOTE : 트랜지션이 완전히 끝난 뒤에 레이어를 교체해야할 수도 있다. 이슈가 생기면 그때 바꾸자... m_curLayerRef = toLayer; // 현재 레이어를 트랜지션 타겟 레이어로 교체. OnLayerTransitionStart(toLayer); // 이벤트 호출 return(m_useTransitionDelay? longestDuration : 0); // 트랜지션 딜레이를 사용하지 않는다면 딜레이 시간은 0으로 }
/// <summary> /// 레이어에 후처리 필요할 때 /// </summary> /// <param name="newLayer"></param> protected virtual void OnAfterGenerateNextLayerImage(FSNSnapshot.Layer newLayer) { }
/// <summary> /// 해당 layer와 다음 명령어 조각을 사용해서 다음 layer 상태를 생성하여 리턴한다. /// 현재 Snapshot에 특정 명령어가 적용된 후의 Snapshot을 만들어내는 데 사용. /// </summary> /// <param name="curLayer"></param> /// <param name="nextSeg"></param> /// <returns></returns> public abstract FSNSnapshot.Layer GenerateNextLayerImage(FSNSnapshot.Layer curLayer, params FSNProcessModuleCallParam[] callParams);
public override FSNSnapshot.Layer GenerateNextLayerImage(FSNSnapshot.Layer curLayer, params FSNProcessModuleCallParam[] callParams) { FSNSnapshot.Layer newLayer = curLayer.Clone(); if (curLayer.GetCustomData(c_customDataName) != null) // 이름 dictionary 카피 { newLayer.SetCustomData(c_customDataName, new Dictionary <string, int>(curLayer.GetCustomData(c_customDataName) as Dictionary <string, int>)); } foreach (var callParam in callParams) { if (callParam.segment.type == FSNScriptSequence.Segment.Type.Object) { var objSeg = callParam.segment as SegT; switch (objSeg.command) { case Segments.Object.CommandType.Create: CreateElement(objSeg, newLayer); break; case Segments.Object.CommandType.Remove: RemoveElement(objSeg, newLayer); break; case Segments.Object.CommandType.SetInitial: SetElementInitial(objSeg, newLayer); break; case Segments.Object.CommandType.SetFinal: SetElementFinal(objSeg, newLayer); break; case Segments.Object.CommandType.SetKey: SetElement(objSeg, newLayer); break; case Segments.Object.CommandType.Custom: ProcessCustomElementCommand(objSeg, newLayer); break; } } else if (callParam.segment.type == FSNScriptSequence.Segment.Type.Control) { var controlSeg = callParam.segment as Segments.Control; if (controlSeg.controlType == Segments.Control.ControlType.Clear && acceptClearCommand) // Clear 명령에 반응 { foreach (var rawelem in newLayer.Elements) // finalstate가 세팅되지 않은 오브젝트에 한해서 디폴트 세팅 { var elem = rawelem as ElemT; AutoSetFinalState(elem); } newLayer = new FSNSnapshot.Layer(); // 완전히 새로운 레이어로 교체 // TODO : 힘들게 복제한 레이어를 버리는 구조임. 최적화 여지가 있음. } } else if (callParam.segment.type == FSNScriptSequence.Segment.Type.HardClone) // 레이어 Hard-Clone { newLayer.MakeAllElemsHardClone(); } else { } } // TODO : call 처리 이후, snapshot 마무리 OnAfterGenerateNextLayerImage(newLayer); return(newLayer); }
public virtual void ProcessCustomElementCommand(SegT segment, FSNSnapshot.Layer layer) { }
/// <summary> /// 오브젝트 파괴 세팅, 추가 처리 /// </summary> /// <param name="segment"></param> /// <param name="layer"></param> /// <param name="elemToSet"></param> protected virtual void OnSetElementFinal(SegT segment, FSNSnapshot.Layer layer, ElemT elemToSet) { }