SuperCombiner.cs 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System;
  5. using System.IO;
  6. using System.Text;
  7. using LunarCatsStudio.SuperCombiner;
  8. using System.Linq;
  9. #if UNITY_EDITOR
  10. using UnityEditor;
  11. #endif
  12. namespace LunarCatsStudio.SuperCombiner
  13. {
  14. /// <summary>
  15. /// Main class of Super Combiner asset.
  16. /// </summary>
  17. public class SuperCombiner : MonoBehaviour
  18. {
  19. public string versionNumber { get { return "1.6.6"; } }
  20. public enum CombineStatesList
  21. {
  22. Uncombined,
  23. Combining,
  24. CombinedMaterials,
  25. Combined
  26. }
  27. public CombineStatesList _combiningState = CombineStatesList.Uncombined;
  28. public List<LunarCatsStudio.SuperCombiner.TexturePacker> _texturePackers = new List<LunarCatsStudio.SuperCombiner.TexturePacker>();
  29. public LunarCatsStudio.SuperCombiner.MeshCombiner _meshCombiner = new LunarCatsStudio.SuperCombiner.MeshCombiner();
  30. // Editable Parameters
  31. // General settings
  32. public string _sessionName = "combinedSession";
  33. public bool _combineAtRuntime = false;
  34. // Texture Atlas settings
  35. public int _textureAtlasSize = 2048;
  36. public List<string> _customTextureProperies = new List<string>();
  37. public float _tilingFactor = 1f;
  38. public int _atlasPadding = 0;
  39. public bool _combineMaterials = true;
  40. public bool _forceUVTo0_1 = false;
  41. // Multiple materials
  42. public bool _multipleMaterialsMode = false;
  43. public bool _combineEachGroupAsSubmesh = false;
  44. public List<Material> multiMaterials0 = new List<Material>();
  45. public List<Material> multiMaterials1 = new List<Material>();
  46. public List<Material> multiMaterials2 = new List<Material>();
  47. public List<Material> multiMaterials3 = new List<Material>();
  48. public List<Material> multiMaterials4 = new List<Material>();
  49. public List<Material> multiMaterials5 = new List<Material>();
  50. public List<Material> multiMaterials6 = new List<Material>();
  51. public List<Material> multiMaterials7 = new List<Material>();
  52. public List<Material> multiMaterials8 = new List<Material>();
  53. public List<Material> multiMaterials9 = new List<Material>();
  54. public List<Material> multiMaterials10 = new List<Material>();
  55. public List<Material> multiMaterialsAllOthers = new List<Material>();
  56. // Meshes settings
  57. public bool _combineMeshes = false;
  58. public bool _manageLodLevel = false;
  59. public int _managedLodLevel = 0;
  60. public bool _generateUv2 = true;
  61. public int _meshOutput;
  62. public bool _manageColliders = false;
  63. public GameObject _targetGameObject;
  64. /// <summary>
  65. /// The list of multi _material list defined by user
  66. /// </summary>
  67. public List<List<Material>> _multiMaterialsList = new List<List<Material>>();
  68. public int _multiMaterialsCount;
  69. /// <summary>
  70. /// The list of _material list to combine
  71. /// </summary>
  72. List<List<MaterialToCombine>> _materialsToCombine = new List<List<MaterialToCombine>>();
  73. // Saving options
  74. public bool _savePrefabs = true;
  75. public bool _saveMeshObj = false;
  76. public bool _saveMeshFbx = false;
  77. public bool _saveMaterials = true;
  78. public bool _saveTextures = true;
  79. public string _folderDestination = "Assets/SuperCombiner/Combined";
  80. // Internal combine process variables
  81. /// <summary>
  82. /// List of all original MeshRenderer in children to combine
  83. /// </summary>
  84. public List<RendererObject<MeshRenderer>> _meshList = new List<RendererObject<MeshRenderer>>();
  85. /// <summary>
  86. /// List of all original SkinnedMeshRenderer in children to combine
  87. /// </summary>
  88. public List<RendererObject<SkinnedMeshRenderer>> _skinnedMeshList = new List<RendererObject<SkinnedMeshRenderer>>();
  89. /// <summary>
  90. /// List of copied meshes instancesId associated with their original sharedMesh and sharedMaterial instanceId.
  91. /// This is usefull not to save duplicated mesh when exporting
  92. /// Key=Mesh instanceID
  93. /// Value=Concatenation of sharedMeshName + sharedMaterialName + GameObjectName
  94. /// </summary>
  95. public Dictionary<int, string> _uniqueCombinedMeshId = new Dictionary<int, string>();
  96. /// <summary>
  97. /// Links original shared meshes with the copy created
  98. /// Key=original shared mesh instanceID
  99. /// Value=The value of _uniqueCombinedMeshId[Key]
  100. /// </summary>
  101. public Dictionary<int, string> _copyMeshId = new Dictionary<int, string>();
  102. /// <summary>
  103. /// List of transformed game objects for prefab saving
  104. /// </summary>
  105. public List<GameObject> _toSavePrefabList = new List<GameObject>();
  106. /// <summary>
  107. /// List of transformed game objects for saving purpose
  108. /// </summary>
  109. public List<MeshRenderer> _toSaveObjectList = new List<MeshRenderer>();
  110. /// <summary>
  111. /// List of meshes to save
  112. /// </summary>
  113. public List<Mesh> _toSaveMeshList = new List<Mesh>();
  114. /// <summary>
  115. /// List of transformed skinned game objects for saving purpose
  116. /// </summary>
  117. public List<SkinnedMeshRenderer> _toSaveSkinnedObjectList = new List<SkinnedMeshRenderer>();
  118. // <summary>
  119. // CombinedGameObjects[i] will use uvs[combinedTextureIndex[i]]
  120. // </summary>
  121. //public List<int> combinedTextureIndex = new List<int>();
  122. /// <summary>
  123. /// The parent GameObject for every combined object
  124. /// </summary>
  125. public GameObject _targetParentForCombinedGameObjects;
  126. private DateTime _timeStart; // The date time when starting the process
  127. /// <summary>
  128. /// The result of the combine process is stored in this class. It is instanciated the first time combine process is executed
  129. /// </summary>
  130. public CombinedResult _combinedResult;
  131. /// <summary>
  132. /// input setting of supper combiner
  133. /// </summary>
  134. public SuperCombinerSettings _scSettings;
  135. private SuperCombiner()
  136. {
  137. // Nothing to do here
  138. }
  139. void Start()
  140. {
  141. if (_combineAtRuntime)
  142. {
  143. CombineChildren();
  144. }
  145. }
  146. /// <summary>
  147. /// Find and fill the list of enabled meshes to combine
  148. /// </summary>
  149. public void FindMeshesToCombine()
  150. {
  151. _meshList = FindEnabledMeshes(transform);
  152. _skinnedMeshList = FindEnabledSkinnedMeshes(transform);
  153. }
  154. /// <summary>
  155. /// Combine process
  156. /// </summary>
  157. public void CombineChildren()
  158. {
  159. Logger.Instance.ClearLogs();
  160. _timeStart = DateTime.Now;
  161. _combiningState = CombineStatesList.Combining;
  162. // Getting the list of meshes ...
  163. FindMeshesToCombine();
  164. Combine(_meshList, _skinnedMeshList);
  165. }
  166. /// <summary>
  167. /// Combine Materials and Create Atlas texture
  168. /// </summary>
  169. /// <param name="meshesToCombine"></param>
  170. /// <param name="skinnedMeshesToCombine"></param>
  171. /// <returns>True if process has been successfull</returns>
  172. public bool CombineMaterials(List<RendererObject<MeshRenderer>> meshesToCombine, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshesToCombine)
  173. {
  174. #if UNITY_EDITOR
  175. // UI Progress bar display in Editor
  176. EditorUtility.DisplayProgressBar("Super Combiner", "Materials and textures listing...", 0.1f);
  177. #endif
  178. // Initialize multi _material parameters
  179. InitializeMultipleMaterialElements();
  180. // If _combinedResult has not been created yet, create it
  181. if (_combinedResult == null)
  182. {
  183. _combinedResult = (CombinedResult)ScriptableObject.CreateInstance(typeof(CombinedResult));
  184. }
  185. // Getting list of materials
  186. List<MaterialToCombine> enabledMaterials = FindEnabledMaterials(meshesToCombine, skinnedMeshesToCombine);
  187. _combinedResult._materialCombinedCount = enabledMaterials.Count;
  188. foreach (MaterialToCombine mat in enabledMaterials)
  189. {
  190. bool found = false;
  191. for (int i = 0; i < _multiMaterialsList.Count; i++)
  192. {
  193. if (_multiMaterialsList[i].Contains(mat._material))
  194. {
  195. // This _material was listed in the multi _material list by user, we add it to it's right _index in '_materialsToCombine' list
  196. _materialsToCombine[i].Add(mat);
  197. found = true;
  198. }
  199. }
  200. if (!found)
  201. {
  202. // This _material was not listed in the multi _material list, so we add it to the last element
  203. _materialsToCombine[_materialsToCombine.Count - 1].Add(mat);
  204. }
  205. }
  206. // List all texture from enabled materials to be combined
  207. int progressCount = 0;
  208. for (int i = 0; i < _materialsToCombine.Count; i++)
  209. {
  210. _combinedResult._originalMaterialList.Add(new Dictionary<int, MaterialToCombine>());
  211. _combinedResult.AddNewCombinedMaterial();
  212. if (i == _multiMaterialsList.Count && _materialsToCombine[i].Count > 0 || i < _multiMaterialsList.Count && _multiMaterialsList[i].Count > 0)
  213. {
  214. // Instanciate a new texture Packer
  215. TexturePacker texturePacker = new TexturePacker
  216. {
  217. // Assign the _combinedResult reference to texturePacker
  218. CombinedResult = _combinedResult,
  219. CombinedIndex = i
  220. };
  221. // Setting up the custom shader property _names
  222. texturePacker.SetCustomPropertyNames(_customTextureProperies);
  223. // Add this texture packer to the list
  224. _texturePackers.Add(texturePacker);
  225. foreach (MaterialToCombine mat in _materialsToCombine[i])
  226. {
  227. _combinedResult.AddMaterialToCombine(mat, i);
  228. #if UNITY_EDITOR
  229. // Cancelable UI Progress bar display in Editor
  230. bool cancel = false;
  231. EditorUtility.DisplayProgressBar("Super Combiner", "Processing _material " + mat._material.name, progressCount / (float)enabledMaterials.Count);
  232. if (cancel)
  233. {
  234. UnCombine();
  235. return false;
  236. }
  237. #endif
  238. /*Rect materialUVBoundToUse = mat.GetScaledAndOffsetedUVBounds();
  239. if(_forceUVTo0_1)
  240. {
  241. materialUVBoundToUse = new Rect(0, 0, 1, 1);
  242. }*/
  243. // Add all textures from this material on the list of textures
  244. texturePacker.SetTextures(mat._material, _combineMaterials, mat, _tilingFactor);
  245. /*if (!mat.HasProperty ("_MainTex") || mat.mainTexture == null) {
  246. // Correction of uv for mesh without diffuse texture
  247. uvBound.size = Vector2.Scale (uvBound.size, new Vector2 (1.2f, 1.2f));
  248. uvBound.position -= new Vector2 (0.1f, 0.1f);
  249. }*/
  250. progressCount++;
  251. }
  252. if (_materialsToCombine[i].Count == 0)
  253. {
  254. if (_multiMaterialsList[i].Count == 0)
  255. {
  256. Logger.Instance.AddLog("SuperCombiner", "Source materials group " + i + " is empty. Skipping this combine process", Logger.LogLevel.LOG_WARNING);
  257. }
  258. else
  259. {
  260. Logger.Instance.AddLog("SuperCombiner", "Cannot combined materials for group " + i + " because none of the _material were found in the list of game objects to combine", Logger.LogLevel.LOG_WARNING);
  261. }
  262. }
  263. else if (_materialsToCombine[i].Count == 1)
  264. {
  265. if (_materialsToCombine.Count == 1)
  266. {
  267. Logger.Instance.AddLog("SuperCombiner", "Only one material found, skipping combine material process and keep this material (" + _materialsToCombine[i][0]._material.name + ") for the combined mesh.");
  268. }
  269. else
  270. {
  271. Logger.Instance.AddLog("SuperCombiner", "Only one material found for multi material group " + i + ", skipping combine material process and keep this material (" + _materialsToCombine[i][0]._material.name + ") for the combined mesh.");
  272. }
  273. _combinedResult.SetCombinedMaterial(_materialsToCombine[i][0]._material, i, true);
  274. _combinedResult._combinedMaterials[i].uvs = new Rect[1];
  275. _combinedResult._combinedMaterials[i].uvs[0] = new Rect(0, 0, 1, 1);
  276. texturePacker.SetCopiedMaterial(_materialsToCombine[i][0]._material);
  277. }
  278. else
  279. {
  280. #if UNITY_EDITOR
  281. // UI Progress bar display in Editor
  282. EditorUtility.DisplayProgressBar("Super Combiner", "Packing textures...", 0f);
  283. #endif
  284. // Pack the textures
  285. texturePacker.PackTextures(_textureAtlasSize, _atlasPadding, _combineMaterials, _sessionName);
  286. }
  287. }
  288. else
  289. {
  290. // There are no materials to combine in this _combinedIndex
  291. _texturePackers.Add(null);
  292. }
  293. }
  294. _combiningState = CombineStatesList.CombinedMaterials;
  295. #if UNITY_EDITOR
  296. EditorUtility.ClearProgressBar();
  297. #endif
  298. return false;
  299. }
  300. public void SetTargetParentForCombinedGameObject()
  301. {
  302. if (_targetGameObject == null)
  303. {
  304. // Create the parent Game object
  305. _targetParentForCombinedGameObjects = new GameObject(_sessionName);
  306. _targetParentForCombinedGameObjects.transform.parent = this.transform;
  307. _targetParentForCombinedGameObjects.transform.localPosition = Vector3.zero;
  308. }
  309. else
  310. {
  311. _targetParentForCombinedGameObjects = _targetGameObject;
  312. }
  313. }
  314. /// <summary>
  315. /// Combines the meshes
  316. /// </summary>
  317. /// <param name="meshesToCombine">Meshes to combine.</param>
  318. /// <param name="skinnedMeshesToCombine">Skinned meshes to combine.</param>
  319. public void CombineMeshes(List<RendererObject<MeshRenderer>> meshesToCombine, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshesToCombine, Transform parent)
  320. {
  321. // Assign the _combinedResult reference to texturePacker and MeshCombiner
  322. _meshCombiner.CombinedResult = _combinedResult;
  323. _combinedResult._meshesCombinedCount = meshesToCombine.Count;
  324. _combinedResult._skinnedMeshesCombinedCount = skinnedMeshesToCombine.Count;
  325. // Check if there is at least 2 meshes in the current combine session
  326. if (_combineMeshes)
  327. {
  328. // Careful here we do not take into account renderers that will not be combined from the list
  329. if (meshesToCombine.Count + skinnedMeshesToCombine.Count < 1)
  330. {
  331. if (meshesToCombine.Count == 0)
  332. {
  333. #if UNITY_EDITOR
  334. EditorUtility.DisplayDialog("Super Combiner", "Zero meshes found.\nUnable to proceed without at least 1 mesh.", "Ok");
  335. #endif
  336. UnCombine();
  337. }
  338. return;
  339. }
  340. }
  341. // Parametrize MeshCombiner
  342. _meshCombiner.SetParameters(_sessionName, _generateUv2);
  343. #if UNITY_EDITOR
  344. // UI Progress bar display in Editor
  345. EditorUtility.DisplayProgressBar("Super Combiner", "Combining meshes", 0.5f);
  346. #endif
  347. // Combine process
  348. if (_combineMeshes)
  349. {
  350. // Get the ordered by _combinedIndex list of meshes to combine
  351. List<MeshRendererAndOriginalMaterials> meshIndexedList = GetMeshRenderersByCombineIndex(meshesToCombine, skinnedMeshesToCombine, _targetParentForCombinedGameObjects.transform);
  352. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  353. {
  354. _combinedResult._combinedGameObjectFromMeshList.Add(new List<GameObject>());
  355. _combinedResult._combinedGameObjectFromSkinnedMeshList.Add(new List<GameObject>());
  356. if (_combinedResult._originalMaterialList[i].Count > 0)
  357. {
  358. if ((LunarCatsStudio.SuperCombiner.MeshOutput)_meshOutput == LunarCatsStudio.SuperCombiner.MeshOutput.Mesh)
  359. {
  360. // Combine the meshes together
  361. _combinedResult._combinedGameObjectFromMeshList[i] = _meshCombiner.CombineToMeshes(meshIndexedList[i]._meshRenderers, meshIndexedList[i]._skinnedMeshRenderers, parent, i);
  362. // Add the copy mesh instanceId with its original sharedMesh and sharedMaterial instanceId
  363. if (!_combineEachGroupAsSubmesh)
  364. {
  365. foreach (GameObject go in _combinedResult._combinedGameObjectFromMeshList[i])
  366. {
  367. _uniqueCombinedMeshId.Add(go.GetComponent<MeshFilter>().sharedMesh.GetInstanceID(), go.name);
  368. }
  369. }
  370. }
  371. else
  372. {
  373. _combinedResult._combinedGameObjectFromSkinnedMeshList[i] = _meshCombiner.CombineToSkinnedMeshes(meshIndexedList[i]._meshRenderers, meshIndexedList[i]._skinnedMeshRenderers, parent, i);
  374. if (!_combineEachGroupAsSubmesh)
  375. {
  376. // Add the copy mesh instanceId with its original sharedMesh and sharedMaterial instanceId
  377. foreach (GameObject go in _combinedResult._combinedGameObjectFromSkinnedMeshList[i])
  378. {
  379. _uniqueCombinedMeshId.Add(go.GetComponent<SkinnedMeshRenderer>().sharedMesh.GetInstanceID(), go.name);
  380. }
  381. }
  382. }
  383. if (_combinedResult._combinedGameObjectFromMeshList.Count + _combinedResult._combinedGameObjectFromSkinnedMeshList.Count == 0)
  384. {
  385. Logger.Instance.AddLog("SuperCombiner", "No mesh could be combined", Logger.LogLevel.LOG_ERROR);
  386. // Error, Nothing could be combined
  387. //UnCombine();
  388. //return;
  389. }
  390. }
  391. // Remove all temporary splitted GameObjects created
  392. for (int j = 0; j < meshIndexedList[i]._splittedGameObject.Count; j++)
  393. {
  394. DestroyImmediate(meshIndexedList[i]._splittedGameObject[j]);
  395. }
  396. }
  397. // Combine each material group to a submesh to a unique combined mesh
  398. if (_multipleMaterialsMode && _combineEachGroupAsSubmesh)
  399. {
  400. List<Mesh> meshes = new List<Mesh>();
  401. for (int i = 0; i < _combinedResult._combinedGameObjectFromMeshList.Count; i++)
  402. {
  403. if (_combinedResult._combinedGameObjectFromMeshList[i].Count > 0)
  404. {
  405. if ((LunarCatsStudio.SuperCombiner.MeshOutput)_meshOutput == LunarCatsStudio.SuperCombiner.MeshOutput.Mesh)
  406. {
  407. MeshFilter mf = _combinedResult._combinedGameObjectFromMeshList[i][0].GetComponent<MeshFilter>();
  408. meshes.Add(mf.sharedMesh);
  409. // Destroy the combined GameObject as we do not need it anymore
  410. DestroyImmediate(_combinedResult._combinedGameObjectFromMeshList[i][0]);
  411. }
  412. else
  413. {
  414. SkinnedMeshRenderer mf = _combinedResult._combinedGameObjectFromSkinnedMeshList[i][0].GetComponent<SkinnedMeshRenderer>();
  415. meshes.Add(mf.sharedMesh);
  416. // Destroy the combined GameObject as we do not need it anymore
  417. DestroyImmediate(_combinedResult._combinedGameObjectFromSkinnedMeshList[i][0]);
  418. }
  419. }
  420. }
  421. // Get the combined mesh with submeshes
  422. GameObject go = _meshCombiner.CombineMeshToSubmeshes(meshes, (LunarCatsStudio.SuperCombiner.MeshOutput)_meshOutput);
  423. go.transform.SetParent(parent);
  424. go.transform.localPosition = Vector3.zero;
  425. // Add the copy mesh instanceId with its original sharedMesh and sharedMaterial instanceId
  426. if ((LunarCatsStudio.SuperCombiner.MeshOutput)_meshOutput == LunarCatsStudio.SuperCombiner.MeshOutput.Mesh)
  427. {
  428. _combinedResult._combinedGameObjectFromMeshList[0][0] = go;
  429. _uniqueCombinedMeshId.Add(go.GetComponent<MeshFilter>().sharedMesh.GetInstanceID(), go.name);
  430. }
  431. else
  432. {
  433. _combinedResult._combinedGameObjectFromSkinnedMeshList[0][0] = go;
  434. _uniqueCombinedMeshId.Add(go.GetComponent<SkinnedMeshRenderer>().sharedMesh.GetInstanceID(), go.name);
  435. }
  436. }
  437. // Manage Colliders if needed
  438. if (_manageColliders)
  439. {
  440. // Create new parent GameObject for all colliders
  441. GameObject collidersParent = new GameObject("colliders");
  442. collidersParent.transform.parent = parent;
  443. Collider[] colliders = transform.GetComponentsInChildren<Collider>();
  444. foreach (Collider collider in colliders)
  445. {
  446. if (collider != null && collider.enabled)
  447. {
  448. CollidersHandler.CreateNewCollider(collidersParent.transform, collider);
  449. }
  450. }
  451. }
  452. }
  453. else
  454. {
  455. // Create a copy of all game objects children of this one
  456. CopyGameObjectsHierarchy(parent);
  457. List<RendererObject<MeshRenderer>> copyMeshList = FindEnabledMeshes(parent);
  458. List<RendererObject<SkinnedMeshRenderer>> copySkinnedMeshList = FindEnabledSkinnedMeshes(parent);
  459. // Get the ordered by _combinedIndex list of meshes to combine
  460. List<MeshRendererAndOriginalMaterials> copyMeshIndexedList = GetMeshRenderersByCombineIndex(copyMeshList, copySkinnedMeshList, null);
  461. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  462. {
  463. _combinedResult._combinedGameObjectFromMeshList.Add(new List<GameObject>());
  464. _combinedResult._combinedGameObjectFromSkinnedMeshList.Add(new List<GameObject>());
  465. // Generate the new GameObjects and assign combined materials to renderers
  466. if (copyMeshIndexedList[i]._meshRenderers.Count > 0)
  467. {
  468. _combinedResult._combinedGameObjectFromMeshList[i].AddRange(GenerateTransformedGameObjects(parent, copyMeshIndexedList[i]._meshRenderers));
  469. }
  470. if (copyMeshIndexedList[i]._skinnedMeshRenderers.Count > 0)
  471. {
  472. _combinedResult._combinedGameObjectFromSkinnedMeshList[i].AddRange(GenerateTransformedGameObjects(parent, copyMeshIndexedList[i]._skinnedMeshRenderers));
  473. }
  474. // Generate new UVs only if there are more than 1 _material combined
  475. if (_combinedResult._originalMaterialList[i].Count > 1)
  476. {
  477. for (int j = 0; j < copyMeshIndexedList[i]._meshRenderers.Count; j++)
  478. {
  479. GenerateUVs(copyMeshIndexedList[i]._meshRenderers[j].GetComponent<MeshFilter>().sharedMesh, copyMeshIndexedList[i]._originalMaterials[j], copyMeshIndexedList[i]._meshRenderers[j].name, i);
  480. }
  481. for (int j = 0; j < copyMeshIndexedList[i]._skinnedMeshRenderers.Count; j++)
  482. {
  483. GenerateUVs(copyMeshIndexedList[i]._skinnedMeshRenderers[j].sharedMesh, copyMeshIndexedList[i]._originalskinnedMeshMaterials[j], copyMeshIndexedList[i]._skinnedMeshRenderers[j].name, i);
  484. }
  485. }
  486. }
  487. }
  488. _combiningState = CombineStatesList.Combined;
  489. // Deactivate original renderers
  490. DisableRenderers(_meshList, _skinnedMeshList);
  491. #if UNITY_EDITOR
  492. EditorUtility.ClearProgressBar();
  493. #endif
  494. }
  495. /// <summary>
  496. /// Return the list of MeshRendererAndOriginalMaterials for a given list of MeshRenderer and SkinnedMeshRenderer to combine.
  497. /// The returned list also contains the list of splitted submeshes if this was necessary
  498. /// </summary>
  499. /// <param name="meshRenderers"></param>
  500. /// <param name="skinnedMeshRenderers"></param>
  501. /// <param name="parent"></param>
  502. /// <returns></returns>
  503. private List<MeshRendererAndOriginalMaterials> GetMeshRenderersByCombineIndex(List<RendererObject<MeshRenderer>> meshRenderers, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshRenderers, Transform parent)
  504. {
  505. // The list to be returned
  506. List<MeshRendererAndOriginalMaterials> meshRenderersByCombineIndex = new List<MeshRendererAndOriginalMaterials>();
  507. // A temporary list of list of submeshes indexes to be splitted
  508. List<List<int>> submeshToCombinedIndex = new List<List<int>>();
  509. if (_combinedResult._originalMaterialList.Count == 0)
  510. {
  511. Logger.Instance.AddLog("SuperCombiner", "List of materials to combine has been lost. Try to uncombine and combine again.", Logger.LogLevel.LOG_ERROR);
  512. return meshRenderersByCombineIndex;
  513. }
  514. // Initialize lists
  515. for (int i = 0; i < _combinedResult._originalMaterialList.Count; i++)
  516. {
  517. meshRenderersByCombineIndex.Add(new MeshRendererAndOriginalMaterials());
  518. submeshToCombinedIndex.Add(new List<int>());
  519. }
  520. foreach (RendererObject<MeshRenderer> meshRenderer in meshRenderers)
  521. {
  522. if (meshRenderer.WillBeCombined)
  523. {
  524. Material[] materials = meshRenderer.Renderer.sharedMaterials;
  525. // We assume here the number of sharedMaterials is equal to the number of submeshes
  526. _combinedResult._subMeshCount += materials.Length - 1;
  527. // List all _combinedIndex for each _material in this meshRenderer
  528. for (int i = 0; i < materials.Length; i++)
  529. {
  530. if (materials[i] != null)
  531. {
  532. int index = _combinedResult.GetCombinedIndex(materials[i]);
  533. submeshToCombinedIndex[index].Add(i);
  534. }
  535. else
  536. {
  537. Logger.Instance.AddLog("SuperCombiner", "MeshRenderer of '" + meshRenderer.Renderer.name + "' has some missing _material references.", Logger.LogLevel.LOG_WARNING);
  538. }
  539. }
  540. // If needed, split the submeshes
  541. bool hasSplitSubmeshes = false;
  542. for (int i = 0; i < _combinedResult._originalMaterialList.Count; i++)
  543. {
  544. if (submeshToCombinedIndex[i].Count > 0)
  545. {
  546. if (submeshToCombinedIndex[i].Count < materials.Length)
  547. {
  548. // Some materials in this meshRenderer correspond to different combined _index, split submesh accordingly
  549. MeshRenderer newMesh = SubmeshSplitter.SplitSubmeshes(meshRenderer.Renderer.GetComponent<MeshFilter>(), submeshToCombinedIndex[i].ToArray(), i);
  550. meshRenderersByCombineIndex[i]._meshRenderers.Add(newMesh);
  551. meshRenderersByCombineIndex[i]._originalMaterials.Add(newMesh.sharedMaterials);
  552. meshRenderersByCombineIndex[i]._splittedGameObject.Add(newMesh.gameObject);
  553. Logger.Instance.AddLog("SuperCombiner", "Splitting submeshes for " + meshRenderer, Logger.LogLevel.LOG_DEBUG, false);
  554. hasSplitSubmeshes = true;
  555. }
  556. else
  557. {
  558. // All materials in this meshRenderer correspond to the same combined _index, no need to split submesh
  559. meshRenderersByCombineIndex[i]._meshRenderers.Add(meshRenderer.Renderer);
  560. meshRenderersByCombineIndex[i]._originalMaterials.Add(meshRenderer.Renderer.sharedMaterials);
  561. }
  562. }
  563. }
  564. // If mesh has been splitted we don't combine mesh, destroy the old meshRenderer and MeshFilter component because there are copies that won't be used anymore
  565. if (hasSplitSubmeshes && parent == null)
  566. {
  567. DestroyImmediate(meshRenderer.Renderer.GetComponent<MeshFilter>());
  568. DestroyImmediate(meshRenderer.Renderer);
  569. }
  570. // Clear the combined _index list
  571. for (int i = 0; i < _combinedResult._originalMaterialList.Count; i++)
  572. {
  573. submeshToCombinedIndex[i].Clear();
  574. }
  575. }
  576. }
  577. foreach (RendererObject<SkinnedMeshRenderer> skinnedMeshRenderer in skinnedMeshRenderers)
  578. {
  579. if (skinnedMeshRenderer.WillBeCombined)
  580. {
  581. Material[] materials = skinnedMeshRenderer.Renderer.sharedMaterials;
  582. _combinedResult._subMeshCount += materials.Length - 1;
  583. // List all _combinedIndex for each _material in this meshRenderer
  584. for (int i = 0; i < materials.Length; i++)
  585. {
  586. if (materials[i] != null)
  587. {
  588. int index = _combinedResult.GetCombinedIndex(materials[i]);
  589. submeshToCombinedIndex[index].Add(i);
  590. }
  591. else
  592. {
  593. Logger.Instance.AddLog("SuperCombiner", "SkinnedMeshRenderer of '" + skinnedMeshRenderer.Renderer.name + "' has some missing _material references.", Logger.LogLevel.LOG_WARNING);
  594. }
  595. }
  596. // If needed, split the submeshes
  597. bool hasSplitSubmeshes = false;
  598. for (int i = 0; i < _combinedResult._originalMaterialList.Count; i++)
  599. {
  600. if (submeshToCombinedIndex[i].Count > 0)
  601. {
  602. if (submeshToCombinedIndex[i].Count < materials.Length)
  603. {
  604. // Some materials in this meshRenderer correspond to different combined _index, split submesh accordingly
  605. SkinnedMeshRenderer newMesh = SubmeshSplitter.SplitSubmeshes(skinnedMeshRenderer.Renderer, submeshToCombinedIndex[i].ToArray(), i);
  606. meshRenderersByCombineIndex[i]._skinnedMeshRenderers.Add(newMesh);
  607. meshRenderersByCombineIndex[i]._originalskinnedMeshMaterials.Add(newMesh.sharedMaterials);
  608. meshRenderersByCombineIndex[i]._splittedGameObject.Add(newMesh.gameObject);
  609. Logger.Instance.AddLog("SuperCombiner", "Splitting submeshes for " + skinnedMeshRenderer, Logger.LogLevel.LOG_DEBUG, false);
  610. hasSplitSubmeshes = true;
  611. }
  612. else
  613. {
  614. // All materials in this meshRenderer correspond to the same combined _index, no need to split submesh
  615. meshRenderersByCombineIndex[i]._skinnedMeshRenderers.Add(skinnedMeshRenderer.Renderer);
  616. meshRenderersByCombineIndex[i]._originalskinnedMeshMaterials.Add(skinnedMeshRenderer.Renderer.sharedMaterials);
  617. }
  618. }
  619. }
  620. // If mesh has been splitted we don't combine mesh, destroy the old meshRenderer and MeshFilter component because there are copies that won't be used anymore
  621. if (hasSplitSubmeshes && parent == null)
  622. {
  623. DestroyImmediate(skinnedMeshRenderer.Renderer.GetComponent<MeshFilter>());
  624. DestroyImmediate(skinnedMeshRenderer.Renderer);
  625. }
  626. // Clear the combined _index list
  627. for (int i = 0; i < _combinedResult._originalMaterialList.Count; i++)
  628. {
  629. submeshToCombinedIndex[i].Clear();
  630. }
  631. }
  632. }
  633. return meshRenderersByCombineIndex;
  634. }
  635. public void Combine(List<MeshRenderer> meshesToCombine, List<SkinnedMeshRenderer> skinnedMeshesToCombine)
  636. {
  637. List<RendererObject<MeshRenderer>> rendererObjectsToCombine = new List<RendererObject<MeshRenderer>>();
  638. List<RendererObject<SkinnedMeshRenderer>> skinnedRendererObjectsToCombine = new List<RendererObject<SkinnedMeshRenderer>>();
  639. foreach (MeshRenderer mr in meshesToCombine)
  640. {
  641. rendererObjectsToCombine.Add(new RendererObject<MeshRenderer>(mr));
  642. }
  643. foreach (SkinnedMeshRenderer mr in skinnedMeshesToCombine)
  644. {
  645. skinnedRendererObjectsToCombine.Add(new RendererObject<SkinnedMeshRenderer>(mr));
  646. }
  647. Combine(rendererObjectsToCombine, skinnedRendererObjectsToCombine);
  648. }
  649. /// <summary>
  650. /// Combine the specified MeshRenderers and SkinnedMeshRenderers
  651. /// </summary>
  652. /// <param name="meshesToCombine">Meshes to combine.</param>
  653. /// <param name="skinnedMeshesToCombine">Skinned meshes to combine.</param>
  654. public void Combine(List<RendererObject<MeshRenderer>> meshesToCombine, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshesToCombine)
  655. {
  656. // Start timer if necessary
  657. if (_combiningState == CombineStatesList.Uncombined)
  658. {
  659. _timeStart = DateTime.Now;
  660. _combiningState = CombineStatesList.Combining;
  661. }
  662. Logger.Instance.AddLog("SuperCombiner", "Start processing...");
  663. #if UNITY_EDITOR
  664. // UI Progress bar display in Editor
  665. EditorUtility.DisplayProgressBar("Super Combiner", "Meshes listing...", 0.1f);
  666. #endif
  667. // Combine Materials
  668. bool cancel = CombineMaterials(meshesToCombine, skinnedMeshesToCombine);
  669. if (cancel)
  670. {
  671. #if UNITY_EDITOR
  672. EditorUtility.ClearProgressBar();
  673. #endif
  674. return;
  675. }
  676. // Initialte target parent gameObject
  677. SetTargetParentForCombinedGameObject();
  678. // Combine Meshes
  679. CombineMeshes(meshesToCombine, skinnedMeshesToCombine, _targetParentForCombinedGameObjects.transform);
  680. #if UNITY_EDITOR
  681. // Combine process is finished
  682. EditorUtility.ClearProgressBar();
  683. #endif
  684. // Process is finished
  685. _combiningState = CombineStatesList.Combined;
  686. _combinedResult._duration = DateTime.Now - _timeStart;
  687. Logger.Instance.AddLog("SuperCombiner", "Successfully combined game objects!\nExecution time is " + _combinedResult._duration);
  688. }
  689. /// <summary>
  690. /// Initialize multiple _material elements
  691. /// </summary>
  692. public void InitializeMultipleMaterialElements()
  693. {
  694. if (_multipleMaterialsMode)
  695. {
  696. _multiMaterialsList.Add(multiMaterials0);
  697. _multiMaterialsList.Add(multiMaterials1);
  698. _multiMaterialsList.Add(multiMaterials2);
  699. _multiMaterialsList.Add(multiMaterials3);
  700. _multiMaterialsList.Add(multiMaterials4);
  701. _multiMaterialsList.Add(multiMaterials5);
  702. _multiMaterialsList.Add(multiMaterials6);
  703. _multiMaterialsList.Add(multiMaterials7);
  704. _multiMaterialsList.Add(multiMaterials8);
  705. _multiMaterialsList.Add(multiMaterials9);
  706. _multiMaterialsList.Add(multiMaterials10);
  707. }
  708. // Fill the materials to combine list
  709. for (int i = 0; i < _multiMaterialsList.Count + 1; i++)
  710. {
  711. // The last one in this list correspond to all other materials
  712. _materialsToCombine.Add(new List<MaterialToCombine>());
  713. }
  714. }
  715. /// <summary>
  716. /// Copy all GameObjects children
  717. /// </summary>
  718. /// <param name="parent"></param>
  719. private void CopyGameObjectsHierarchy(Transform parent)
  720. {
  721. Transform[] children = this.transform.GetComponentsInChildren<Transform>();
  722. foreach (Transform child in children)
  723. {
  724. if (child.parent == this.transform && child != parent)
  725. {
  726. GameObject go = InstantiateCopy(child.gameObject, false);
  727. go.transform.SetParent(parent);
  728. }
  729. }
  730. }
  731. /// <summary>
  732. /// Generate the new uvs of the mesh in texture atlas
  733. /// </summary>
  734. /// <param name="mesh"></param>
  735. /// <param name="originalMaterials"></param>
  736. /// <param name="objectName"></param>
  737. /// <param name="combinedIndex"></param>
  738. private void GenerateUVs(Mesh mesh, Material[] originalMaterials, string objectName, int combinedIndex)
  739. {
  740. int[] textureIndexes = new int[originalMaterials.Length];
  741. for (int j = 0; j < originalMaterials.Length; j++)
  742. {
  743. Material mat = originalMaterials[j];
  744. textureIndexes[j] = _combinedResult.FindCorrespondingMaterialIndex(mat, combinedIndex);
  745. }
  746. if (!_meshCombiner.GenerateUV(mesh, textureIndexes, _combinedResult._combinedMaterials[combinedIndex].scaleFactors.ToArray(), objectName, combinedIndex))
  747. {
  748. UnCombine();
  749. return;
  750. }
  751. }
  752. /// <summary>
  753. /// Reactivate original GameObjects
  754. /// </summary>
  755. /// <param name="meshes"></param>
  756. /// <param name="skinnedMeshes"></param>
  757. private void EnableRenderers(List<RendererObject<MeshRenderer>> meshes, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshes)
  758. {
  759. foreach (RendererObject<MeshRenderer> go in meshes)
  760. {
  761. if (go != null)
  762. {
  763. go.Renderer.gameObject.SetActive(true);
  764. }
  765. }
  766. foreach (RendererObject<SkinnedMeshRenderer> go in skinnedMeshes)
  767. {
  768. if (go != null)
  769. {
  770. go.Renderer.gameObject.SetActive(true);
  771. }
  772. }
  773. }
  774. /// <summary>
  775. /// Deactivate original GameObjects
  776. /// </summary>
  777. /// <param name="meshes"></param>
  778. /// <param name="skinnedMeshes"></param>
  779. private void DisableRenderers(List<RendererObject<MeshRenderer>> meshes, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshes)
  780. {
  781. foreach (RendererObject<MeshRenderer> go in meshes)
  782. {
  783. if (go != null && go.Renderer.gameObject != _targetGameObject)
  784. {
  785. go.Renderer.gameObject.SetActive(false);
  786. }
  787. }
  788. foreach (RendererObject<SkinnedMeshRenderer> go in skinnedMeshes)
  789. {
  790. if (go != null && go.Renderer.gameObject != _targetGameObject)
  791. {
  792. go.Renderer.gameObject.SetActive(false);
  793. }
  794. }
  795. }
  796. /// <summary>
  797. /// Generate the new transformed gameobjects and apply new materials to them, when no combining meshes
  798. /// </summary>
  799. /// <param name="parent"></param>
  800. /// <param name="originalMeshRenderer"></param>
  801. /// <returns></returns>
  802. private List<GameObject> GenerateTransformedGameObjects(Transform parent, List<MeshRenderer> originalMeshRenderer)
  803. {
  804. List<GameObject> copyList = new List<GameObject>();
  805. for (int i = 0; i < originalMeshRenderer.Count; i++)
  806. {
  807. // Copy the new mesh to the created GameObject copy
  808. Mesh copyOfMesh = _meshCombiner.copyMesh(originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh);
  809. // Add the copy mesh instanceId with its original sharedMesh and sharedMaterial instanceId
  810. if (originalMeshRenderer[i].GetComponent<Renderer>().sharedMaterial != null)
  811. {
  812. _uniqueCombinedMeshId.Add(copyOfMesh.GetInstanceID(), originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh.GetInstanceID().ToString() + originalMeshRenderer[i].GetComponent<Renderer>().sharedMaterial.GetInstanceID().ToString() + copyOfMesh.name);
  813. }
  814. else
  815. {
  816. _uniqueCombinedMeshId.Add(copyOfMesh.GetInstanceID(), originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh.GetInstanceID().ToString() + copyOfMesh.name);
  817. }
  818. _copyMeshId[originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh.GetInstanceID()] = _uniqueCombinedMeshId[copyOfMesh.GetInstanceID()];
  819. originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh = copyOfMesh;
  820. #if UNITY_EDITOR
  821. // Unwrap UV2 for lightmap
  822. Unwrapping.GenerateSecondaryUVSet(originalMeshRenderer[i].GetComponent<MeshFilter>().sharedMesh);
  823. #endif
  824. // Assign new materials
  825. if (_combineMaterials)
  826. {
  827. Material[] originalMaterials = originalMeshRenderer[i].GetComponent<Renderer>().sharedMaterials;
  828. Material[] newMats = new Material[originalMaterials.Length];
  829. for (int k = 0; k < newMats.Length; k++)
  830. {
  831. newMats[k] = _combinedResult.GetCombinedMaterial(originalMaterials[k]);
  832. }
  833. originalMeshRenderer[i].GetComponent<Renderer>().sharedMaterials = newMats;
  834. }
  835. else
  836. {
  837. // If materials are not combined
  838. /*Material[] mat = objects [i].GetComponent<Renderer> ().sharedMaterials;
  839. Material[] newMats = new Material[mat.Length];
  840. for (int a = 0; a < mat.Length; a++) {
  841. newMats [a] = _texturePackers[0].getTransformedMaterialValue (objects [i].GetComponent<Renderer> ().sharedMaterials [a].name);
  842. // Find corresponding _material
  843. combinedTextureIndex.Add (_combinedResult.FindCorrespondingMaterialIndex(mat[a], 0));
  844. }
  845. objects[i].GetComponent<Renderer> ().sharedMaterials = newMats;*/
  846. }
  847. copyList.Add(originalMeshRenderer[i].gameObject);
  848. }
  849. return copyList;
  850. }
  851. /// <summary>
  852. /// Generate the new transformed gameobjects and apply new materials to them, when no combining meshes
  853. /// For Skinned Mesh renderers, when no combining meshes
  854. /// </summary>
  855. /// <param name="parent"></param>
  856. /// <param name="originalSkinnedMeshRenderer"></param>
  857. /// <returns></returns>
  858. private List<GameObject> GenerateTransformedGameObjects(Transform parent, List<SkinnedMeshRenderer> originalSkinnedMeshRenderer)
  859. {
  860. List<GameObject> copyList = new List<GameObject>();
  861. for (int i = 0; i < originalSkinnedMeshRenderer.Count; i++)
  862. {
  863. // Copy the new mesh to the created GameObject copy
  864. Mesh copyOfMesh = _meshCombiner.copyMesh(originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMesh);
  865. // Add the copy mesh instanceId with its original sharedMesh and sharedMaterial instanceId
  866. if (originalSkinnedMeshRenderer[i].GetComponent<Renderer>().sharedMaterial != null)
  867. {
  868. _uniqueCombinedMeshId.Add(copyOfMesh.GetInstanceID(), originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMesh.GetInstanceID().ToString() + originalSkinnedMeshRenderer[i].GetComponent<Renderer>().sharedMaterial.GetInstanceID().ToString() + copyOfMesh.name);
  869. }
  870. else
  871. {
  872. _uniqueCombinedMeshId.Add(copyOfMesh.GetInstanceID(), originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMesh.GetInstanceID().ToString() + copyOfMesh.name);
  873. }
  874. _copyMeshId[originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMesh.GetInstanceID()] = _uniqueCombinedMeshId[copyOfMesh.GetInstanceID()];
  875. originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMesh = copyOfMesh;
  876. #if UNITY_EDITOR
  877. // Unwrap UV2 for lightmap
  878. //Unwrapping.GenerateSecondaryUVSet(skinnedObjects[i].GetComponent<SkinnedMeshRenderer>().sharedMesh);
  879. #endif
  880. // Assign new materials
  881. if (_combineMaterials)
  882. {
  883. Material[] originalMaterials = originalSkinnedMeshRenderer[i].GetComponent<Renderer>().sharedMaterials;
  884. Material[] newMats = new Material[originalMaterials.Length];
  885. for (int k = 0; k < newMats.Length; k++)
  886. {
  887. newMats[k] = _combinedResult.GetCombinedMaterial(originalMaterials[k]);
  888. }
  889. originalSkinnedMeshRenderer[i].GetComponent<SkinnedMeshRenderer>().sharedMaterials = newMats;
  890. }
  891. else
  892. {
  893. // If materials are not combined
  894. /*Material[] mat = skinnedObjects [i].sharedMaterials;
  895. Material[] newMats = new Material[mat.Length];
  896. for (int a = 0; a < mat.Length; a++) {
  897. newMats [a] = _texturePackers[0].getTransformedMaterialValue (skinnedObjects [i].sharedMaterials [a].name);
  898. // Find corresponding _material
  899. combinedTextureIndex.Add (_combinedResult.FindCorrespondingMaterialIndex(mat[a], 0));
  900. }
  901. skinnedObjects[i].GetComponent<SkinnedMeshRenderer> ().sharedMaterials = newMats;*/
  902. }
  903. copyList.Add(originalSkinnedMeshRenderer[i].gameObject);
  904. }
  905. return copyList;
  906. }
  907. // Instantiate a copy of the GameObject, keeping it's transform values identical
  908. private GameObject InstantiateCopy(GameObject original, bool deleteChidren = true)
  909. {
  910. GameObject copy = Instantiate(original) as GameObject;
  911. copy.transform.parent = original.transform.parent;
  912. copy.transform.localPosition = original.transform.localPosition;
  913. copy.transform.localRotation = original.transform.localRotation;
  914. copy.transform.localScale = original.transform.localScale;
  915. copy.name = original.name;
  916. if (deleteChidren)
  917. {
  918. // Delete all children
  919. foreach (Transform child in copy.transform)
  920. {
  921. DestroyImmediate(child.gameObject);
  922. }
  923. }
  924. return copy;
  925. }
  926. // Find all enabled mesh colliders
  927. private List<MeshCollider> FindEnabledMeshColliders(Transform parent)
  928. {
  929. MeshCollider[] colliders;
  930. colliders = parent.GetComponentsInChildren<MeshCollider>();
  931. List<MeshCollider> meshColliders = new List<MeshCollider>();
  932. foreach (MeshCollider collider in colliders)
  933. {
  934. if (collider.sharedMesh != null)
  935. {
  936. meshColliders.Add(collider);
  937. }
  938. }
  939. return meshColliders;
  940. }
  941. // Find and store all enabled meshes
  942. private List<RendererObject<MeshRenderer>> FindEnabledMeshes(Transform parent)
  943. {
  944. MeshFilter[] filters;
  945. LODGroup[] lodGroups;
  946. Dictionary<MeshRenderer, RendererObject<MeshRenderer>> meshToRendererObject = new Dictionary<MeshRenderer, RendererObject<MeshRenderer>>();
  947. filters = parent.GetComponentsInChildren<MeshFilter>();
  948. List<RendererObject<MeshRenderer>> meshRendererList = new List<RendererObject<MeshRenderer>>();
  949. // Get all valid meshFilter
  950. foreach (MeshFilter filter in filters)
  951. {
  952. if (filter.sharedMesh != null)
  953. {
  954. MeshRenderer renderer = filter.GetComponent<MeshRenderer>();
  955. if (renderer != null && renderer.enabled && renderer.sharedMaterials.Length > 0)
  956. {
  957. RendererObject<MeshRenderer> rendererObject = new RendererObject<MeshRenderer>(renderer);
  958. meshToRendererObject.Add(renderer, rendererObject);
  959. meshRendererList.Add(rendererObject);
  960. }
  961. }
  962. }
  963. // Remove all non-desired Lods level
  964. if (_manageLodLevel)
  965. {
  966. lodGroups = parent.GetComponentsInChildren<LODGroup>();
  967. foreach (LODGroup lodGroup in lodGroups)
  968. {
  969. LOD[] lods = lodGroup.GetLODs();
  970. for (int i = 0; i < lods.Length; i++)
  971. {
  972. if (i != _managedLodLevel)
  973. {
  974. Renderer[] renderers = lods[i].renderers;
  975. foreach (Renderer rd in renderers)
  976. {
  977. MeshRenderer meshrd = rd.GetComponent<MeshRenderer>();
  978. if (meshrd != null)
  979. {
  980. meshToRendererObject[meshrd].WillBeCombined = false;
  981. }
  982. }
  983. }
  984. }
  985. if (_managedLodLevel > lods.Length)
  986. {
  987. Logger.Instance.AddLog("SuperCombiner", "Selected lod level " + _managedLodLevel + " is higher than LODs available in " + lodGroup.name, Logger.LogLevel.LOG_WARNING);
  988. }
  989. }
  990. }
  991. return meshRendererList;
  992. }
  993. // Find and store all enabled skin meshes
  994. private List<RendererObject<SkinnedMeshRenderer>> FindEnabledSkinnedMeshes(Transform parent)
  995. {
  996. // Skinned meshes
  997. SkinnedMeshRenderer[] skinnedMeshes = parent.GetComponentsInChildren<SkinnedMeshRenderer>();
  998. List<RendererObject<SkinnedMeshRenderer>> skinnedMeshRendererList = new List<RendererObject<SkinnedMeshRenderer>>();
  999. foreach (SkinnedMeshRenderer skin in skinnedMeshes)
  1000. {
  1001. if (skin.sharedMesh != null)
  1002. {
  1003. if (skin.enabled && skin.sharedMaterials.Length > 0)
  1004. {
  1005. RendererObject<SkinnedMeshRenderer> rendererObject = new RendererObject<SkinnedMeshRenderer>(skin);
  1006. skinnedMeshRendererList.Add(rendererObject);
  1007. }
  1008. }
  1009. }
  1010. return skinnedMeshRendererList;
  1011. }
  1012. /// <summary>
  1013. /// Find and return all enabled materials in given meshes and skinnedMeshes
  1014. /// </summary>
  1015. /// <param name="meshes"></param>
  1016. /// <param name="skinnedMeshes"></param>
  1017. /// <returns></returns>
  1018. private List<MaterialToCombine> FindEnabledMaterials(List<RendererObject<MeshRenderer>> meshes, List<RendererObject<SkinnedMeshRenderer>> skinnedMeshes)
  1019. {
  1020. // List of materials linked with their instanceID
  1021. Dictionary<int, MaterialToCombine> matList = new Dictionary<int, MaterialToCombine>();
  1022. // Meshes renderer
  1023. foreach (RendererObject<MeshRenderer> mesh in meshes)
  1024. {
  1025. Mesh sharedMesh = mesh.Renderer.GetComponent<MeshFilter>().sharedMesh;
  1026. Rect uvBound = getUVBounds(sharedMesh.uv);
  1027. foreach (Material material in mesh.Renderer.sharedMaterials)
  1028. {
  1029. if (material != null)
  1030. {
  1031. int instanceId = material.GetInstanceID();
  1032. if (!matList.ContainsKey(instanceId))
  1033. {
  1034. // Material has not been listed yet, add it to the list
  1035. MaterialToCombine matToCombine = new MaterialToCombine();
  1036. matToCombine._material = material;
  1037. matToCombine._uvBounds = uvBound;
  1038. matToCombine._meshHavingBiggestUVBounds = sharedMesh;
  1039. matList.Add(instanceId, matToCombine);
  1040. }
  1041. else
  1042. {
  1043. // This _material has already been found, check if the uv bounds is bigger
  1044. Rect maxRect = getMaxRect(matList[instanceId]._uvBounds, uvBound);
  1045. MaterialToCombine matToCombine = matList[instanceId];
  1046. matToCombine._uvBounds = maxRect;
  1047. matToCombine._meshHavingBiggestUVBounds = sharedMesh;
  1048. matList[instanceId] = matToCombine;
  1049. }
  1050. }
  1051. else
  1052. {
  1053. // The _material is null
  1054. }
  1055. }
  1056. }
  1057. // SkinnedMeshes renderer
  1058. foreach (RendererObject<SkinnedMeshRenderer> skinnedMesh in skinnedMeshes)
  1059. {
  1060. Rect uvBound = getUVBounds(skinnedMesh.Renderer.sharedMesh.uv);
  1061. foreach (Material material in skinnedMesh.Renderer.sharedMaterials)
  1062. {
  1063. if (material != null)
  1064. {
  1065. int instanceId = material.GetInstanceID();
  1066. if (!matList.ContainsKey(instanceId))
  1067. {
  1068. // Material has not been listed yet, add it to the list
  1069. MaterialToCombine matToCombine = new MaterialToCombine();
  1070. matToCombine._material = material;
  1071. matToCombine._uvBounds = uvBound;
  1072. matList.Add(instanceId, matToCombine);
  1073. }
  1074. else
  1075. {
  1076. // This _material has already been found, check if the uv bounds is bigger
  1077. Rect maxRect = getMaxRect(matList[instanceId]._uvBounds, uvBound);
  1078. MaterialToCombine matToCombine = matList[instanceId];
  1079. matToCombine._uvBounds = maxRect;
  1080. matList[instanceId] = matToCombine;
  1081. }
  1082. }
  1083. else
  1084. {
  1085. // The _material is null
  1086. }
  1087. }
  1088. }
  1089. return new List<MaterialToCombine>(matList.Values);
  1090. }
  1091. // Return the bound of the uv list (min, max for x and y axis)
  1092. private Rect getUVBounds(Vector2[] uvs)
  1093. {
  1094. if (uvs.Length > 0)
  1095. {
  1096. float[] x = new float[uvs.Length];
  1097. float[] y = new float[uvs.Length];
  1098. for (int i = 0; i < uvs.Length; i++)
  1099. {
  1100. x[i] = uvs[i].x;
  1101. y[i] = uvs[i].y;
  1102. }
  1103. return new Rect(x.Min(), y.Min(), x.Max() - x.Min(), y.Max() - y.Min());
  1104. }
  1105. else
  1106. {
  1107. return new Rect(0, 0, 1, 1);
  1108. }
  1109. }
  1110. // Return the maximum rect based on the two rect parameters
  1111. private Rect getMaxRect(Rect uv1, Rect uv2)
  1112. {
  1113. Rect newRect = new Rect();
  1114. newRect.xMin = Math.Min(uv1.xMin, uv2.xMin);
  1115. newRect.yMin = Math.Min(uv1.yMin, uv2.yMin);
  1116. newRect.xMax = Math.Max(uv1.xMax, uv2.xMax);
  1117. newRect.yMax = Math.Max(uv1.yMax, uv2.yMax);
  1118. return newRect;
  1119. }
  1120. /// <summary>
  1121. /// Reverse combine process, destroy all created objects and reactivate original mesh renderers
  1122. /// </summary>
  1123. public void UnCombine()
  1124. {
  1125. #if UNITY_EDITOR
  1126. // Hide progressbar
  1127. EditorUtility.ClearProgressBar();
  1128. #endif
  1129. // Reactivate original renderers
  1130. EnableRenderers(_meshList, _skinnedMeshList);
  1131. if (_targetParentForCombinedGameObjects == _targetGameObject && _combinedResult != null)
  1132. {
  1133. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  1134. {
  1135. if (_combinedResult._combinedGameObjectFromMeshList.Count > i)
  1136. {
  1137. foreach (GameObject go in _combinedResult._combinedGameObjectFromMeshList[i])
  1138. {
  1139. DestroyImmediate(go);
  1140. }
  1141. foreach (GameObject go in _combinedResult._combinedGameObjectFromSkinnedMeshList[i])
  1142. {
  1143. DestroyImmediate(go);
  1144. }
  1145. }
  1146. }
  1147. }
  1148. else
  1149. {
  1150. DestroyImmediate(_targetParentForCombinedGameObjects);
  1151. }
  1152. // Clear the packed textures
  1153. _texturePackers.Clear();
  1154. _materialsToCombine.Clear();
  1155. _multiMaterialsList.Clear();
  1156. _meshCombiner.Clear();
  1157. _meshList.Clear();
  1158. _skinnedMeshList.Clear();
  1159. _uniqueCombinedMeshId.Clear();
  1160. _copyMeshId.Clear();
  1161. _toSavePrefabList.Clear();
  1162. _toSaveObjectList.Clear();
  1163. _toSaveMeshList.Clear();
  1164. _toSaveSkinnedObjectList.Clear();
  1165. if (_combinedResult != null)
  1166. {
  1167. _combinedResult.Clear();
  1168. }
  1169. _combiningState = CombineStatesList.Uncombined;
  1170. Logger.Instance.AddLog("SuperCombiner", "Successfully uncombined game objects.");
  1171. }
  1172. /// <summary>
  1173. /// Get the first level children list of the parents
  1174. /// </summary>
  1175. /// <param name="parent"></param>
  1176. /// <returns></returns>
  1177. private List<Transform> GetFirstLevelChildren(Transform parent)
  1178. {
  1179. List<Transform> children = new List<Transform>();
  1180. for (int i = 0; i < parent.transform.childCount; i++)
  1181. {
  1182. children.Add(parent.transform.GetChild(i));
  1183. }
  1184. return children;
  1185. }
  1186. /// <summary>
  1187. /// Save combined objects
  1188. /// </summary>
  1189. public void Save()
  1190. {
  1191. #if UNITY_EDITOR
  1192. // Combine process is finished
  1193. EditorUtility.ClearProgressBar();
  1194. if (_folderDestination == "")
  1195. {
  1196. // Default export folder destination
  1197. _folderDestination = "Assets/SuperCombiner/Combined";
  1198. }
  1199. // Check if destination folder exists
  1200. if (!Directory.Exists(_folderDestination))
  1201. {
  1202. Directory.CreateDirectory(_folderDestination);
  1203. }
  1204. // Generate new instances (copy from modifiedObjectList) to be saved, so that objects in modifiedObjectList won't be affected by user's modification/deletion
  1205. _toSavePrefabList.Clear();
  1206. _toSaveObjectList.Clear();
  1207. _toSaveMeshList.Clear();
  1208. _toSaveSkinnedObjectList.Clear();
  1209. Material[] savedMaterial = new Material[_combinedResult.GetCombinedIndexCount()];
  1210. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  1211. {
  1212. if (_combinedResult._combinedMaterials[i].material != null)
  1213. {
  1214. _texturePackers[i].GenerateCopyedMaterialToSave();
  1215. if (_texturePackers[i].GetCombinedMaterialToSave() == null)
  1216. {
  1217. Logger.Instance.AddLog("SuperCombiner", "Instance of combined _material has been lost, try to combine again before saving.", Logger.LogLevel.LOG_ERROR);
  1218. }
  1219. else
  1220. {
  1221. // We need to know if the combined _material has already been saved
  1222. savedMaterial[i] = AssetDatabase.LoadAssetAtPath<Material>(_folderDestination + "/Materials/" + _texturePackers[i]._copyedMaterials.name + ".mat");
  1223. }
  1224. }
  1225. }
  1226. if (_combiningState == CombineStatesList.Combined)
  1227. {
  1228. // List of all different meshes found on every game objects to save, with no duplication
  1229. Dictionary<string, Mesh> meshMaterialId = new Dictionary<string, Mesh>();
  1230. bool outputSkinnedMesh = false;
  1231. List<Transform> children = new List<Transform>();
  1232. if (_combineMeshes && (LunarCatsStudio.SuperCombiner.MeshOutput)_meshOutput == LunarCatsStudio.SuperCombiner.MeshOutput.SkinnedMesh)
  1233. {
  1234. // If output is skinnedMesh, we save a copy of modifiedParent as prefab
  1235. GameObject copy = InstantiateCopy(_targetParentForCombinedGameObjects, false);
  1236. _toSavePrefabList.Add(copy);
  1237. outputSkinnedMesh = true;
  1238. children = GetFirstLevelChildren(copy.transform);
  1239. }
  1240. else
  1241. {
  1242. children = GetFirstLevelChildren(_targetParentForCombinedGameObjects.transform);
  1243. }
  1244. // Generate copy of game objects to be saved
  1245. foreach (Transform child in children)
  1246. {
  1247. GameObject copy;
  1248. if (outputSkinnedMesh)
  1249. {
  1250. copy = child.gameObject;
  1251. }
  1252. else
  1253. {
  1254. copy = InstantiateCopy(child.gameObject, false);
  1255. }
  1256. List<RendererObject<MeshRenderer>> meshes = FindEnabledMeshes(copy.transform);
  1257. List<RendererObject<SkinnedMeshRenderer>> skinnedMeshes = FindEnabledSkinnedMeshes(copy.transform);
  1258. List<MeshCollider> meshColliders = FindEnabledMeshColliders(copy.transform);
  1259. // Create a copy of mesh
  1260. foreach (RendererObject<MeshRenderer> mesh in meshes)
  1261. {
  1262. int instanceId = mesh.Renderer.GetComponent<MeshFilter>().sharedMesh.GetInstanceID();
  1263. if (_uniqueCombinedMeshId.ContainsKey(instanceId))
  1264. {
  1265. if (meshMaterialId.ContainsKey(_uniqueCombinedMeshId[instanceId]))
  1266. {
  1267. // This mesh is shared with other game objects, so we reuse the first instance to avoid duplication
  1268. mesh.Renderer.GetComponent<MeshFilter>().sharedMesh = meshMaterialId[_uniqueCombinedMeshId[instanceId]];
  1269. }
  1270. else
  1271. {
  1272. Mesh copyOfMesh = _meshCombiner.copyMesh(mesh.Renderer.GetComponent<MeshFilter>().sharedMesh);
  1273. mesh.Renderer.GetComponent<MeshFilter>().sharedMesh = copyOfMesh;
  1274. meshMaterialId.Add(_uniqueCombinedMeshId[instanceId], copyOfMesh);
  1275. _toSaveMeshList.Add(copyOfMesh);
  1276. }
  1277. // Apply a copy of the _material to save
  1278. Material[] newMat = new Material[mesh.Renderer.sharedMaterials.Length];
  1279. for (int j = 0; j < mesh.Renderer.sharedMaterials.Length; j++)
  1280. {
  1281. if (_combineMaterials)
  1282. {
  1283. // Get the _index of this combined _material
  1284. int index = 0;
  1285. for (int k = 0; k < _combinedResult._combinedMaterials.Count; k++)
  1286. {
  1287. if (mesh.Renderer.sharedMaterials[j] == _combinedResult._combinedMaterials[k].material)
  1288. {
  1289. index = k;
  1290. }
  1291. }
  1292. if (savedMaterial[index] != null)
  1293. {
  1294. // If the combined _material already exists, assign it
  1295. newMat[j] = savedMaterial[index];
  1296. }
  1297. else
  1298. {
  1299. newMat[j] = _texturePackers[index].GetCombinedMaterialToSave();
  1300. }
  1301. }
  1302. else
  1303. {
  1304. //newMat[j] = _texturePackers[i].GetTransformedMaterialToSave(mesh.sharedMaterials[j].name);
  1305. }
  1306. }
  1307. mesh.Renderer.sharedMaterials = newMat;
  1308. _toSaveObjectList.Add(mesh.Renderer);
  1309. }
  1310. else
  1311. {
  1312. Logger.Instance.AddLog("SuperCombiner", "Could not find " + mesh.Renderer.name + " in _uniqueCombinedMeshId, data may has been lost, try to combine again before saving.", Logger.LogLevel.LOG_ERROR);
  1313. }
  1314. }
  1315. foreach (RendererObject<SkinnedMeshRenderer> skinnedmesh in skinnedMeshes)
  1316. {
  1317. int instanceId = skinnedmesh.Renderer.sharedMesh.GetInstanceID();
  1318. if (_uniqueCombinedMeshId.ContainsKey(instanceId))
  1319. {
  1320. if (meshMaterialId.ContainsKey(_uniqueCombinedMeshId[instanceId]))
  1321. {
  1322. // This mesh is shared with other game objects, so we reuse the first instance to avoid duplication
  1323. skinnedmesh.Renderer.sharedMesh = meshMaterialId[_uniqueCombinedMeshId[instanceId]];
  1324. }
  1325. else
  1326. {
  1327. Mesh copyOfMesh = _meshCombiner.copyMesh(skinnedmesh.Renderer.sharedMesh);
  1328. skinnedmesh.Renderer.sharedMesh = copyOfMesh;
  1329. meshMaterialId.Add(_uniqueCombinedMeshId[instanceId], copyOfMesh);
  1330. _toSaveMeshList.Add(copyOfMesh);
  1331. }
  1332. // Apply a copy of the _material to save
  1333. Material[] newMat = new Material[skinnedmesh.Renderer.sharedMaterials.Length];
  1334. for (int j = 0; j < skinnedmesh.Renderer.sharedMaterials.Length; j++)
  1335. {
  1336. if (_combineMaterials)
  1337. {
  1338. // Get the _index of this combined _material
  1339. int index = 0;
  1340. for (int k = 0; k < _combinedResult._combinedMaterials.Count; k++)
  1341. {
  1342. if (skinnedmesh.Renderer.sharedMaterials[j] == _combinedResult._combinedMaterials[k].material)
  1343. {
  1344. index = k;
  1345. }
  1346. }
  1347. if (savedMaterial[index] != null)
  1348. {
  1349. // If the combined _material already exists, assign it
  1350. newMat[j] = savedMaterial[index];
  1351. }
  1352. else
  1353. {
  1354. newMat[j] = _texturePackers[index].GetCombinedMaterialToSave();
  1355. }
  1356. }
  1357. else
  1358. {
  1359. //newMat[j] = _texturePackers[i].GetTransformedMaterialToSave(skinnedmesh.sharedMaterials[j].name);
  1360. }
  1361. }
  1362. skinnedmesh.Renderer.sharedMaterials = newMat;
  1363. _toSaveSkinnedObjectList.Add(skinnedmesh.Renderer);
  1364. }
  1365. else
  1366. {
  1367. Logger.Instance.AddLog("SuperCombiner", "Could not find " + skinnedmesh.Renderer.name + " in _uniqueCombinedMeshId, data may has been lost, try to combine again before saving.", Logger.LogLevel.LOG_ERROR);
  1368. }
  1369. }
  1370. // Assign to mesh colliders the mesh that will be saved
  1371. foreach (MeshCollider collider in meshColliders)
  1372. {
  1373. int instanceId = collider.sharedMesh.GetInstanceID();
  1374. string id = null;
  1375. _copyMeshId.TryGetValue(instanceId, out id);
  1376. if (id != null)
  1377. {
  1378. if (meshMaterialId.ContainsKey(id))
  1379. {
  1380. collider.sharedMesh = meshMaterialId[id];
  1381. }
  1382. }
  1383. else
  1384. {
  1385. // This means the collider has a mesh that is not present in the combine list
  1386. // In this case, keep the meshCollider component intact
  1387. }
  1388. }
  1389. // Add this GameObject to the list of prefab to save
  1390. if (!outputSkinnedMesh)
  1391. {
  1392. _toSavePrefabList.Add(copy);
  1393. }
  1394. }
  1395. }
  1396. // Saving process
  1397. if (_saveTextures)
  1398. {
  1399. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  1400. {
  1401. if (_combinedResult._combinedMaterials[i].material != null)
  1402. {
  1403. Saver.SaveTextures(i, _folderDestination, _sessionName, _texturePackers[i]);
  1404. }
  1405. }
  1406. }
  1407. if (_saveMaterials)
  1408. {
  1409. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  1410. {
  1411. if (_combinedResult._combinedMaterials[i].material != null)
  1412. {
  1413. Saver.SaveMaterial(i, _folderDestination, _sessionName, _texturePackers[i]);
  1414. }
  1415. }
  1416. }
  1417. if (_savePrefabs)
  1418. {
  1419. Saver.SavePrefabs(_toSavePrefabList, _toSaveMeshList, _folderDestination, _sessionName);
  1420. for (int n = 0; n < _toSavePrefabList.Count; n++)
  1421. {
  1422. DestroyImmediate(_toSavePrefabList[n]);
  1423. }
  1424. _toSavePrefabList.Clear();
  1425. _toSaveMeshList.Clear();
  1426. }
  1427. if (_saveMeshObj)
  1428. {
  1429. for (int i = 0; i < _combinedResult.GetCombinedIndexCount(); i++)
  1430. {
  1431. if (_combinedResult._combinedMaterials[i].material != null)
  1432. {
  1433. Saver.SaveMeshesObj(_combinedResult._combinedGameObjectFromMeshList[i], _combinedResult._combinedGameObjectFromSkinnedMeshList[i], _folderDestination);
  1434. for (int n = 0; n < _toSaveObjectList.Count; n++)
  1435. {
  1436. DestroyImmediate(_toSaveObjectList[n]);
  1437. }
  1438. for (int n = 0; n < _toSaveSkinnedObjectList.Count; n++)
  1439. {
  1440. DestroyImmediate(_toSaveSkinnedObjectList[n]);
  1441. }
  1442. _toSaveObjectList.Clear();
  1443. _toSaveSkinnedObjectList.Clear();
  1444. }
  1445. }
  1446. }
  1447. if (_saveMeshFbx)
  1448. {
  1449. //SaveMeshesFbx();
  1450. }
  1451. //Save the combine settings
  1452. createSuperCombinerSettings();
  1453. Saver.SaveCombinedSettings(_scSettings, _folderDestination, _sessionName);
  1454. // Saves the combined result asset
  1455. _combinedResult._logs = Logger.Instance.GetLogs();
  1456. Saver.SaveCombinedResults(_combinedResult, _folderDestination, _sessionName);
  1457. EditorUtility.DisplayDialog("Super Combiner", "Objects saved in '" + _folderDestination + "/' \n\nThanks for using Super Combiner.", "Ok");
  1458. // Hide progressbar
  1459. EditorUtility.ClearProgressBar();
  1460. #endif
  1461. }
  1462. /// <summary>
  1463. /// create and set the super combiner settings scriptable object
  1464. /// </summary>
  1465. private void createSuperCombinerSettings()
  1466. {
  1467. // If _scSettings has not been created yet, create it
  1468. if (_scSettings == null)
  1469. {
  1470. _scSettings = (SuperCombinerSettings)ScriptableObject.CreateInstance(typeof(SuperCombinerSettings));
  1471. }
  1472. // General settings
  1473. _scSettings.generalSettings.versionNumber = versionNumber;
  1474. _scSettings.generalSettings.combineAtRuntime = _combineAtRuntime;
  1475. _scSettings.generalSettings.sessionName = _sessionName;
  1476. _scSettings.generalSettings.targetGameObject = _targetGameObject;
  1477. // Textures settings
  1478. _scSettings.textureSettings.atlasSize = _textureAtlasSize;
  1479. _scSettings.textureSettings.padding = _atlasPadding;
  1480. _scSettings.textureSettings.tilingFactor = _tilingFactor;
  1481. // Materials settings
  1482. _scSettings.materialSettings.multipleMaterialsCount = _multiMaterialsCount;
  1483. _scSettings.materialSettings.multipleMaterialsMode = _multipleMaterialsMode;
  1484. _scSettings.materialSettings.multiMaterials0 = multiMaterials0;
  1485. _scSettings.materialSettings.multiMaterials1 = multiMaterials1;
  1486. _scSettings.materialSettings.multiMaterials2 = multiMaterials2;
  1487. _scSettings.materialSettings.multiMaterials3 = multiMaterials3;
  1488. _scSettings.materialSettings.multiMaterials4 = multiMaterials4;
  1489. _scSettings.materialSettings.multiMaterials5 = multiMaterials5;
  1490. _scSettings.materialSettings.multiMaterials6 = multiMaterials6;
  1491. _scSettings.materialSettings.multiMaterials7 = multiMaterials7;
  1492. _scSettings.materialSettings.multiMaterials8 = multiMaterials8;
  1493. _scSettings.materialSettings.multiMaterials9 = multiMaterials9;
  1494. _scSettings.materialSettings.multiMaterials10 = multiMaterials10;
  1495. _scSettings.materialSettings.customShaderProperties = _customTextureProperies;
  1496. // Meshs settings
  1497. _scSettings.meshSettings.manageLODs = _manageLodLevel;
  1498. _scSettings.meshSettings.managedLODLevel = _managedLodLevel;
  1499. _scSettings.meshSettings.manageColliders = _manageColliders;
  1500. _scSettings.meshSettings.targetGameObject = _targetGameObject;
  1501. _scSettings.meshSettings.combineMeshs = _combineMeshes;
  1502. _scSettings.meshSettings.generateUv2 = _generateUv2;
  1503. _scSettings.meshSettings.meshOutputType = (MeshSettings.MeshOutputType)_meshOutput;
  1504. }
  1505. }
  1506. }