예제 #1
0
        public void AdaptToControlParam_Opt(float weight, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
            if (!_isCalculated)
            {
                return;
            }

            switch (_targetControlParam._valueType)
            {
            //case apControlParam.TYPE.Bool:
            //	_targetControlParam.SetCalculated_Bool(_value_Bool, weight, blendMethod);
            //	break;

            case apControlParam.TYPE.Int:
                _targetControlParam.SetCalculated_Int(_value_Int, weight, blendMethod);
                break;

            case apControlParam.TYPE.Float:
                _targetControlParam.SetCalculated_Float(_value_Float, weight, blendMethod);
                break;

            case apControlParam.TYPE.Vector2:
                _targetControlParam.SetCalculated_Vector2(_value_Vec2, weight, blendMethod);
                break;

                //case apControlParam.TYPE.Vector3:
                //	_targetControlParam.SetCalculated_Vector3(_value_Vec3, weight, blendMethod);
                //	break;


                //case apControlParam.TYPE.Color:
                //	_targetControlParam.SetCalculated_Color(_value_Color, weight, blendMethod);
                //	break;
            }
        }
        // Functions
        //-------------------------------------------------
        public bool AddTrack(
#if UNITY_2017_1_OR_NEWER
            PlayableDirector playableDirector,
#endif
            string trackName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
#if UNITY_2017_1_OR_NEWER
            if (playableDirector == null)
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. PlayableDirector is Null.");
                return(false);
            }
            if (playableDirector.playableAsset == null)
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. PlayableAsset(Timeline) is Null.");
                return(false);
            }
#endif
            if (string.IsNullOrEmpty(trackName))
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. Track Name is empty.");
                return(false);
            }

#if UNITY_2017_1_OR_NEWER
            bool isValidTrack = DirectorTrackSet.CheckTrackValidation(playableDirector, playableDirector.playableAsset, trackName);
            if (!isValidTrack)
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. The requested track could not be found.");
                return(false);
            }

            //이미 등록된 Director에 대하여 새로운 Track을 추가하는 경우일 수 있다.
            //없다면 새로 Director를 만들고, 있으면 재활용

            DirectorTrackSet targetDirectorSet = _trackSets.Find(delegate(DirectorTrackSet a)
            {
                return(a._playableDirector == playableDirector && a._playableAsset == playableDirector.playableAsset);
            });

            if (targetDirectorSet == null)
            {
                //새로운 Director로 등록해야 한다.
                targetDirectorSet = new DirectorTrackSet();
                targetDirectorSet.SetPlayableDirector(playableDirector, playableDirector.playableAsset);
                _trackSets.Add(targetDirectorSet);

                _nTrackSets = _trackSets.Count;
            }

            bool result = targetDirectorSet.AddTrack(trackName, layer, blendMethod, _portrait, _animPlayManager);

            return(result);
#else
            return(false);
#endif
        }
        //추가 : AnimPlayData로 PlayQueued를 바로 실행하는 함수가 나오면서, 이름으로 검색하는 건 오버로드로 뺌
        public apAnimPlayData CrossFadeQueued(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false)
        {
            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]");
                return(null);
            }
            return(CrossFadeQueued(playData, layer, blendMethod, fadeTime, isAutoEndIfNotloop));
        }
        public apAnimPlayData CrossFadeAt(string animClipName, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false)
        {
            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]");
                return(null);
            }
            return(CrossFadeAt(playData, frame, layer, blendMethod, fadeTime, playOption, isAutoEndIfNotloop));
        }
예제 #5
0
 public void ReadyToUpdate()
 {
     _isCalculated = false;
     _isPlaying    = false;
     _playedLayer  = 0;
     _playOrder    = 0;
     _blendMethod  = apAnimPlayUnit.BLEND_METHOD.Interpolation;
     _speed        = 0.0f;
     _weight       = 0.0f;
     _timeRatio    = -1.0f;
 }
예제 #6
0
        /// <summary>
        /// Wait for the previous animation to finish, then play it smoothly.
        /// (If the previously playing animation is a loop animation, it will not be executed.)
        /// </summary>
        /// <param name="animClipName">Name of the Animation Clip</param>
        /// <param name="fadeTime">Fade Time</param>
        /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param>
        /// <param name="blendMethod">How it is blended with the animation of the lower layers</param>
        /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param>
        /// <returns>Animation data to be played. If it fails, null is returned.</returns>
        public apAnimPlayData CrossFadeQueued(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false)
        {
            //Debug.LogError("Start CrossFadeQueued [" + animClipName + "]");

            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]");
                return(null);
            }

            if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX)
            {
                Debug.LogError("CrossFade Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX);
                return(null);
            }

            if (fadeTime < 0.0f)
            {
                fadeTime = 0.0f;
            }

            //Debug.Log("CrossFadeQueued [" + animClipName + "]");

            apAnimPlayQueue playQueue      = _animPlayQueues[layer];
            apAnimPlayUnit  resultPlayUnit = playQueue.PlayQueued(playData, blendMethod, fadeTime, isAutoEndIfNotloop);

            if (resultPlayUnit == null)
            {
                return(null);
            }

            //float delayTime = resultPlayUnit.DelayToPlayTime;
            //float delayTime = Mathf.Clamp01(resultPlayUnit.RemainPlayTime - fadeTime);

            //if (playOption == PLAY_OPTION.StopAllLayers)
            //{
            //	//다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다.
            //	for (int i = 0; i < _animPlayQueues.Count; i++)
            //	{
            //		if (i == layer)
            //		{ continue; }
            //		_animPlayQueues[i].StopAll(delayTime);
            //	}
            //}

            RefreshPlayOrders();

            return(playData);
        }
        //----------------------------------------------------------------------------------------
        public apAnimPlayData PlayAt(string animClipName, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false, bool isDebugMsg = true)
        {
            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                if (isDebugMsg)
                {
                    Debug.LogError("PlayAt Failed : No AnimClip [" + animClipName + "]");
                }
                return(null);
            }
            return(PlayAt(playData, frame, layer, blendMethod, playOption, isAutoEndIfNotloop, isDebugMsg));
        }
예제 #8
0
        /// <summary>
        /// AnimClip 이름을 인자로 받아서 애니메이션을 재생한다.
        /// Fade 타임을 받아서 다른 모든 클립에서 자연스럽게 변환된다.
        /// </summary>
        /// <param name="animClipName">Clip 이름. 맞지 않을 경우 처리 실패</param>
        /// <param name="layer">실행되는 레이어. 0부터 실행되며 최대값은 20</param>
        /// <param name="blendMethod">다른 레이어와 블렌드시 옵션</param>
        /// <param name="playOption">StopAllLayer인 경우 요청된 레이어 외의 Clip들이 다음 Clip이 실행되는 순간 같이 종료된다.</param>
        /// <param name="isAutoEndIfNotloop">[Loop 타입이 아닌 경우] True이면 재생 종료시 자동으로 처리 데이터가 삭제된다.</param>
        /// <param name="fadeTime">페이드 시간. 기본값은 0.3</param>
        /// <returns></returns>
        public apAnimPlayData CrossFade(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false)
        {
            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]");
                return(null);
            }

            if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX)
            {
                Debug.LogError("CrossFade Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX);
                return(null);
            }

            if (fadeTime < 0.0f)
            {
                fadeTime = 0.0f;
            }

            apAnimPlayQueue playQueue      = _animPlayQueues[layer];
            apAnimPlayUnit  resultPlayUnit = playQueue.Play(playData, blendMethod, fadeTime, isAutoEndIfNotloop);

            if (resultPlayUnit == null)
            {
                return(null);
            }


            //float fadeInTime = resultPlayUnit.FadeInTime;

            if (playOption == PLAY_OPTION.StopAllLayers)
            {
                //다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다.
                for (int i = 0; i < _animPlayQueues.Count; i++)
                {
                    if (i == layer)
                    {
                        continue;
                    }
                    _animPlayQueues[i].StopAll(fadeTime);
                }
            }

            RefreshPlayOrders();

            return(playData);
        }
