// [런타임에서] Portrait를 연결하고, Portrait를 검색하여 animPlayData를 세팅한다. // 다른 Link가 모두 끝난뒤에 호출하자 /// <summary> /// Connect to Portrait and initialize it for runtime processing. /// </summary> /// <param name="portrait"></param> public void LinkPortrait(apPortrait portrait) { _portrait = portrait; InitAndLink(); if (_animPlayDataList == null) { _animPlayDataList = new List <apAnimPlayData>(); } apAnimPlayData animPlayData = null; for (int i = 0; i < _animPlayDataList.Count; i++) { animPlayData = _animPlayDataList[i]; animPlayData._isValid = false; //일단 유효성 초기화 (나중에 값 넣으면 자동으로 true) apAnimClip animClip = _portrait.GetAnimClip(animPlayData._animClipID); apOptRootUnit rootUnit = _portrait._optRootUnitList.Find(delegate(apOptRootUnit a) { if (a._rootOptTransform != null) { if (a._rootOptTransform._meshGroupUniqueID == animPlayData._meshGroupID) { return(true); } } return(false); }); if (animClip != null && rootUnit != null) { animPlayData.Link(animClip, rootUnit); //추가 : 여기서 ControlParamResult를 미리 만들어서 이후에 AnimClip이 미리 만들수 있게 해주자 animClip.MakeAndLinkControlParamResults(); } } //추가 : 메카님 연동 _mecanim.LinkPortrait(portrait, this); if (portrait._isUsingMecanim && portrait._animator != null) { _isMecanim = true; } else { _isMecanim = false; } }
public apAnimPlayUnit _playUnit = null; //<<미리 만들어놓고, 실행중일 때에는 연결, 그렇지 않을 때에는 해제한다. public MecanimClipData(AnimationClip clipAsset, apAnimClip animClip, apOptRootUnit linkedRootUnit) { _clipAsset = clipAsset; _animClip = animClip; _linkedRootUnit = linkedRootUnit; //Mecanim용 PlayUnit을 만든다. _playUnit = new apAnimPlayUnit(null, -1, -1); _playUnit.SetMecanimPlayUnit(); _isCalculatedPrev = false; ReadyToUpdate(); Unlink(); }
/// <summary> /// Set Playing Root Unit. /// </summary> /// <param name="rootUnit"></param> public void SetOptRootUnit(apOptRootUnit rootUnit) { //Debug.LogError("SetOptRootUnit [" + rootUnit.transform.name + "]"); if (_curPlayedRootUnit != rootUnit) { _curPlayedRootUnit = rootUnit; _portrait.ShowRootUnit(_curPlayedRootUnit); //AnimQueue를 돌면서 해당 RootUnit이 아닌 PlayUnit은 강제 종료한다. for (int i = 0; i < _animPlayQueues.Count; i++) { _animPlayQueues[i].StopWithInvalidRootUnit(_curPlayedRootUnit); } } }
public TimelineClipData( #if UNITY_2017_1_OR_NEWER TimelineClip timelineClip, #endif apAnimClip animClip, apOptRootUnit linkedRootUnit) { #if UNITY_2017_1_OR_NEWER _timelineClip = timelineClip; _clipAsset = timelineClip.animationClip; #endif _animClip = animClip; _linkedRootUnit = linkedRootUnit; _isCalculated = false; _isCalculatedPrev = false; _isPlaying = false; //Mecanim용 PlayUnit을 만든다. _playUnit = new apAnimPlayUnit(null, -1, -1); _playUnit.SetMecanimPlayUnit(); ReadyToUpdate(); Unlink(); }
public override void OnInspectorGUI() { //return; //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"); //Profiler.EndSample(); return; } try { bool prevImportant = _targetPortrait._isImportant; MonoBehaviour prevAnimEventListener = _targetPortrait._optAnimEventListener; int prevSortingLayerID = _targetPortrait._sortingLayerID; int prevSortingOrder = _targetPortrait._sortingOrder; _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); int nextLayerOrder = EditorGUILayout.IntField("Sorting Order", _targetPortrait._sortingOrder); if (nextLayerIndex != layerIndex) { //Sorting Layer를 바꾸자 if (nextLayerIndex >= 0 && nextLayerIndex < SortingLayer.layers.Length) { string nextLayerName = SortingLayer.layers[nextLayerIndex].name; _targetPortrait.SetSortingLayer(nextLayerName); } } if (nextLayerOrder != _targetPortrait._sortingOrder) { _targetPortrait.SetSortingOrder(nextLayerOrder); } if (prevImportant != _targetPortrait._isImportant || prevAnimEventListener != _targetPortrait._optAnimEventListener || prevSortingLayerID != _targetPortrait._sortingLayerID || prevSortingOrder != _targetPortrait._sortingOrder) { apEditorUtil.SetEditorDirty(); } GUILayout.Space(5); _isFold_RootPortraits = EditorGUILayout.Foldout(_isFold_RootPortraits, "Root Portraits"); if (_isFold_RootPortraits) { string strRootPortrait = ""; if (_targetPortrait._optRootUnitList.Count == 0) { strRootPortrait = "No Baked Portrait"; } else if (_targetPortrait._optRootUnitList.Count == 1) { strRootPortrait = "1 Baked Portrait"; } else { strRootPortrait = _targetPortrait._optRootUnitList.Count + " Baked Portraits"; } EditorGUILayout.LabelField(strRootPortrait); GUILayout.Space(5); for (int i = 0; i < _targetPortrait._optRootUnitList.Count; i++) { apOptRootUnit rootUnit = _targetPortrait._optRootUnitList[i]; EditorGUILayout.ObjectField("[" + i + "]", rootUnit, typeof(apOptRootUnit), true); } GUILayout.Space(20); } _isFold_AnimationClips = EditorGUILayout.Foldout(_isFold_AnimationClips, "Animation Clips"); if (_isFold_AnimationClips) { string strAnimClips = ""; if (_targetPortrait._animClips.Count == 0) { strAnimClips = "No Animation Clip"; } else if (_targetPortrait._animClips.Count == 1) { strAnimClips = "1 Animation Clip"; } else { strAnimClips = _targetPortrait._animClips.Count + " Animation Clips"; } EditorGUILayout.LabelField(strAnimClips); GUILayout.Space(5); for (int i = 0; i < _targetPortrait._animClips.Count; i++) { apAnimClip animClip = _targetPortrait._animClips[i]; if (animClip._uniqueID == _targetPortrait._autoPlayAnimClipID) { EditorGUILayout.TextField("[" + i + "] (Auto Play)", animClip._name); } else { EditorGUILayout.TextField("[" + i + "]", animClip._name); } } GUILayout.Space(20); } bool isChanged = false; _isFold_ConrolParameters = EditorGUILayout.Foldout(_isFold_ConrolParameters, "Control Parameters"); if (_isFold_ConrolParameters) { #if UNITY_2017_3_OR_NEWER _curControlCategory = (apControlParam.CATEGORY)EditorGUILayout.EnumFlagsField(new GUIContent("Category"), _curControlCategory); #else _curControlCategory = (apControlParam.CATEGORY)EditorGUILayout.EnumMaskPopup(new GUIContent("Category"), _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(20); } GUILayout.Space(10); //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(); } } catch (Exception ex) { Debug.LogError("apInspector_Portrait Exception : " + ex); } //Profiler.EndSample(); }
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 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); }