SuperCombinerEditor.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. //
  2. // SuperCombinerEditor.cs
  3. //
  4. // Author:
  5. // Lunar Cats Studio <lunarcatsstudio@gmail.com>
  6. //
  7. // Copyright (c) 2018 Lunar Cats Studio
  8. using UnityEditor;
  9. using UnityEngine;
  10. using System.Collections;
  11. using System.Collections.Generic;
  12. using LunarCatsStudio.SuperCombiner;
  13. namespace LunarCatsStudio.SuperCombiner
  14. {
  15. /// <summary>
  16. /// Super combiner editor class, manage gui editor for interact with super combiner script
  17. /// </summary>
  18. [CustomEditor(typeof(SuperCombiner))]
  19. public class SuperCombinerEditor : Editor
  20. {
  21. #region Inspector
  22. //private enum CombineStatesList {Uncombined, Combining, Combined}
  23. // Reference to the SuperCombiner script
  24. private SuperCombiner _superCombiner;
  25. public List<int> _TextureAtlasSizes = new List<int>() {
  26. 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192
  27. };
  28. public List<string> _TextureAtlasSizesNames = new List<string>() {
  29. "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192"
  30. };
  31. public bool _include_dependencies = true;
  32. // Constants
  33. public const int MAX_MULTI_MATERIAL_COUNT = 10;
  34. // Serialized
  35. private SerializedObject _serializedCombiner;
  36. private SerializedProperty _customShaderProperties;
  37. private List<SerializedProperty> _multiMaterialsSC = new List<SerializedProperty>();
  38. private List<int> _multiMaterialsOrder = new List<int>();
  39. // Scroll views
  40. private Vector2 _originalMaterialsPosition;
  41. private Vector2 _combinedMaterialsPosition;
  42. private Vector2 _combinedMeshsPosition;
  43. // Editor Foldouts
  44. public bool _showInstructions = true;
  45. public bool _showCombineSettings = false;
  46. public bool _showMeshSettings = false;
  47. public bool _showTextureSettings = true;
  48. public bool _showAdditionalParameters = false;
  49. public bool _showMeshResults = false;
  50. public bool _showOriginalMaterials = false;
  51. public bool _showCombinedAtlas = false;
  52. public bool _showCombinedMaterials = false;
  53. public bool _showCombinedMesh = false;
  54. public bool _showSaveOptions = false;
  55. public bool _showMultiMaterials = false;
  56. public bool _showPackageOptions = true;
  57. // Info popup to display more information about combining results
  58. private InfoPopup infoPopup;
  59. /// <summary>
  60. /// Raises the enable event.
  61. /// </summary>
  62. private void OnEnable()
  63. {
  64. _superCombiner = (SuperCombiner)target;
  65. _serializedCombiner = new SerializedObject(_superCombiner);
  66. _customShaderProperties = _serializedCombiner.FindProperty("_customTextureProperies");
  67. for (int i = 0; i < MAX_MULTI_MATERIAL_COUNT; i++)
  68. {
  69. _multiMaterialsSC.Add(_serializedCombiner.FindProperty("multiMaterials" + i));
  70. _multiMaterialsOrder.Add(i);
  71. }
  72. }
  73. /// <summary>
  74. /// Raises the inspector GUI event.
  75. /// </summary>
  76. public override void OnInspectorGUI()
  77. {
  78. EditorStyles.whiteBoldLabel.fontSize = 15;
  79. DisplayHelpSection();
  80. // Display settings sections
  81. GUILayout.Label("Combine Settings", EditorStyles.whiteBoldLabel);
  82. DisplayMainSettingsSection();
  83. DisplayTextureSettingsSection();
  84. DisplayMeshesSettingsSection();
  85. DisplayCombineButton();
  86. // Display results sections
  87. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Combined)
  88. {
  89. GUILayout.Label("Combine results", EditorStyles.whiteBoldLabel);
  90. if (_superCombiner._combinedResult != null)
  91. {
  92. DisplayWarningMessages();
  93. DisplayMeshStatsSection();
  94. DisplayCombinedAtlasSection();
  95. DisplayOriginalMaterialsSection();
  96. DisplayCombinedMaterialsSection();
  97. DisplayCombinedMeshSection();
  98. DisplaySaveSection();
  99. }
  100. else
  101. {
  102. GUILayout.Label("No reference of combine results have been found");
  103. }
  104. }
  105. else if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  106. {
  107. GUILayout.Label("Combine results", EditorStyles.whiteBoldLabel);
  108. if (_superCombiner._combinedResult != null)
  109. {
  110. DisplayWarningMessages();
  111. DisplayCombinedAtlasSection();
  112. DisplayOriginalMaterialsSection();
  113. DisplayCombinedMaterialsSection();
  114. DisplaySaveSection();
  115. }
  116. else
  117. {
  118. GUILayout.Label("No reference of combine results have been found");
  119. }
  120. }
  121. _serializedCombiner.ApplyModifiedProperties();
  122. _serializedCombiner.Update();
  123. /*#if UNITY_2017_1_OR_NEWER
  124. EditorGUIUtility.ExitGUI();
  125. #endif*/
  126. }
  127. /// <summary>
  128. ///
  129. /// </summary>
  130. private void UnCombineSession()
  131. {
  132. if (infoPopup != null)
  133. {
  134. infoPopup.Close();
  135. }
  136. _superCombiner.UnCombine();
  137. }
  138. /// <summary>
  139. /// Display the combine button.
  140. /// </summary>
  141. private void DisplayCombineButton()
  142. {
  143. EditorGUILayout.Space();
  144. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  145. {
  146. if (GUILayout.Button(new GUIContent("Combine", "This will launch the combine process of combining materials to create atlas textures and the combine meshes to adjust UVs so that they fit the new atlas."), GUILayout.MinHeight(30)))
  147. {
  148. _superCombiner.CombineChildren();
  149. }
  150. }
  151. else if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Combining)
  152. {
  153. EditorGUILayout.Space();
  154. if (GUILayout.Button(new GUIContent("Uncombine", "This will revert the combine process so that everything will be back to normal."), GUILayout.MinHeight(30)))
  155. {
  156. UnCombineSession();
  157. }
  158. Rect r = EditorGUILayout.BeginVertical();
  159. EditorGUI.ProgressBar(r, 0.1f, "Combining in progress ... ");
  160. GUILayout.Space(20);
  161. EditorGUILayout.EndVertical();
  162. }
  163. else if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  164. {
  165. if (GUILayout.Button(new GUIContent("Combine meshes", "This will finish the combine process by combining meshes to adjust UVs so that they fit the new atlas."), GUILayout.MinHeight(30)))
  166. {
  167. _superCombiner.SetTargetParentForCombinedGameObject();
  168. _superCombiner.CombineMeshes(_superCombiner._meshList, _superCombiner._skinnedMeshList, _superCombiner._targetParentForCombinedGameObjects.transform);
  169. }
  170. }
  171. else
  172. {
  173. if (GUILayout.Button(new GUIContent("Uncombine", "This will revert the combine process so that everything will be back to normal."), GUILayout.MinHeight(30)))
  174. {
  175. UnCombineSession();
  176. }
  177. }
  178. }
  179. /// <summary>
  180. /// Display the header (version number and instructions).
  181. /// </summary>
  182. private void DisplayHelpSection()
  183. {
  184. EditorGUILayout.Space();
  185. _showInstructions = EditorGUILayout.Foldout(_showInstructions, "Instructions for Super Combiner (v " + _superCombiner.versionNumber + ")");
  186. if (_showInstructions)
  187. {
  188. GUILayout.Label("Put all you prefabs to combine as children of me. " +
  189. "Select your session name, the texture atlas size and whether or not to combine meshes. " +
  190. "When you are ready click 'Combine' button to _start the process (it may take a while depending on the quantity of different assets). " +
  191. "When the process is finished you'll see the result on the scene (all original mesh renderers will be deactivated). " +
  192. "If you want to save the combined assets, select your saving options and click 'Save' button. " +
  193. "To revert the process just click 'Uncombine' button.", EditorStyles.helpBox);
  194. }
  195. EditorGUILayout.Space();
  196. }
  197. /// <summary>
  198. /// Display the main section.
  199. /// </summary>
  200. private void DisplayMainSettingsSection()
  201. {
  202. _showCombineSettings = EditorGUILayout.Foldout(_showCombineSettings, "General Settings:");
  203. if (_showCombineSettings)
  204. {
  205. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  206. {
  207. GUI.enabled = true;
  208. }
  209. else
  210. {
  211. GUI.enabled = false;
  212. }
  213. _superCombiner._sessionName = EditorGUILayout.TextField(new GUIContent("Session name", "Your session name should be different for every SuperCombiner instance. Avoid using special characters."), _superCombiner._sessionName, GUILayout.ExpandWidth(true));
  214. _superCombiner._combineAtRuntime = EditorGUILayout.Toggle(new GUIContent("Combine at runtime?", "Set to true if you want the process to combine at startup during runtime (beware that combining is a complex task that may takes some time to process)"), _superCombiner._combineAtRuntime);
  215. GUI.enabled = true;
  216. }
  217. }
  218. /// <summary>
  219. /// Display the texture section.
  220. /// </summary>
  221. private void DisplayTextureSettingsSection()
  222. {
  223. _showTextureSettings = EditorGUILayout.Foldout(_showTextureSettings, "Texture Atlas Settings:");
  224. if (_showTextureSettings)
  225. {
  226. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  227. GUI.enabled = true;
  228. else
  229. GUI.enabled = false;
  230. //GUILayout.Label ("Texture Atlas", EditorStyles.boldLabel);
  231. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  232. GUILayout.Label("The first material found in all game objects to combine will be used as a reference for the combined material.", EditorStyles.wordWrappedMiniLabel);
  233. // Atlas Texture Size choice
  234. _superCombiner._textureAtlasSize = EditorGUILayout.IntPopup("Texture Atlas size", _superCombiner._textureAtlasSize, _TextureAtlasSizesNames.ToArray(), _TextureAtlasSizes.ToArray(), GUILayout.ExpandWidth(true));
  235. _showAdditionalParameters = EditorGUILayout.Foldout(_showAdditionalParameters, "Additional parameters");
  236. if (_showAdditionalParameters)
  237. {
  238. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  239. // Multi materials group
  240. DisplayMultiMaterialSettingsSection();
  241. // Custom Shader propertues
  242. EditorGUILayout.PropertyField(_customShaderProperties, new GUIContent("Custom shader properties", "Super Combiner uses the list of texture properties from standard shader. If you are using custom shader with different texture properties, add their exact name in the list."), true);
  243. // Tiling factor
  244. _superCombiner._tilingFactor = EditorGUILayout.Slider(new GUIContent("tiling factor", "Apply a tiling factor on the textures. This may be helpfull if you observe strange artifacts after combining materials with heightmap"), _superCombiner._tilingFactor, 1, 2, GUILayout.ExpandWidth(true));
  245. //Atlas Padding
  246. _superCombiner._atlasPadding = EditorGUILayout.IntField(new GUIContent("padding", "Padding between textures in the atlas"), _superCombiner._atlasPadding, GUILayout.ExpandWidth(true));
  247. // Force UV to [0, 1] mode
  248. //_superCombiner._forceUVTo0_1 = EditorGUILayout.Toggle(new GUIContent("Force UV to [0,1]", "Only consider UV that are in [0, 1] range so that textures won't be tiled in the atlas"), _superCombiner._forceUVTo0_1);
  249. EditorGUILayout.EndVertical();
  250. }
  251. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  252. {
  253. if (GUILayout.Button(new GUIContent("Create atlas texture", "This will combine materials and create the atlas texture(s) only. This is usefull to check if atlas texture(s) are correct without having to combine meshes which is time consuming. When materials have been combined, you'll need to hit 'Combine' button to finish the process and combine meshes."), GUILayout.MinHeight(20)))
  254. {
  255. _superCombiner.FindMeshesToCombine();
  256. //_superCombiner.InitializeMultipleMaterialElements();
  257. _superCombiner.CombineMaterials(_superCombiner._meshList, _superCombiner._skinnedMeshList);
  258. }
  259. }
  260. else if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  261. {
  262. GUI.enabled = true;
  263. if (GUILayout.Button("Uncombine materials", GUILayout.MinHeight(20)))
  264. {
  265. UnCombineSession();
  266. }
  267. }
  268. EditorGUILayout.EndVertical();
  269. GUI.enabled = true;
  270. }
  271. }
  272. /// <summary>
  273. /// Display the multi _material section
  274. /// </summary>
  275. private void DisplayMultiMaterialSettingsSection()
  276. {
  277. _superCombiner._multipleMaterialsMode = EditorGUILayout.Toggle(new GUIContent("Multiple materials", "The multi material feature lets you combine to several materials (up to 10) from the listed source materials. This is usually usefull when combining meshes that have various materials (submeshes) that cannot be combined together."), _superCombiner._multipleMaterialsMode);
  278. if (_superCombiner._multipleMaterialsMode)
  279. {
  280. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  281. EditorGUILayout.LabelField("Define here every source materials for each combined material. If more materials than the one listed below are found, they will be automatically assigned to the last combined material", EditorStyles.wordWrappedLabel);
  282. _superCombiner._combineEachGroupAsSubmesh = EditorGUILayout.Toggle(new GUIContent("Set as submesh", "If set to true, each combined mesh for each material source group will be a submesh of the final combine mesh. If set to false, each material source group will be a separate mesh in a separate GameObject."), _superCombiner._combineEachGroupAsSubmesh);
  283. // Foldout
  284. EditorGUILayout.BeginHorizontal();
  285. _showMultiMaterials = EditorGUILayout.Foldout(_showMultiMaterials, "combined materials (" + _superCombiner._multiMaterialsCount + ")");
  286. // Add new _material group button
  287. EditorGUI.BeginDisabledGroup(_superCombiner._multiMaterialsCount >= MAX_MULTI_MATERIAL_COUNT);
  288. if (GUILayout.Button("+", EditorStyles.miniButtonLeft, GUILayout.MaxWidth(20f)))
  289. {
  290. _superCombiner._multiMaterialsCount++;
  291. }
  292. EditorGUI.EndDisabledGroup();
  293. // Remove new _material group button
  294. EditorGUI.BeginDisabledGroup(_superCombiner._multiMaterialsCount == 0);
  295. if (GUILayout.Button("-", EditorStyles.miniButtonRight, GUILayout.MaxWidth(20f)))
  296. {
  297. _superCombiner._multiMaterialsCount--;
  298. _serializedCombiner.Update();
  299. _multiMaterialsSC[_multiMaterialsOrder[_superCombiner._multiMaterialsCount]].ClearArray();
  300. }
  301. EditorGUI.EndDisabledGroup();
  302. EditorGUILayout.EndHorizontal();
  303. if (_showMultiMaterials)
  304. {
  305. for (int i = 0; i < _superCombiner._multiMaterialsCount; i++)
  306. {
  307. EditorGUILayout.BeginHorizontal();
  308. // Source materials
  309. EditorGUILayout.PropertyField(_multiMaterialsSC[_multiMaterialsOrder[i]], new GUIContent("source materials (group " + _multiMaterialsOrder[i] + ")", "Define here all the source material to be included in combined material " + _multiMaterialsOrder[i]), true);
  310. // Remove a _material group button
  311. if (GUILayout.Button(new GUIContent("-", "remove this combined material"), EditorStyles.miniButtonRight, GUILayout.MaxWidth(20f)))
  312. {
  313. _superCombiner._multiMaterialsCount--;
  314. _serializedCombiner.Update();
  315. _multiMaterialsSC[_multiMaterialsOrder[i]].ClearArray();
  316. SerializedProperty tmp = _multiMaterialsSC[i];
  317. _multiMaterialsSC.RemoveAt(i);
  318. _multiMaterialsSC.Add(tmp);
  319. }
  320. EditorGUILayout.EndHorizontal();
  321. }
  322. }
  323. EditorGUILayout.EndVertical();
  324. }
  325. }
  326. /// <summary>
  327. /// Display the meshes section.
  328. /// </summary>
  329. private void DisplayMeshesSettingsSection()
  330. {
  331. _showMeshSettings = EditorGUILayout.Foldout(_showMeshSettings, "Meshes Settings:");
  332. if (_showMeshSettings)
  333. {
  334. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.Uncombined || _superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  335. {
  336. GUI.enabled = true;
  337. }
  338. else
  339. {
  340. GUI.enabled = false;
  341. }
  342. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  343. // Combine MeshSettings
  344. _superCombiner._combineMeshes = EditorGUILayout.Toggle(new GUIContent("Combine meshes?", "If set to false, only materials and textures will be combined, all meshes will remain separated. If set to true, all meshes will be combined into a unique combined mesh."), _superCombiner._combineMeshes);
  345. if (_superCombiner._combineMeshes)
  346. {
  347. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  348. _superCombiner._generateUv2 = EditorGUILayout.Toggle(new GUIContent("Generate UV2?", "If set to true, Super Combiner will generate UV2 for the combined mesh."), _superCombiner._generateUv2);
  349. _superCombiner._meshOutput = EditorGUILayout.IntPopup(new GUIContent("Mesh output", "Chose to combine into a Mesh or a SkinnedMesh. Combining into SkinnedMesh is in alpha release, it will only works properly if there are only SkinnedMeshes as input. Combining Meshes and SkinnedMeshes into a SkinnedMesh is not supported yet."), _superCombiner._meshOutput, new GUIContent[] {
  350. new GUIContent ("Mesh"),
  351. new GUIContent ("SkinnedMesh (alpha)")
  352. }, new int[] {
  353. 0,
  354. 1
  355. }, GUILayout.ExpandWidth(true));
  356. // Collider Settings
  357. _superCombiner._manageColliders = EditorGUILayout.Toggle(new GUIContent("Include colliders", "If set to true, SuperCombiner will integrate all colliders into the combined GameObject"), _superCombiner._manageColliders);
  358. EditorGUILayout.EndVertical();
  359. }
  360. // LOD Level Settings
  361. EditorGUILayout.BeginHorizontal();
  362. _superCombiner._manageLodLevel = EditorGUILayout.Toggle(new GUIContent("Manage LOD level", "If set to true, SuperCombiner will only take into account the specified LOD level for each LODGroup in the list of GameObjects to combine."), _superCombiner._manageLodLevel);
  363. if (_superCombiner._manageLodLevel)
  364. {
  365. _superCombiner._managedLodLevel = EditorGUILayout.IntField(new GUIContent("LOD level to take into account", "LOD Level to take into account"), _superCombiner._managedLodLevel, GUILayout.ExpandWidth(true));
  366. }
  367. EditorGUILayout.EndHorizontal();
  368. // Target GameObject Settings
  369. _superCombiner._targetGameObject = (GameObject)EditorGUILayout.ObjectField(new GUIContent("Target GameObject", "The GameObject into which the combined GameObject(s) will be created. If you leave it empty, a new GameObject will be created under this GameObject with the name of you session name."), _superCombiner._targetGameObject, typeof(GameObject), true);
  370. /*if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  371. {
  372. if (GUILayout.Button("Combine meshes", GUILayout.MinHeight(20)))
  373. {
  374. _superCombiner.SetTargetParentForCombinedGameObject();
  375. _superCombiner.CombineMeshes(_superCombiner._meshList, _superCombiner._skinnedMeshList, _superCombiner._targetParentForCombinedGameObjects.transform);
  376. }
  377. }*/
  378. EditorGUILayout.EndVertical();
  379. GUI.enabled = true;
  380. }
  381. }
  382. #endregion // Inspector
  383. #region CombinedResult
  384. /// <summary>
  385. /// Display warning messages and button to display InfoPopup if needed
  386. /// </summary>
  387. private void DisplayWarningMessages()
  388. {
  389. /* if (_superCombiner._combinedResult._warningMessages.Count > 0)
  390. {
  391. EditorGUILayout.BeginHorizontal();
  392. GUIContent warnMessage = new GUIContent("The combine process has generated some warnings", EditorGUIUtility.IconContent("console.warnicon").image);
  393. GUIContent guiContentShowWarningsButton = new GUIContent("Show", "Click here to get more details about possible issues with this combine session");
  394. GUIContent guiContentShowWarningsButtonHide = new GUIContent("Hide", "Click here to get more details about possible issues with this combine session");
  395. GUILayout.Box(warnMessage);
  396. if (infoPopup == null)
  397. {
  398. if (GUILayout.Button(guiContentShowWarningsButton, GUILayout.ExpandHeight(true)))
  399. {
  400. infoPopup = ScriptableObject.CreateInstance<InfoPopup>();
  401. infoPopup.position = new Rect(Screen.width, Screen.height / 2, 600, 250);
  402. //infoPopup.text = Screen.width + " / " + Screen.height;
  403. foreach (string warning in _superCombiner._combinedResult._warningMessages)
  404. {
  405. infoPopup.text.Add(warning);
  406. }
  407. infoPopup.ShowPopup();
  408. }
  409. }
  410. else
  411. {
  412. if (GUILayout.Button(guiContentShowWarningsButtonHide, GUILayout.ExpandHeight(true)))
  413. {
  414. infoPopup.Close();
  415. }
  416. }
  417. EditorGUILayout.EndHorizontal();
  418. } */
  419. }
  420. /// <summary>
  421. /// Display the stats.
  422. /// </summary>
  423. private void DisplayMeshStatsSection()
  424. {
  425. _showMeshResults = EditorGUILayout.Foldout(_showMeshResults, "Meshes:");
  426. if (_showMeshResults)
  427. {
  428. GUILayout.Label("Found " + _superCombiner._combinedResult._meshesCombinedCount + " different mesh(s)");
  429. if (_superCombiner._skinnedMeshList.Count > 0)
  430. {
  431. GUILayout.Label("Found " + _superCombiner._combinedResult._skinnedMeshesCombinedCount + " different skinned mesh(es)");
  432. }
  433. }
  434. }
  435. /// <summary>
  436. /// Display the combined atlas.
  437. /// </summary>
  438. private void DisplayCombinedAtlasSection()
  439. {
  440. _showCombinedAtlas = EditorGUILayout.Foldout(_showCombinedAtlas, "Combined Atlas textures:");
  441. if (_showCombinedAtlas)
  442. {
  443. foreach (TexturePacker texturePacker in _superCombiner._texturePackers)
  444. {
  445. if (texturePacker != null && texturePacker._packedTextures.Count > 0)
  446. {
  447. EditorGUILayout.LabelField("Combined _material " + _superCombiner._combinedResult._combinedMaterials[texturePacker.CombinedIndex].displayedIndex, EditorStyles.boldLabel);
  448. foreach (KeyValuePair<string, Texture2D> keyValue in texturePacker._packedTextures)
  449. {
  450. if (keyValue.Value != null)
  451. {
  452. string PropertyName = keyValue.Key;
  453. texturePacker.TexturePropertyNames.TryGetValue(keyValue.Key, out PropertyName);
  454. EditorGUILayout.BeginVertical();
  455. //EditorGUILayout.PrefixLabel(PropertyName + " AtlasTexture preview:);
  456. EditorGUILayout.ObjectField(PropertyName + ":", keyValue.Value, typeof(Texture2D), false);
  457. EditorGUILayout.EndVertical();
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. /// <summary>
  465. /// Display the original _material(s) section.
  466. /// </summary>
  467. private void DisplayOriginalMaterialsSection()
  468. {
  469. _showOriginalMaterials = EditorGUILayout.Foldout(_showOriginalMaterials, "Original Materials (" + _superCombiner._combinedResult._materialCombinedCount + ")");
  470. if (_showOriginalMaterials)
  471. {
  472. if (_superCombiner._combinedResult._materialCombinedCount > 8)
  473. {
  474. _originalMaterialsPosition = EditorGUILayout.BeginScrollView(_originalMaterialsPosition, GUILayout.MinHeight(150));
  475. }
  476. for (int j = 0; j < _superCombiner._combinedResult._originalMaterialList.Count; j++)
  477. {
  478. foreach (MaterialToCombine mat in _superCombiner._combinedResult._originalMaterialList[j].Values)
  479. {
  480. EditorGUILayout.ObjectField("", mat._material, typeof(Material), false);
  481. }
  482. }
  483. if (_superCombiner._combinedResult._materialCombinedCount > 8)
  484. {
  485. EditorGUILayout.EndScrollView();
  486. }
  487. }
  488. if (!Selection.activeTransform)
  489. {
  490. _showOriginalMaterials = false;
  491. }
  492. }
  493. /// <summary>
  494. /// Display the combined _material section.
  495. /// </summary>
  496. private void DisplayCombinedMaterialsSection()
  497. {
  498. _showCombinedMaterials = EditorGUILayout.Foldout(_showCombinedMaterials, "Combined Materials (" + _superCombiner._combinedResult._combinedMaterialCount + ")");
  499. if (_showCombinedMaterials)
  500. {
  501. for (int i = 0; i < _superCombiner._combinedResult._combinedMaterials.Count; i++)
  502. {
  503. // TODO: The order must be correct
  504. if (_superCombiner._combinedResult._combinedMaterials[i].material != null)
  505. {
  506. EditorGUILayout.ObjectField("", _superCombiner._combinedResult._combinedMaterials[i].material, typeof(Material), false);
  507. }
  508. }
  509. }
  510. if (!Selection.activeTransform)
  511. {
  512. _showCombinedMaterials = false;
  513. }
  514. }
  515. /// <summary>
  516. /// Display the combined mesh(es) section.
  517. /// </summary>
  518. private void DisplayCombinedMeshSection()
  519. {
  520. // Display created meshes
  521. if (_superCombiner._combineMeshes)
  522. {
  523. _showCombinedMesh = EditorGUILayout.Foldout(_showCombinedMesh, "Combined Meshs (" + _superCombiner._combinedResult._meshResults.Count + ")");
  524. if (_showCombinedMesh)
  525. {
  526. if (_superCombiner._combinedResult._meshResults.Count > 5)
  527. {
  528. _combinedMeshsPosition = EditorGUILayout.BeginScrollView(_combinedMeshsPosition, GUILayout.MinHeight(100));
  529. }
  530. for (int i = 0; i < _superCombiner._combinedResult._combinedGameObjectFromMeshList.Count; i++)
  531. {
  532. // Meshes
  533. if (_superCombiner._meshOutput == 0)
  534. {
  535. if (_superCombiner._combinedResult._combinedGameObjectFromMeshList[i].Count > 0)
  536. {
  537. for (int j = 0; j < _superCombiner._combinedResult._combinedGameObjectFromMeshList[i].Count; j++)
  538. {
  539. EditorGUILayout.ObjectField("", _superCombiner._combinedResult._combinedGameObjectFromMeshList[i][j].GetComponent<MeshFilter>().sharedMesh, typeof(MeshFilter), false);
  540. }
  541. }
  542. }
  543. // SkinnedMeshes
  544. else if (_superCombiner._meshOutput == 1)
  545. {
  546. if (_superCombiner._combinedResult._combinedGameObjectFromSkinnedMeshList[i].Count > 0)
  547. {
  548. for (int j = 0; j < _superCombiner._combinedResult._combinedGameObjectFromSkinnedMeshList[i].Count; j++)
  549. {
  550. EditorGUILayout.ObjectField("", _superCombiner._combinedResult._combinedGameObjectFromSkinnedMeshList[i][j].GetComponent<SkinnedMeshRenderer>().sharedMesh, typeof(MeshFilter), false);
  551. }
  552. }
  553. }
  554. }
  555. if (_superCombiner._combinedResult._meshResults.Count > 5)
  556. {
  557. EditorGUILayout.EndScrollView();
  558. }
  559. }
  560. }
  561. }
  562. /// <summary>
  563. /// Display the save section.
  564. /// </summary>
  565. private void DisplaySaveSection()
  566. {
  567. // Saving settings
  568. _showSaveOptions = EditorGUILayout.Foldout(_showSaveOptions, "Saving settings");
  569. if (_showSaveOptions)
  570. {
  571. _superCombiner._saveMaterials = EditorGUILayout.Toggle("Save materials", _superCombiner._saveMaterials);
  572. _superCombiner._saveTextures = EditorGUILayout.Toggle("Save textures", _superCombiner._saveTextures);
  573. if (_superCombiner._combiningState == SuperCombiner.CombineStatesList.CombinedMaterials)
  574. {
  575. GUI.enabled = false;
  576. }
  577. _superCombiner._savePrefabs = EditorGUILayout.Toggle("Save prefabs", _superCombiner._savePrefabs);
  578. _superCombiner._saveMeshObj = EditorGUILayout.Toggle("Save meshes as Obj", _superCombiner._saveMeshObj);
  579. GUI.enabled = true;
  580. //this.SuperCombiner._saveMeshFbx = EditorGUILayout.Toggle ("Save meshes as Fbx", this.SuperCombiner._saveMeshFbx);
  581. if (GUILayout.Button("Save in: " + _superCombiner._folderDestination + " ...", GUILayout.MinHeight(20)))
  582. {
  583. //this.SuperCombiner._folderDestination = EditorUtility.OpenFolderPanel("Destination Directory", "", "");
  584. string folderPath = EditorUtility.SaveFolderPanel("Destination Directory", "", "combined");
  585. if (folderPath != null)
  586. {
  587. int startIndex = folderPath.IndexOf("Assets/");
  588. string relativePath = "Assets/";
  589. if (startIndex > 0)
  590. {
  591. relativePath = folderPath.Substring(startIndex);
  592. }
  593. else
  594. {
  595. Logger.Instance.AddLog("SuperCombiner", "Please, specify a folder under Assets/", Logger.LogLevel.LOG_ERROR);
  596. }
  597. _superCombiner._folderDestination = relativePath;
  598. }
  599. }
  600. }
  601. EditorGUILayout.Space();
  602. if (GUILayout.Button("Save", GUILayout.MinHeight(30)))
  603. {
  604. _superCombiner.Save();
  605. }
  606. if (AssetDatabase.IsValidFolder(_superCombiner._folderDestination))
  607. {
  608. EditorGUILayout.Space();
  609. _showPackageOptions = EditorGUILayout.Foldout(_showPackageOptions, "Unity Package Options:");
  610. if (_showPackageOptions)
  611. {
  612. _include_dependencies = EditorGUILayout.Toggle("Include Dependencies: ", _include_dependencies);
  613. }
  614. if (GUILayout.Button("Generate Unity Package", GUILayout.MinHeight(30)))
  615. {
  616. if (_include_dependencies)
  617. AssetDatabase.ExportPackage(_superCombiner._folderDestination, _superCombiner._sessionName + ".unitypackage", ExportPackageOptions.Interactive | ExportPackageOptions.Recurse | ExportPackageOptions.IncludeDependencies);
  618. else
  619. AssetDatabase.ExportPackage(_superCombiner._folderDestination, _superCombiner._sessionName + ".unitypackage", ExportPackageOptions.Interactive | ExportPackageOptions.Recurse);
  620. }
  621. }
  622. }
  623. #endregion //CombinedResult
  624. #region Menus
  625. /// <summary>
  626. /// Launch combine command for all SuperCombiner in current scene
  627. /// </summary>
  628. [MenuItem("SuperCombiner/Combine All")]
  629. static void CombineAll()
  630. {
  631. SuperCombiner[] sc_list = FindObjectsOfType<SuperCombiner>();
  632. foreach (SuperCombiner sc in sc_list)
  633. {
  634. if (sc._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  635. sc.CombineChildren();
  636. }
  637. }
  638. /// <summary>
  639. /// Launch save command for all SuperCombiner in current scene
  640. /// </summary>
  641. [MenuItem("SuperCombiner/Save All")]
  642. static void SaveAll()
  643. {
  644. SuperCombiner[] sc_list = FindObjectsOfType<SuperCombiner>();
  645. foreach (SuperCombiner sc in sc_list)
  646. {
  647. if (sc._combiningState != SuperCombiner.CombineStatesList.Uncombined)
  648. sc.Save();
  649. }
  650. }
  651. /// <summary>
  652. /// Launch uncombine command for all SuperCombiner in current scene
  653. /// </summary>
  654. [MenuItem("SuperCombiner/UnCombine All")]
  655. static void UnCombineAll()
  656. {
  657. SuperCombiner[] sc_list = FindObjectsOfType<SuperCombiner>();
  658. foreach (SuperCombiner sc in sc_list)
  659. {
  660. if (sc._combiningState != SuperCombiner.CombineStatesList.Uncombined)
  661. sc.UnCombine();
  662. }
  663. }
  664. /// <summary>
  665. /// Launch combine command for each SuperCombiner seleted in editor
  666. /// </summary>
  667. [MenuItem("SuperCombiner/Combine selected")]
  668. static void CombineSelected()
  669. {
  670. foreach (GameObject obj in Selection.gameObjects)
  671. {
  672. SuperCombiner sc = obj.GetComponent<SuperCombiner>();
  673. if (sc != null)
  674. {
  675. if (sc._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  676. sc.CombineChildren();
  677. }
  678. }
  679. }
  680. /// <summary>
  681. /// activativate "combine selected" item menu when objects with SuperCombiner component are selected
  682. /// </summary>
  683. /// <returns><c>true</c>, if SuperCombiner components are selected, <c>false</c> otherwise.</returns>
  684. [MenuItem("SuperCombiner/Combine selected", true)]
  685. static bool ValidateCombineSelected()
  686. {
  687. bool valide = false;
  688. foreach (GameObject obj in Selection.gameObjects)
  689. {
  690. if (obj.GetComponent<SuperCombiner>() != null)
  691. {
  692. valide = true;
  693. }
  694. }
  695. return valide;
  696. }
  697. /// <summary>
  698. /// Launch save command for each SuperCombiner seleted in editor
  699. /// </summary>
  700. [MenuItem("SuperCombiner/Save selected")]
  701. static void SaveSelected()
  702. {
  703. foreach (GameObject obj in Selection.gameObjects)
  704. {
  705. SuperCombiner sc = obj.GetComponent<SuperCombiner>();
  706. if (sc != null)
  707. {
  708. if (sc._combiningState != SuperCombiner.CombineStatesList.Uncombined)
  709. sc.Save();
  710. }
  711. }
  712. }
  713. /// <summary>
  714. /// activativate "save selected" item menu when objects with SuperCombiner component are selected
  715. /// </summary>
  716. /// <returns><c>true</c>, if SuperCombiner components are selected, <c>false</c> otherwise.</returns>
  717. [MenuItem("SuperCombiner/Save selected", true)]
  718. static bool ValidateSaveSelected()
  719. {
  720. bool valide = false;
  721. foreach (GameObject obj in Selection.gameObjects)
  722. {
  723. if (obj.GetComponent<SuperCombiner>() != null)
  724. {
  725. valide = true;
  726. }
  727. }
  728. return valide;
  729. }
  730. /// <summary>
  731. /// Launch uncombine command for each SuperCombiner seleted in editor
  732. /// </summary>
  733. [MenuItem("SuperCombiner/UnCombine selected")]
  734. static void UnCombineSelected()
  735. {
  736. foreach (GameObject obj in Selection.gameObjects)
  737. {
  738. SuperCombiner sc = obj.GetComponent<SuperCombiner>();
  739. if (sc != null)
  740. {
  741. if (sc._combiningState != SuperCombiner.CombineStatesList.Uncombined)
  742. sc.UnCombine();
  743. }
  744. }
  745. }
  746. /// <summary>
  747. /// activativate "uncombine selected" item menu when objects with SuperCombiner component are selected
  748. /// </summary>
  749. /// <returns><c>true</c>, if SuperCombiner components are selected, <c>false</c> otherwise.</returns>
  750. [MenuItem("SuperCombiner/UnCombine selected", true)]
  751. static bool ValidateUnCombineSelected()
  752. {
  753. bool valide = false;
  754. foreach (GameObject obj in Selection.gameObjects)
  755. {
  756. if (obj.GetComponent<SuperCombiner>() != null)
  757. {
  758. valide = true;
  759. }
  760. }
  761. return valide;
  762. }
  763. // Add a menu item called "Combine" to a superCombiner's context menu.
  764. /// <summary>
  765. /// Create contextual for Launch combine process
  766. /// </summary>
  767. /// <param name="command">Command.</param>
  768. [MenuItem("CONTEXT/SuperCombiner/Combine")]
  769. static void Combine(MenuCommand command)
  770. {
  771. Logger.Instance.AddLog("SuperCombiner", "Combine All...");
  772. SuperCombiner sc = (SuperCombiner)command.context;
  773. sc.CombineChildren();
  774. }
  775. /// <summary>
  776. /// Create contextual menu for uncombine result
  777. /// </summary>
  778. /// <param name="command">Command.</param>
  779. [MenuItem("CONTEXT/SuperCombiner/UnCombine")]
  780. static void UnCombine(MenuCommand command)
  781. {
  782. SuperCombiner sc = (SuperCombiner)command.context;
  783. sc.UnCombine();
  784. }
  785. /// <summary>
  786. /// Create contextual menu for save combine result
  787. /// </summary>
  788. /// <param name="command">Command.</param>
  789. [MenuItem("CONTEXT/SuperCombiner/Save")]
  790. static void Save(MenuCommand command)
  791. {
  792. SuperCombiner sc = (SuperCombiner)command.context;
  793. sc.Save();
  794. }
  795. /// <summary>
  796. /// Determines if we have combine result
  797. /// </summary>
  798. /// <returns><c>true</c> if is combined the specified command; otherwise, <c>false</c>.</returns>
  799. /// <param name="command">Command.</param>
  800. [MenuItem("CONTEXT/SuperCombiner/UnCombine", true)]
  801. [MenuItem("CONTEXT/SuperCombiner/Save", true)]
  802. static bool IsCombined(MenuCommand command)
  803. {
  804. SuperCombiner sc = (SuperCombiner)command.context;
  805. if (sc._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  806. return false;
  807. else
  808. return true;
  809. }
  810. /// <summary>
  811. /// Determines if is uncombined the specified command.
  812. /// </summary>
  813. /// <returns><c>true</c> if is uncombined the specified command; otherwise, <c>false</c>.</returns>
  814. /// <param name="command">Command.</param>
  815. [MenuItem("CONTEXT/SuperCombiner/Combine", true)]
  816. static bool IsUnCombined(MenuCommand command)
  817. {
  818. SuperCombiner sc = (SuperCombiner)command.context;
  819. if (sc._combiningState == SuperCombiner.CombineStatesList.Uncombined)
  820. return true;
  821. else
  822. return false;
  823. }
  824. /// <summary>
  825. /// Add a menu item to create game object with a SuperCombiner component.
  826. /// Priority 1 ensures it is grouped with the other menu items of the same kind
  827. /// and propagated to the hierarchy dropdown and hierarch context menus.
  828. /// </summary>
  829. /// <param name="menuCommand">Menu command.</param>
  830. [MenuItem("GameObject/SuperCombiner/SuperCombiner", false, 10)]
  831. static void CreateSuperCombinerGameObject(MenuCommand menuCommand)
  832. {
  833. // Create a empty game object
  834. GameObject go = new GameObject("SuperCombiner");
  835. //add supercombiner componant
  836. go.AddComponent<SuperCombiner>();
  837. // Ensure it gets reparented if this was a context click (otherwise does nothing)
  838. GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
  839. // Register the creation in the undo system
  840. Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
  841. Selection.activeObject = go;
  842. }
  843. #endregion //Menus
  844. }
  845. }