예제 #9
0
        //public void SetCalculated_Bool(bool bValue, float weight, apAnimPlayUnit.BLEND_METHOD blendMethod)
        //{
        //	weight = Mathf.Clamp01(weight);
        //	_totalWeight += weight;

        //	if(!_isUpdated)
        //	{
        //		_bool_CalculatedLayer = bValue;
        //		_isUpdated = true;
        //		return;
        //	}

        //	if(blendMethod == apAnimPlayUnit.BLEND_METHOD.Interpolation)
        //	{
        //		if(weight > 0.5f)
        //		{
        //			_bool_CalculatedLayer = bValue;
        //		}
        //	}
        //	else
        //	{
        //		//Bool에 Additive가 있나?
        //		if(bValue)
        //		{
        //			_bool_CalculatedLayer = true;
        //		}
        //	}
        //}

        public void SetCalculated_Int(int iValue, float weight, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
            weight        = Mathf.Clamp01(weight);
            _totalWeight += weight;

            if (blendMethod == apAnimPlayUnit.BLEND_METHOD.Interpolation || !_isUpdated)
            {
                _int_CalculatedLayer = (int)(_int_CalculatedLayer * (1.0f - weight) + iValue * (weight) + 0.5f);
            }
            else
            {
                _int_CalculatedLayer += (int)(iValue * weight + 0.5f);
            }
            _isUpdated = true;
        }
예제 #10
0
        public void SetCalculated_Float(float fValue, float weight, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
            weight        = Mathf.Clamp01(weight);
            _totalWeight += weight;

            if (blendMethod == apAnimPlayUnit.BLEND_METHOD.Interpolation || !_isUpdated)
            {
                _float_CalculatedLayer = _float_CalculatedLayer * (1.0f - weight) + fValue * (weight);
            }
            else
            {
                _float_CalculatedLayer += fValue * weight;
            }
            _isUpdated = true;
        }
예제 #11
0
        private apAnimPlayUnit MakePlayUnit(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop)
        {
            //새로 만들고
            //그 전에..
            //재생중인 PlayUnit이 있으면 그걸 사용하자
            //레이어는 같아야 한다.
            apAnimPlayUnit existPlayUnit = null;

            for (int i = 0; i < _animPlayUnits.Count; i++)
            {
                if (_animPlayUnits[i]._linkedAnimClip == playData._linkedAnimClip &&
                    _animPlayUnits[i].IsUpdatable

                    )
                {
                    existPlayUnit = _animPlayUnits[i];
                    break;
                }
            }
            if (existPlayUnit != null)
            {
                //Debug.Log("아직 재생중인 PlayUnit을 다시 재생하는 요청이 왔다. [" + existPlayUnit._linkedAnimClip._name + "]");
                existPlayUnit.SetSubOption(blendMethod, isAutoEndIfNotloop, GetNextPlayUnitRequestOrder(), GetNextRequestLinkKey());

                _nPlayedUnit = _animPlayUnits.Count;
                return(existPlayUnit);
            }

            apAnimPlayUnit newPlayUnit = new apAnimPlayUnit(this, GetNextPlayUnitRequestOrder(), GetNextRequestLinkKey());

            newPlayUnit.SetAnimClip(playData, _layer, blendMethod, isAutoEndIfNotloop, false);

            //if(!newPlayUnit._linkedAnimClip.IsPlaying)
            //{
            //	if(newPlayUnit.Frame != newPlayUnit.StartFrame)
            //	{
            //		Debug.Log("새로운 재생 요청 - 프레임이 초기화되지 않음 [" + newPlayUnit._linkedAnimClip._name + "]");
            //	}
            //	newPlayUnit.ResetPlay();
            //}

            //리스트에 넣자
            _animPlayUnits.Add(newPlayUnit);

            _nPlayedUnit    = _animPlayUnits.Count;
            _isInitPlayUnit = false;
            return(newPlayUnit);
        }
예제 #12
0
 public void SetData(int playedLayer,
                     int playOrder,
                     apAnimPlayUnit.BLEND_METHOD blendMethod,
                     float speed,
                     float weight,
                     float timeRatio)
 {
     _isCalculated = true;
     _isPlaying    = true;
     _playedLayer  = playedLayer;
     _playOrder    = playOrder;
     _blendMethod  = blendMethod;
     _speed        = speed;
     _weight       = weight;
     _timeRatio    = timeRatio;
 }
        /// <summary>
        /// Play the animation
        /// </summary>
        /// <param name="animClipName">Name of the Animation Clip</param>
        /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param>
        /// <param name="blendMethod">How it is blended with the animation of the lower layers</param>
        /// <param name="playOption">How to stop which animations</param>
        /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param>
        /// <returns>Animation data to be played. If it fails, null is returned.</returns>
        public apAnimPlayData Play(apAnimPlayData playData, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false, bool isDebugMsg = true)
        {
            if (playData == null)
            {
                if (isDebugMsg)
                {
                    Debug.LogError("Play Failed : Unknown AnimPlayData");
                }
                return(null);
            }

            if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX)
            {
                if (isDebugMsg)
                {
                    Debug.LogError("Play Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX);
                }
                return(null);
            }

            apAnimPlayQueue playQueue      = _animPlayQueues[layer];
            apAnimPlayUnit  resultPlayUnit = playQueue.Play(playData, blendMethod, 0.0f, isAutoEndIfNotloop);

            if (resultPlayUnit == null)
            {
                return(null);
            }



            if (playOption == PLAY_OPTION.StopAllLayers)
            {
                //다른 레이어를 모두 정지시킨다.
                for (int i = 0; i < _animPlayQueues.Count; i++)
                {
                    if (i == layer)
                    {
                        continue;
                    }
                    _animPlayQueues[i].StopAll(0.0f);
                }
            }

            RefreshPlayOrders();

            return(playData);
        }
            public void SetData(bool isClipA, float weight, float localPlayedTime, apAnimPlayUnit.BLEND_METHOD blendMethod, int layerIndex)
            {
                _isCalculated = true;
                _isPlaying    = true;
                if (isClipA)
                {
                    _playOrder = 0;
                }
                else
                {
                    _playOrder = 1;
                }
                //TimelineClip의 Speed는 LocalTime 계산시 포함되어있다.
                //_speed = speed;
                _weight = weight;

                _timeRatio = localPlayedTime / _animClip.TimeLength;

                _blendMethod = blendMethod;
                _layerIndex  = layerIndex;
            }
        /// <summary>
        /// Wait for the previous animation to finish, then play it.
        /// (If the previously playing animation is a loop animation, it will not be executed.)
        /// </summary>
        /// <param name="animClipName">Name of the Animation Clip</param>
        /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param>
        /// <param name="blendMethod">How it is blended with the animation of the lower layers</param>
        /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param>
        /// <returns>Animation data to be played. If it fails, null is returned.</returns>
        public apAnimPlayData PlayQueued(apAnimPlayData playData, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop = false)
        {
            if (playData == null)
            {
                Debug.LogError("PlayQueued Failed : Unknown AnimPlayData");
                return(null);
            }

            if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX)
            {
                Debug.LogError("PlayQueued Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX);
                return(null);
            }

            apAnimPlayQueue playQueue      = _animPlayQueues[layer];
            apAnimPlayUnit  resultPlayUnit = playQueue.PlayQueued(playData, blendMethod, 0.0f, isAutoEndIfNotloop);

            if (resultPlayUnit == null)
            {
                return(null);
            }



            //if (playOption == PLAY_OPTION.StopAllLayers)
            //{
            //	//다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다.
            //	for (int i = 0; i < _animPlayQueues.Count; i++)
            //	{
            //		if (i == layer)
            //		{ continue; }
            //		_animPlayQueues[i].StopAll(delayTime);
            //	}
            //}

            RefreshPlayOrders();

            return(playData);
        }
            //트랙을 추가한다.
            public bool AddTrack(string trackName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, apPortrait portrait, apAnimPlayManager animPlayManager)
            {
                //이미 적용된 트랙이 있다면, 에러 메시지를 보낸다.
                bool isExist = _trackData.Exists(delegate(TimelineTrackData a)
                {
                    return(a._trackName.Equals(trackName));
                });

                if (isExist)
                {
                    Debug.LogError("AnyPortrait : A track with the same name has already been registered. [ " + trackName + " ]");
                    return(false);
                }

                TimelineTrackData newTrackData = new TimelineTrackData(this);
                bool isResult = newTrackData.SetTrack(trackName, layer, blendMethod, portrait, animPlayManager);

                if (!isResult)
                {
                    return(false);
                }

                //리스트에 트랙 추가
                _trackData.Add(newTrackData);
                _nTrackData = _trackData.Count;

                //트랙을 추가했으면, Layer에 맞게 정렬한다. (오름차순)
                _trackData.Sort(delegate(TimelineTrackData a, TimelineTrackData b)
                {
                    return(a._layerIndex - b._layerIndex);
                });

                for (int i = 0; i < _trackData.Count; i++)
                {
                    _trackData[i].SetLayerOrder(i);                    //<<레이어의 순서를 다시 지정한다.
                }

                return(true);
            }
