UnityEditor.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /**
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2012-2017 DragonBones team and other contributors
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  7. * this software and associated documentation files (the "Software"), to deal in
  8. * the Software without restriction, including without limitation the rights to
  9. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10. * the Software, and to permit persons to whom the Software is furnished to do so,
  11. * subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. using System.Collections.Generic;
  24. using System.IO;
  25. using UnityEngine;
  26. using UnityEditor;
  27. using UnityEditor.SceneManagement;
  28. using System.Text.RegularExpressions;
  29. namespace DragonBones
  30. {
  31. public class UnityEditor
  32. {
  33. [MenuItem("GameObject/DragonBones/Armature Object", false, 10)]
  34. private static void _CreateArmatureObjectMenuItem()
  35. {
  36. _CreateEmptyObject(GetSelectionParentTransform());
  37. }
  38. [MenuItem("Assets/Create/DragonBones/Armature Object", true)]
  39. private static bool _CreateArmatureObjectFromSkeValidateMenuItem()
  40. {
  41. return _GetDragonBonesSkePaths().Count > 0;
  42. }
  43. [MenuItem("Assets/Create/DragonBones/Armature Object", false, 10)]
  44. private static void _CreateArmatureObjectFromSkeMenuItem()
  45. {
  46. var parentTransform = GetSelectionParentTransform();
  47. foreach (var dragonBonesJSONPath in _GetDragonBonesSkePaths())
  48. {
  49. var armatureComponent = _CreateEmptyObject(parentTransform);
  50. var dragonBonesJSON = AssetDatabase.LoadMainAssetAtPath(dragonBonesJSONPath) as TextAsset;
  51. ChangeDragonBonesData(armatureComponent, dragonBonesJSON);
  52. }
  53. }
  54. [MenuItem("GameObject/DragonBones/Armature Object(UGUI)", false, 11)]
  55. private static void _CreateUGUIArmatureObjectMenuItem()
  56. {
  57. var armatureComponent = _CreateEmptyObject(GetSelectionParentTransform());
  58. armatureComponent.isUGUI = true;
  59. if (armatureComponent.GetComponentInParent<Canvas>() == null)
  60. {
  61. var canvas = GameObject.Find("/Canvas");
  62. if (canvas)
  63. {
  64. armatureComponent.transform.SetParent(canvas.transform);
  65. }
  66. }
  67. armatureComponent.transform.localScale = Vector2.one * 100.0f;
  68. armatureComponent.transform.localPosition = Vector3.zero;
  69. }
  70. [MenuItem("Assets/Create/DragonBones/Armature Object(UGUI)", true)]
  71. private static bool _CreateUGUIArmatureObjectFromJSONValidateMenuItem()
  72. {
  73. return _GetDragonBonesSkePaths().Count > 0;
  74. }
  75. [MenuItem("Assets/Create/DragonBones/Armature Object(UGUI)", false, 11)]
  76. private static void _CreateUGUIArmatureObjectFromJSOIMenuItem()
  77. {
  78. var parentTransform = GetSelectionParentTransform();
  79. foreach (var dragonBonesJSONPath in _GetDragonBonesSkePaths())
  80. {
  81. var armatureComponent = _CreateEmptyObject(parentTransform);
  82. armatureComponent.isUGUI = true;
  83. if (armatureComponent.GetComponentInParent<Canvas>() == null)
  84. {
  85. var canvas = GameObject.Find("/Canvas");
  86. if (canvas)
  87. {
  88. armatureComponent.transform.SetParent(canvas.transform);
  89. }
  90. }
  91. armatureComponent.transform.localScale = Vector2.one * 100.0f;
  92. armatureComponent.transform.localPosition = Vector3.zero;
  93. var dragonBonesJSON = AssetDatabase.LoadMainAssetAtPath(dragonBonesJSONPath) as TextAsset;
  94. ChangeDragonBonesData(armatureComponent, dragonBonesJSON);
  95. }
  96. }
  97. [MenuItem("Assets/Create/DragonBones/Create Unity Data", true)]
  98. private static bool _CreateUnityDataValidateMenuItem()
  99. {
  100. return _GetDragonBonesSkePaths(true).Count > 0;
  101. }
  102. [MenuItem("Assets/Create/DragonBones/Create Unity Data", false, 32)]
  103. private static void _CreateUnityDataMenuItem()
  104. {
  105. foreach (var dragonBonesSkePath in _GetDragonBonesSkePaths(true))
  106. {
  107. var dragonBonesSke = AssetDatabase.LoadMainAssetAtPath(dragonBonesSkePath) as TextAsset;
  108. var textureAtlasJSONs = new List<string>();
  109. GetTextureAtlasConfigs(textureAtlasJSONs, AssetDatabase.GetAssetPath(dragonBonesSke.GetInstanceID()));
  110. UnityDragonBonesData.TextureAtlas[] textureAtlas = new UnityDragonBonesData.TextureAtlas[textureAtlasJSONs.Count];
  111. for (int i = 0; i < textureAtlasJSONs.Count; ++i)
  112. {
  113. string path = textureAtlasJSONs[i];
  114. //load textureAtlas data
  115. UnityDragonBonesData.TextureAtlas ta = new UnityDragonBonesData.TextureAtlas();
  116. ta.textureAtlasJSON = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
  117. //load texture
  118. path = path.Substring(0, path.LastIndexOf(".json"));
  119. ta.texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path + ".png");
  120. //load material
  121. ta.material = AssetDatabase.LoadAssetAtPath<Material>(path + "_Mat.mat");
  122. ta.uiMaterial = AssetDatabase.LoadAssetAtPath<Material>(path + "_UI_Mat.mat");
  123. textureAtlas[i] = ta;
  124. }
  125. //
  126. CreateUnityDragonBonesData(dragonBonesSke, textureAtlas);
  127. }
  128. }
  129. public static UnityDragonBonesData.TextureAtlas[] GetTextureAtlasByJSONs(List<string> textureAtlasJSONs)
  130. {
  131. UnityDragonBonesData.TextureAtlas[] textureAtlas = new UnityDragonBonesData.TextureAtlas[textureAtlasJSONs.Count];
  132. for (int i = 0; i < textureAtlasJSONs.Count; ++i)
  133. {
  134. string path = textureAtlasJSONs[i];
  135. //load textureAtlas data
  136. UnityDragonBonesData.TextureAtlas ta = new UnityDragonBonesData.TextureAtlas();
  137. ta.textureAtlasJSON = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
  138. //load texture
  139. path = path.Substring(0, path.LastIndexOf(".json"));
  140. ta.texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path + ".png");
  141. //load material
  142. ta.material = AssetDatabase.LoadAssetAtPath<Material>(path + "_Mat.mat");
  143. ta.uiMaterial = AssetDatabase.LoadAssetAtPath<Material>(path + "_UI_Mat.mat");
  144. textureAtlas[i] = ta;
  145. }
  146. return textureAtlas;
  147. }
  148. public static bool ChangeDragonBonesData(UnityArmatureComponent _armatureComponent, TextAsset dragonBoneJSON)
  149. {
  150. if (dragonBoneJSON != null)
  151. {
  152. var textureAtlasJSONs = new List<string>();
  153. UnityEditor.GetTextureAtlasConfigs(textureAtlasJSONs, AssetDatabase.GetAssetPath(dragonBoneJSON.GetInstanceID()));
  154. UnityDragonBonesData.TextureAtlas[] textureAtlas = UnityEditor.GetTextureAtlasByJSONs(textureAtlasJSONs);
  155. UnityDragonBonesData data = UnityEditor.CreateUnityDragonBonesData(dragonBoneJSON, textureAtlas);
  156. _armatureComponent.unityData = data;
  157. var dragonBonesData = UnityFactory.factory.LoadData(data, _armatureComponent.isUGUI);
  158. if (dragonBonesData != null)
  159. {
  160. Undo.RecordObject(_armatureComponent, "Set DragonBones");
  161. _armatureComponent.unityData = data;
  162. var armatureName = dragonBonesData.armatureNames[0];
  163. ChangeArmatureData(_armatureComponent, armatureName, _armatureComponent.unityData.dataName);
  164. _armatureComponent.gameObject.name = armatureName;
  165. EditorUtility.SetDirty(_armatureComponent);
  166. return true;
  167. }
  168. else
  169. {
  170. EditorUtility.DisplayDialog("Error", "Could not load dragonBones data.", "OK", null);
  171. return false;
  172. }
  173. }
  174. else if (_armatureComponent.unityData != null)
  175. {
  176. Undo.RecordObject(_armatureComponent, "Set DragonBones");
  177. _armatureComponent.unityData = null;
  178. if (_armatureComponent.armature != null)
  179. {
  180. _armatureComponent.Dispose(false);
  181. }
  182. EditorUtility.SetDirty(_armatureComponent);
  183. return true;
  184. }
  185. return false;
  186. }
  187. public static void ChangeArmatureData(UnityArmatureComponent _armatureComponent, string armatureName, string dragonBonesName)
  188. {
  189. bool isUGUI = _armatureComponent.isUGUI;
  190. UnityDragonBonesData unityData = null;
  191. Slot slot = null;
  192. if (_armatureComponent.armature != null)
  193. {
  194. unityData = _armatureComponent.unityData;
  195. slot = _armatureComponent.armature.parent;
  196. _armatureComponent.Dispose(false);
  197. UnityFactory.factory._dragonBones.AdvanceTime(0.0f);
  198. _armatureComponent.unityData = unityData;
  199. }
  200. _armatureComponent.armatureName = armatureName;
  201. _armatureComponent.isUGUI = isUGUI;
  202. _armatureComponent = UnityFactory.factory.BuildArmatureComponent(_armatureComponent.armatureName, dragonBonesName, null, _armatureComponent.unityData.dataName, _armatureComponent.gameObject, _armatureComponent.isUGUI);
  203. if (slot != null)
  204. {
  205. slot.childArmature = _armatureComponent.armature;
  206. }
  207. _armatureComponent.sortingLayerName = _armatureComponent.sortingLayerName;
  208. _armatureComponent.sortingOrder = _armatureComponent.sortingOrder;
  209. }
  210. public static UnityEngine.Transform GetSelectionParentTransform()
  211. {
  212. var parent = Selection.activeObject as GameObject;
  213. return parent != null ? parent.transform : null;
  214. }
  215. public static void GetTextureAtlasConfigs(List<string> textureAtlasFiles, string filePath, string rawName = null, string suffix = "tex")
  216. {
  217. var folder = Directory.GetParent(filePath).ToString();
  218. var name = rawName != null ? rawName : filePath.Substring(0, filePath.LastIndexOf(".")).Substring(filePath.LastIndexOf("/") + 1);
  219. if (name.LastIndexOf("_ske") == name.Length - 4)
  220. {
  221. name = name.Substring(0, name.LastIndexOf("_ske"));
  222. }
  223. int index = 0;
  224. var textureAtlasName = "";
  225. var textureAtlasConfigFile = "";
  226. textureAtlasName = !string.IsNullOrEmpty(name) ? name + (!string.IsNullOrEmpty(suffix) ? "_" + suffix : suffix) : suffix;
  227. textureAtlasConfigFile = folder + "/" + textureAtlasName + ".json";
  228. if (File.Exists(textureAtlasConfigFile))
  229. {
  230. textureAtlasFiles.Add(textureAtlasConfigFile);
  231. return;
  232. }
  233. while (true)
  234. {
  235. textureAtlasName = (!string.IsNullOrEmpty(name) ? name + (!string.IsNullOrEmpty(suffix) ? "_" + suffix : suffix) : suffix) + "_" + (index++);
  236. textureAtlasConfigFile = folder + "/" + textureAtlasName + ".json";
  237. if (File.Exists(textureAtlasConfigFile))
  238. {
  239. textureAtlasFiles.Add(textureAtlasConfigFile);
  240. }
  241. else if (index > 1)
  242. {
  243. break;
  244. }
  245. }
  246. if (textureAtlasFiles.Count > 0 || rawName != null)
  247. {
  248. return;
  249. }
  250. GetTextureAtlasConfigs(textureAtlasFiles, filePath, "", suffix);
  251. if (textureAtlasFiles.Count > 0)
  252. {
  253. return;
  254. }
  255. index = name.LastIndexOf("_");
  256. if (index >= 0)
  257. {
  258. name = name.Substring(0, index);
  259. GetTextureAtlasConfigs(textureAtlasFiles, filePath, name, suffix);
  260. if (textureAtlasFiles.Count > 0)
  261. {
  262. return;
  263. }
  264. GetTextureAtlasConfigs(textureAtlasFiles, filePath, name, "");
  265. if (textureAtlasFiles.Count > 0)
  266. {
  267. return;
  268. }
  269. }
  270. if (suffix != "texture")
  271. {
  272. GetTextureAtlasConfigs(textureAtlasFiles, filePath, null, "texture");
  273. }
  274. }
  275. public static UnityDragonBonesData CreateUnityDragonBonesData(TextAsset dragonBonesAsset, UnityDragonBonesData.TextureAtlas[] textureAtlas)
  276. {
  277. if (dragonBonesAsset != null)
  278. {
  279. bool isDirty = false;
  280. string path = AssetDatabase.GetAssetPath(dragonBonesAsset);
  281. path = path.Substring(0, path.Length - 5);
  282. int index = path.LastIndexOf("_ske");
  283. if (index > 0)
  284. {
  285. path = path.Substring(0, index);
  286. }
  287. //
  288. string dataPath = path + "_Data.asset";
  289. var jsonObject = (Dictionary<string, object>)MiniJSON.Json.Deserialize(dragonBonesAsset.text);
  290. if (dragonBonesAsset.text == "DBDT")
  291. {
  292. int headerLength = 0;
  293. jsonObject = BinaryDataParser.DeserializeBinaryJsonData(dragonBonesAsset.bytes, out headerLength);
  294. }
  295. else
  296. {
  297. jsonObject = MiniJSON.Json.Deserialize(dragonBonesAsset.text) as Dictionary<string, object>;
  298. }
  299. var dataName = jsonObject.ContainsKey("name") ? jsonObject["name"] as string : "";
  300. //先从缓存里面取
  301. UnityDragonBonesData data = UnityFactory.factory.GetCacheUnityDragonBonesData(dataName);
  302. //缓存中没有,从资源里面取
  303. if (data == null)
  304. {
  305. data = AssetDatabase.LoadAssetAtPath<UnityDragonBonesData>(dataPath);
  306. }
  307. //资源里面也没有,那么重新创建
  308. if (data == null)
  309. {
  310. data = UnityDragonBonesData.CreateInstance<UnityDragonBonesData>();
  311. data.dataName = dataName;
  312. AssetDatabase.CreateAsset(data, dataPath);
  313. isDirty = true;
  314. }
  315. //
  316. if (string.IsNullOrEmpty(data.dataName) || !data.dataName.Equals(dataName))
  317. {
  318. //走到这里,说明原先已经创建了,之后手动改了名字,既然又走了创建流程,那么名字也重置下
  319. data.dataName = dataName;
  320. isDirty = true;
  321. }
  322. if (data.dragonBonesJSON != dragonBonesAsset)
  323. {
  324. data.dragonBonesJSON = dragonBonesAsset;
  325. isDirty = true;
  326. }
  327. if (textureAtlas != null && textureAtlas.Length > 0 && textureAtlas[0] != null && textureAtlas[0].texture != null)
  328. {
  329. if (data.textureAtlas == null || data.textureAtlas.Length != textureAtlas.Length)
  330. {
  331. isDirty = true;
  332. }
  333. else
  334. {
  335. for (int i = 0; i < textureAtlas.Length; ++i)
  336. {
  337. if (textureAtlas[i].material != data.textureAtlas[i].material ||
  338. textureAtlas[i].uiMaterial != data.textureAtlas[i].uiMaterial ||
  339. textureAtlas[i].texture != data.textureAtlas[i].texture ||
  340. textureAtlas[i].textureAtlasJSON != data.textureAtlas[i].textureAtlasJSON
  341. )
  342. {
  343. isDirty = true;
  344. break;
  345. }
  346. }
  347. }
  348. data.textureAtlas = textureAtlas;
  349. }
  350. if (isDirty)
  351. {
  352. AssetDatabase.Refresh();
  353. EditorUtility.SetDirty(data);
  354. }
  355. //
  356. UnityFactory.factory.AddCacheUnityDragonBonesData(data);
  357. AssetDatabase.SaveAssets();
  358. return data;
  359. }
  360. return null;
  361. }
  362. private static List<string> _GetDragonBonesSkePaths(bool isCreateUnityData = false)
  363. {
  364. var dragonBonesSkePaths = new List<string>();
  365. foreach (var guid in Selection.assetGUIDs)
  366. {
  367. var assetPath = AssetDatabase.GUIDToAssetPath(guid);
  368. if (assetPath.EndsWith(".json"))
  369. {
  370. var jsonCode = File.ReadAllText(assetPath);
  371. if (jsonCode.IndexOf("\"armature\":") > 0)
  372. {
  373. dragonBonesSkePaths.Add(assetPath);
  374. }
  375. }
  376. if (assetPath.EndsWith(".bytes"))
  377. {
  378. TextAsset asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath);
  379. if (asset && asset.text == "DBDT")
  380. {
  381. dragonBonesSkePaths.Add(assetPath);
  382. }
  383. }
  384. else if (!isCreateUnityData && assetPath.EndsWith("_Data.asset"))
  385. {
  386. UnityDragonBonesData data = AssetDatabase.LoadAssetAtPath<UnityDragonBonesData>(assetPath);
  387. dragonBonesSkePaths.Add(AssetDatabase.GetAssetPath(data.dragonBonesJSON));
  388. }
  389. }
  390. return dragonBonesSkePaths;
  391. }
  392. private static UnityArmatureComponent _CreateEmptyObject(UnityEngine.Transform parentTransform)
  393. {
  394. var gameObject = new GameObject("New Armature Object", typeof(UnityArmatureComponent));
  395. var armatureComponent = gameObject.GetComponent<UnityArmatureComponent>();
  396. gameObject.transform.SetParent(parentTransform, false);
  397. //
  398. EditorUtility.FocusProjectWindow();
  399. Selection.activeObject = gameObject;
  400. EditorGUIUtility.PingObject(Selection.activeObject);
  401. Undo.RegisterCreatedObjectUndo(gameObject, "Create Armature Object");
  402. EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
  403. return armatureComponent;
  404. }
  405. }
  406. }