EditorPresetUtility.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using UnityEditor;
  7. using UnityEngine;
  8. namespace MagicaCloth
  9. {
  10. /// <summary>
  11. /// ClothParamクラスのプリセットに関するユーティリティ
  12. /// </summary>
  13. public static class EditorPresetUtility
  14. {
  15. const string configName = "preset folder";
  16. public static void DrawPresetButton(MonoBehaviour owner, ClothParams clothParam)
  17. {
  18. using (var horizontalScope = new GUILayout.HorizontalScope())
  19. {
  20. EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel);
  21. GUI.backgroundColor = Color.green;
  22. if (EditorGUILayout.DropdownButton(new GUIContent("Preset"), FocusType.Keyboard, GUILayout.Width(70), GUILayout.Height(16)))
  23. {
  24. CreatePresetPopupMenu(owner, clothParam);
  25. GUI.backgroundColor = Color.white;
  26. GUIUtility.ExitGUI();
  27. }
  28. GUI.backgroundColor = Color.white;
  29. if (GUILayout.Button("Save", GUILayout.Width(40), GUILayout.Height(16)))
  30. {
  31. SavePreset(owner, clothParam);
  32. GUIUtility.ExitGUI();
  33. }
  34. if (GUILayout.Button("Load", GUILayout.Width(40), GUILayout.Height(16)))
  35. {
  36. LoadPreset(owner, clothParam);
  37. GUIUtility.ExitGUI();
  38. }
  39. }
  40. }
  41. private static string GetComponentTypeName(MonoBehaviour owner)
  42. {
  43. string componentTypeName = string.Empty;
  44. if (owner is MagicaBoneCloth)
  45. componentTypeName = "BoneCloth";
  46. else if (owner is MagicaBoneSpring)
  47. componentTypeName = "BoneSpring";
  48. else if (owner is MagicaMeshCloth)
  49. componentTypeName = "MeshCloth";
  50. else if (owner is MagicaMeshSpring)
  51. componentTypeName = "MeshSpring";
  52. return componentTypeName;
  53. }
  54. private class PresetInfo
  55. {
  56. public string presetPath;
  57. public string presetName;
  58. public TextAsset text;
  59. }
  60. private static void CreatePresetPopupMenu(MonoBehaviour owner, ClothParams clothParam)
  61. {
  62. // コンポーネントにより検索するプリセット名を変更する
  63. string presetTypeName = GetComponentTypeName(owner);
  64. if (string.IsNullOrEmpty(presetTypeName))
  65. return;
  66. var guidArray = AssetDatabase.FindAssets($"{presetTypeName} t:" + nameof(TextAsset));
  67. if (guidArray == null)
  68. return;
  69. Dictionary<string, List<PresetInfo>> dict = new Dictionary<string, List<PresetInfo>>();
  70. foreach (var guid in guidArray)
  71. {
  72. var filePath = AssetDatabase.GUIDToAssetPath(guid);
  73. // json確認
  74. if (filePath.EndsWith(".json") == false)
  75. continue;
  76. var text = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
  77. if (text)
  78. {
  79. var info = new PresetInfo();
  80. info.presetPath = filePath;
  81. var fname = Path.GetFileNameWithoutExtension(filePath);
  82. fname = fname.Replace(presetTypeName, "");
  83. if (fname.StartsWith("_"))
  84. fname = fname.Remove(0, 1); // 頭の_は削除する
  85. info.presetName = fname;
  86. info.text = text;
  87. // ディレクトリごとに記録する
  88. var dirName = Path.GetDirectoryName(filePath);
  89. if (dict.ContainsKey(dirName) == false)
  90. {
  91. dict.Add(dirName, new List<PresetInfo>());
  92. }
  93. dict[dirName].Add(info);
  94. }
  95. }
  96. // ポップアップメニューの作成
  97. // ディレクトリごとにセパレータで分けて表示する
  98. var menu = new GenericMenu();
  99. int line = 0;
  100. foreach (var kv in dict)
  101. {
  102. if (line > 0)
  103. {
  104. menu.AddSeparator("");
  105. }
  106. foreach (var info in kv.Value)
  107. {
  108. var textAsset = info.text;
  109. var presetName = info.presetName;
  110. var presetPath = info.presetPath;
  111. menu.AddItem(new GUIContent(presetName), false, () =>
  112. {
  113. var json = textAsset.text;
  114. //Debug.Log(json);
  115. // load
  116. Debug.Log("Load preset file:" + presetPath);
  117. LoadClothParam(owner, clothParam, json);
  118. Debug.Log("Complete.");
  119. });
  120. }
  121. line++;
  122. }
  123. menu.ShowAsContext();
  124. }
  125. /// <summary>
  126. /// プリセットファイル保存
  127. /// </summary>
  128. /// <param name="clothParam"></param>
  129. private static void SavePreset(MonoBehaviour owner, ClothParams clothParam)
  130. {
  131. // フォルダを読み込み
  132. string folder = EditorUserSettings.GetConfigValue(configName);
  133. // 接頭語
  134. string presetTypeName = GetComponentTypeName(owner);
  135. // 保存ダイアログ
  136. string path = UnityEditor.EditorUtility.SaveFilePanelInProject(
  137. "Save Preset",
  138. $"{presetTypeName}_xxx",
  139. "json",
  140. "Enter a name for the preset json.",
  141. folder
  142. );
  143. if (string.IsNullOrEmpty(path))
  144. return;
  145. // フォルダを記録
  146. folder = Path.GetDirectoryName(path);
  147. EditorUserSettings.SetConfigValue(configName, folder);
  148. Debug.Log("Save preset file:" + path);
  149. // json
  150. string json = JsonUtility.ToJson(clothParam);
  151. // save
  152. File.WriteAllText(path, json);
  153. AssetDatabase.Refresh();
  154. Debug.Log("Complete.");
  155. }
  156. /// <summary>
  157. /// プリセットファイル読み込み
  158. /// </summary>
  159. /// <param name="owner"></param>
  160. /// <param name="clothParam"></param>
  161. private static void LoadPreset(MonoBehaviour owner, ClothParams clothParam)
  162. {
  163. // フォルダを読み込み
  164. string folder = EditorUserSettings.GetConfigValue(configName);
  165. // 読み込みダイアログ
  166. string path = UnityEditor.EditorUtility.OpenFilePanel("Load Preset", folder, "json");
  167. if (string.IsNullOrEmpty(path))
  168. return;
  169. // フォルダを記録
  170. folder = Path.GetDirectoryName(path);
  171. EditorUserSettings.SetConfigValue(configName, folder);
  172. // json
  173. Debug.Log("Load preset file:" + path);
  174. string json = File.ReadAllText(path);
  175. // load
  176. LoadClothParam(owner, clothParam, json);
  177. Debug.Log("Complete.");
  178. }
  179. /// <summary>
  180. /// jsonテキストからパラメータを復元する
  181. /// </summary>
  182. /// <param name="owner"></param>
  183. /// <param name="clothParam"></param>
  184. /// <param name="json"></param>
  185. private static void LoadClothParam(MonoBehaviour owner, ClothParams clothParam, string json)
  186. {
  187. if (string.IsNullOrEmpty(json) == false)
  188. {
  189. // 上書きしないプロパティを保持
  190. Transform influenceTarget = clothParam.GetInfluenceTarget();
  191. Transform disableReferenceObject = clothParam.DisableReferenceObject;
  192. //Transform directionalDampingObject = clothParam.DirectionalDampingObject;
  193. // undo
  194. Undo.RecordObject(owner, "Load preset");
  195. JsonUtility.FromJsonOverwrite(json, clothParam);
  196. // 上書きしないプロパティを書き戻し
  197. clothParam.SetInfluenceTarget(influenceTarget);
  198. clothParam.DisableReferenceObject = disableReferenceObject;
  199. //clothParam.DirectionalDampingObject = directionalDampingObject;
  200. }
  201. }
  202. }
  203. }