예제 #17
0
        private apAnimPlayUnit MakePlayUnit(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop)
        {
            //새로 만들고
            //그 전에..
            //재생중인 PlayUnit이 있으면 그걸 사용하자
            //레이어는 같아야 한다.
            apAnimPlayUnit existPlayUnit = null;

            for (int i = 0; i < _animPlayUnits.Count; i++)
            {
                if (_animPlayUnits[i]._linkedAnimClip == playData._linkedAnimClip &&
                    _animPlayUnits[i].IsUpdatable

                    )
                {
                    existPlayUnit = _animPlayUnits[i];
                    break;
                }
            }
            if (existPlayUnit != null)
            {
                //Debug.Log("아직 재생중인 PlayUnit을 다시 재생하는 요청이 왔다. [" + existPlayUnit._linkedAnimClip._name + "]");
                existPlayUnit.SetSubOption(blendMethod, isAutoEndIfNotloop);

                _nPlayedUnit = _animPlayUnits.Count;
                return(existPlayUnit);
            }

            apAnimPlayUnit newPlayUnit = new apAnimPlayUnit(this);

            newPlayUnit.SetAnimClip(playData, _layer, blendMethod, isAutoEndIfNotloop, false);

            //리스트에 넣자
            _animPlayUnits.Add(newPlayUnit);

            _nPlayedUnit = _animPlayUnits.Count;
            return(newPlayUnit);
        }
예제 #18
0
        //----------------------------------------------------
        // 재생/정지 요청 함수들
        //----------------------------------------------------

        /// <summary>
        /// AnimClip을 PlayUnit에 담아서 재생한다.
        /// Queue에 저장된 모든 클립은 무시되며 블렌드되지 않는다.
        /// </summary>
        /// <param name="blendMethod"></param>
        /// <param name="isAutoEndIfNotloop">True이면 Clip의 재생 후 자동으로 종료한다. (Loop일 경우 무시됨)</param>
        public apAnimPlayUnit Play(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true)
        {
            //Request를 생성한다.
            apAnimPlayRequest request = PopRequest();

            request.SetCurrentPlayedUnits(this, _animPlayUnits);


            apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);

            //newPlayUnit.Play();

            //Play 명령을 준다.
            request.PlayNew(newPlayUnit, blendTime);

            #region [미사용 코드]
            //TODO : 이 AnimClip을 CalculatedParam에 연결해야한다.
            //Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다");

            ////플레이 유닛은 플레이 시작
            ////나머지는 End로 만든다.
            //for (int i = 0; i < _animPlayUnits.Count; i++)
            //{
            //	if (newPlayUnit != _animPlayUnits[i])
            //	{
            //		_animPlayUnits[i].SetEnd();
            //	}
            //}
            #endregion

            _nPlayedUnit = _animPlayUnits.Count;



            //Debug.Log("Next Play Units [" + _nPlayedUnit + "]");
            return(newPlayUnit);
        }
예제 #19
0
        //----------------------------------------------------
        // 재생/정지 요청 함수들
        //----------------------------------------------------

        //AnimClip을 PlayUnit에 담아서 재생한다.
        //Queue에 저장된 모든 클립은 무시되며 블렌드되지 않는다.
        public apAnimPlayUnit Play(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true)
        {
            //현재 상태에서 실행되지 않은 Queued 애니메이션 재생 요청은 삭제한다.
            PushAllNoActiveRequests();

            //Request를 생성한다.
            apAnimPlayRequest request = PopRequest();

            //request.SetCurrentPlayedUnits(this, _animPlayUnits);
            request.SetCurrentPlayedUnits(this);

            //현재 플레이 중인 AnimPlayUnit들의 LinkKey를 넣어준다.
            //Debug.Log("Add Play Unit Link Key");

            for (int i = 0; i < _animPlayUnits.Count; i++)
            {
                //Debug.Log(_animPlayUnits[i]._linkedAnimClip._name + " : " + _animPlayUnits[i].LinkKey + " / " + _animPlayUnits[i].PlayStatus);
                request.AddPrevPlayUnitKeyLink(_animPlayUnits[i].LinkKey, _animPlayUnits[i].UnitWeight);
            }

            apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);

            //newPlayUnit.Play();
            newPlayUnit.Resume();            //Pause가 걸려있으면 풀어주자


            //Play 명령을 준다.

            request.PlayNew(newPlayUnit, blendTime);

            //이때, 만약 PlayQueued 타입이며 newPlayUnit을 타겟으로 하는게 있으면 처리할 때 무력화시켜야 한다.
            apAnimPlayRequest overlapQueuedRequest = _requests_Live.Find(delegate(apAnimPlayRequest a)
            {
                return(a != request && a.RequestType == apAnimPlayRequest.REQUEST_TYPE.Queued && a._nextPlayUnit == newPlayUnit);
            });

            if (overlapQueuedRequest != null)
            {
                //Debug.Log("겹치는 Queue Request를 그냥 바로 삭제");
                PushRequest(overlapQueuedRequest);
            }

            #region [미사용 코드]
            //TODO : 이 AnimClip을 CalculatedParam에 연결해야한다.
            //Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다");

            ////플레이 유닛은 플레이 시작
            ////나머지는 End로 만든다.
            //for (int i = 0; i < _animPlayUnits.Count; i++)
            //{
            //	if (newPlayUnit != _animPlayUnits[i])
            //	{
            //		_animPlayUnits[i].SetEnd();
            //	}
            //}
            #endregion

            _nPlayedUnit = _animPlayUnits.Count;


            //Order를 갱신한다.
            RefreshOrder();



            //Debug.Log("Next Play Units [" + _nPlayedUnit + "]");
            return(newPlayUnit);
        }
        /// <summary>
        /// Wait for the previous animation to finish, then play it smoothly.
        /// (If the previously playing animation is a loop animation, it will not be executed.)
        /// </summary>
        /// <param name="animClipName">Name of the Animation Clip</param>
        /// <param name="fadeTime">Fade Time</param>
        /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param>
        /// <param name="blendMethod">How it is blended with the animation of the lower layers</param>
        /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param>
        /// <returns>Animation data to be played. If it fails, null is returned.</returns>
        public apAnimPlayData CrossFadeQueuedAt(apAnimPlayData playData, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false)
        {
            if (playData == null)
            {
                Debug.LogError("CrossFadeQueuedAt Failed : Unknown AnimPlayData");
                return(null);
            }

            if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX)
            {
                Debug.LogError("CrossFadeQueuedAt Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX);
                return(null);
            }

            if (fadeTime < 0.0f)
            {
                fadeTime = 0.0f;
            }

            //Debug.Log("CrossFadeQueued [" + animClipName + "]");

            apAnimPlayQueue playQueue      = _animPlayQueues[layer];
            apAnimPlayUnit  resultPlayUnit = playQueue.PlayQueuedAt(playData, frame, blendMethod, fadeTime, isAutoEndIfNotloop);

            if (resultPlayUnit == null)
            {
                return(null);
            }

            RefreshPlayOrders();

            return(playData);
        }
