MagicaBoneClothInspector.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using UnityEditor;
  6. using UnityEngine;
  7. namespace MagicaCloth
  8. {
  9. /// <summary>
  10. /// ボーンクロスのエディタ拡張
  11. /// </summary>
  12. [CustomEditor(typeof(MagicaBoneCloth))]
  13. public class MagicaBoneClothInspector : ClothEditor
  14. {
  15. protected override void OnEnable()
  16. {
  17. base.OnEnable();
  18. }
  19. public override void OnInspectorGUI()
  20. {
  21. MagicaBoneCloth scr = target as MagicaBoneCloth;
  22. // データ状態
  23. EditorInspectorUtility.DispVersionStatus(scr);
  24. EditorInspectorUtility.DispDataStatus(scr);
  25. serializedObject.Update();
  26. Undo.RecordObject(scr, "CreateBoneCloth");
  27. // データ検証
  28. if (EditorApplication.isPlaying == false)
  29. VerifyData();
  30. // モニターボタン
  31. EditorInspectorUtility.MonitorButtonInspector();
  32. // メイン
  33. MainInspector();
  34. // コライダー
  35. ColliderInspector();
  36. // スキニング
  37. SkinningInspector();
  38. // パラメータ
  39. EditorGUILayout.Space();
  40. EditorGUILayout.Space();
  41. EditorPresetUtility.DrawPresetButton(scr, scr.Params);
  42. {
  43. var cparam = serializedObject.FindProperty("clothParams");
  44. if (EditorInspectorUtility.AlgorithmInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.Algorithm), ConvertToLatestAlgorithmParameters))
  45. scr.Params.SetChangeParam(ClothParams.ParamType.Algorithm);
  46. if (EditorInspectorUtility.RadiusInspector(cparam))
  47. scr.Params.SetChangeParam(ClothParams.ParamType.Radius);
  48. if (EditorInspectorUtility.MassInspector(cparam))
  49. scr.Params.SetChangeParam(ClothParams.ParamType.Mass);
  50. if (EditorInspectorUtility.GravityInspector(cparam))
  51. scr.Params.SetChangeParam(ClothParams.ParamType.Gravity);
  52. if (EditorInspectorUtility.ExternalForceInspector(cparam))
  53. scr.Params.SetChangeParam(ClothParams.ParamType.ExternalForce);
  54. if (EditorInspectorUtility.DragInspector(cparam))
  55. scr.Params.SetChangeParam(ClothParams.ParamType.Drag);
  56. if (EditorInspectorUtility.MaxVelocityInspector(cparam))
  57. scr.Params.SetChangeParam(ClothParams.ParamType.MaxVelocity);
  58. if (EditorInspectorUtility.WorldInfluenceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.WorldInfluence)))
  59. scr.Params.SetChangeParam(ClothParams.ParamType.WorldInfluence);
  60. if (EditorInspectorUtility.DistanceDisableInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.DistanceDisable)))
  61. scr.Params.SetChangeParam(ClothParams.ParamType.DistanceDisable);
  62. if (EditorInspectorUtility.ClampDistanceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ClampDistance)))
  63. scr.Params.SetChangeParam(ClothParams.ParamType.ClampDistance);
  64. if (EditorInspectorUtility.ClampPositionInspector(cparam, true, scr.HasChangedParam(ClothParams.ParamType.ClampPosition)))
  65. scr.Params.SetChangeParam(ClothParams.ParamType.ClampPosition);
  66. if (EditorInspectorUtility.ClampRotationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ClampRotation), scr.ClothData))
  67. scr.Params.SetChangeParam(ClothParams.ParamType.ClampRotation);
  68. if (EditorInspectorUtility.RestoreDistanceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RestoreDistance)))
  69. scr.Params.SetChangeParam(ClothParams.ParamType.RestoreDistance);
  70. if (EditorInspectorUtility.RestoreRotationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RestoreRotation), scr.ClothData))
  71. scr.Params.SetChangeParam(ClothParams.ParamType.RestoreRotation);
  72. if (scr.ClothTarget.IsMeshConnection)
  73. {
  74. if (EditorInspectorUtility.TriangleBendInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.TriangleBend), scr.ClothData))
  75. scr.Params.SetChangeParam(ClothParams.ParamType.TriangleBend);
  76. }
  77. if (EditorInspectorUtility.CollisionInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ColliderCollision)))
  78. scr.Params.SetChangeParam(ClothParams.ParamType.ColliderCollision);
  79. if (EditorInspectorUtility.PenetrationInspector(serializedObject, cparam, scr.HasChangedParam(ClothParams.ParamType.Penetration)))
  80. scr.Params.SetChangeParam(ClothParams.ParamType.Penetration);
  81. //if (EditorInspectorUtility.BaseSkinningInspector(serializedObject, cparam))
  82. // scr.Params.SetChangeParam(ClothParams.ParamType.BaseSkinning);
  83. if (EditorInspectorUtility.RotationInterpolationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RotationInterpolation)))
  84. scr.Params.SetChangeParam(ClothParams.ParamType.RotationInterpolation);
  85. }
  86. serializedObject.ApplyModifiedProperties();
  87. // データ作成
  88. if (EditorApplication.isPlaying == false)
  89. {
  90. EditorGUI.BeginDisabledGroup(CheckCreate() == false);
  91. EditorGUILayout.Space();
  92. EditorGUILayout.Space();
  93. GUI.backgroundColor = Color.red;
  94. if (GUILayout.Button("Create"))
  95. {
  96. Undo.RecordObject(scr, "CreateBoneCloth");
  97. // 共有選択データが存在しない場合は作成する
  98. if (scr.ClothSelection == null)
  99. InitSelectorData();
  100. BuildManager.CreateComponent(scr);
  101. }
  102. GUI.backgroundColor = Color.white;
  103. EditorGUI.EndDisabledGroup();
  104. }
  105. else
  106. {
  107. EditorGUILayout.Space();
  108. EditorGUILayout.Space();
  109. GUI.backgroundColor = Color.blue;
  110. if (GUILayout.Button("Reset Position"))
  111. {
  112. scr.ResetCloth();
  113. }
  114. GUI.backgroundColor = Color.white;
  115. }
  116. EditorGUILayout.Space();
  117. }
  118. //=========================================================================================
  119. /// <summary>
  120. /// 作成を実行できるか判定する
  121. /// </summary>
  122. /// <returns></returns>
  123. protected override bool CheckCreate()
  124. {
  125. if (PointSelector.EditEnable)
  126. return false;
  127. return true;
  128. }
  129. /// <summary>
  130. /// データ検証
  131. /// </summary>
  132. private void VerifyData()
  133. {
  134. MagicaBoneCloth scr = target as MagicaBoneCloth;
  135. if (scr.VerifyData() != Define.Error.None)
  136. {
  137. // 検証エラー
  138. serializedObject.ApplyModifiedProperties();
  139. }
  140. }
  141. //=========================================================================================
  142. void MainInspector()
  143. {
  144. MagicaBoneCloth scr = target as MagicaBoneCloth;
  145. EditorGUILayout.LabelField("Main Setup", EditorStyles.boldLabel);
  146. // ルートリスト
  147. EditorInspectorUtility.DrawObjectList<Transform>(
  148. serializedObject.FindProperty("clothTarget.rootList"),
  149. scr.gameObject,
  150. false, true,
  151. () => scr.gameObject.transform.root.GetComponentsInChildren<Transform>()
  152. );
  153. //EditorGUILayout.Space();
  154. // 接続モード
  155. EditorGUILayout.PropertyField(serializedObject.FindProperty("clothTarget.connection"), new GUIContent("Connection Mode"));
  156. if (scr.ClothTarget.IsMeshConnection)
  157. EditorGUILayout.PropertyField(serializedObject.FindProperty("clothTarget.sameSurfaceAngle"), new GUIContent("Same Surface Angle"));
  158. if (scr.ClothTarget.Connection == BoneClothTarget.ConnectionMode.MeshSequentialLoop || scr.ClothTarget.Connection == BoneClothTarget.ConnectionMode.MeshSequentialNoLoop)
  159. {
  160. // 警告
  161. EditorGUILayout.HelpBox("RootList must be registered in the order of connection for sequential connection.", MessageType.Info);
  162. }
  163. // チーム項目
  164. TeamBasicInspector();
  165. // アニメーション連動
  166. //scr.ClothTarget.IsAnimationBone = EditorGUILayout.Toggle("Is Animation Bones", scr.ClothTarget.IsAnimationBone);
  167. //scr.ClothTarget.IsAnimationPosition = EditorGUILayout.Toggle("Is Animation Position", scr.ClothTarget.IsAnimationPosition);
  168. //scr.ClothTarget.IsAnimationRotation = EditorGUILayout.Toggle("Is Animation Rotation", scr.ClothTarget.IsAnimationRotation);
  169. // ポイント選択
  170. DrawInspectorGUI(scr);
  171. EditorGUILayout.Space();
  172. // カリング
  173. CullingInspector();
  174. }
  175. //=========================================================================================
  176. /// <summary>
  177. /// 選択データの初期化
  178. /// 配列はすでに頂点数分が確保されゼロクリアされています。
  179. /// </summary>
  180. /// <param name="selectorData"></param>
  181. protected override void OnResetSelector(List<int> selectorData)
  182. {
  183. // ルートトランスフォームのみ固定で初期化する
  184. MagicaBoneCloth scr = target as MagicaBoneCloth;
  185. // 現在の頂点選択データをコピー
  186. // また新規データの場合はボーン階層のルートを固定化する
  187. if (scr.ClothSelection != null)
  188. {
  189. // 既存
  190. var sel = scr.ClothSelection.GetSelectionData(scr.MeshData, null);
  191. for (int i = 0; i < selectorData.Count; i++)
  192. {
  193. if (i < sel.Count)
  194. selectorData[i] = sel[i];
  195. }
  196. }
  197. else
  198. {
  199. // 新規
  200. var tlist = scr.GetTransformList();
  201. for (int i = 0; i < tlist.Count; i++)
  202. {
  203. var t = tlist[i];
  204. int data = 0;
  205. if (scr.ClothTarget.GetRootIndex(t) >= 0)
  206. {
  207. // 固定
  208. data = SelectionData.Fixed;
  209. }
  210. else
  211. {
  212. // 移動
  213. data = SelectionData.Move;
  214. }
  215. selectorData[i] = data;
  216. }
  217. }
  218. }
  219. /// <summary>
  220. /// 選択データの決定
  221. /// </summary>
  222. /// <param name="selectorData"></param>
  223. protected override void OnFinishSelector(List<int> selectorData)
  224. {
  225. MagicaBoneCloth scr = target as MagicaBoneCloth;
  226. // 必ず新規データを作成する(ヒエラルキーでのコピー対策)
  227. var sel = CreateSelection(scr, "clothSelection");
  228. // 選択データコピー
  229. sel.SetSelectionData(scr.MeshData, selectorData, null);
  230. // 現在のデータと比較し差異がない場合は抜ける
  231. if (scr.ClothSelection != null && scr.ClothSelection.Compare(sel))
  232. return;
  233. //if (scr.ClothSelection != null)
  234. // Undo.RecordObject(scr.ClothSelection, "Set Selector");
  235. // 保存
  236. var cdata = serializedObject.FindProperty("clothSelection");
  237. cdata.objectReferenceValue = sel;
  238. serializedObject.ApplyModifiedProperties();
  239. }
  240. }
  241. }