VoxelSkinnedAnimationObjectEditor.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEngine.Assertions;
  4. using UnityEditorInternal;
  5. using System;
  6. using System.IO;
  7. using System.Reflection;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. #if UNITY_2018_3_OR_NEWER
  11. using UnityEditor.Experimental.SceneManagement;
  12. #endif
  13. namespace VoxelImporter
  14. {
  15. [CustomEditor(typeof(VoxelSkinnedAnimationObject))]
  16. public class VoxelSkinnedAnimationObjectEditor : VoxelObjectEditor
  17. {
  18. public VoxelSkinnedAnimationObject animationTarget { get; private set; }
  19. public VoxelSkinnedAnimationObjectCore animationCore { get; protected set; }
  20. public override Mesh mesh { get { return animationTarget.mesh; } set { animationTarget.mesh = value; } }
  21. public override List<Material> materials { get { return animationTarget.materials; } set { animationTarget.materials = value; } }
  22. public override Texture2D atlasTexture { get { return animationTarget.atlasTexture; } set { animationTarget.atlasTexture = value; } }
  23. protected override void OnEnable()
  24. {
  25. base.OnEnable();
  26. animationTarget = target as VoxelSkinnedAnimationObject;
  27. if (animationTarget == null) return;
  28. baseCore = objectCore = animationCore = new VoxelSkinnedAnimationObjectCore(animationTarget);
  29. OnEnableInitializeSet();
  30. }
  31. protected override void InspectorGUI()
  32. {
  33. if (animationTarget == null) return;
  34. base.InspectorGUI();
  35. #if UNITY_2018_3_OR_NEWER
  36. {
  37. if (prefabType == PrefabAssetType.Regular && !baseCore.isPrefabEditMode)
  38. {
  39. EditorGUI.BeginDisabledGroup(true);
  40. }
  41. }
  42. #endif
  43. Action<UnityEngine.Object, string> TypeTitle = (o, title) =>
  44. {
  45. if (o == null)
  46. EditorGUILayout.LabelField(title, guiStyleMagentaBold);
  47. else
  48. EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
  49. };
  50. #region Animation
  51. if (!string.IsNullOrEmpty(baseTarget.voxelFilePath))
  52. {
  53. animationTarget.edit_animationFoldout = EditorGUILayout.Foldout(animationTarget.edit_animationFoldout, "Animation", guiStyleFoldoutBold);
  54. if (animationTarget.edit_animationFoldout)
  55. {
  56. EditorGUILayout.BeginVertical(GUI.skin.box);
  57. {
  58. EditorGUILayout.BeginHorizontal();
  59. TypeTitle(animationTarget.rootBone, "Bone");
  60. {
  61. EditorGUI.BeginDisabledGroup(animationTarget.rootBone == null);
  62. if (GUILayout.Button("Save as template", GUILayout.Width(128)))
  63. {
  64. #region Save as template
  65. string BoneTemplatesPath = Application.dataPath + "/VoxelImporter/Scripts/Editor/BoneTemplates";
  66. if (!Directory.Exists(BoneTemplatesPath))
  67. {
  68. BoneTemplatesPath = Application.dataPath;
  69. }
  70. string path = EditorUtility.SaveFilePanel("Save as template", BoneTemplatesPath, string.Format("{0}.asset", baseTarget.gameObject.name), "asset");
  71. if (!string.IsNullOrEmpty(path))
  72. {
  73. if (path.IndexOf(Application.dataPath) < 0)
  74. {
  75. SaveInsideAssetsFolderDisplayDialog();
  76. }
  77. else
  78. {
  79. path = path.Replace(Application.dataPath, "Assets");
  80. var boneTemplate = ScriptableObject.CreateInstance<BoneTemplate>();
  81. boneTemplate.Set(animationTarget.rootBone);
  82. AssetDatabase.CreateAsset(boneTemplate, path);
  83. }
  84. }
  85. #endregion
  86. }
  87. EditorGUI.EndDisabledGroup();
  88. if (GUILayout.Button("Create", guiStyleDropDown, GUILayout.Width(64)))
  89. {
  90. #region Create
  91. VoxelHumanoidConfigreAvatar.Destroy();
  92. Dictionary<string, BoneTemplate> boneTemplates = new Dictionary<string, BoneTemplate>();
  93. {
  94. {
  95. var boneTemplate = ScriptableObject.CreateInstance<BoneTemplate>();
  96. boneTemplate.boneInitializeData.Add(new BoneTemplate.BoneInitializeData() { name = "Root" });
  97. boneTemplate.boneInitializeData.Add(new BoneTemplate.BoneInitializeData() { name = "Bone", parentName = "Root", position = new Vector3(0f, 2f, 0f) });
  98. boneTemplates.Add("Default", boneTemplate);
  99. }
  100. {
  101. var guids = AssetDatabase.FindAssets("t:bonetemplate");
  102. for (int i = 0; i < guids.Length; i++)
  103. {
  104. var path = AssetDatabase.GUIDToAssetPath(guids[i]);
  105. var boneTemplate = AssetDatabase.LoadAssetAtPath<BoneTemplate>(path);
  106. if (boneTemplate == null) continue;
  107. var name = path.Remove(0, "Assets/".Length);
  108. boneTemplates.Add(name, boneTemplate);
  109. }
  110. }
  111. }
  112. Action<BoneTemplate> MenuCallback = (boneTemplate) =>
  113. {
  114. GameObject goRoot = baseTarget.gameObject;
  115. VoxelBase clRoot = baseTarget;
  116. #if !UNITY_2018_3_OR_NEWER
  117. if (isPrefab)
  118. {
  119. goRoot = (GameObject)PrefabUtility.InstantiatePrefab(baseTarget.gameObject);
  120. clRoot = goRoot.GetComponent<VoxelBase>();
  121. }
  122. #endif
  123. {
  124. var bones = clRoot.GetComponentsInChildren<VoxelSkinnedAnimationObjectBone>();
  125. for (int i = 0; i < bones.Length; i++)
  126. {
  127. for (int j = 0; j < bones[i].transform.childCount; j++)
  128. {
  129. var child = bones[i].transform.GetChild(j);
  130. if (child.GetComponent<VoxelSkinnedAnimationObjectBone>() == null)
  131. {
  132. Undo.SetTransformParent(child, animationTarget.transform, "Create Bone");
  133. i--;
  134. }
  135. }
  136. }
  137. for (int i = 0; i < bones.Length; i++)
  138. {
  139. if (bones[i] == null || bones[i].gameObject == null) continue;
  140. Undo.DestroyObjectImmediate(bones[i].gameObject);
  141. }
  142. }
  143. {
  144. List<GameObject> createList = new List<GameObject>();
  145. for (int i = 0; i < boneTemplate.boneInitializeData.Count; i++)
  146. {
  147. var tp = boneTemplate.boneInitializeData[i];
  148. GameObject go = new GameObject(tp.name);
  149. Undo.RegisterCreatedObjectUndo(go, "Create Bone");
  150. var bone = Undo.AddComponent<VoxelSkinnedAnimationObjectBone>(go);
  151. {
  152. bone.edit_disablePositionAnimation = tp.disablePositionAnimation;
  153. bone.edit_disableRotationAnimation = tp.disableRotationAnimation;
  154. bone.edit_disableScaleAnimation = tp.disableScaleAnimation;
  155. bone.edit_mirrorSetBoneAnimation = tp.mirrorSetBoneAnimation;
  156. bone.edit_mirrorSetBonePosition = tp.mirrorSetBonePosition;
  157. bone.edit_mirrorSetBoneWeight = tp.mirrorSetBoneWeight;
  158. }
  159. if (string.IsNullOrEmpty(tp.parentName))
  160. {
  161. Undo.SetTransformParent(go.transform, goRoot.transform, "Create Bone");
  162. }
  163. else
  164. {
  165. int parentIndex = createList.FindIndex(a => a.name == tp.parentName);
  166. Debug.Assert(parentIndex >= 0);
  167. GameObject parent = createList[parentIndex];
  168. Assert.IsNotNull(parent);
  169. Undo.SetTransformParent(go.transform, parent.transform, "Create Bone");
  170. }
  171. go.transform.localPosition = tp.position;
  172. go.transform.localRotation = Quaternion.identity;
  173. go.transform.localScale = Vector3.one;
  174. createList.Add(go);
  175. }
  176. }
  177. animationTarget.humanDescription.firstAutomapDone = false;
  178. Refresh();
  179. #if !UNITY_2018_3_OR_NEWER
  180. if (isPrefab)
  181. {
  182. #if UNITY_2018_2_OR_NEWER
  183. var prefab = PrefabUtility.GetCorrespondingObjectFromSource(goRoot);
  184. #else
  185. var prefab = PrefabUtility.GetPrefabParent(goRoot);
  186. #endif
  187. PrefabUtility.ReplacePrefab(goRoot, prefab, ReplacePrefabOptions.ConnectToPrefab);
  188. DestroyImmediate(goRoot);
  189. }
  190. #endif
  191. };
  192. GenericMenu menu = new GenericMenu();
  193. {
  194. var enu = boneTemplates.GetEnumerator();
  195. while (enu.MoveNext())
  196. {
  197. var value = enu.Current.Value;
  198. menu.AddItem(new GUIContent(enu.Current.Key), false, () =>
  199. {
  200. MenuCallback(value);
  201. });
  202. }
  203. }
  204. menu.ShowAsContext();
  205. #endregion
  206. }
  207. }
  208. EditorGUILayout.EndHorizontal();
  209. if (baseTarget.advancedMode)
  210. {
  211. EditorGUI.indentLevel++;
  212. if (animationTarget.rootBone != null)
  213. {
  214. #region Root
  215. {
  216. EditorGUI.BeginDisabledGroup(isPrefab);
  217. EditorGUILayout.BeginHorizontal();
  218. {
  219. EditorGUILayout.LabelField("Root");
  220. #region Add Root Bone
  221. {
  222. if (GUILayout.Button("Add Root Bone"))
  223. {
  224. var beforeRoot = animationTarget.rootBone.GetComponent<VoxelSkinnedAnimationObjectBone>();
  225. Undo.RecordObject(beforeRoot, "Add Root Bone");
  226. GameObject go = new GameObject("Root");
  227. Undo.RegisterCreatedObjectUndo(go, "Add Root Bone");
  228. Undo.AddComponent<VoxelSkinnedAnimationObjectBone>(go);
  229. Undo.SetTransformParent(go.transform, animationTarget.transform, "Add Root Bone");
  230. go.transform.localPosition = Vector3.zero;
  231. go.transform.localRotation = Quaternion.identity;
  232. go.transform.localScale = Vector3.one;
  233. Undo.SetTransformParent(animationTarget.rootBone, go.transform, "Add Root Bone");
  234. EditorGUIUtility.PingObject(go);
  235. animationCore.UpdateBoneWeight();
  236. animationCore.FixMissingAnimation();
  237. #region FixBoneWeight
  238. for (int i = 0; i < animationTarget.voxelData.voxels.Length; i++)
  239. {
  240. var pos = animationTarget.voxelData.voxels[i].position;
  241. for (var vindex = (VoxelBase.VoxelVertexIndex)0; vindex < VoxelBase.VoxelVertexIndex.Total; vindex++)
  242. {
  243. var weight = animationCore.GetBoneWeight(pos, vindex);
  244. var power = 0f;
  245. if (weight.boneIndex0 == 0 && weight.weight0 > 0f)
  246. power = weight.weight0;
  247. else if (weight.boneIndex1 == 0 && weight.weight1 > 0f)
  248. power = weight.weight1;
  249. else if (weight.boneIndex2 == 0 && weight.weight2 > 0f)
  250. power = weight.weight2;
  251. else if (weight.boneIndex3 == 0 && weight.weight3 > 0f)
  252. power = weight.weight3;
  253. if (power <= 0f) continue;
  254. var weights = beforeRoot.weightData.GetWeight(pos);
  255. if (weights == null)
  256. weights = new WeightData.VoxelWeight();
  257. weights.SetWeight(vindex, power);
  258. beforeRoot.weightData.SetWeight(pos, weights);
  259. }
  260. }
  261. #endregion
  262. Refresh();
  263. InternalEditorUtility.RepaintAllViews();
  264. }
  265. }
  266. #endregion
  267. #region Remove Root Bone
  268. {
  269. bool disabled = false;
  270. {
  271. int count = 0;
  272. for (int i = 0; i < animationTarget.rootBone.childCount; i++)
  273. {
  274. var child = animationTarget.rootBone.GetChild(i);
  275. if (child.GetComponent<VoxelSkinnedAnimationObjectBone>() != null)
  276. count++;
  277. }
  278. disabled = count != 1;
  279. }
  280. EditorGUI.BeginDisabledGroup(disabled);
  281. if (GUILayout.Button("Remove Root Bone"))
  282. {
  283. for (int i = 0; i < animationTarget.rootBone.childCount; i++)
  284. {
  285. var child = animationTarget.rootBone.GetChild(i);
  286. if (child.GetComponent<VoxelSkinnedAnimationObjectBone>() != null)
  287. Undo.RecordObject(animationTarget.rootBone, "Remove Root Bone");
  288. Undo.SetTransformParent(child, animationTarget.transform, "Remove Root Bone");
  289. i--;
  290. }
  291. Undo.DestroyObjectImmediate(animationTarget.rootBone.gameObject);
  292. animationCore.UpdateBoneBindposes();
  293. EditorGUIUtility.PingObject(animationTarget.rootBone.gameObject);
  294. animationCore.FixMissingAnimation();
  295. Refresh();
  296. InternalEditorUtility.RepaintAllViews();
  297. }
  298. EditorGUI.EndDisabledGroup();
  299. }
  300. #endregion
  301. }
  302. EditorGUILayout.EndHorizontal();
  303. EditorGUI.EndDisabledGroup();
  304. }
  305. #endregion
  306. #region Reset
  307. {
  308. EditorGUILayout.BeginHorizontal();
  309. EditorGUILayout.LabelField("Reset");
  310. {
  311. if (GUILayout.Button("All"))
  312. {
  313. for (int i = 0; i < animationTarget.bones.Length; i++)
  314. {
  315. Undo.RecordObject(animationTarget.bones[i].transform, "Reset Bone Transform");
  316. if (animationTarget.bones[i].bonePositionSave)
  317. {
  318. animationTarget.bones[i].transform.localPosition = animationTarget.bones[i].bonePosition;
  319. animationTarget.bones[i].transform.localRotation = animationTarget.bones[i].boneRotation;
  320. }
  321. animationTarget.bones[i].transform.localScale = Vector3.one;
  322. }
  323. }
  324. if (GUILayout.Button("Position"))
  325. {
  326. for (int i = 0; i < animationTarget.bones.Length; i++)
  327. {
  328. Undo.RecordObject(animationTarget.bones[i].transform, "Reset Bone Position");
  329. if (animationTarget.bones[i].bonePositionSave)
  330. animationTarget.bones[i].transform.localPosition = animationTarget.bones[i].bonePosition;
  331. }
  332. }
  333. if (GUILayout.Button("Rotation"))
  334. {
  335. for (int i = 0; i < animationTarget.bones.Length; i++)
  336. {
  337. Undo.RecordObject(animationTarget.bones[i].transform, "Reset Bone Rotation");
  338. if (animationTarget.bones[i].bonePositionSave)
  339. animationTarget.bones[i].transform.localRotation = animationTarget.bones[i].boneRotation;
  340. }
  341. }
  342. if (GUILayout.Button("Scale"))
  343. {
  344. for (int i = 0; i < animationTarget.bones.Length; i++)
  345. {
  346. Undo.RecordObject(animationTarget.bones[i].transform, "Reset Bone Scale");
  347. animationTarget.bones[i].transform.localScale = Vector3.one;
  348. }
  349. }
  350. }
  351. EditorGUILayout.EndHorizontal();
  352. }
  353. #endregion
  354. #region Count
  355. {
  356. EditorGUILayout.LabelField("Count", animationTarget.rootBone != null ? animationTarget.bones.Length.ToString() : "");
  357. }
  358. #endregion
  359. }
  360. EditorGUI.indentLevel--;
  361. }
  362. if (animationTarget.mesh != null)
  363. {
  364. if (animationTarget.rootBone == null)
  365. {
  366. EditorGUILayout.HelpBox("Bone not found. Please create bone.", MessageType.Error);
  367. }
  368. }
  369. }
  370. if (animationTarget.rootBone != null)
  371. {
  372. EditorGUILayout.LabelField("Rig", EditorStyles.boldLabel);
  373. {
  374. EditorGUI.indentLevel++;
  375. {
  376. #region Update the Animator Avatar
  377. if (baseTarget.advancedMode)
  378. {
  379. EditorGUI.BeginChangeCheck();
  380. var updateAnimatorAvatar = EditorGUILayout.ToggleLeft("Update the Animator Avatar", animationTarget.updateAnimatorAvatar);
  381. if (EditorGUI.EndChangeCheck())
  382. {
  383. if (EditorUtility.DisplayDialog("Update the Animator Avatar", "It will be changed.\nAre you sure?", "ok", "cancel"))
  384. {
  385. UndoRecordObject("Inspector");
  386. animationTarget.updateAnimatorAvatar = updateAnimatorAvatar;
  387. baseCore.SetRendererCompornent();
  388. }
  389. }
  390. }
  391. #endregion
  392. #region AnimationType
  393. {
  394. EditorGUI.BeginChangeCheck();
  395. var rigAnimationType = (VoxelSkinnedAnimationObject.RigAnimationType)EditorGUILayout.EnumPopup("Animation Type", animationTarget.rigAnimationType);
  396. if (EditorGUI.EndChangeCheck())
  397. {
  398. UndoRecordObject("Inspector");
  399. #region ChangeAnimationType
  400. Action RemoveAnimation = () =>
  401. {
  402. EditorApplication.delayCall += () =>
  403. {
  404. if (animationTarget == null || animationTarget.gameObject == null) return;
  405. var animation = animationTarget.gameObject.GetComponent<Animation>();
  406. if (animation != null)
  407. Undo.DestroyObjectImmediate(animation);
  408. };
  409. };
  410. Action RemoveAnimator = () =>
  411. {
  412. EditorApplication.delayCall += () =>
  413. {
  414. if (animationTarget == null || animationTarget.gameObject == null) return;
  415. var animator = animationTarget.gameObject.GetComponent<Animator>();
  416. if (animator != null)
  417. Undo.DestroyObjectImmediate(animator);
  418. };
  419. };
  420. Action CreateAnimation = () =>
  421. {
  422. var animation = animationTarget.gameObject.GetComponent<Animation>();
  423. if (animation == null)
  424. {
  425. animation = animationTarget.gameObject.AddComponent<Animation>();
  426. Undo.RegisterCreatedObjectUndo(animation, "Inspector");
  427. }
  428. };
  429. Action CreateAnimator = () =>
  430. {
  431. var animator = animationTarget.gameObject.GetComponent<Animator>();
  432. if (animator == null)
  433. {
  434. animator = animationTarget.gameObject.AddComponent<Animator>();
  435. Undo.RegisterCreatedObjectUndo(animator, "Inspector");
  436. }
  437. };
  438. switch (rigAnimationType)
  439. {
  440. case VoxelSkinnedAnimationObject.RigAnimationType.None:
  441. RemoveAnimation();
  442. RemoveAnimator();
  443. break;
  444. case VoxelSkinnedAnimationObject.RigAnimationType.Legacy:
  445. RemoveAnimator();
  446. CreateAnimation();
  447. break;
  448. case VoxelSkinnedAnimationObject.RigAnimationType.Generic:
  449. case VoxelSkinnedAnimationObject.RigAnimationType.Humanoid:
  450. RemoveAnimation();
  451. CreateAnimator();
  452. break;
  453. }
  454. #endregion
  455. VoxelHumanoidConfigreAvatar.Destroy();
  456. animationTarget.rigAnimationType = rigAnimationType;
  457. animationTarget.humanDescription.firstAutomapDone = false;
  458. Refresh();
  459. }
  460. }
  461. #endregion
  462. #region Avatar
  463. if (baseTarget.advancedMode &&
  464. (animationTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Generic || animationTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Humanoid))
  465. {
  466. EditorGUILayout.BeginHorizontal();
  467. {
  468. EditorGUI.BeginDisabledGroup(true);
  469. EditorGUILayout.ObjectField("Avatar", animationTarget.avatar, typeof(Avatar), false);
  470. EditorGUI.EndDisabledGroup();
  471. }
  472. if (animationTarget.avatar != null)
  473. {
  474. if (!IsMainAsset(animationTarget.avatar))
  475. {
  476. if (GUILayout.Button("Save", GUILayout.Width(48), GUILayout.Height(16)))
  477. {
  478. #region Create Avatar
  479. string path = EditorUtility.SaveFilePanel("Save avatar", objectCore.GetDefaultPath(), string.Format("{0}_avatar.asset", baseTarget.gameObject.name), "asset");
  480. if (!string.IsNullOrEmpty(path))
  481. {
  482. if (path.IndexOf(Application.dataPath) < 0)
  483. {
  484. EditorUtility.DisplayDialog("Error!", "Please save a lower than \"Assets\"", "ok");
  485. }
  486. else
  487. {
  488. UndoRecordObject("Save Avatar");
  489. path = path.Replace(Application.dataPath, "Assets");
  490. AssetDatabase.CreateAsset(Avatar.Instantiate(animationTarget.avatar), path);
  491. animationTarget.avatar = AssetDatabase.LoadAssetAtPath<Avatar>(path);
  492. Refresh();
  493. }
  494. }
  495. #endregion
  496. }
  497. }
  498. {
  499. if (GUILayout.Button("Reset", GUILayout.Width(48), GUILayout.Height(16)))
  500. {
  501. #region Reset Avatar
  502. UndoRecordObject("Reset Avatar");
  503. animationTarget.avatar = null;
  504. Refresh();
  505. #endregion
  506. }
  507. }
  508. }
  509. EditorGUILayout.EndHorizontal();
  510. }
  511. if ((animationTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Generic || animationTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Humanoid))
  512. {
  513. EditorGUI.indentLevel++;
  514. if (animationTarget.avatar != null && !animationTarget.avatar.isValid)
  515. {
  516. EditorGUILayout.HelpBox("Invalid mecanim avatar.\nCheck the bone please.", MessageType.Error);
  517. }
  518. #region AvatarSetWarning
  519. if (animationTarget.updateAnimatorAvatar)
  520. {
  521. var animator = animationTarget.GetComponent<Animator>();
  522. if (animator != null && animator.avatar != animationTarget.avatar)
  523. {
  524. EditorGUILayout.HelpBox("Animator's Avatar is not set.\nIt needs to be updated.\nPlease press 'Refresh'.", MessageType.Warning);
  525. }
  526. }
  527. #endregion
  528. EditorGUI.indentLevel--;
  529. }
  530. #endregion
  531. #region Configre Avatar
  532. if (animationTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Humanoid)
  533. {
  534. EditorGUI.BeginDisabledGroup(isPrefab);
  535. EditorGUILayout.BeginHorizontal();
  536. EditorGUILayout.Space();
  537. if (GUILayout.Button("Configure Avatar", VoxelHumanoidConfigreAvatar.instance == null ? GUI.skin.button : guiStyleBoldActiveButton))
  538. {
  539. if (VoxelHumanoidConfigreAvatar.instance == null)
  540. VoxelHumanoidConfigreAvatar.Create(animationTarget);
  541. else
  542. VoxelHumanoidConfigreAvatar.instance.Close();
  543. }
  544. EditorGUILayout.Space();
  545. EditorGUILayout.EndHorizontal();
  546. EditorGUI.EndDisabledGroup();
  547. EditorGUILayout.Space();
  548. }
  549. #endregion
  550. }
  551. EditorGUI.indentLevel--;
  552. }
  553. }
  554. if (baseTarget.advancedMode && animationTarget.rootBone != null)
  555. {
  556. TypeTitle(animationTarget.mesh, "Mesh");
  557. {
  558. EditorGUI.indentLevel++;
  559. {
  560. #region skinnedMeshBoundsUpdate
  561. {
  562. EditorGUI.BeginChangeCheck();
  563. var skinnedMeshBoundsUpdate = EditorGUILayout.ToggleLeft("Update the Skinned Mesh Renderer Bounds", animationTarget.skinnedMeshBoundsUpdate);
  564. if (EditorGUI.EndChangeCheck())
  565. {
  566. if (EditorUtility.DisplayDialog("Update the Skinned Mesh Renderer Bounds", "It will be changed.\nAre you sure?", "ok", "cancel"))
  567. {
  568. UndoRecordObject("Inspector");
  569. animationTarget.skinnedMeshBoundsUpdate = skinnedMeshBoundsUpdate;
  570. animationCore.UpdateSkinnedMeshBounds();
  571. }
  572. }
  573. }
  574. #endregion
  575. #region skinnedMeshBoundsUpdateScale
  576. if (animationTarget.skinnedMeshBoundsUpdate)
  577. {
  578. EditorGUI.indentLevel++;
  579. EditorGUI.BeginChangeCheck();
  580. var skinnedMeshBoundsUpdateScale = EditorGUILayout.Vector3Field("Scale", animationTarget.skinnedMeshBoundsUpdateScale);
  581. if (EditorGUI.EndChangeCheck())
  582. {
  583. UndoRecordObject("Inspector");
  584. animationTarget.skinnedMeshBoundsUpdateScale = skinnedMeshBoundsUpdateScale;
  585. animationCore.UpdateSkinnedMeshBounds();
  586. }
  587. EditorGUI.indentLevel--;
  588. }
  589. #endregion
  590. }
  591. EditorGUI.indentLevel--;
  592. }
  593. }
  594. EditorGUILayout.EndVertical();
  595. }
  596. }
  597. #endregion
  598. base.InspectorGUI_Refresh();
  599. #if UNITY_2018_3_OR_NEWER
  600. {
  601. if (prefabType == PrefabAssetType.Regular && !baseCore.isPrefabEditMode)
  602. {
  603. EditorGUI.EndDisabledGroup();
  604. }
  605. }
  606. #endif
  607. }
  608. protected override void InspectorGUI_ImportOpenBefore()
  609. {
  610. base.InspectorGUI_ImportOpenBefore();
  611. VoxelHumanoidConfigreAvatar.Destroy();
  612. }
  613. protected override void InspectorGUI_ImportOffsetSetExtra(GenericMenu menu)
  614. {
  615. #region Feet
  616. menu.AddItem(new GUIContent("Feet"), false, () =>
  617. {
  618. UndoRecordObject("Inspector", true);
  619. baseTarget.importOffset = -animationCore.GetVoxelsFeet();
  620. Refresh();
  621. });
  622. #endregion
  623. }
  624. protected override void InspectorGUI_Refresh() { }
  625. protected override void SaveAllUnsavedAssets()
  626. {
  627. ContextSaveAllUnsavedAssets(new MenuCommand(baseTarget));
  628. }
  629. [MenuItem("CONTEXT/VoxelSkinnedAnimationObject/Save All Unsaved Assets")]
  630. private static void ContextSaveAllUnsavedAssets(MenuCommand menuCommand)
  631. {
  632. var objectTarget = menuCommand.context as VoxelSkinnedAnimationObject;
  633. if (objectTarget == null) return;
  634. var objectCore = new VoxelSkinnedAnimationObjectCore(objectTarget);
  635. var folder = EditorUtility.OpenFolderPanel("Save all", objectCore.GetDefaultPath(), null);
  636. if (string.IsNullOrEmpty(folder)) return;
  637. if (folder.IndexOf(Application.dataPath) < 0)
  638. {
  639. SaveInsideAssetsFolderDisplayDialog();
  640. return;
  641. }
  642. Undo.RecordObject(objectTarget, "Save All Unsaved Assets");
  643. #region Mesh
  644. if (objectTarget.mesh != null && !IsMainAsset(objectTarget.mesh))
  645. {
  646. var path = folder + "/" + string.Format("{0}_mesh.asset", objectTarget.gameObject.name);
  647. path = path.Replace(Application.dataPath, "Assets");
  648. path = AssetDatabase.GenerateUniqueAssetPath(path);
  649. AssetDatabase.CreateAsset(Mesh.Instantiate(objectTarget.mesh), path);
  650. objectTarget.mesh = AssetDatabase.LoadAssetAtPath<Mesh>(path);
  651. }
  652. #endregion
  653. #region Material
  654. if (objectTarget.materials != null)
  655. {
  656. for (int index = 0; index < objectTarget.materials.Count; index++)
  657. {
  658. if (objectTarget.materials[index] == null || IsMainAsset(objectTarget.materials[index])) continue;
  659. var path = folder + "/" + string.Format("{0}_mat{1}.mat", objectTarget.gameObject.name, index);
  660. path = path.Replace(Application.dataPath, "Assets");
  661. path = AssetDatabase.GenerateUniqueAssetPath(path);
  662. AssetDatabase.CreateAsset(Material.Instantiate(objectTarget.materials[index]), path);
  663. objectTarget.materials[index] = AssetDatabase.LoadAssetAtPath<Material>(path);
  664. }
  665. }
  666. #endregion
  667. #region Texture
  668. if (objectTarget.atlasTexture != null && !IsMainAsset(objectTarget.atlasTexture))
  669. {
  670. var path = folder + "/" + string.Format("{0}_tex.png", objectTarget.gameObject.name);
  671. {
  672. path = AssetDatabase.GenerateUniqueAssetPath(path.Replace(Application.dataPath, "Assets"));
  673. path = (Application.dataPath + path).Replace("AssetsAssets", "Assets");
  674. }
  675. File.WriteAllBytes(path, objectTarget.atlasTexture.EncodeToPNG());
  676. path = path.Replace(Application.dataPath, "Assets");
  677. AssetDatabase.ImportAsset(path);
  678. objectCore.SetTextureImporterSetting(path, objectTarget.atlasTexture);
  679. objectTarget.atlasTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
  680. }
  681. #endregion
  682. #region Avatar
  683. if (objectTarget.avatar != null && !IsMainAsset(objectTarget.avatar))
  684. {
  685. var path = folder + "/" + string.Format("{0}_avatar.asset", objectTarget.gameObject.name);
  686. path = path.Replace(Application.dataPath, "Assets");
  687. path = AssetDatabase.GenerateUniqueAssetPath(path);
  688. AssetDatabase.CreateAsset(Avatar.Instantiate(objectTarget.avatar), path);
  689. objectTarget.avatar = AssetDatabase.LoadAssetAtPath<Avatar>(path);
  690. }
  691. #endregion
  692. objectCore.ReCreate();
  693. InternalEditorUtility.RepaintAllViews();
  694. }
  695. [MenuItem("CONTEXT/VoxelSkinnedAnimationObject/Reset All Assets")]
  696. private static void ResetAllSavedAssets(MenuCommand menuCommand)
  697. {
  698. var objectTarget = menuCommand.context as VoxelSkinnedAnimationObject;
  699. if (objectTarget == null) return;
  700. var objectCore = new VoxelSkinnedAnimationObjectCore(objectTarget);
  701. Undo.RecordObject(objectTarget, "Reset All Assets");
  702. #region Mesh
  703. objectTarget.mesh = null;
  704. #endregion
  705. #region Material
  706. if (objectTarget.materials != null)
  707. {
  708. for (int i = 0; i < objectTarget.materials.Count; i++)
  709. {
  710. if (objectTarget.materials[i] == null) continue;
  711. if (!IsMainAsset(objectTarget.materials[i]))
  712. objectTarget.materials[i] = null;
  713. else
  714. objectTarget.materials[i] = Instantiate<Material>(objectTarget.materials[i]);
  715. }
  716. }
  717. #endregion
  718. #region Texture
  719. objectTarget.atlasTexture = null;
  720. #endregion
  721. #region Avatar
  722. objectTarget.avatar = null;
  723. #endregion
  724. objectCore.ReCreate();
  725. InternalEditorUtility.RepaintAllViews();
  726. }
  727. [MenuItem("CONTEXT/VoxelSkinnedAnimationObject/Export COLLADA(dae) File", false, 10000)]
  728. private static void ExportDaeFile(MenuCommand menuCommand)
  729. {
  730. var objectTarget = menuCommand.context as VoxelSkinnedAnimationObject;
  731. if (objectTarget == null) return;
  732. var objectCore = new VoxelSkinnedAnimationObjectCore(objectTarget);
  733. DaeExporterWindow.Open(objectTarget.rigAnimationType == VoxelSkinnedAnimationObject.RigAnimationType.Humanoid, () =>
  734. {
  735. string path = EditorUtility.SaveFilePanel("Export COLLADA(dae) File", objectCore.GetDefaultPath(), string.Format("{0}.dae", Path.GetFileNameWithoutExtension(objectTarget.voxelFilePath)), "dae");
  736. if (string.IsNullOrEmpty(path)) return;
  737. if (!objectCore.ExportDaeFileWithAnimation(path, DaeExporterWindow.exportMesh, DaeExporterWindow.exportAnimation, DaeExporterWindow.enableFootIK))
  738. {
  739. Debug.LogErrorFormat("<color=green>[Voxel Importer]</color> Export COLLADA(dae) File error. file:{0}", path);
  740. }
  741. });
  742. }
  743. [MenuItem("CONTEXT/VoxelSkinnedAnimationObject/Export COLLADA(dae) File", true)]
  744. private static bool IsValidateExportDaeFile(MenuCommand menuCommand)
  745. {
  746. var objectTarget = menuCommand.context as VoxelSkinnedAnimationObject;
  747. if (objectTarget == null) return false;
  748. #if UNITY_2018_3_OR_NEWER
  749. return true;
  750. #else
  751. return PrefabUtility.GetPrefabType(objectTarget) != PrefabType.Prefab;
  752. #endif
  753. }
  754. [MenuItem("CONTEXT/VoxelSkinnedAnimationObject/Remove All Voxel Importer Compornent", false, 10100)]
  755. private static void RemoveAllVoxelImporterCompornent(MenuCommand menuCommand)
  756. {
  757. var objectTarget = menuCommand.context as VoxelSkinnedAnimationObject;
  758. if (objectTarget == null) return;
  759. if (objectTarget.bones != null)
  760. {
  761. for (int i = 0; i < objectTarget.bones.Length; i++)
  762. {
  763. Undo.DestroyObjectImmediate(objectTarget.bones[i]);
  764. }
  765. }
  766. Undo.DestroyObjectImmediate(objectTarget);
  767. }
  768. }
  769. }