예제 #21
0
        public override void OnInspectorGUI()
        {
            //return;
            LoadImages();


            //base.OnInspectorGUI();
            apPortrait targetPortrait = target as apPortrait;

            if (targetPortrait != _targetPortrait)
            {
                _targetPortrait = targetPortrait;
                Init();
            }
            if (_targetPortrait == null)
            {
                //Profiler.EndSample();
                return;
            }

            //Profiler.BeginSample("anyPortrait Inspector GUI");


            //return;
            if (apEditor.IsOpen())
            {
                //에디터가 작동중에는 안보이도록 하자
                //EditorGUILayout.LabelField("Editor is opened");
                GUILayout.Space(10);

                EditorGUILayout.LabelField(_guiContent_EditorIsOpen, GUILayout.Height(36));

                //Profiler.EndSample();

                return;
            }

            try
            {
                bool          request_OpenEditor    = false;
                bool          request_QuickBake     = false;
                bool          request_RefreshMeshes = false;
                bool          prevImportant         = _targetPortrait._isImportant;
                MonoBehaviour prevAnimEventListener = _targetPortrait._optAnimEventListener;
                int           prevSortingLayerID    = _targetPortrait._sortingLayerID;
                apPortrait.SORTING_ORDER_OPTION prevSortingOrderOption = _targetPortrait._sortingOrderOption;
                int prevSortingOrder = _targetPortrait._sortingOrder;

                if (!EditorApplication.isPlaying)
                {
                    int iconWidth    = 32;
                    int iconHeight   = 34;
                    int buttonHeight = 34;

                    //추가 19.5.26 : 용량 최적화 기능이 추가되었는가
                    if (!_targetPortrait._isSizeOptimizedV117)
                    {
                        GUILayout.Space(10);

                        Color prevBackColor = GUI.backgroundColor;
                        GUI.backgroundColor = new Color(1.0f, 0.7f, 0.7f, 1.0f);
                        GUILayout.Box("[File size reduction] has not been applied.\nExecute the [Bake] again.",
                                      _guiStyle_subTitle,
                                      GUILayout.Width((int)EditorGUIUtility.currentViewWidth - 36), GUILayout.Height(40));
                        GUI.backgroundColor = prevBackColor;
                    }

                    if (!_targetPortrait._isOptimizedPortrait)
                    {
                        GUILayout.Space(10);

                        EditorGUILayout.BeginHorizontal(GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        EditorGUILayout.LabelField(_guiContent_OpenEditor, _guiStyle_buttonIcon, GUILayout.Width(iconWidth), GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        if (GUILayout.Button("Open Editor and Select", GUILayout.Height(buttonHeight)))
                        {
                            request_OpenEditor = true;
                        }
                        EditorGUILayout.EndHorizontal();

                        EditorGUILayout.BeginHorizontal(GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        EditorGUILayout.LabelField(_guiContent_QuickBake, _guiStyle_buttonIcon, GUILayout.Width(iconWidth), GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        if (GUILayout.Button("Quick Bake", GUILayout.Height(buttonHeight)))
                        {
                            request_QuickBake = true;
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                    else
                    {
                        GUILayout.Space(10);

                        EditorGUILayout.BeginHorizontal(GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        EditorGUILayout.LabelField(_guiContent_OpenEditor, _guiStyle_buttonIcon, GUILayout.Width(iconWidth), GUILayout.Height(iconHeight));
                        GUILayout.Space(5);
                        if (GUILayout.Button("Open Editor (Not Selectable)", GUILayout.Height(buttonHeight)))
                        {
                            //열기만 하고 선택은 못함
                            request_OpenEditor = true;
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                    //추가 12.18 : Mesh를 리프레시 하자

                    EditorGUILayout.BeginHorizontal(GUILayout.Height(iconHeight));
                    GUILayout.Space(5);
                    EditorGUILayout.LabelField(_guiContent_RefreshMeshes, _guiStyle_buttonIcon, GUILayout.Width(iconWidth), GUILayout.Height(iconHeight));
                    GUILayout.Space(5);
                    if (GUILayout.Button("Refresh Meshes", GUILayout.Height(buttonHeight)))
                    {
                        request_RefreshMeshes = true;
                    }
                    EditorGUILayout.EndHorizontal();
                }

                GUILayout.Space(10);


                //BasicSettings
                //-----------------------------------------------------------------------------
                //"Basic Settings"

                int width          = (int)EditorGUIUtility.currentViewWidth;
                int subTitleWidth  = width - 44;
                int subTitleHeight = 26;

                GUILayout.Box(_guiContent_BasicSettings, _guiStyle_subTitle, GUILayout.Width(subTitleWidth), GUILayout.Height(subTitleHeight));


                _targetPortrait._isImportant          = EditorGUILayout.Toggle("Is Important", _targetPortrait._isImportant);
                _targetPortrait._optAnimEventListener = (MonoBehaviour)EditorGUILayout.ObjectField("Event Listener", _targetPortrait._optAnimEventListener, typeof(MonoBehaviour), true);


                GUILayout.Space(5);
                //추가3.22
                //Sorting Layer
                string[] sortingLayerName = new string[SortingLayer.layers.Length];
                int      layerIndex       = -1;
                for (int i = 0; i < SortingLayer.layers.Length; i++)
                {
                    sortingLayerName[i] = SortingLayer.layers[i].name;
                    if (SortingLayer.layers[i].id == _targetPortrait._sortingLayerID)
                    {
                        layerIndex = i;
                    }
                }
                int nextLayerIndex = EditorGUILayout.Popup("Sorting Layer", layerIndex, sortingLayerName);
                apPortrait.SORTING_ORDER_OPTION nextSortingOption = (apPortrait.SORTING_ORDER_OPTION)EditorGUILayout.EnumPopup("Sorting Order Option", _targetPortrait._sortingOrderOption);

                int nextLayerOrder = _targetPortrait._sortingOrder;
                if (_targetPortrait._sortingOrderOption == apPortrait.SORTING_ORDER_OPTION.SetOrder)
                {
                    nextLayerOrder = EditorGUILayout.IntField("Sorting Order", _targetPortrait._sortingOrder);

                    if (nextLayerOrder != _targetPortrait._sortingOrder)
                    {
                        _targetPortrait.SetSortingOrder(nextLayerOrder);
                    }
                }


                if (nextLayerIndex != layerIndex)
                {
                    //Sorting Layer를 바꾸자
                    if (nextLayerIndex >= 0 && nextLayerIndex < SortingLayer.layers.Length)
                    {
                        string nextLayerName = SortingLayer.layers[nextLayerIndex].name;
                        _targetPortrait.SetSortingLayer(nextLayerName);
                    }
                }
                if (nextSortingOption != _targetPortrait._sortingOrderOption)
                {
                    _targetPortrait._sortingOrderOption = nextSortingOption;
                    //변경된 Sorting Order Option에 따라서 바로 Sorting을 해야한다.
                    _targetPortrait.ApplySortingOptionToOptRootUnits();
                    switch (_targetPortrait._sortingOrderOption)
                    {
                    case apPortrait.SORTING_ORDER_OPTION.SetOrder:
                        _targetPortrait.SetSortingOrder(_targetPortrait._sortingOrder);
                        break;

                    case apPortrait.SORTING_ORDER_OPTION.DepthToOrder:
                    case apPortrait.SORTING_ORDER_OPTION.ReverseDepthToOrder:
                        _targetPortrait.SetSortingOrderChangedAutomatically(true);
                        _targetPortrait.RefreshSortingOrderByDepth();
                        break;
                    }
                }



                if (prevImportant != _targetPortrait._isImportant ||
                    prevAnimEventListener != _targetPortrait._optAnimEventListener ||
                    prevSortingLayerID != _targetPortrait._sortingLayerID ||
                    prevSortingOrderOption != _targetPortrait._sortingOrderOption ||
                    prevSortingOrder != _targetPortrait._sortingOrder)
                {
                    apEditorUtil.SetEditorDirty();
                }


                GUILayout.Space(5);

                //빌보드
                apPortrait.BILLBOARD_TYPE nextBillboard = (apPortrait.BILLBOARD_TYPE)EditorGUILayout.EnumPopup("Billboard Type", _targetPortrait._billboardType);
                if (nextBillboard != _targetPortrait._billboardType)
                {
                    _targetPortrait._billboardType = nextBillboard;
                    apEditorUtil.SetEditorDirty();
                }

                GUILayout.Space(20);

                // Root Portraits
                //-----------------------------------------------------------------------------
                GUILayout.Box(_guiContent_RootPortraits, _guiStyle_subTitle, GUILayout.Width(subTitleWidth), GUILayout.Height(subTitleHeight));

                _isFold_RootPortraits = EditorGUILayout.Foldout(_isFold_RootPortraits, "Portraits");
                if (_isFold_RootPortraits)
                {
                    for (int i = 0; i < _targetPortrait._optRootUnitList.Count; i++)
                    {
                        apOptRootUnit rootUnit = _targetPortrait._optRootUnitList[i];
                        EditorGUILayout.ObjectField("[" + i + "]", rootUnit, typeof(apOptRootUnit), true);
                    }
                }

                GUILayout.Space(20);


                // Animation Settings
                //-----------------------------------------------------------------------------

                GUILayout.Box(_guiContent_AnimationSettings, _guiStyle_subTitle, GUILayout.Width(subTitleWidth), GUILayout.Height(subTitleHeight));

                _isFold_AnimationClips = EditorGUILayout.Foldout(_isFold_AnimationClips, "Animation Clips");
                if (_isFold_AnimationClips)
                {
                    for (int i = 0; i < _targetPortrait._animClips.Count; i++)
                    {
                        EditorGUILayout.BeginHorizontal();
                        GUILayout.Space(5);
                        apAnimClip animClip = _targetPortrait._animClips[i];
                        if (animClip._uniqueID == _targetPortrait._autoPlayAnimClipID)
                        {
                            EditorGUILayout.LabelField("[" + i + "] (Auto)", GUILayout.Width(80));
                        }
                        else
                        {
                            EditorGUILayout.LabelField("[" + i + "]", GUILayout.Width(80));
                        }
                        EditorGUILayout.TextField(animClip._name);
                        try
                        {
                            AnimationClip nextAnimationClip = EditorGUILayout.ObjectField(animClip._animationClipForMecanim, typeof(AnimationClip), false) as AnimationClip;
                            if (nextAnimationClip != animClip._animationClipForMecanim)
                            {
                                UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                                Undo.IncrementCurrentGroup();
                                Undo.RegisterCompleteObjectUndo(_targetPortrait, "Animation Changed");

                                animClip._animationClipForMecanim = nextAnimationClip;
                            }
                        }
                        catch (Exception)
                        { }

                        EditorGUILayout.EndHorizontal();
                    }
                }

                GUILayout.Space(10);

                AnimationClip nextEmptyAnimClip = EditorGUILayout.ObjectField("Empty Anim Clip", _targetPortrait._emptyAnimClipForMecanim, typeof(AnimationClip), false) as AnimationClip;
                if (nextEmptyAnimClip != _targetPortrait._emptyAnimClipForMecanim)
                {
                    UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                    Undo.IncrementCurrentGroup();
                    Undo.RegisterCompleteObjectUndo(_targetPortrait, "Animation Changed");

                    _targetPortrait._emptyAnimClipForMecanim = nextEmptyAnimClip;
                }

                GUILayout.Space(10);

                //EditorGUILayout.LabelField("Mecanim Settings");
                EditorGUILayout.LabelField(_guiContent_Mecanim, GUILayout.Height(24));

                bool isNextUsingMecanim = EditorGUILayout.Toggle("Use Mecanim", _targetPortrait._isUsingMecanim);
                if (_targetPortrait._isUsingMecanim != isNextUsingMecanim)
                {
                    UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                    Undo.IncrementCurrentGroup();
                    Undo.RegisterCompleteObjectUndo(_targetPortrait, "Mecanim Setting Changed");

                    _targetPortrait._isUsingMecanim = isNextUsingMecanim;
                }


                if (_targetPortrait._isUsingMecanim)
                {
                    //GUILayout.Space(10);
                    try
                    {
                        Animator nextAnimator = EditorGUILayout.ObjectField("Animator", _targetPortrait._animator, typeof(Animator), true) as Animator;
                        if (nextAnimator != _targetPortrait._animator)
                        {
                            //하위에 있는 Component일 때에만 변동 가능
                            if (nextAnimator == null)
                            {
                                _targetPortrait._animator = null;
                            }
                            else
                            {
                                if (nextAnimator == _targetPortrait.GetComponent <Animator>())
                                {
                                    _targetPortrait._animator = nextAnimator;
                                }
                                else
                                {
                                    EditorUtility.DisplayDialog("Invalid Animator", "Invalid Animator. Only the Animator, which is its own component, is valid.", "Okay");
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                    if (_targetPortrait._animator == null)
                    {
                        //1. Animator가 없다면
                        // > 생성하기
                        // > 생성되어 있다면 다시 링크
                        GUIStyle guiStyle_WarningText = new GUIStyle(GUI.skin.label);
                        guiStyle_WarningText.normal.textColor = Color.red;
                        EditorGUILayout.LabelField("Warning : No Animator!", guiStyle_WarningText);
                        GUILayout.Space(5);

                        if (GUILayout.Button("Add / Check Animator", GUILayout.Height(25)))
                        {
                            UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                            Undo.IncrementCurrentGroup();
                            Undo.RegisterCompleteObjectUndo(_targetPortrait, "Mecanim Setting Changed");

                            Animator animator = _targetPortrait.gameObject.GetComponent <Animator>();
                            if (animator == null)
                            {
                                animator = _targetPortrait.gameObject.AddComponent <Animator>();
                            }
                            _targetPortrait._animator = animator;
                        }
                    }
                    else
                    {
                        //2. Animator가 있다면
                        if (GUILayout.Button("Refresh Layers", GUILayout.Height(25)))
                        {
                            UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                            Undo.IncrementCurrentGroup();
                            Undo.RegisterCompleteObjectUndo(_targetPortrait, "Mecanim Setting Changed");

                            //Animator의 Controller가 있는지 체크해야한다.

                            if (_targetPortrait._animator.runtimeAnimatorController == null)
                            {
                                //AnimatorController가 없다면 Layer는 초기화
                                _targetPortrait._animatorLayerBakedData.Clear();
                            }
                            else
                            {
                                //AnimatorController가 있다면 레이어에 맞게 설정
                                _targetPortrait._animatorLayerBakedData.Clear();
                                UnityEditor.Animations.AnimatorController animatorController = _targetPortrait._animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;

                                if (animatorController != null && animatorController.layers.Length > 0)
                                {
                                    for (int iLayer = 0; iLayer < animatorController.layers.Length; iLayer++)
                                    {
                                        apAnimMecanimData_Layer newLayerData = new apAnimMecanimData_Layer();
                                        newLayerData._layerIndex = iLayer;
                                        newLayerData._layerName  = animatorController.layers[iLayer].name;
                                        newLayerData._blendType  = apAnimMecanimData_Layer.MecanimLayerBlendType.Unknown;
                                        switch (animatorController.layers[iLayer].blendingMode)
                                        {
                                        case UnityEditor.Animations.AnimatorLayerBlendingMode.Override:
                                            newLayerData._blendType = apAnimMecanimData_Layer.MecanimLayerBlendType.Override;
                                            break;

                                        case UnityEditor.Animations.AnimatorLayerBlendingMode.Additive:
                                            newLayerData._blendType = apAnimMecanimData_Layer.MecanimLayerBlendType.Additive;
                                            break;
                                        }

                                        _targetPortrait._animatorLayerBakedData.Add(newLayerData);
                                    }
                                }
                            }
                        }
                        GUILayout.Space(5);
                        EditorGUILayout.LabelField("Animator Controller Layers");
                        for (int i = 0; i < _targetPortrait._animatorLayerBakedData.Count; i++)
                        {
                            apAnimMecanimData_Layer layer = _targetPortrait._animatorLayerBakedData[i];
                            EditorGUILayout.BeginHorizontal();
                            GUILayout.Space(5);
                            EditorGUILayout.LabelField("[" + layer._layerIndex + "]", GUILayout.Width(50));
                            EditorGUILayout.TextField(layer._layerName);
                            apAnimMecanimData_Layer.MecanimLayerBlendType nextBlendType = (apAnimMecanimData_Layer.MecanimLayerBlendType)EditorGUILayout.EnumPopup(layer._blendType);
                            EditorGUILayout.EndHorizontal();

                            if (nextBlendType != layer._blendType)
                            {
                                UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                                Undo.IncrementCurrentGroup();
                                Undo.RegisterCompleteObjectUndo(_targetPortrait, "Mecanim Setting Changed");

                                _targetPortrait._animatorLayerBakedData[i]._blendType = nextBlendType;
                            }
                        }
                    }
                }


                GUILayout.Space(20);


                //추가 3.4 : 타임라인 설정
#if UNITY_2017_1_OR_NEWER
                EditorGUILayout.LabelField(_guiContent_Timeline, GUILayout.Height(24));

                _isFold_Timeline = EditorGUILayout.Foldout(_isFold_Timeline, "Track Data");
                if (_isFold_Timeline)
                {
                    int nextTimelineTracks = EditorGUILayout.DelayedIntField("Size", _nTimelineTrackSet);
                    if (nextTimelineTracks != _nTimelineTrackSet)
                    {
                        //TimelineTrackSet의 개수가 바뀌었다.
                        UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                        Undo.IncrementCurrentGroup();
                        Undo.RegisterCompleteObjectUndo(_targetPortrait, "Track Setting Changed");
                        _nTimelineTrackSet = nextTimelineTracks;
                        if (_nTimelineTrackSet < 0)
                        {
                            _nTimelineTrackSet = 0;
                        }

                        //일단 이전 개수만큼 복사를 한다.
                        int nPrev = 0;
                        List <apPortrait.TimelineTrackPreset> prevSets = new List <apPortrait.TimelineTrackPreset>();
                        if (targetPortrait._timelineTrackSets != null && targetPortrait._timelineTrackSets.Length > 0)
                        {
                            for (int i = 0; i < targetPortrait._timelineTrackSets.Length; i++)
                            {
                                prevSets.Add(targetPortrait._timelineTrackSets[i]);
                            }
                            nPrev = targetPortrait._timelineTrackSets.Length;
                        }

                        //배열을 새로 만들자
                        targetPortrait._timelineTrackSets = new apPortrait.TimelineTrackPreset[_nTimelineTrackSet];

                        //가능한 이전 소스를 복사한다.
                        for (int i = 0; i < _nTimelineTrackSet; i++)
                        {
                            if (i < nPrev)
                            {
                                targetPortrait._timelineTrackSets[i] = new apPortrait.TimelineTrackPreset();
                                targetPortrait._timelineTrackSets[i]._playableDirector = prevSets[i]._playableDirector;
                                targetPortrait._timelineTrackSets[i]._trackName        = prevSets[i]._trackName;
                                targetPortrait._timelineTrackSets[i]._layer            = prevSets[i]._layer;
                                targetPortrait._timelineTrackSets[i]._blendMethod      = prevSets[i]._blendMethod;
                            }
                            else
                            {
                                targetPortrait._timelineTrackSets[i] = new apPortrait.TimelineTrackPreset();
                            }
                        }


                        apEditorUtil.ReleaseGUIFocus();
                    }

                    GUILayout.Space(5);

                    if (targetPortrait._timelineTrackSets != null)
                    {
                        apPortrait.TimelineTrackPreset curTrackSet = null;
                        for (int i = 0; i < targetPortrait._timelineTrackSets.Length; i++)
                        {
                            //트랙을 하나씩 적용
                            curTrackSet = targetPortrait._timelineTrackSets[i];

                            EditorGUILayout.LabelField("[" + i + "] : " + (curTrackSet._playableDirector == null ? "<None>" : curTrackSet._playableDirector.name));
                            PlayableDirector nextDirector  = EditorGUILayout.ObjectField("Director", curTrackSet._playableDirector, typeof(PlayableDirector), true) as PlayableDirector;
                            string           nextTrackName = EditorGUILayout.DelayedTextField("Track Name", curTrackSet._trackName);
                            int nextLayer = EditorGUILayout.DelayedIntField("Layer", curTrackSet._layer);
                            apAnimPlayUnit.BLEND_METHOD nextBlendMethod = (apAnimPlayUnit.BLEND_METHOD)EditorGUILayout.EnumPopup("Blend", curTrackSet._blendMethod);

                            if (nextDirector != curTrackSet._playableDirector ||
                                nextTrackName != curTrackSet._trackName ||
                                nextLayer != curTrackSet._layer ||
                                nextBlendMethod != curTrackSet._blendMethod
                                )
                            {
                                UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
                                Undo.IncrementCurrentGroup();
                                Undo.RegisterCompleteObjectUndo(_targetPortrait, "Track Setting Changed");

                                curTrackSet._playableDirector = nextDirector;
                                curTrackSet._trackName        = nextTrackName;
                                curTrackSet._layer            = nextLayer;
                                curTrackSet._blendMethod      = nextBlendMethod;

                                apEditorUtil.ReleaseGUIFocus();
                            }

                            GUILayout.Space(5);
                        }
                    }
                }

                GUILayout.Space(20);
#endif

                bool isChanged = false;

                // Control Parameters
                //-----------------------------------------------------------------------------

                if (_guiContent_Category == null)
                {
                    _guiContent_Category = apGUIContentWrapper.Make("Category", false);
                }


                GUILayout.Box(_guiContent_ControlParams, _guiStyle_subTitle, GUILayout.Width(subTitleWidth), GUILayout.Height(subTitleHeight));

#if UNITY_2017_3_OR_NEWER
                _curControlCategory = (apControlParam.CATEGORY)EditorGUILayout.EnumFlagsField(_guiContent_Category.Content, _curControlCategory);
#else
                _curControlCategory = (apControlParam.CATEGORY)EditorGUILayout.EnumMaskPopup(_guiContent_Category.Content, _curControlCategory);
#endif

                EditorGUILayout.Space();
                //1. 컨르롤러를 제어할 수 있도록 하자

                if (_controlParams != null)
                {
                    for (int i = 0; i < _controlParams.Count; i++)
                    {
                        if ((int)(_controlParams[i]._category & _curControlCategory) != 0)
                        {
                            if (GUI_ControlParam(_controlParams[i]))
                            {
                                isChanged = true;
                            }
                        }
                    }
                }

                GUILayout.Space(30);

                //2. 토글 버튼을 두어서 기본 Inspector 출력 여부를 결정하자.
                string strBaseButton = "Show All Properties";
                if (_showBaseInspector)
                {
                    strBaseButton = "Hide Properties";
                }

                if (GUILayout.Button(strBaseButton, GUILayout.Height(20)))
                {
                    _showBaseInspector = !_showBaseInspector;
                }

                if (_showBaseInspector)
                {
                    base.OnInspectorGUI();
                }


                if (!Application.isPlaying && isChanged)
                {
                    //플레이 중이라면 자동으로 업데이트 될 것이다.
                    _targetPortrait.UpdateForce();
                }

                if (_targetPortrait != null)
                {
                    if (request_OpenEditor)
                    {
                        if (_targetPortrait._isOptimizedPortrait)
                        {
                            RequestDelayedOpenEditor(_targetPortrait, REQUEST_TYPE.Open);
                        }
                        else
                        {
                            RequestDelayedOpenEditor(_targetPortrait, REQUEST_TYPE.OpenAndSet);
                        }
                        //apEditor anyPortraitEditor = apEditor.ShowWindow();
                        //if (anyPortraitEditor != null && !_targetPortrait._isOptimizedPortrait)
                        //{
                        //	anyPortraitEditor.SetPortraitByInspector(_targetPortrait, false);
                        //}
                    }
                    else if (request_QuickBake)
                    {
                        RequestDelayedOpenEditor(_targetPortrait, REQUEST_TYPE.QuickBake);
                        //apEditor anyPortraitEditor = apEditor.ShowWindow();
                        //if (anyPortraitEditor != null)
                        //{
                        //	anyPortraitEditor.SetPortraitByInspector(_targetPortrait, true);

                        //	Selection.activeObject = _targetPortrait.gameObject;
                        //}
                    }
                    else if (request_RefreshMeshes)
                    {
                        _targetPortrait.OnMeshResetInEditor();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("apInspector_Portrait Exception : " + ex);
            }

            //Profiler.EndSample();
        }
        public apAnimPlayData PlayQueuedAt(string animClipName, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop = false)
        {
            apAnimPlayData playData = GetAnimPlayData_Opt(animClipName);

            if (playData == null)
            {
                Debug.LogError("PlayQueuedAt Failed : No AnimClip [" + animClipName + "]");
                return(null);
            }
            return(PlayQueuedAt(playData, frame, layer, blendMethod, isAutoEndIfNotloop));
        }
예제 #23
0
        // Functions
        //---------------------------------------------
        // 외부 제어 함수들 - 주로 Timeline
#if UNITY_2017_1_OR_NEWER
        public bool AddTimelineTrack(UnityEngine.Playables.PlayableDirector playableDirector, string trackName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
            if (_timlinePlay == null)
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. It is not ready to be associated with the Timeline. Please try again in the next frame.");
                return(false);
            }

            return(_timlinePlay.AddTrack(playableDirector, trackName, layer, blendMethod));
        }
        //추가 3.8 : 타임라인 관련 함수들
        //Timeline이 유니티 2017의 기능이므로 그 전에는 막혀있다.
#if UNITY_2017_1_OR_NEWER
        public bool AddTimelineTrack(UnityEngine.Playables.PlayableDirector playableDirector, string trackName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod)
        {
            if (!_isMecanim)
            {
                Debug.LogError("AnyPortrait : AddTimelineTrack() is Failed. Mecanim is not activated.");
                return(false);
            }
            return(_mecanim.AddTimelineTrack(playableDirector, trackName, layer, blendMethod));
        }
예제 #25
0
        //AnimClip을 PlayUnit에 담아서 재생한다.
        //Queue에 저장된 클립들이 모두 끝나면 블렌드 없이 바로 실행된다.
        public apAnimPlayUnit PlayQueued(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true)
        {
            //현재 재생되는 플레이 유닛 중에서 "가장 많이 남은 플레이 시간"을 기준으로 타이머를 잡자
            //Fade 타임은 없고, 자동 삭제 타이머 + 자동 재생 대기 타이머를 지정

            //현재 Queue에 있는 객체가 없다면 Play와 동일하다

            //수정 :
            //이전에는 Queue 조건을 PlayUnit이 재생되는가..로 판별했다. -> 그러면 Stop 도중의 Unit도 Queue로 인식해버림
            //이젠 이전에 존재하는 Request가 있는지 확인하고 Chain으로 연결한다.
            //Chain 연결시에는 연결된 양쪽이 서로를 알고 있어야 한다.
            //Request가 없는 경우에 한해서 PlayUnit에 연결한다.
            //마지막 연결이
            apAnimPlayRequest lastRequest = null;

            if (_requests_Live.Count > 0)
            {
                //1. Request가 있는 경우/
                //Chain을 시도한다.
                //마지막 Request를 찾는다. (End가 아닌거면 다 됨)

                for (int i = _requests_Live.Count - 1; i >= 0; i--)
                {
                    if (_requests_Live[i].Status != apAnimPlayRequest.STATUS.End)
                    {
                        lastRequest = _requests_Live[i];
                        break;
                    }
                }

                //아직 처리중인 마지막 Request가 있을 때
                //Request 타입과 해당 AnimPlayUnit에 따라
                //1) Chain+Queued을 할지, 2) 그냥 Play를 할 지, 3) 처리를 포기할 지
                //결정을 한다.
                if (lastRequest != null)
                {
                    int chainType = -1;
                    switch (lastRequest.RequestType)
                    {
                    case apAnimPlayRequest.REQUEST_TYPE.New:
                    case apAnimPlayRequest.REQUEST_TYPE.Queued:
                    {
                        //대기 중이거나 재생 중이다.
                        //1. 같은 PlayUnit이라면 -> Loop 타입이라면 취소, Once 타입이라면 Chain 처리
                        //2. Loop 타입이라면 -> 그냥 Play
                        //3. 그외 -> Chain 처리
                        if (lastRequest._nextPlayUnit._linkedAnimClip == playData._linkedAnimClip)
                        {
                            //1. 같은 PlayUnit이다.
                            if (lastRequest._nextPlayUnit.IsLoop)
                            {
                                //Loop 타입이라면 취소
                                chainType = QUEUE_CHAIN__3_SKIP;
                            }
                            else
                            {
                                //Once 타입이라면 Chain 처리
                                //chainType = QUEUE_CHAIN__1_LINK_CHAIN;

                                //변경 : 이미 같은 애니메이션에 대하여 New, Queued가 등록된 요청이다.
                                //처리하지 않는걸로 하자
                                chainType = QUEUE_CHAIN__3_SKIP;
                            }
                        }
                        else if (lastRequest._nextPlayUnit.IsLoop)
                        {
                            //2. 마지막 PlayUnit이 Loop 타입이다.
                            // -> 그냥 Play
                            chainType = QUEUE_CHAIN__2_PLAY;
                        }
                        else
                        {
                            //3. 그외 -> Chain 처리
                            chainType = QUEUE_CHAIN__1_LINK_CHAIN;
                        }
                    }
                    break;

                    case apAnimPlayRequest.REQUEST_TYPE.Stop:
                    {
                        //정지 요청이 있다.
                        //Chain 없이 Play를 시도한다. (Stop 이후이므로)
                        chainType = QUEUE_CHAIN__2_PLAY;
                    }
                    break;
                    }

                    switch (chainType)
                    {
                    case QUEUE_CHAIN__1_LINK_CHAIN:
                    {
                        //Last Unit과 Chain으로 연결한다.
                    }
                    break;

                    case QUEUE_CHAIN__2_PLAY:
                        //Debug.LogError("Play Queued -> 2) Play");
                        return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop));

                    case QUEUE_CHAIN__3_SKIP:
                        //Debug.LogError("Play Queued -> 3) Skip");
                        return(null);
                    }
                }
            }

            apAnimPlayUnit lastPlayUnit = null;

            if (lastRequest != null)
            {
                //Chain 처리가 되었다면
                //-> LastPlayUnit은 Chain된 Request의 PlayUnit으로 삼는다.
                lastPlayUnit = lastRequest._nextPlayUnit;
            }
            else
            {
                //Chain 처리가 안되었을 때
                //마지막 PlayUnit을 비교하여 처리한다.
                //1. 마지막 PlayUnit이 없는 경우 -> 바로 Play
                //2. 마지막 PlayUnit이 Loop 타입이어서 기다릴 수 없는 경우 -> 바로 Play

                if (_nPlayedUnit == 0)
                {
                    //Debug.LogError("현재 남은 PlayUnit이 없으므로 바로 실행 [" + playData._animClipName + "]");
                    return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop));
                }

                //마지막 PlayUnit을 가져오자
                lastPlayUnit = _animPlayUnits[_animPlayUnits.Count - 1];

                if (lastPlayUnit.IsLoop)
                {
                    //만약 마지막 PlayUnit이 Loop라면 => Queued 되지 않는다. 자동으로 [Play]로 바뀜
                    //Debug.LogError("마지막 PlayUnit [" + lastPlayUnit._linkedAnimClip._name + "] 이 Loop 타입이어서 그냥 무시하고 CrossFade로 실행");
                    return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop));
                }
            }

            if (lastPlayUnit != null && lastPlayUnit._linkedAnimClip == playData._linkedAnimClip)
            {
                //Debug.LogError("이미 재생중인 애니메이션이다.");
                return(null);
            }



            //Request를 생성한다.
            apAnimPlayRequest request = PopRequest();

            //request.SetCurrentPlayedUnits(this, _animPlayUnits);
            request.SetCurrentPlayedUnits(this);


            //현재 플레이 중인 AnimPlayUnit들의 LinkKey를 넣어준다.
            for (int i = 0; i < _animPlayUnits.Count; i++)
            {
                request.AddPrevPlayUnitKeyLink(_animPlayUnits[i].LinkKey, _animPlayUnits[i].UnitWeight);
            }

            apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);

            newPlayUnit.Pause();


            //Play Queued 명령을 준다.
            request.PlayQueued(newPlayUnit, lastPlayUnit, blendTime);


            //추가 : Chain 처리를 해주자
            if (lastRequest != null)
            {
                //if(lastRequest._chainedRequest_Next != null)
                //{
                //	Debug.LogError("마지막 Unit을 Chain하려고 했으나 이미 연결되어 있다;;;");
                //}

                //LastRequest.Next <-> Request.Prev

                lastRequest._chainedRequest_Next = request;
                request._chainedRequest_Prev     = lastRequest;
            }



            #region [미사용 코드] 미리 시간을 예상해서 처리하는 것은 문제가 많다.
            //float maxRemainPlayTime = -1.0f;
            //float curRemainPlayTime = 0.0f;
            //bool isAnyOnceAnimClip = false;
            //for (int i = 0; i < _nPlayedUnit; i++)
            //{
            //	_tmpCurPlayUnit = _animPlayUnits[i];
            //	if(_tmpCurPlayUnit.IsLoop)
            //	{
            //		//하나라도 루프이면 실패다.
            //		//Queue에 넣어도 작동하지 않는다.

            //		//>수정
            //		//루프는 무시하고 Queue 시간을 잡자
            //		//만약 Loop를 만나고 Queue가 있다면 그냥 기본값인 0.5초를 Queue 시간으로 쓴다.

            //		//Debug.LogError("PlayQueued Failed : Any Clip has Loop Option. Adding to Queue will be ignored");
            //		//return null;
            //		continue;
            //	}

            //	isAnyOnceAnimClip = true;
            //	curRemainPlayTime = _tmpCurPlayUnit.GetRemainPlayTime;
            //	if(maxRemainPlayTime < curRemainPlayTime)
            //	{
            //		maxRemainPlayTime = curRemainPlayTime;
            //	}
            //}

            //if(!isAnyOnceAnimClip)
            //{
            //	maxRemainPlayTime = 0.5f;
            //}
            //if(maxRemainPlayTime < 0.0f)
            //{
            //	maxRemainPlayTime = 0.0f;
            //}

            ////최대 RemainPlayTime 만큼 Delay한다.
            //// Delay후 신규 플레이 또는 플레이 종료를 한다.
            ////Fade 시간은 0

            //apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);
            //newPlayUnit.Play(0.0f, maxRemainPlayTime);

            ////Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다");

            //for (int i = 0; i < _nPlayedUnit; i++)
            //{
            //	_tmpCurPlayUnit = _animPlayUnits[i];
            //	if (newPlayUnit != _tmpCurPlayUnit)
            //	{
            //		_tmpCurPlayUnit.FadeOut(0.0f, maxRemainPlayTime);
            //	}
            //}
            #endregion

            _nPlayedUnit = _animPlayUnits.Count;

            //Order를 갱신한다.
            RefreshOrder();



            return(newPlayUnit);
        }
예제 #26
0
        /// <summary>
        /// AnimClip을 PlayUnit에 담아서 재생한다.
        /// Queue에 저장된 클립들이 모두 끝나면 블렌드 없이 바로 실행된다.
        /// </summary>
        /// <param name="blendMethod"></param>
        /// <param name="isAutoEndIfNotloop">True이면 Clip의 재생 후 자동으로 종료한다. (Loop일 경우 무시됨)</param>
        /// <returns></returns>
        public apAnimPlayUnit PlayQueued(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true)
        {
            //현재 재생되는 플레이 유닛 중에서 "가장 많이 남은 플레이 시간"을 기준으로 타이머를 잡자
            //Fade 타임은 없고, 자동 삭제 타이머 + 자동 재생 대기 타이머를 지정

            //현재 Queue에 있는 객체가 없다면 Play와 동일하다
            if (_nPlayedUnit == 0)
            {
                return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop));
            }

            //마지막 PlayUnit을 가져오자
            apAnimPlayUnit lastPlayUnit = _animPlayUnits[_animPlayUnits.Count - 1];

            if (lastPlayUnit.IsLoop)
            {
                //만약 마지막 PlayUnit이 Loop라면 => Queued 되지 않는다. 자동으로 [Play]로 바뀜
                return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop));
            }

            //Request를 생성한다.
            apAnimPlayRequest request = PopRequest();

            request.SetCurrentPlayedUnits(this, _animPlayUnits);


            apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);

            newPlayUnit.Pause();

            //Play Queued 명령을 준다.
            request.PlayQueued(newPlayUnit, lastPlayUnit, blendTime);



            #region [미사용 코드] 미리 시간을 예상해서 처리하는 것은 문제가 많다.
            //float maxRemainPlayTime = -1.0f;
            //float curRemainPlayTime = 0.0f;
            //bool isAnyOnceAnimClip = false;
            //for (int i = 0; i < _nPlayedUnit; i++)
            //{
            //	_tmpCurPlayUnit = _animPlayUnits[i];
            //	if(_tmpCurPlayUnit.IsLoop)
            //	{
            //		//하나라도 루프이면 실패다.
            //		//Queue에 넣어도 작동하지 않는다.

            //		//>수정
            //		//루프는 무시하고 Queue 시간을 잡자
            //		//만약 Loop를 만나고 Queue가 있다면 그냥 기본값인 0.5초를 Queue 시간으로 쓴다.

            //		//Debug.LogError("PlayQueued Failed : Any Clip has Loop Option. Adding to Queue will be ignored");
            //		//return null;
            //		continue;
            //	}

            //	isAnyOnceAnimClip = true;
            //	curRemainPlayTime = _tmpCurPlayUnit.GetRemainPlayTime;
            //	if(maxRemainPlayTime < curRemainPlayTime)
            //	{
            //		maxRemainPlayTime = curRemainPlayTime;
            //	}
            //}

            //if(!isAnyOnceAnimClip)
            //{
            //	maxRemainPlayTime = 0.5f;
            //}
            //if(maxRemainPlayTime < 0.0f)
            //{
            //	maxRemainPlayTime = 0.0f;
            //}

            ////최대 RemainPlayTime 만큼 Delay한다.
            //// Delay후 신규 플레이 또는 플레이 종료를 한다.
            ////Fade 시간은 0

            //apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop);
            //newPlayUnit.Play(0.0f, maxRemainPlayTime);

            ////Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다");

            //for (int i = 0; i < _nPlayedUnit; i++)
            //{
            //	_tmpCurPlayUnit = _animPlayUnits[i];
            //	if (newPlayUnit != _tmpCurPlayUnit)
            //	{
            //		_tmpCurPlayUnit.FadeOut(0.0f, maxRemainPlayTime);
            //	}
            //}
            #endregion

            _nPlayedUnit = _animPlayUnits.Count;

            return(newPlayUnit);
        }
        /// <summary>
        /// [Editor] 업데이트 중 Control Param 제어 Timeline에 대해 업데이트 후 적용을 한다.
        /// [Runtime] isAdaptToWeight = false로 두고 나머지 처리를 한다.
        /// </summary>
        /// <param name="isAdaptToWeight1">[Editor]에서 Weight=1로 두고 적용을 한다</param>
        public void UpdateControlParam(bool isAdaptToWeight1, int optLayer = 0, float optWeight = 1.0f, apAnimPlayUnit.BLEND_METHOD optBlendMethod = apAnimPlayUnit.BLEND_METHOD.Interpolation)
        {
            if (_controlParamResult.Count == 0)
            {
                return;
            }

            for (int i = 0; i < _controlParamResult.Count; i++)
            {
                _controlParamResult[i].Init();
            }

            apAnimTimeline      timeline = null;
            apAnimTimelineLayer layer    = null;

            int   curFrame  = CurFrame;
            float curFrameF = CurFrameFloat;

            //apAnimKeyframe firstKeyframe = null;
            //apAnimKeyframe lastKeyframe = null;

            apAnimKeyframe curKeyframe  = null;
            apAnimKeyframe prevKeyframe = null;
            apAnimKeyframe nextKeyframe = null;

            int lengthFrames = _endFrame - _startFrame;
            int tmpCurFrame  = 0;

            apAnimControlParamResult cpResult = null;

            for (int iTL = 0; iTL < _timelines.Count; iTL++)
            {
                timeline = _timelines[iTL];
                if (timeline._linkType != LINK_TYPE.ControlParam)
                {
                    continue;
                }

                for (int iL = 0; iL < timeline._layers.Count; iL++)
                {
                    layer = timeline._layers[iL];
                    if (layer._linkedControlParam == null || layer._linkedControlParamResult == null)
                    {
                        continue;
                    }

                    cpResult = layer._linkedControlParamResult;

                    //firstKeyframe = layer._firstKeyFrame;
                    //lastKeyframe = layer._lastKeyFrame;

                    for (int iK = 0; iK < layer._keyframes.Count; iK++)
                    {
                        curKeyframe  = layer._keyframes[iK];
                        prevKeyframe = curKeyframe._prevLinkedKeyframe;
                        nextKeyframe = curKeyframe._nextLinkedKeyframe;

                        if (curFrame == curKeyframe._frameIndex ||
                            ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curKeyframe._loopFrameIndex == curFrame)
                            )
                        {
                            cpResult.SetKeyframeResult(curKeyframe, 1.0f);
                        }
                        else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Prev))
                        {
                            //Prev - Cur 범위 안에 들었다.
                            if (prevKeyframe != null)
                            {
                                //Prev 키가 있다면
                                tmpCurFrame = curFrame;
                                if (tmpCurFrame > curKeyframe._frameIndex)
                                {
                                    //한바퀴 돌았다면
                                    tmpCurFrame -= lengthFrames;
                                }

                                //TODO : 여길 나중에 "정식 Curve로 변경"할 것
                                //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, prevKeyframe._curveKey, tmpCurFrame, true);

                                //>> 변경
                                float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, true);

                                cpResult.SetKeyframeResult(curKeyframe, itp);
                            }
                            else
                            {
                                //Prev 키가 없다면 이게 100%다
                                cpResult.SetKeyframeResult(curKeyframe, 1.0f);
                            }
                        }
                        else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Next))
                        {
                            //Cur - Next 범위 안에 들었다.
                            if (nextKeyframe != null)
                            {
                                //Next 키가 있다면
                                tmpCurFrame = curFrame;
                                if (tmpCurFrame < curKeyframe._frameIndex)
                                {
                                    //한바퀴 돌았다면
                                    tmpCurFrame += lengthFrames;
                                }

                                //TODO : 여길 나중에 "정식 Curve로 변경"할 것
                                //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, tmpCurFrame, false);

                                //>> 변경
                                float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, false);

                                cpResult.SetKeyframeResult(curKeyframe, itp);
                            }
                            else
                            {
                                //Prev 키가 없다면 이게 100%다
                                cpResult.SetKeyframeResult(curKeyframe, 1.0f);
                            }
                        }
                    }
                }
            }


            //Control Param에 적용을 해야한다.
            if (isAdaptToWeight1)
            {
                //Editor인 경우 Weight 1로 강제한다.
                for (int i = 0; i < _controlParamResult.Count; i++)
                {
                    _controlParamResult[i].AdaptToControlParam();
                }
            }
            else
            {
                //Runtime인 경우 지정된 Weight, Layer로 처리한다.
                for (int i = 0; i < _controlParamResult.Count; i++)
                {
                    //Debug.Log("AnimClip [" + _name + " > Control Param : " + _controlParamResult[i]._targetControlParam._keyName + " ]");
                    _controlParamResult[i].AdaptToControlParam_Opt(optWeight, optBlendMethod);
                }
            }
        }
            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);
            }