public void UnlinkAll() { #if UNITY_2017_1_OR_NEWER for (int i = 0; i < _nClipData; i++) { _c_curClipData = _clipData[i]; _c_curClipData.Unlink(); _c_curClipData._isCalculated = false; _c_curClipData._isCalculatedPrev = false; } #endif }
public void Update(apAnimPlayManager animPlayManager) { #if UNITY_2017_1_OR_NEWER _c_curTime = _parentTrackSet._playableDirector.time; _lastPlayedTimelineClip = null; #endif _lastPlayedLocalTime = 0.0f; //1. 전체 Reday To Update for (int i = 0; i < _nClipData; i++) { _clipData[i].ReadyToUpdate(); } #if UNITY_2017_1_OR_NEWER //2. 범위 체크해서 업데이트 여부 결정과 Set Data _c_curClipData = null; _c_clipA = null; _c_clipB = null; _c_localTimeA = 0.0; _c_localTimeB = 0.0; _c_weightA = 0.0f; _c_weightB = 0.0f; _c_nPlayClips = 0; for (int i = 0; i < _nClipData; i++) { _c_curClipData = _clipData[i]; if (_c_curTime < _c_curClipData._timelineClip.start || _c_curTime > _c_curClipData._timelineClip.end) { continue; } if (_c_clipA == null) { _c_clipA = _c_curClipData; _c_nPlayClips = 1; _c_localTimeA = _c_clipA._timelineClip.ToLocalTimeUnbound(_c_curTime); } else if (_c_clipB == null) { //단, A와 AnimClip이 겹치면 안된다. if (_c_clipA._animClip != _c_curClipData._animClip) { _c_clipB = _c_curClipData; _c_nPlayClips = 2; _c_localTimeB = _c_clipB._timelineClip.ToLocalTimeUnbound(_c_curTime); break; //B까지 연결했으면 끝 } } } if (_c_nPlayClips == 1) { //PlayClip이 1개일 때 if (_c_localTimeA < _c_clipA._timelineClip.easeInDuration) { _c_weightA = GetWeightIn(_c_localTimeA, _c_clipA._timelineClip.easeInDuration); } else if (_c_localTimeA < _c_clipA._timelineClip.duration - _c_clipA._timelineClip.easeOutDuration) { _c_weightA = 1.0f; } else { _c_weightA = GetWeightOut(_c_localTimeA, _c_clipA._timelineClip.easeOutDuration, _c_clipA._timelineClip.duration); } _c_clipA.SetData(true, _c_weightA, (float)_c_localTimeA, _blendMethod, _layerOrder); //Clip A가 마지막에 계산되었다. _lastPlayedTimelineClip = _c_clipA._timelineClip; _lastPlayedLocalTime = (float)_c_localTimeA; } else if (_c_nPlayClips == 2) { //PlayClip이 2개일 때 (무조건 Blend) _c_weightA = GetWeightOut(_c_localTimeA, _c_clipA._timelineClip.blendOutDuration, _c_clipA._timelineClip.duration); _c_weightB = 1.0f - _c_weightA; _c_clipA.SetData(true, _c_weightA, (float)_c_localTimeA, _blendMethod, _layerOrder); _c_clipB.SetData(false, _c_weightB, (float)_c_localTimeB, _blendMethod, _layerOrder); //Clip B가 마지막에 계산되었다. _lastPlayedTimelineClip = _c_clipB._timelineClip; _lastPlayedLocalTime = (float)_c_localTimeB; } //3. 클립데이터 확인하여 Link/Unlink 및 Update for (int i = 0; i < _nClipData; i++) { _c_curClipData = _clipData[i]; if (!_c_curClipData._isCalculated) { //업데이트가 안되었다면 Release if (_c_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 되었던 ClipData다. _c_curClipData.Unlink(); } } else { //업데이트가 되었으면 연결을 하고, 프레임과 Weight를 업데이트 한다. if (!_c_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 안되었다. _c_curClipData.Link(); //Root Unit을 갱신할 수도 있다. animPlayManager.SetOptRootUnit(_c_curClipData._linkedRootUnit); } //업데이트 <중요!> _c_curClipData.UpdateTimelineClipAndPlayUnit(); } //Prev 갱신 _c_curClipData._isCalculatedPrev = _c_curClipData._isCalculated; } #endif }
public bool SetTrack(string trackName, int layerIndex, apAnimPlayUnit.BLEND_METHOD blendMethod, apPortrait portrait, apAnimPlayManager animPlayManager) { #if UNITY_2017_1_OR_NEWER //PlayableDirector playDirector = _parentTrackSet._playableDirector; PlayableAsset playAsset = _parentTrackSet._playableAsset; #endif _trackName = trackName; _layerIndex = layerIndex; #if UNITY_2017_1_OR_NEWER _layerOrder = _layerIndex; #endif _blendMethod = blendMethod; if (string.IsNullOrEmpty(_trackName)) { //이름이 빈칸이거나 null이다. return(false); } _clipData = new List <TimelineClipData>(); #if UNITY_2017_1_OR_NEWER _timelineClips = new List <TimelineClip>(); _clipDataByTrack = new Dictionary <TimelineClip, TimelineClipData>(); #endif _nClipData = 0; //연결을 하자 bool isFind = false; #if UNITY_2017_1_OR_NEWER _animationTrack = null; #endif //그 전에 AnimClip <-> AnimationClipAsset을 서로 연결해야한다. apAnimClip curAnimClip = null; AnimationClip curAnimationClipAsset = null; Dictionary <AnimationClip, apAnimClip> animClipAsset2AnimClip = new Dictionary <AnimationClip, apAnimClip>(); for (int i = 0; i < portrait._animClips.Count; i++) { curAnimClip = portrait._animClips[i]; if (curAnimClip == null) { continue; } curAnimationClipAsset = curAnimClip._animationClipForMecanim; if (curAnimationClipAsset == null) { continue; } if (animClipAsset2AnimClip.ContainsKey(curAnimationClipAsset)) { continue; } animClipAsset2AnimClip.Add(curAnimationClipAsset, curAnimClip); } //apAnimClip에 해당하는 apOptRootUnit을 알아야 한다. //apAnimPlayData에 그 정보가 저장되어 있으니 참조하자 apAnimPlayData curPlayData = null; Dictionary <apAnimClip, apOptRootUnit> animClip2RootUnit = new Dictionary <apAnimClip, apOptRootUnit>(); for (int i = 0; i < animPlayManager._animPlayDataList.Count; i++) { curPlayData = animPlayManager._animPlayDataList[i]; if (curPlayData == null) { continue; } if (curPlayData._linkedAnimClip == null || curPlayData._linkedOptRootUnit == null) { continue; } if (animClip2RootUnit.ContainsKey(curPlayData._linkedAnimClip)) { continue; } //apAnimClip -> apOptRootUnit으로 연결 데이터 추가 animClip2RootUnit.Add(curPlayData._linkedAnimClip, curPlayData._linkedOptRootUnit); } #if UNITY_2017_1_OR_NEWER foreach (PlayableBinding playableBinding in playAsset.outputs) { #endif #if UNITY_2018_1_OR_NEWER bool isAnimTrack = playableBinding.sourceObject != null && playableBinding.sourceObject is AnimationTrack; #elif UNITY_2017_1_OR_NEWER bool isAnimTrack = playableBinding.streamType == DataStreamType.Animation; #endif //if (playableBinding.streamType != DataStreamType.Animation) #if UNITY_2017_1_OR_NEWER if (!isAnimTrack) { //애니메이션 타입이 아니라면 패스 continue; } AnimationTrack animTrack = playableBinding.sourceObject as AnimationTrack; if (animTrack == null) { continue; } //if(animTrack.isEmpty) //{ // //클립이 아예 없는데용 // continue; //} if (!animTrack.name.Equals(_trackName)) { //이름이 다르다. continue; } if (animTrack.isEmpty) { //클립이 아예 없는데용 //continue; Debug.LogWarning("AnyPortrait : ( Warning ) No Clip in the requested track. [ " + trackName + " ]"); //일단 처리는 하자 } //이름도 같고 유효한 트랙을 찾았다! isFind = true; _animationTrack = animTrack; AnimationClip animClipInTrack = null; apAnimClip targetAnimClip = null; apOptRootUnit targetRootUnit = null; foreach (TimelineClip timelineClip in _animationTrack.GetClips()) { //Track의 TimelineClip 중에서 유효한 AnimationClip만 선택한다. animClipInTrack = timelineClip.animationClip; if (!animClipAsset2AnimClip.ContainsKey(animClipInTrack)) { //유효한 AnimationClip이 아니다. continue; } targetAnimClip = animClipAsset2AnimClip[animClipInTrack]; if (targetAnimClip == null) { //animClip이 비어있다. continue; } if (!animClip2RootUnit.ContainsKey(targetAnimClip)) { //apAnimClip -> apOptRootUnit을 조회할 수 없다. continue; } targetRootUnit = animClip2RootUnit[targetAnimClip]; if (targetRootUnit == null) { //RootUnit이 null이다. continue; } TimelineClipData newClipData = new TimelineClipData(timelineClip, targetAnimClip, targetRootUnit); _clipData.Add(newClipData); _timelineClips.Add(timelineClip); _clipDataByTrack.Add(timelineClip, newClipData); //_clipDataByAnimClip.Add(targetAnimClip, newClipData); _nClipData++; } //Debug.Log("Track [" + trackName + "] Added"); //<<추가>> 시간대에 따라서 Sort _clipData.Sort(delegate(TimelineClipData a, TimelineClipData b) { return((int)((a._timelineClip.start - b._timelineClip.start) * 100.0)); }); if (isFind) { break; } } #endif if (!isFind) { Debug.LogError("AnyPortrait : No track with the requested name. [" + trackName + "]"); } return(isFind); }