// [런타임에서] Portrait를 연결하고, Portrait를 검색하여 animPlayData를 세팅한다. // 다른 Link가 모두 끝난뒤에 호출하자 /// <summary> /// Connect to Portrait and initialize it for runtime processing. /// </summary> /// <param name="portrait"></param> public IEnumerator LinkPortraitAsync(apPortrait portrait, apAsyncTimer asyncTimer) { _portrait = portrait; InitAndLink(); //Async Wait if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } 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(); } //Async Wait if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } } //추가 : 메카님 연동 _mecanim.LinkPortrait(portrait, this); //Async Wait if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } if (portrait._isUsingMecanim && portrait._animator != null) { _isMecanim = true; } else { _isMecanim = false; } }
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(); }
/// <summary> /// GIF Animation을 만든다. /// </summary> /// <param name="filePath"></param> /// <param name="meshGroup"></param> /// <param name="animClip"></param> /// <param name="loopCount"></param> /// <param name="winPosX"></param> /// <param name="winPosY"></param> /// <param name="srcSizeWidth"></param> /// <param name="srcSizeHeight"></param> /// <param name="dstSizeWidth"></param> /// <param name="dstSizeHeight"></param> /// <param name="clearColor"></param> /// <param name="quality">1 ~ 256</param> /// <returns></returns> public bool MakeGIFAnimation(string filePath, apMeshGroup meshGroup, apAnimClip animClip, int loopCount, int winPosX, int winPosY, int srcSizeWidth, int srcSizeHeight, int dstSizeWidth, int dstSizeHeight, Color clearColor, int quality) { if (_editor == null || _editor._portrait == null || meshGroup == null || animClip == null) { return(false); } int startFrame = animClip.StartFrame; int endFrame = animClip.EndFrame; if (endFrame < startFrame) { endFrame = startFrame; } if (loopCount < 1) { loopCount = 1; } //모든 AnimClip 정지 for (int i = 0; i < _editor._portrait._animClips.Count; i++) { _editor._portrait._animClips[i].Stop_Editor(); } _editor._portrait._animPlayManager.Stop_Editor(); _editor._portrait._animPlayManager.SetAnimClip_Editor(animClip); meshGroup.RefreshForce(); int curFrame = startFrame; bool isLoop = animClip.IsLoop; //Loop라면 마지막 프레임을 생략한다. int lastFrame = endFrame; if (isLoop) { lastFrame = endFrame - 1; } if (lastFrame < startFrame) { lastFrame = startFrame; } float secPerFrame = 1.0f / (float)animClip.FPS; FileStream fs = null; try { fs = new FileStream(filePath, FileMode.Create, FileAccess.Write); _ngif.WriteHeader(fs); _ngif.SetGIFSetting((int)((secPerFrame * 100.0f) + 0.5f), 0, dstSizeWidth, dstSizeHeight); //WriteString("GIF89a", fs); // header //_gifDelay = (int)((secPerFrame * 100.0f) + 0.5f);//Delay //_gifRepeatCount = 0;//반복 //_gifWidth = dstSizeWidth; //_gifHeight = dstSizeHeight; //_gifPixels = null; //_gifIndexedPixels = null; //_gifColorDepth = 0; //_gifColorTab = null; //_gifPalSize = 7; //for (int i = 0; i < _gifUsedEntry.Length; i++) //{ // _gifUsedEntry[i] = false; //} bool isFirstFrame = true; //애니메이션을 돌면서 Bake를 한다. for (int iLoop = 0; iLoop < loopCount; iLoop++) { curFrame = startFrame; while (true) { animClip.SetFrame_Editor(curFrame); //메시가 자동으로 업데이트를 한다. meshGroup.UpdateRenderUnits(secPerFrame, true); Texture2D bakeImage = RenderToTexture(meshGroup, winPosX, winPosY, srcSizeWidth, srcSizeHeight, dstSizeWidth, dstSizeHeight, clearColor); _ngif.AddFrame(bakeImage, fs, isFirstFrame, quality); isFirstFrame = false; UnityEngine.Object.DestroyImmediate(bakeImage); curFrame++; if (curFrame > lastFrame) { break; } } } _ngif.Finish(fs); fs.Close(); fs = null; return(true); } catch (Exception ex) { Debug.LogError("GIF Exception : " + ex); } if (fs != null) { fs.Close(); fs = null; } return(false); }
// Functions //--------------------------------------------- public void ResetAllUnits() { _isNeedReset = false; _units_All.Clear(); _units_Root.Clear(); //메인 루트들을 만들어주자 //_rootUnit_Overall = AddUnit_OnlyButton(null, "Portrait", CATEGORY.Overall_Name, null, true, null); _rootUnit_Overall = AddUnit_Label(null, Editor.GetUIWord(UIWORD.RootUnits), CATEGORY.Overall_Name, null, true, null); _rootUnit_Image = AddUnit_Label(null, Editor.GetUIWord(UIWORD.Images), CATEGORY.Images_Name, null, true, null); _rootUnit_Mesh = AddUnit_Label(null, Editor.GetUIWord(UIWORD.Meshes), CATEGORY.Mesh_Name, null, true, null); _rootUnit_MeshGroup = AddUnit_Label(null, Editor.GetUIWord(UIWORD.MeshGroups), CATEGORY.MeshGroup_Name, null, true, null); //_rootUnit_Face = AddUnit_Label(null, "Faces", CATEGORY.Face_Name, null, true, null); _rootUnit_Animation = AddUnit_Label(null, Editor.GetUIWord(UIWORD.AnimationClips), CATEGORY.Animation_Name, null, true, null); _rootUnit_Param = AddUnit_Label(null, Editor.GetUIWord(UIWORD.ControlParameters), CATEGORY.Param_Name, null, true, null); if (Editor == null || Editor._portrait == null) { return; } List <apRootUnit> rootUnits = Editor._portrait._rootUnits; for (int i = 0; i < rootUnits.Count; i++) { apRootUnit rootUnit = rootUnits[i]; AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Root), "Root Unit " + i, CATEGORY.Overall_Item, rootUnit, false, _rootUnit_Overall); } //1. 이미지 파일들을 검색하자 List <apTextureData> textures = Editor._portrait._textureData; for (int i = 0; i < textures.Count; i++) { apTextureData textureData = textures[i]; AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Image), textureData._name, CATEGORY.Images_Item, textureData, false, _rootUnit_Image); } AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Add), Editor.GetUIWord(UIWORD.AddImage), CATEGORY.Images_Add, null, false, _rootUnit_Image); AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_AddPSD), Editor.GetUIWord(UIWORD.ImportPSDFile), CATEGORY.Images_AddPSD, null, false, _rootUnit_Image); //추가 : PSD //2. 메시 들을 검색하자 List <apMesh> meshes = Editor._portrait._meshes; for (int i = 0; i < meshes.Count; i++) { apMesh mesh = meshes[i]; AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh), mesh._name, CATEGORY.Mesh_Item, mesh, false, _rootUnit_Mesh); } AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Add), Editor.GetUIWord(UIWORD.AddMesh), CATEGORY.Mesh_Add, null, false, _rootUnit_Mesh); //3. 메시 그룹들을 검색하자 //메시 그룹들은 하위에 또다른 Mesh Group을 가지고 있다. List <apMeshGroup> meshGroups = Editor._portrait._meshGroups; for (int i = 0; i < meshGroups.Count; i++) { apMeshGroup meshGroup = meshGroups[i]; if (meshGroup._parentMeshGroup == null || meshGroup._parentMeshGroupID < 0) { //Debug.Log("Reset H : MeshGroup(" + meshGroup._name + ") - Root"); apEditorHierarchyUnit addedHierarchyUnit = AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_MeshGroup), meshGroup._name, CATEGORY.MeshGroup_Item, meshGroup, false, _rootUnit_MeshGroup); if (meshGroup._childMeshGroupTransforms.Count > 0) { AddUnit_SubMeshGroup(meshGroup, addedHierarchyUnit); } } else { //Debug.Log("Reset H : MeshGroup(" + meshGroup._name + ") - Child"); } } AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Add), Editor.GetUIWord(UIWORD.AddMeshGroup), CATEGORY.MeshGroup_Add, null, false, _rootUnit_MeshGroup); //7. 파라미터들을 검색하자 List <apControlParam> cParams = Editor.ParamControl._controlParams; for (int i = 0; i < cParams.Count; i++) { apControlParam cParam = cParams[i]; AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Param), cParam._keyName, CATEGORY.Param_Item, cParam, false, _rootUnit_Param); } AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Add), Editor.GetUIWord(UIWORD.AddControlParameter), CATEGORY.Param_Add, null, false, _rootUnit_Param); //8. 애니메이션을 넣자 List <apAnimClip> animClips = Editor._portrait._animClips; for (int i = 0; i < animClips.Count; i++) { apAnimClip animClip = animClips[i]; AddUnit_ToggleButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Animation), animClip._name, CATEGORY.Animation_Item, animClip, false, _rootUnit_Animation); } AddUnit_OnlyButton(Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Add), Editor.GetUIWord(UIWORD.AddAnimationClip), CATEGORY.Animation_Add, null, false, _rootUnit_Animation); }
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(); }
/// <summary> /// AnimTimeline을 선택하고, 그 안의 AnimTimeLayer를 모두 활성화한다. /// 일반적으로 [선택하지 않은 AnimTimeline]들을 모두 해제하는 반면에, /// 여기서는 해당 ParamSetGroup에 연동된 AnimTimeline이 AnimClip에 포함된다면 모두 포함시킨다. /// </summary> /// <param name="modifier"></param> /// <param name="paramSetGroups"></param> public void SetExclusiveModifierInEditing_MultipleParamSetGroup_General(apModifierBase modifier, apAnimClip targetAnimClip) { //apCalculatedResultParam.RESULT_TYPE targetResultType = modifier.CalculatedResultType; //추가 //요청한 Modifier가 BoneTransform을 지원하는 경우 //Rigging은 비활성화 되어서는 안된다. apModifierBase.MODIFIER_TYPE[] exGeneralTypes = modifier.GetGeneralExEditableModTypes(); if (exGeneralTypes == null) { exGeneralTypes = new apModifierBase.MODIFIER_TYPE[] { modifier.ModifierType }; } for (int i = 0; i < _modifiers.Count; i++) { bool isValidType = false; for (int iGT = 0; iGT < exGeneralTypes.Length; iGT++) { if (exGeneralTypes[iGT] == _modifiers[i].ModifierType) { isValidType = true; break; } } if (isValidType) { //AnimClip을 포함하는 ParamSetGroup에 한해서 _modifiers[i]._editorExclusiveActiveMod = apModifierBase.MOD_EDITOR_ACTIVE.ExclusiveEnabled; for (int iP = 0; iP < _modifiers[i]._paramSetGroup_controller.Count; iP++) { apModifierParamSetGroup paramSetGroup = _modifiers[i]._paramSetGroup_controller[iP]; if (paramSetGroup._keyAnimClip == targetAnimClip) { paramSetGroup._isEnabledExclusive = true; } else { paramSetGroup._isEnabledExclusive = false; } } } else { //지원하는 타입이 아니다. //모두 Disabled한다. _modifiers[i]._editorExclusiveActiveMod = apModifierBase.MOD_EDITOR_ACTIVE.Disabled; for (int iP = 0; iP < _modifiers[i]._paramSetGroup_controller.Count; iP++) { apModifierParamSetGroup paramSetGroup = _modifiers[i]._paramSetGroup_controller[iP]; paramSetGroup._isEnabledExclusive = false; } } } //Child MeshGroup에도 모두 적용하자 if (_parentMeshGroup != null) { if (_parentMeshGroup._childMeshGroupTransforms != null) { for (int i = 0; i < _parentMeshGroup._childMeshGroupTransforms.Count; i++) { apTransform_MeshGroup meshGroupTransform = _parentMeshGroup._childMeshGroupTransforms[i]; if (meshGroupTransform._meshGroup != null && meshGroupTransform._meshGroup != _parentMeshGroup) { meshGroupTransform._meshGroup._modifierStack.SetExclusiveModifierInEditing_MultipleParamSetGroup_General(modifier, targetAnimClip); } } } } }
// Refresh (without Reset) //----------------------------------------------------------------------------------------- public void RefreshUnits() { if (Editor == null || Editor._portrait == null || _isNeedReset) { ResetAllUnits(); return; } List <apEditorHierarchyUnit> deletedUnits = new List <apEditorHierarchyUnit>(); //0. 루트 유닛들을 검색하자 List <apRootUnit> rootUnits = Editor._portrait._rootUnits; for (int i = 0; i < rootUnits.Count; i++) { apRootUnit rootUnit = Editor._portrait._rootUnits[i]; RefreshUnit(CATEGORY.Overall_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Root), rootUnit, "Root Unit " + i, Editor.Select.RootUnit, _rootUnit_Overall); } CheckRemovableUnits <apRootUnit>(deletedUnits, CATEGORY.Overall_Item, rootUnits); //1. 이미지 파일들을 검색하자 -> 있는건 없애고, 없는건 만들자 List <apTextureData> textures = Editor._portrait._textureData; for (int i = 0; i < textures.Count; i++) { apTextureData textureData = textures[i]; RefreshUnit(CATEGORY.Images_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Image), textureData, textureData._name, Editor.Select.TextureData, _rootUnit_Image); } CheckRemovableUnits <apTextureData>(deletedUnits, CATEGORY.Images_Item, textures); //2. 메시 들을 검색하자 List <apMesh> meshes = Editor._portrait._meshes; for (int i = 0; i < meshes.Count; i++) { apMesh mesh = meshes[i]; RefreshUnit(CATEGORY.Mesh_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh), mesh, mesh._name, Editor.Select.Mesh, _rootUnit_Mesh); } CheckRemovableUnits <apMesh>(deletedUnits, CATEGORY.Mesh_Item, meshes); //3. Mesh Group들을 검색하자 List <apMeshGroup> meshGroups = Editor._portrait._meshGroups; for (int i = 0; i < meshGroups.Count; i++) { //이건 재귀 함수 -_-; if (meshGroups[i]._parentMeshGroup == null) { RefreshUnit_MeshGroup(meshGroups[i], _rootUnit_MeshGroup); } } CheckRemovableUnits <apMeshGroup>(deletedUnits, CATEGORY.MeshGroup_Item, meshGroups); //7. 파라미터들을 검색하자 List <apControlParam> cParams = Editor.ParamControl._controlParams; for (int i = 0; i < cParams.Count; i++) { apControlParam cParam = cParams[i]; RefreshUnit(CATEGORY.Param_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Param), cParam, cParam._keyName, Editor.Select.Param, _rootUnit_Param); CheckRemovableUnits <apControlParam>(deletedUnits, CATEGORY.Param_Item, cParams); } //8. 애니메이션을 넣자 List <apAnimClip> animClips = Editor._portrait._animClips; for (int i = 0; i < animClips.Count; i++) { apAnimClip animClip = animClips[i]; RefreshUnit(CATEGORY.Animation_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Animation), animClip, animClip._name, Editor.Select.AnimClip, _rootUnit_Animation); CheckRemovableUnits <apAnimClip>(deletedUnits, CATEGORY.Animation_Item, animClips); } //삭제할 유닛을 체크하고 계산하자 for (int i = 0; i < deletedUnits.Count; i++) { //1. 먼저 All에서 없앤다. //2. Parent가 있는경우, Parent에서 없애달라고 한다. apEditorHierarchyUnit dUnit = deletedUnits[i]; if (dUnit._parentUnit != null) { dUnit._parentUnit._childUnits.Remove(dUnit); } _units_All.Remove(dUnit); } //전체 Sort를 한다. //재귀적으로 실행 for (int i = 0; i < _units_Root.Count; i++) { SortUnit_Recv(_units_Root[i]); } }
public void LinkPortrait(apPortrait portrait, apAnimPlayManager animPlayManager) { _portrait = portrait; _animPlayManager = animPlayManager; _animator = _portrait._animator; _animController = null; _isValidAnimator = false; if (_animator == null) { //Debug.LogError("No Animator"); return; } _animController = _animator.runtimeAnimatorController; if (_animController == null) { Debug.LogError("AnyPortrait : No RuntimeAnimatorController on Animator"); return; } _isValidAnimator = true; _layers.Clear(); _clipData.Clear(); _clipDataByAsset.Clear(); _clipDataByAnimClip.Clear(); //레이어 정보를 담자 _nLayers = _animator.layerCount; //저장된 AnimClip 체크를 위해서 리스트를 만들자 //유효하지 않은 AnimClip은 제외해야한다. List <AnimationClip> allClips = new List <AnimationClip>(); List <AnimationClip> validClips = new List <AnimationClip>(); for (int iLayer = 0; iLayer < _animator.layerCount; iLayer++) { MecanimLayer newLayer = new MecanimLayer(); newLayer._index = iLayer; newLayer._blendType = apAnimPlayUnit.BLEND_METHOD.Interpolation; if (iLayer < portrait._animatorLayerBakedData.Count) { if (portrait._animatorLayerBakedData[iLayer]._blendType == apAnimMecanimData_Layer.MecanimLayerBlendType.Additive) { //미리 설정된 데이터가 있고, Additive라면 Additive로 설정 newLayer._blendType = apAnimPlayUnit.BLEND_METHOD.Additive; } } _layers.Add(newLayer); } //어떤 AnimClip이 있는지 체크하자 for (int i = 0; i < _animController.animationClips.Length; i++) { if (!allClips.Contains(_animController.animationClips[i])) { allClips.Add(_animController.animationClips[i]); } } //apAnimClip <-> AnimationClip Asset을 서로 연결하자 _animClip2Asset.Clear(); _asset2AnimClip.Clear(); //Debug.Log("animPlayManager._animPlayDataList Count : " + animPlayManager._animPlayDataList.Count); for (int i = 0; i < animPlayManager._animPlayDataList.Count; i++) { apAnimPlayData playData = animPlayManager._animPlayDataList[i]; //Debug.Log("[" + i + "] : " + playData._animClipName); apAnimClip animClip = playData._linkedAnimClip; if (animClip == null) { //Debug.LogError("[" + i + "] : " + playData._animClipName + " >> Linked Anim Clip is Null"); continue; } AnimationClip assetClip = animClip._animationClipForMecanim; if (assetClip != null) { _animClip2Asset.Add(animClip, assetClip); _asset2AnimClip.Add(assetClip, animClip); MecanimClipData newClipData = new MecanimClipData(assetClip, animClip, playData._linkedOptRootUnit); _clipData.Add(newClipData); _clipDataByAsset.Add(assetClip, newClipData); _clipDataByAnimClip.Add(animClip, newClipData); if (!validClips.Contains(assetClip)) { validClips.Add(assetClip); } //Debug.Log("[" + i + "] : " + playData._animClipName + " >> " + assetClip.name); } else { if (Application.isPlaying) { Debug.LogError("[" + i + "] : " + playData._animClipName + " >> AnimAsset is Null"); } } } _nClipData = _clipData.Count; //여기서 유효성 체크 //(유효성 체크는 Application 실행 시에) //if (Application.isPlaying) { for (int i = 0; i < allClips.Count; i++) { if (!validClips.Contains(allClips[i])) { if (allClips[i] != _portrait._emptyAnimClipForMecanim) { //유효하지 않은 Clip이 발견되었다. Debug.LogError("AnyPortrait : ( Caution! ) Contains an invalid AnimationClip. An error may occur when playing. [" + allClips[i].name + " < " + _portrait.gameObject.name + "]"); Debug.LogError("Valid Clips : " + validClips.Count); } } } } }
// Show Window / Close Dialog //------------------------------------------------------------------------ public static object ShowDialog(FUNC_RETARGET_SINGLE_POSE_IMPORT_ANIM funcResult_Anim, apEditor editor, apMeshGroup targetMeshGroup, apAnimClip targetAnimClip, apAnimTimeline targetAnimTimeline, int targetFrame) { return(ShowDialog(funcResult_Anim, null, editor, targetMeshGroup, null, null, targetAnimClip, targetAnimTimeline, targetFrame)); }
// Refresh (without Reset) //----------------------------------------------------------------------------------------- public void RefreshUnits() { if (Editor == null || Editor._portrait == null || _isNeedReset) { ResetAllUnits(); return; } ReloadGUIContent(); List <apEditorHierarchyUnit> deletedUnits = new List <apEditorHierarchyUnit>(); //0. 루트 유닛들을 검색하자 //이전 //List<apRootUnit> rootUnits = Editor._portrait._rootUnits; //변경 List <apObjectOrders.OrderSet> rootUnitSets = Editor._portrait._objectOrders.RootUnits; for (int i = 0; i < rootUnitSets.Count; i++) { //이전 //apRootUnit rootUnit = Editor._portrait._rootUnits[i]; //변경 apRootUnit rootUnit = rootUnitSets[i]._linked_RootUnit; RefreshUnit(CATEGORY.Overall_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Root), rootUnit, "Root Unit " + i + " (" + rootUnit.Name + ")", //<<변경 Editor.Select.RootUnit, _rootUnit_Overall, i); } //이전 //CheckRemovableUnits<apRootUnit>(deletedUnits, CATEGORY.Overall_Item, rootUnits); //변경 CheckRemovableUnits <apRootUnit>(deletedUnits, CATEGORY.Overall_Item, Editor._portrait._rootUnits); //1. 이미지 파일들을 검색하자 -> 있는건 없애고, 없는건 만들자 //이전 //List<apTextureData> textures = Editor._portrait._textureData; //변경 List <apObjectOrders.OrderSet> textureSets = Editor._portrait._objectOrders.Images; for (int i = 0; i < textureSets.Count; i++) { //이전 //apTextureData textureData = textures[i]; //변경 apTextureData textureData = textureSets[i]._linked_Image; RefreshUnit(CATEGORY.Images_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Image), textureData, textureData._name, Editor.Select.TextureData, _rootUnit_Image, i); } //이전 //CheckRemovableUnits<apTextureData>(deletedUnits, CATEGORY.Images_Item, textures); //변경 CheckRemovableUnits <apTextureData>(deletedUnits, CATEGORY.Images_Item, Editor._portrait._textureData); //2. 메시 들을 검색하자 //이전 //List<apMesh> meshes = Editor._portrait._meshes; //변경 List <apObjectOrders.OrderSet> mesheSets = Editor._portrait._objectOrders.Meshes; for (int i = 0; i < mesheSets.Count; i++) { //이전 //apMesh mesh = meshes[i]; //변경 apMesh mesh = mesheSets[i]._linked_Mesh; RefreshUnit(CATEGORY.Mesh_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh), mesh, mesh._name, Editor.Select.Mesh, _rootUnit_Mesh, i); } //이전 //CheckRemovableUnits<apMesh>(deletedUnits, CATEGORY.Mesh_Item, meshes); //변경 CheckRemovableUnits <apMesh>(deletedUnits, CATEGORY.Mesh_Item, Editor._portrait._meshes); //3. Mesh Group들을 검색하자 //이전 //List<apMeshGroup> meshGroups = Editor._portrait._meshGroups; //변경 List <apObjectOrders.OrderSet> meshGroupSets = Editor._portrait._objectOrders.MeshGroups; for (int i = 0; i < meshGroupSets.Count; i++) { //이건 재귀 함수 -_-; apMeshGroup meshGroup = meshGroupSets[i]._linked_MeshGroup; if (meshGroup._parentMeshGroup == null) { RefreshUnit_MeshGroup(meshGroup, _rootUnit_MeshGroup, i); } } //이전 //CheckRemovableUnits<apMeshGroup>(deletedUnits, CATEGORY.MeshGroup_Item, meshGroups); //변경 CheckRemovableUnits <apMeshGroup>(deletedUnits, CATEGORY.MeshGroup_Item, Editor._portrait._meshGroups); //7. 파라미터들을 검색하자 //이전 //List<apControlParam> cParams = Editor.ParamControl._controlParams; //변경 List <apObjectOrders.OrderSet> cParamSets = Editor._portrait._objectOrders.ControlParams; for (int i = 0; i < cParamSets.Count; i++) { //이전 //apControlParam cParam = cParams[i]; //변경 apControlParam cParam = cParamSets[i]._linked_ControlParam; RefreshUnit(CATEGORY.Param_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Param), cParam, cParam._keyName, Editor.Select.Param, _rootUnit_Param, i); } //이전 //CheckRemovableUnits<apControlParam>(deletedUnits, CATEGORY.Param_Item, cParams); //변경 CheckRemovableUnits <apControlParam>(deletedUnits, CATEGORY.Param_Item, Editor.ParamControl._controlParams); //8. 애니메이션을 넣자 //이전 //List<apAnimClip> animClips = Editor._portrait._animClips; List <apObjectOrders.OrderSet> animClipSets = Editor._portrait._objectOrders.AnimClips; for (int i = 0; i < animClipSets.Count; i++) { //이전 //apAnimClip animClip = animClips[i]; //변경 apAnimClip animClip = animClipSets[i]._linked_AnimClip; RefreshUnit(CATEGORY.Animation_Item, Editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Animation), animClip, animClip._name, Editor.Select.AnimClip, _rootUnit_Animation, i); } //이전 //CheckRemovableUnits<apAnimClip>(deletedUnits, CATEGORY.Animation_Item, animClips); //변경 CheckRemovableUnits <apAnimClip>(deletedUnits, CATEGORY.Animation_Item, Editor._portrait._animClips); //삭제할 유닛을 체크하고 계산하자 for (int i = 0; i < deletedUnits.Count; i++) { //1. 먼저 All에서 없앤다. //2. Parent가 있는경우, Parent에서 없애달라고 한다. apEditorHierarchyUnit dUnit = deletedUnits[i]; if (dUnit._parentUnit != null) { dUnit._parentUnit._childUnits.Remove(dUnit); } _units_All.Remove(dUnit); } //전체 Sort를 한다. //재귀적으로 실행 for (int i = 0; i < _units_Root.Count; i++) { SortUnit_Recv(_units_Root[i]); } }
// Functions //----------------------------------------------- public static bool SaveAnimFile(apAnimClip animClip, string filePath) { if (string.IsNullOrEmpty(filePath)) { return(false); } if (animClip == null || animClip._targetMeshGroup == null) { return(false); } //데이터를 넣자 int animUniqueID = animClip._uniqueID; string animName = animClip._name; int FPS = animClip.FPS; int startFrame = animClip.StartFrame; int endFrame = animClip.EndFrame; bool isLoop = animClip.IsLoop; List <apRetargetTimelineUnit> timelineUnits = new List <apRetargetTimelineUnit>(); int animTargetMeshGroupID = animClip._targetMeshGroup._uniqueID; apMeshGroup targetMeshGroup = animClip._targetMeshGroup; string meshGroupName = animClip._targetMeshGroup._name; //1. Timeline을 설정하자 int curTimelineUnitID = 0; for (int i = 0; i < animClip._timelines.Count; i++) { apRetargetTimelineUnit timelineUnit = new apRetargetTimelineUnit(); timelineUnit.SetTimeline(curTimelineUnitID, animClip._timelines[i]); timelineUnits.Add(timelineUnit); curTimelineUnitID++; } //2. Transform/Bone 을 설정 List <apRetargetSubUnit> transforms_All = new List <apRetargetSubUnit>(); List <apRetargetSubUnit> bones_All = new List <apRetargetSubUnit>(); List <apRetargetSubUnit> transforms_Root = new List <apRetargetSubUnit>(); List <apRetargetSubUnit> bones_Root = new List <apRetargetSubUnit>(); MakeSubUnits(targetMeshGroup, transforms_All, transforms_Root, bones_All, bones_Root); //2-2. AnimEvent 설정 List <apRetargetAnimEvent> animEvents = new List <apRetargetAnimEvent>(); if (animClip._animEvents.Count > 0) { for (int i = 0; i < animClip._animEvents.Count; i++) { apRetargetAnimEvent newEvent = new apRetargetAnimEvent(); newEvent.SetAnimationEvent(animClip._animEvents[i]); animEvents.Add(newEvent); } } //3. Control Param 설정 List <apRetargetControlParam> controlParams = new List <apRetargetControlParam>(); int nControlParams = targetMeshGroup._parentPortrait._controller._controlParams.Count; int curContolParamUnitID = 0; for (int i = 0; i < nControlParams; i++) { apControlParam controlParam = targetMeshGroup._parentPortrait._controller._controlParams[i]; apRetargetControlParam cpUnit = new apRetargetControlParam(); cpUnit.SetControlParam(curContolParamUnitID, controlParam); curContolParamUnitID++; controlParams.Add(cpUnit); } FileStream fs = null; StreamWriter sw = null; try { fs = new FileStream(filePath, FileMode.Create, FileAccess.Write); sw = new StreamWriter(fs); sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine("Animation Clip"); sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine(animUniqueID); sw.WriteLine(animName); sw.WriteLine(FPS); sw.WriteLine(startFrame); sw.WriteLine(endFrame); sw.WriteLine((isLoop ? "1" : "0")); sw.WriteLine(animTargetMeshGroupID); sw.WriteLine(meshGroupName); sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine("SubTransforms"); sw.WriteLine(transforms_All.Count); sw.WriteLine("-----------------------------------------------------------------------------------"); for (int i = 0; i < transforms_All.Count; i++) { sw.WriteLine(transforms_All[i].GetEncodingData()); } sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine("SubBones"); sw.WriteLine(bones_All.Count); sw.WriteLine("-----------------------------------------------------------------------------------"); for (int i = 0; i < bones_All.Count; i++) { sw.WriteLine(bones_All[i].GetEncodingData()); } sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine("Animation Timelines"); sw.WriteLine(timelineUnits.Count); sw.WriteLine("-----------------------------------------------------------------------------------"); for (int i = 0; i < timelineUnits.Count; i++) { timelineUnits[i].EncodeToFile(sw); } sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine("Animation Events"); sw.WriteLine(animEvents.Count); sw.WriteLine("-----------------------------------------------------------------------------------"); if (animEvents.Count > 0) { for (int i = 0; i < animEvents.Count; i++) { animEvents[i].EncodeToFile(sw); } } sw.WriteLine("-----------------------------------------------------------------------------------"); sw.WriteLine(" Controller Parameters "); sw.WriteLine(controlParams.Count); sw.WriteLine("-----------------------------------------------------------------------------------"); if (controlParams.Count > 0) { for (int i = 0; i < controlParams.Count; i++) { sw.WriteLine(controlParams[i].GetEncodingData()); } } sw.Close(); fs.Close(); sw = null; fs = null; } catch (Exception ex) { Debug.LogError("SaveAnimFile Exception : " + ex); if (sw != null) { sw.Close(); sw = null; } if (fs != null) { fs.Close(); fs = null; } return(false); } return(true); }
public void OnUnitClickOrderChanged(apEditorHierarchyUnit eventUnit, int savedKey, object savedObj, bool isOrderUp) { //Hierarchy의 항목 순서를 바꾸자 if (Editor == null || Editor._portrait == null) { return; } apObjectOrders orders = Editor._portrait._objectOrders; bool isChanged = false; bool isResult = false; CATEGORY category = (CATEGORY)savedKey; switch (category) { case CATEGORY.Overall_Item: { apRootUnit rootUnit = savedObj as apRootUnit; if (rootUnit != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.RootUnit, rootUnit._childMeshGroup._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; case CATEGORY.Images_Item: { apTextureData textureData = savedObj as apTextureData; if (textureData != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.Image, textureData._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; case CATEGORY.Mesh_Item: { apMesh mesh = savedObj as apMesh; if (mesh != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.Mesh, mesh._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; case CATEGORY.MeshGroup_Item: { apMeshGroup meshGroup = savedObj as apMeshGroup; if (meshGroup != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.MeshGroup, meshGroup._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; case CATEGORY.Animation_Item: { apAnimClip animClip = savedObj as apAnimClip; if (animClip != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.AnimClip, animClip._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; case CATEGORY.Param_Item: { apControlParam cParam = savedObj as apControlParam; if (cParam != null) { isResult = orders.ChangeOrder(Editor._portrait, apObjectOrders.OBJECT_TYPE.ControlParam, cParam._uniqueID, isOrderUp); if (isResult) { isChanged = true; } } } break; } if (isChanged) { apEditorUtil.SetEditorDirty(); Editor.RefreshControllerAndHierarchy(false); } }
// Functions //---------------------------------------------------- public void Sync(apPortrait portrait) { //Debug.Log("Sync : " + portrait.name); List <apRootUnit> rootUnits = portrait._rootUnits; List <apTextureData> images = portrait._textureData; List <apMesh> meshes = portrait._meshes; List <apMeshGroup> meshGroups = portrait._meshGroups; List <apAnimClip> animClips = portrait._animClips; List <apControlParam> controlParams = portrait._controller._controlParams; //일단 모두 초기화 foreach (KeyValuePair <OBJECT_TYPE, List <OrderSet> > subOrderSet in _orderSets) { List <OrderSet> orderSets = subOrderSet.Value; for (int i = 0; i < orderSets.Count; i++) { orderSets[i]._isExist = false; //<<플래그를 세운다. (응?) } } OrderSet existOrderSet = null; List <OrderSet> newOrderSets = new List <OrderSet>(); //1. Root Unit apRootUnit curRootUnit = null; for (int i = 0; i < rootUnits.Count; i++) { curRootUnit = rootUnits[i]; if (curRootUnit == null || curRootUnit._childMeshGroup == null) { continue; } existOrderSet = _orderSets_RootUnit.Find(delegate(OrderSet a) { return(a._ID == curRootUnit._childMeshGroup._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_RootUnit = curRootUnit; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetRootUnit(curRootUnit, i); newOrderSets.Add(newOrderSet); } } //2. Images apTextureData curImage = null; for (int i = 0; i < images.Count; i++) { curImage = images[i]; if (curImage == null) { continue; } existOrderSet = _orderSets_Image.Find(delegate(OrderSet a) { return(a._ID == curImage._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_Image = curImage; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetImage(curImage, i); newOrderSets.Add(newOrderSet); } } //3. Meshes apMesh curMesh = null; for (int i = 0; i < meshes.Count; i++) { curMesh = meshes[i]; if (curMesh == null) { continue; } existOrderSet = _orderSets_Mesh.Find(delegate(OrderSet a) { return(a._ID == curMesh._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_Mesh = curMesh; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetMesh(curMesh, i); newOrderSets.Add(newOrderSet); } } //4. MeshGroup apMeshGroup curMeshGroup = null; for (int i = 0; i < meshGroups.Count; i++) { curMeshGroup = meshGroups[i]; if (curMeshGroup == null) { continue; } //자식 MeshGroup인 경우 처리하지 않는다. if (curMeshGroup._parentMeshGroup != null) { continue; } existOrderSet = _orderSets_MeshGroup.Find(delegate(OrderSet a) { return(a._ID == curMeshGroup._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_MeshGroup = curMeshGroup; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetMeshGroup(curMeshGroup, i); newOrderSets.Add(newOrderSet); } } //5. AnimClip apAnimClip curAnimClip = null; for (int i = 0; i < animClips.Count; i++) { curAnimClip = animClips[i]; if (curAnimClip == null) { continue; } existOrderSet = _orderSets_AnimClip.Find(delegate(OrderSet a) { return(a._ID == curAnimClip._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_AnimClip = curAnimClip; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetAnimClip(curAnimClip, i); newOrderSets.Add(newOrderSet); } } //6. Control Param apControlParam curControlParam = null; for (int i = 0; i < controlParams.Count; i++) { curControlParam = controlParams[i]; if (curControlParam == null) { continue; } existOrderSet = _orderSets_ControlParam.Find(delegate(OrderSet a) { return(a._ID == curControlParam._uniqueID); }); if (existOrderSet != null) { //이미 등록된 OrderSet이다. existOrderSet._isExist = true; existOrderSet._regOrder = i; existOrderSet._linked_ControlParam = curControlParam; } else { //아직 등록되지 않은 OrderSet이다. OrderSet newOrderSet = new OrderSet(); newOrderSet.SetControlParam(curControlParam, i); newOrderSets.Add(newOrderSet); } } bool isAnyChanged = false; // 연결이 안된 OrderSet 을 삭제 foreach (KeyValuePair <OBJECT_TYPE, List <OrderSet> > subOrderSet in _orderSets) { List <OrderSet> orderSets = subOrderSet.Value; int nRemoved = orderSets.RemoveAll(delegate(OrderSet a) { return(!a._isExist); }); if (nRemoved > 0) { isAnyChanged = true; } } //새로 추가될 OrderSet을 추가한다. 이때, Order를 잘 체크하자 if (newOrderSets.Count > 0) { isAnyChanged = true; OrderSet newOrderSet = null; List <OrderSet> targetList = null; for (int i = 0; i < newOrderSets.Count; i++) { newOrderSet = newOrderSets[i]; targetList = _orderSets[newOrderSet._objectType]; newOrderSet.SetOrder(targetList.Count); //리스트의 크기만큼의 Order값을 넣자 targetList.Add(newOrderSet); //<<리스트에 추가! } } if (isAnyChanged) { //Sort를 하고 CustomOrder를 작성하자 foreach (KeyValuePair <OBJECT_TYPE, List <OrderSet> > subOrderSet in _orderSets) { List <OrderSet> orderSets = subOrderSet.Value; orderSets.Sort(delegate(OrderSet a, OrderSet b) { return(a._customOrder - b._customOrder); //오름차순 }); for (int i = 0; i < orderSets.Count; i++) { orderSets[i]._customOrder = i; } } } //Debug.Log("Root Units : " + _orderSets[OBJECT_TYPE.RootUnit].Count); //Debug.Log("Images : " + _orderSets[OBJECT_TYPE.Image].Count); //Debug.Log("Meshes : " + _orderSets[OBJECT_TYPE.Mesh].Count); //Debug.Log("Mesh Groups : " + _orderSets[OBJECT_TYPE.MeshGroup].Count); //Debug.Log("AnimClips : " + _orderSets[OBJECT_TYPE.AnimClip].Count); //Debug.Log("Control Params : " + _orderSets[OBJECT_TYPE.ControlParam].Count); }
public void SetAnimClip(apAnimClip animClip, int regOrder) { SetData(OBJECT_TYPE.AnimClip, animClip._uniqueID, regOrder); _linked_AnimClip = animClip; }
public void Bake(apPortrait portrait, apOptModifierUnitBase parentModifier, apModifierParamSetGroup srcParamSetGroup, bool isAnimated) { _portrait = portrait; _parentModifier = parentModifier; _syncTarget = srcParamSetGroup._syncTarget; //_keyControlParamName = srcParamSetGroup._keyControlParamName; _keyControlParamID = srcParamSetGroup._keyControlParamID; _keyControlParam = null; //<<이건 링크로 해결하자 //애니메이션 값도 넣어주자 _keyAnimClipID = srcParamSetGroup._keyAnimClipID; _keyAnimTimelineID = srcParamSetGroup._keyAnimTimelineID; _keyAnimTimelineLayerID = srcParamSetGroup._keyAnimTimelineLayerID; _keyAnimClip = null; _keyAnimTimeline = null; _keyAnimTimelineLayer = null; _paramSetList.Clear(); for (int i = 0; i < srcParamSetGroup._paramSetList.Count; i++) { apModifierParamSet srcParamSet = srcParamSetGroup._paramSetList[i]; apOptParamSet optParamSet = new apOptParamSet(); optParamSet.LinkParamSetGroup(this, portrait); optParamSet.BakeModifierParamSet(srcParamSet, portrait); _paramSetList.Add(optParamSet); } _isEnabled = srcParamSetGroup._isEnabled; _layerIndex = srcParamSetGroup._layerIndex; _layerWeight = srcParamSetGroup._layerWeight; if (!isAnimated) { _blendMethod = srcParamSetGroup._blendMethod; } else { _blendMethod = apModifierParamSetGroup.BLEND_METHOD.Additive; //<<애니메이션에서는 Additive 강제 } _isColorPropertyEnabled = srcParamSetGroup._isColorPropertyEnabled; //<<추가. _calculatedWeightedVertexList.Clear(); for (int i = 0; i < srcParamSetGroup._calculatedWeightedVertexList.Count; i++) { apModifierParamSetGroupVertWeight srcWV = srcParamSetGroup._calculatedWeightedVertexList[i]; apOptParamSetGroupVertWeight optWV = new apOptParamSetGroupVertWeight(); optWV.Bake(srcWV); optWV.Link(portrait.GetOptTransform(optWV._meshTransform_ID)); //OptTransform을 연결한다. _calculatedWeightedVertexList.Add(optWV); } LinkPortrait(portrait, parentModifier); }
public void Link(apAnimClip animClip, apOptRootUnit optRootUnit) { _linkedAnimClip = animClip; _linkedOptRootUnit = optRootUnit; _isValid = true; }
// Init //------------------------------------------------------------------------------------------------ private void Init(apEditor editor, apPortrait portrait, apMeshGroup meshGroup, apModifierBase modifier, apModifiedMesh modMesh, apRenderUnit renderUnit, bool isAnimEdit, apAnimClip animClip, apAnimKeyframe keyframe) { _editor = editor; _portrait = portrait; _meshGroup = meshGroup; _modifier = modifier; _modMesh = modMesh; _renderUnit = modMesh._renderUnit; _isAnimEdit = isAnimEdit; _animClip = animClip; _keyframe = keyframe; _selectionType = _editor.Select.SelectionType; _targetDepth = renderUnit.GetDepth(); _img_DepthCursor = _editor.ImageSet.Get(apImageSet.PRESET.ExtraOption_DepthCursor); _img_DepthMidCursor = _editor.ImageSet.Get(apImageSet.PRESET.ExtraOption_DepthMidCursor); _img_MeshTF = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh); _img_MeshGroupTF = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_MeshGroup); _subUnits_All.Clear(); apRenderUnit parentUnit = _renderUnit._parentRenderUnit; apRenderUnit curRenderUnit = null; for (int i = 0; i < _meshGroup._renderUnits_All.Count; i++) { curRenderUnit = _meshGroup._renderUnits_All[i]; //Parent가 같은 형제 렌더 유닛에 대해서만 처리한다. //단, MeshTransform일 때, Clipping Child는 생략한다. if (curRenderUnit._meshTransform != null && curRenderUnit._meshTransform._isClipping_Child) { continue; } if (curRenderUnit._parentRenderUnit != parentUnit) { continue; } SubUnit subUnit = new SubUnit(curRenderUnit, curRenderUnit._level, (curRenderUnit == _renderUnit), (curRenderUnit == _meshGroup._rootRenderUnit)); _subUnits_All.Add(subUnit); } _subUnits_All.Sort(delegate(SubUnit a, SubUnit b) { return(b._depth - a._depth); }); //여기서는 실제 Depth보다 상대적 Depth만 고려한다. int curDepth = 0; for (int i = _subUnits_All.Count - 1; i >= 0; i--) { _subUnits_All[i]._depth = curDepth; if (_subUnits_All[i]._isTarget) { _targetDepth = curDepth; } curDepth++; } //이미지를 바꿀 수 있는가 RefreshImagePreview(); }
public void Init(apAnimClip.LINK_TYPE linkType, int uniqueID, int modifierUniqueID, apAnimClip animClip) { _uniqueID = uniqueID; _layers.Clear(); _parentAnimClip = animClip; _linkType = linkType; _modifierUniqueID = modifierUniqueID; //_guiColor = new Color(0.4f, 0.8f, 1.0f); _guiColor = new Color(0.15f, 0.5f, 0.7f); _guiTimelineFolded = false; }
//------------------------------------------------------ // 2. 애니메이션의 저장과 로드 //------------------------------------------------------ public static bool SaveAnimClip(apAnimClip animClip, string filePath) { return(apRetargetAnimFile.SaveAnimFile(animClip, filePath)); }
public void Link(apAnimClip animClip, apAnimTimeline timeline) { _parentAnimClip = animClip; _parentTimeline = timeline; _linkType = _parentTimeline._linkType; _parentAnimClip._portrait.RegistUniqueID(apIDManager.TARGET.AnimTimelineLayer, _uniqueID); switch (_linkType) { case apAnimClip.LINK_TYPE.AnimatedModifier: { switch (_linkModType) { case LINK_MOD_TYPE.MeshTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedMeshTransform = _parentAnimClip._targetMeshGroup.GetMeshTransformRecursive(_transformID); if (_linkedMeshTransform == null) { _transformID = -1; } break; case LINK_MOD_TYPE.MeshGroupTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedMeshGroupTransform = _parentAnimClip._targetMeshGroup.GetMeshGroupTransformRecursive(_transformID); if (_linkedMeshGroupTransform == null) { _transformID = -1; } break; case LINK_MOD_TYPE.Bone: _linkedBone = _parentAnimClip._targetMeshGroup.GetBoneRecursive(_boneID); //Recursive 방식으로 검색한다. if (_linkedBone == null) { _boneID = -1; } break; case LINK_MOD_TYPE.None: //?? 이 타입이 들어올리가 없는뎅.. _linkedMeshTransform = null; _linkedMeshGroupTransform = null; _linkedBone = null; _transformID = -1; _boneID = -1; break; } } break; case apAnimClip.LINK_TYPE.ControlParam: { _linkedControlParam = _parentAnimClip._portrait.GetControlParam(_controlParamID); if (_linkedControlParam == null) { _controlParamID = -1; } } break; } for (int i = 0; i < _keyframes.Count; i++) { _keyframes[i].Link(this); } }
// Click Event //----------------------------------------------------------------------------------------- public void OnUnitClick(apEditorHierarchyUnit eventUnit, int savedKey, object savedObj) { if (Editor == null) { return; } apEditorHierarchyUnit selectedUnit = null; //여기서 이벤트를 설정해주자 CATEGORY category = (CATEGORY)savedKey; //Debug.Log("Unit Select : " + category); switch (category) { case CATEGORY.Overall_Name: case CATEGORY.Images_Name: case CATEGORY.Mesh_Name: case CATEGORY.MeshGroup_Name: //case CATEGORY.Face_Name: case CATEGORY.Animation_Name: case CATEGORY.Param_Name: break; case CATEGORY.Overall_Item: //전체 선택 apRootUnit rootUnit = savedObj as apRootUnit; if (rootUnit != null) { Editor.Select.SetOverall(rootUnit); if (Editor.Select.RootUnit == rootUnit) { selectedUnit = eventUnit; } } break; case CATEGORY.Images_Item: { apTextureData textureData = savedObj as apTextureData; if (textureData != null) { Editor.Select.SetImage(textureData); //<< 선택하자 if (Editor.Select.TextureData == textureData) { selectedUnit = eventUnit; } } } break; case CATEGORY.Images_Add: Editor.Controller.AddImage(); break; case CATEGORY.Images_AddPSD: //추가 : PSD 로드 Editor.Controller.ShowPSDLoadDialog(); break; case CATEGORY.Mesh_Item: { apMesh mesh = savedObj as apMesh; if (mesh != null) { Editor.Select.SetMesh(mesh); //<< 선택하자 if (Editor.Select.Mesh == mesh) { selectedUnit = eventUnit; } } } break; case CATEGORY.Mesh_Add: Editor.Controller.AddMesh(); break; case CATEGORY.MeshGroup_Item: { apMeshGroup meshGroup = savedObj as apMeshGroup; if (meshGroup != null) { Editor.Select.SetMeshGroup(meshGroup); if (Editor.Select.MeshGroup == meshGroup) { selectedUnit = eventUnit; } } } break; case CATEGORY.MeshGroup_Add: Editor.Controller.AddMeshGroup(); break; //case CATEGORY.Face_Item: // break; //case CATEGORY.Face_Add: // break; case CATEGORY.Animation_Item: { apAnimClip animClip = savedObj as apAnimClip; if (animClip != null) { Editor.Select.SetAnimClip(animClip); if (Editor.Select.AnimClip == animClip) { selectedUnit = eventUnit; } } } break; case CATEGORY.Animation_Add: { //데모 기능 제한 //Param 개수는 2개로 제한되며, 이걸 넘어가면 추가할 수 없다. if (apVersion.I.IsDemo) { if (Editor._portrait._animClips.Count >= 2) { //이미 2개를 넘었다. EditorUtility.DisplayDialog( Editor.GetText(TEXT.DemoLimitation_Title), Editor.GetText(TEXT.DemoLimitation_Body_AddAnimation), Editor.GetText(TEXT.Okay) ); break; } } Editor.Controller.AddAnimClip(); } break; case CATEGORY.Param_Item: { apControlParam cParam = savedObj as apControlParam; if (cParam != null) { Editor.Select.SetParam(cParam); if (Editor.Select.Param == cParam) { selectedUnit = eventUnit; } } } break; case CATEGORY.Param_Add: { //데모 기능 제한 //Param 개수는 2개로 제한되며, 이걸 넘어가면 추가할 수 없다. if (apVersion.I.IsDemo) { if (Editor.ParamControl._controlParams.Count >= 2) { //이미 2개를 넘었다. EditorUtility.DisplayDialog( Editor.GetText(TEXT.DemoLimitation_Title), Editor.GetText(TEXT.DemoLimitation_Body_AddParam), Editor.GetText(TEXT.Okay) ); break; } } //Param 추가 Editor.Controller.AddParam(); } break; } if (selectedUnit != null) { for (int i = 0; i < _units_All.Count; i++) { if (_units_All[i] == selectedUnit) { //_units_All[i]._isSelected = true; _units_All[i].SetSelected(true); } else { //_units_All[i]._isSelected = false; _units_All[i].SetSelected(false); } } } else { for (int i = 0; i < _units_All.Count; i++) { //_units_All[i]._isSelected = false; _units_All[i].SetSelected(false); } } }
public void LinkOpt(apAnimClip animClip, apAnimTimeline timeline) { _parentAnimClip = animClip; _parentTimeline = timeline; _linkType = _parentTimeline._linkType; if (_parentAnimClip == null) { Debug.Log("AnyPortrait Error : Parent Anim Clip is Null"); } else if (_parentAnimClip._targetOptTranform == null) { Debug.LogError("AnyPortrait Error : Parent Anim Clip TargetOptTranform is Null"); } switch (_linkType) { case apAnimClip.LINK_TYPE.AnimatedModifier: { switch (_linkModType) { case LINK_MOD_TYPE.MeshTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedOptTransform = _parentAnimClip._targetOptTranform.GetMeshTransformRecursive(_transformID); if (_linkedOptTransform == null) { Debug.LogError("AnyPortrait Error : Opt TimelineLayer MeshTransform Linking Failed : " + _transformID); _transformID = -1; } break; case LINK_MOD_TYPE.MeshGroupTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedOptTransform = _parentAnimClip._targetOptTranform.GetMeshGroupTransformRecursive(_transformID); if (_linkedOptTransform == null) { Debug.LogError("AnyPortrait Error : Opt TimelineLayer MeshGroupTransform Linking Failed : " + _transformID); _transformID = -1; } break; case LINK_MOD_TYPE.Bone: //TODO : Bone 타입 연결을 해야한다. _linkedOptBone = _parentAnimClip._targetOptTranform.GetBoneRecursive(_boneID); break; case LINK_MOD_TYPE.None: _linkedOptTransform = null; _transformID = -1; _boneID = -1; break; } } break; case apAnimClip.LINK_TYPE.ControlParam: { _linkedControlParam = _parentAnimClip._portrait.GetControlParam(_controlParamID); if (_linkedControlParam == null) { _controlParamID = -1; } } break; //case apAnimClip.LINK_TYPE.Bone: // { // Debug.LogError("TODO : TimelineLayer의 Bone 타입 연동하기"); // } // break; } for (int i = 0; i < _keyframes.Count; i++) { _keyframes[i].Link(this); } SortAndRefreshKeyframes(); }
/// <summary> /// [Please do not use it] Set AnimClip to get data /// </summary> /// <param name="playData"></param> /// <param name="layer"></param> /// <param name="blendMethod"></param> /// <param name="isAutoEndIfNotLoop"></param> /// <param name="isEditor"></param> public void SetAnimClip(apAnimPlayData playData, int layer, BLEND_METHOD blendMethod, bool isAutoEndIfNotLoop, bool isEditor) { _linkedAnimClip = playData._linkedAnimClip; _targetRootUnit = playData._linkedOptRootUnit; //추가 if (_linkedAnimClip._parentPlayUnit != null && _linkedAnimClip._parentPlayUnit != this) { //이미 다른 PlayUnit이 사용중이었다면.. _linkedAnimClip._parentPlayUnit.SetEnd(); //_linkedAnimClip._parentPlayUnit._linkedAnimClip = null; } _linkedAnimClip._parentPlayUnit = this; _layer = layer; _isLoop = _linkedAnimClip.IsLoop; _isAutoEnd = isAutoEndIfNotLoop; if (_isLoop) { _isAutoEnd = false; //<<Loop일때 AutoEnd는 불가능하다 } _blendMethod = blendMethod; _isPause = false; _playStatus = PLAY_STATUS.Ready; _isPlayStartEventCalled = false; _isEndEventCalled = false; //_fadeInTime = 0.0f; //_fadeOutTime = 0.0f; //_delayToPlayTime = 0.0f; //_delayToEndTime = 0.0f; _speedRatio = 1.0f; _isFirstFrame = true; _nextPlayStatus = _playStatus; if (isEditor) { _linkedAnimClip.Stop_Editor(false); //Stop은 하되 업데이트는 하지 않는다. (false) } else { _linkedAnimClip.Stop_Opt(false); } //_tAnimClipLength = _linkedAnimClip.TimeLength; _unitWeight = 0.0f; _isWeightCalculated = false; _totalRequestWeights = 0.0f; //_prevUnitWeight = 0.0f; //_debugWeight1 = 0.0f; //_debugWeight2 = 0.0f; //_debugWeight3 = 0.0f; //_isDelayIn = false; //_isDelayOut = false; //_tDelay = 0.0f; }
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); }