TC_TerrainArea.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System;
  5. using System.IO;
  6. using System.Runtime.Serialization.Formatters.Binary;
  7. public enum ApplyChanges { Terrain, TerrainArea, AllTerrainAreas }
  8. namespace TerrainComposer2
  9. {
  10. [ExecuteInEditMode]
  11. public class TC_TerrainArea : MonoBehaviour
  12. {
  13. public RenderTexture[] rtSplatmaps;
  14. public RenderTexture rtColormap;
  15. // public RenderTexture rtHeight;
  16. public bool loaded = false;
  17. public ApplyChanges applyChanges;
  18. // terrain area class
  19. public Int2 totalHeightmapResolution, heightTexResolution;
  20. public List<TCUnityTerrain> terrains = new List<TCUnityTerrain>();
  21. public TCUnityTerrain[,] terrainArray;
  22. public bool createTerrainTab = false;
  23. public bool active = true;
  24. public Color color = new Color(1.5f, 1.5f, 1.5f, 1.0f);
  25. public int index;
  26. public bool terrains_active = true;
  27. public bool terrains_scene_active = true;
  28. public bool terrains_foldout = true;
  29. public bool sizeTab, resolutionsTab, settingsTab, splatTab, treeTab, grassTab, resetTab;
  30. public Int2 tiles;
  31. public Int2 selectTiles;
  32. public bool tileLink = true;
  33. public Rect area;
  34. public Vector3 terrainSize = new Vector3(2048, 750, 2048);
  35. public Vector3 center = new Vector3(0.0f, 0.0f, 0.0f);
  36. public Rect menuRect;
  37. public bool display_short;
  38. public string terrainDataPath;
  39. public Transform parent;
  40. public string terrainName = "Terrain";
  41. public bool copy_settings = true;
  42. public int copy_terrain = 0;
  43. public int terrainSelect = 0;
  44. public bool settingsEditor = true;
  45. static public readonly string[] heightmapResolutionList = new string[] { "4097", "2049", "1025", "513", "257", "129", "65", "33" };
  46. static public readonly string[] splatmapResolutionList = new string[] { "2048", "1024", "512", "256", "128", "64", "32", "16" };
  47. static public readonly string[] detailmapResolutionList = new string[] { "2048", "1024", "512", "256", "128", "64", "32", "16", "8" };
  48. static public readonly string[] detailResolutionPerPatchList = new string[] { "8", "16", "32", "64", "128" };
  49. static public readonly string[] imageImportMaxSettings = new string[] { "32", "64", "128", "256", "512", "1024", "2048", "4096" };
  50. void OnEnable()
  51. {
  52. if (!loaded)
  53. {
  54. loaded = true;
  55. terrainDataPath = Application.dataPath;
  56. }
  57. SetNeighbors();
  58. // GetTerrainsFromChildren();
  59. // if (terrains.Count == 0) terrains.Add(new TCTerrain());
  60. }
  61. public bool IsRTPAddedToTerrains()
  62. {
  63. Type t = TC.FindRTP();
  64. if (t == null) return false;
  65. for (int i = 0; i < terrains.Count; i++)
  66. {
  67. Terrain terrain = terrains[i].terrain;
  68. if (terrain == null) continue;
  69. Component c = terrain.GetComponent(t);
  70. if (c == null) return false;
  71. }
  72. return true;
  73. }
  74. public void AddRTPTOTerrains()
  75. {
  76. Type t = TC.FindRTP();
  77. if (t == null) return;
  78. for (int i = 0; i < terrains.Count; i++)
  79. {
  80. Terrain terrain = terrains[i].terrain;
  81. if (terrain == null) continue;
  82. Component c = terrain.GetComponent(t);
  83. if (c == null) terrain.gameObject.AddComponent(t);
  84. }
  85. }
  86. // TODO
  87. public void AssignTerrainArray()
  88. {
  89. bool create = false;
  90. if (terrainArray == null) create = true;
  91. else if (terrainArray.Length != tiles.x * tiles.y) create = true;
  92. if (create)
  93. {
  94. terrainArray = new TCUnityTerrain[tiles.x, tiles.y];
  95. int i = 0;
  96. for (int y = 0; y < tiles.y; y++)
  97. {
  98. for (int x = 0; x < tiles.x; x++) terrainArray[x, y] = terrains[i++];
  99. }
  100. }
  101. }
  102. //void Start()
  103. //{
  104. // // This is needed for custom terrain material to not turn black
  105. // #if UNITY_EDITOR
  106. // UnityEditor.AssetDatabase.Refresh();
  107. // #endif
  108. // // ReassignTerrainMaterial();
  109. //}
  110. //void ReassignTerrainMaterial()
  111. //{
  112. // if (terrains == null) return;
  113. // for (int i = 0; i < terrains.Count; i++)
  114. // {
  115. // Terrain terrain = terrains[i].terrain;
  116. // if (terrain == null) continue;
  117. // Material matTerrain = terrain.materialTemplate;
  118. // if (matTerrain == null) continue;
  119. // if (matTerrain.GetTexture("_Colormap") != null)
  120. // {
  121. // terrain.materialTemplate.SetTexture("_Colormap", terrains[i].texColormap);
  122. // #if UNITY_EDITOR
  123. // UnityEditor.EditorUtility.SetDirty(terrain.materialTemplate);
  124. // #endif
  125. // }
  126. // }
  127. //}
  128. void OnDestroy()
  129. {
  130. DisposeTextures();
  131. }
  132. public void DisposeTextures()
  133. {
  134. TC_Compute.DisposeRenderTextures(ref rtSplatmaps);
  135. TC_Compute.DisposeRenderTexture(ref rtColormap);
  136. for (int i = 0; i < terrains.Count; i++) terrains[i].DisposeTextures();
  137. }
  138. public void Clear()
  139. {
  140. terrains.Clear();
  141. }
  142. public void ResetTextureRTP(string texName)
  143. {
  144. for (int i = 0; i < terrains.Count; i++)
  145. {
  146. terrains[i].AssignTextureRTP(texName, null);
  147. }
  148. }
  149. public void ClearToOne()
  150. {
  151. int length = terrains.Count;
  152. if (terrains[0].terrain != null) DestroyImmediate(terrains[0].terrain.gameObject);
  153. for (int i = 1; i < length; ++i)
  154. {
  155. if (terrains[1].terrain != null) DestroyImmediate(terrains[1].terrain.gameObject);
  156. terrains.RemoveAt(1);
  157. }
  158. }
  159. public void CalcTotalResolutions()
  160. {
  161. // Debug.Log("Calc total heightmap resolution");
  162. if (terrains.Count == 0) return;
  163. if (terrains[0].terrain == null) return;
  164. if (terrains[0].terrain.terrainData == null) return;
  165. int heightmapResolution = terrains[0].terrain.terrainData.heightmapResolution;
  166. totalHeightmapResolution = new Int2(tiles.x * heightmapResolution, tiles.y * heightmapResolution);
  167. heightTexResolution = new Int2(tiles.x * (heightmapResolution - 1), tiles.y * (heightmapResolution - 1));
  168. }
  169. public void CalcTotalArea()
  170. {
  171. Vector2 minPos = new Vector2(terrains[0].terrain.transform.localPosition.x, terrains[0].terrain.transform.localPosition.z);
  172. Vector2 maxPos = minPos + new Vector2(terrains[0].terrain.terrainData.size.x, terrains[0].terrain.terrainData.size.z);
  173. Vector2 pos;
  174. for (int i = 1; i < terrains.Count; i++)
  175. {
  176. if (terrains[i].terrain.transform.localPosition.x < minPos.x) minPos.x = terrains[i].terrain.transform.localPosition.x;
  177. if (terrains[i].terrain.transform.localPosition.z < minPos.y) minPos.y = terrains[i].terrain.transform.localPosition.z;
  178. pos = new Vector2(terrains[i].terrain.transform.localPosition.x + terrains[i].terrain.terrainData.size.x, terrains[i].terrain.transform.localPosition.z + terrains[i].terrain.terrainData.size.z);
  179. if (pos.x > maxPos.x) maxPos.x = pos.x;
  180. if (pos.y > maxPos.y) maxPos.y = pos.y;
  181. }
  182. area = new Rect();
  183. area.xMin = minPos.x;
  184. area.yMin = minPos.y;
  185. area.xMax = maxPos.x;
  186. area.yMax = maxPos.y;
  187. }
  188. public void FitTerrainsPosition()
  189. {
  190. if (terrains.Count == 0) return;
  191. int countTerrain = 0;
  192. Vector3 size = terrains[0].terrain.terrainData.size;
  193. area.xMin = -size.x * (tiles.x / 2.0f);
  194. area.yMin = -size.z * (tiles.y / 2.0f);
  195. for (int y = 0; y < tiles.y; y++)
  196. {
  197. for (int x = 0; x < tiles.x; x++)
  198. {
  199. terrains[countTerrain].tasks = 0;
  200. if (terrains[countTerrain].terrain.terrainData.size != size) terrains[countTerrain].terrain.terrainData.size = size;
  201. terrains[countTerrain].terrain.transform.localPosition = new Vector3(area.xMin + (size.x * x), 0, area.yMin + (size.z * y));
  202. if (++countTerrain > terrains.Count) goto exit;
  203. }
  204. }
  205. exit:;
  206. // tile_resolution = (int)(tiles.x * size.x);
  207. SetNeighbors();
  208. }
  209. public void SetNeighbors()
  210. {
  211. for (int i = 0; i < terrains.Count; i++)
  212. {
  213. TCUnityTerrain t = terrains[i];
  214. if (!t.CheckValidUnityTerrain()) continue;
  215. Terrain top = GetTerrainTile(t.tileX, t.tileZ + 1);
  216. Terrain right = GetTerrainTile(t.tileX + 1, t.tileZ);
  217. Terrain bottom = GetTerrainTile(t.tileX, t.tileZ - 1);
  218. Terrain left = GetTerrainTile(t.tileX - 1, t.tileZ);
  219. t.terrain.SetNeighbors(left, top, right, bottom);
  220. }
  221. }
  222. public void ResetNeighbors()
  223. {
  224. for (int i = 0; i < terrains.Count; i++)
  225. {
  226. TCUnityTerrain t = terrains[i];
  227. if (!t.CheckValidUnityTerrain()) continue;
  228. t.terrain.SetNeighbors(null, null, null, null);
  229. }
  230. }
  231. public Terrain GetTerrainTile(int tileX, int tileZ)
  232. {
  233. if (tileX < 0 || tileX > tiles.x - 1 || tileZ < 0 || tileZ > tiles.y - 1) return null;
  234. int index = (tileZ * tiles.x) + tileX;
  235. if (!terrains[index].CheckValidUnityTerrain()) return null;
  236. return terrains[index].terrain;
  237. }
  238. public TCUnityTerrain GetTCUnityTerrainTile(int tileX, int tileZ)
  239. {
  240. if (tileX < 0 || tileX > tiles.x - 1 || tileZ < 0 || tileZ > tiles.y - 1) return null;
  241. int index = (tileZ * tiles.x) + tileX;
  242. return terrains[index];
  243. }
  244. public void SetTerrainsActive(bool invert)
  245. {
  246. for (int i = 0; i < terrains.Count; ++i)
  247. {
  248. if (!invert) terrains[i].active = terrains_active; else terrains[i].active = !terrains[i].active;
  249. }
  250. }
  251. void GetTerrainsFromChildren()
  252. {
  253. Terrain[] unityTerrains = GetComponentsInChildren<Terrain>(true);
  254. terrains.Clear();
  255. for (int i = 0; i < unityTerrains.Length; i++)
  256. {
  257. terrains.Add(new TCUnityTerrain());
  258. terrains[terrains.Count - 1].terrain = unityTerrains[i];
  259. }
  260. tiles.x = tiles.y = (int)Mathf.Sqrt(terrains.Count);
  261. }
  262. public Int2 IndexToTile(int index)
  263. {
  264. Int2 tile = new Int2();
  265. tile.y = index / tiles.x;
  266. tile.x = index - (tile.y * tiles.x);
  267. return tile;
  268. }
  269. public int TileToIndex(Int2 tile)
  270. {
  271. return (tile.y * tiles.x) + tile.x;
  272. }
  273. public void CreateTerrains()
  274. {
  275. TerrainData terrainData;
  276. GameObject terrainObject;
  277. Terrain terrain;
  278. TerrainCollider terrainCollider;
  279. string tileName;
  280. ClearToOne();
  281. terrains[0].size = terrainSize;
  282. int countTerrain = 0;
  283. index = terrains.Count - 1;
  284. Int2 tile = IndexToTile(terrainSelect);
  285. for (int y = 0; y < selectTiles.y; ++y)
  286. {
  287. for (int x = 0; x < selectTiles.x; ++x)
  288. {
  289. // {
  290. // }
  291. // else if (terrains[countTerrain].terrain != null) { ++countTerrain; continue; }
  292. if (countTerrain != 0)
  293. {
  294. terrains.Add(new TCUnityTerrain());
  295. terrains[countTerrain] = CopyTerrain(terrains[0]);
  296. }
  297. terrains[countTerrain].tileX = x;
  298. terrains[countTerrain].tileZ = y;
  299. terrainObject = new GameObject();
  300. terrainObject.transform.parent = transform;
  301. // terrainObject.transform.hideFlags = HideFlags.NotEditable;
  302. terrain = (Terrain)terrainObject.AddComponent(typeof(Terrain));
  303. terrainCollider = (TerrainCollider)terrainObject.AddComponent(typeof(TerrainCollider));
  304. tileName = "_x" + x.ToString() + "_y" + y.ToString();
  305. terrain.name = terrainName + tileName;
  306. terrainData = new TerrainData();
  307. terrainData.size = terrains[0].size;
  308. terrain.terrainData = terrainData;
  309. terrainCollider.terrainData = terrainData;
  310. terrains[countTerrain].terrain = terrain;
  311. terrains[countTerrain].ApplyAllSettings(terrains[0], settingsEditor);
  312. terrains[countTerrain].terrainSettingsScript = terrain.gameObject.AddComponent<TC_TerrainSettings>();
  313. // script.set_terrain_settings(terrainArea.terrains[index], "(siz)(res)");
  314. //if (script.settings.copy_terrain_material)
  315. //{
  316. // terrain.materialTemplate = terrainArea.terrains[0].terrain.materialTemplate;
  317. //}
  318. #if UNITY_EDITOR
  319. string path = "Assets" + terrainDataPath.Replace(Application.dataPath, String.Empty);
  320. path += "/" + terrain.name + ".asset";
  321. UnityEditor.AssetDatabase.DeleteAsset(path);
  322. UnityEditor.AssetDatabase.CreateAsset(terrainData, path);
  323. #endif
  324. // Debug.Log(terrains[countTerrain].splatPrototypes.Count);
  325. terrains[countTerrain].ApplySplatTextures();
  326. terrains[countTerrain].ApplyTrees();
  327. terrains[countTerrain].ApplyGrass();
  328. terrains[countTerrain].GetSettings(settingsEditor);
  329. // script.set_terrain_parameters(terrainArea.terrains[index], terrainArea.terrains[0]);
  330. // if (terrainArea.terrains[0].rtp_script) { script.assign_rtp_single(terrainArea.terrains[index]); }
  331. ++countTerrain;
  332. }
  333. }
  334. if (terrains[0].terrain != null) TC_Settings.instance.masterTerrain = terrains[0].terrain;
  335. // script.set_all_terrain_area(script.terrains[0]);
  336. // script.set_terrainArea_splat_textures(terrainArea, terrainArea.terrains[0]);
  337. // script.assign_all_terrain_splat_alpha();
  338. // script.set_terrainArea_trees(terrainArea, terrainArea.terrains[0]);
  339. // script.set_terrainArea_details(terrainArea, terrainArea.terrains[0]);
  340. tiles = selectTiles;
  341. FitTerrainsPosition();
  342. CalcTotalResolutions();
  343. terrainSelect = TileToIndex(tile);
  344. if (terrainSelect > tiles.x * tiles.y) terrainSelect = 0;
  345. }
  346. public TCUnityTerrain CopyTerrain(TCUnityTerrain tcTerrain)
  347. {
  348. GameObject go = new GameObject();
  349. SaveTemplate s = go.AddComponent<SaveTemplate>();
  350. s.tcTerrain = tcTerrain;
  351. GameObject go2 = (GameObject)Instantiate(go);
  352. DestroyImmediate(go);
  353. s = go2.GetComponent<SaveTemplate>();
  354. tcTerrain = s.tcTerrain;
  355. tcTerrain.rtHeight = null;
  356. tcTerrain.texHeight = null;
  357. tcTerrain.texColormap = null;
  358. // tcTerrain.materialTemplate = null;
  359. DestroyImmediate(go2);
  360. return tcTerrain;
  361. }
  362. public void GetAll()
  363. {
  364. if (terrains == null) terrains = new List<TCUnityTerrain>();
  365. if (terrains.Count == 0) terrains.Add(new TCUnityTerrain());
  366. if (terrainSelect >= terrains.Count) terrainSelect = 0;
  367. GetSize();
  368. GetSettings();
  369. GetSplatTextures();
  370. GetTrees();
  371. GetGrass();
  372. GetResolutions();
  373. }
  374. public void GetResolutions()
  375. {
  376. terrains[terrainSelect].GetResolutions();
  377. CalcTotalResolutions();
  378. }
  379. public void GetSize()
  380. {
  381. if (!terrains[terrainSelect].CheckValidUnityTerrain()) return;
  382. terrains[terrainSelect].size = terrains[terrainSelect].terrain.terrainData.size;
  383. }
  384. public void GetSettings()
  385. {
  386. terrains[terrainSelect].GetSettings(settingsEditor);
  387. }
  388. public void ApplySize()
  389. {
  390. if (applyChanges == ApplyChanges.Terrain) ApplySizeTerrain(); // TODO Remove
  391. else if (applyChanges == ApplyChanges.TerrainArea) ApplySizeTerrainArea();//TC_Generate.singleton.applyTerrainAreaSize = true;
  392. // else if (applyChanges == ApplyChanges.AllTerrainAreas) GlobalManager.singleton.ApplySizeTerrainAreas();
  393. }
  394. public void ApplySizeTerrain()
  395. {
  396. if (!terrains[terrainSelect].CheckValidUnityTerrain()) return;
  397. terrains[terrainSelect].terrain.terrainData.size = terrainSize;
  398. FitTerrainsPosition();
  399. }
  400. public void ApplySizeTerrainArea()
  401. {
  402. if (!terrains[terrainSelect].CheckValidUnityTerrain()) return;
  403. if (!terrains[0].CheckValidUnityTerrain()) return;
  404. terrains[0].terrain.terrainData.size = terrainSize;
  405. FitTerrainsPosition();
  406. // !if (script.settings.colormap) { script.set_colormap(script.settings.colormap, false); }
  407. }
  408. public void ApplyResolution()
  409. {
  410. // if (applyChanges == ApplyChanges.Terrain) terrains[terrainSelect].ApplyResolutionTerrain(terrains[terrainSelect]);
  411. // else if (applyChanges == ApplyChanges.TerrainArea)
  412. ApplyResolutionTerrainArea(terrains[terrainSelect]);
  413. // else if (applyChanges == ApplyChanges.AllTerrainAreas) TC_Area2D.singleton.ApplyResolutionTerrainAreas(terrains[terrainSelect]);
  414. }
  415. public void ApplyResolutionTerrainArea(TCUnityTerrain sTerrain)
  416. {
  417. for (int i = 0; i < terrains.Count; i++) terrains[i].ApplyResolutionTerrain(sTerrain);
  418. CalcTotalResolutions();
  419. if (TC_Settings.instance.global.showResolutionWarnings)
  420. {
  421. if (sTerrain.heightmapResolution > 513) TC.AddMessage("Heightmap resolution is higher than 513, keep in mind that Auto generate will be too slow to work in realtime.");
  422. if (sTerrain.splatmapResolution > 1024) TC.AddMessage("Splatmap resolution is higher than 1024, keep in mind that Auto generate will be too slow to work in realtime.");
  423. if (sTerrain.detailResolution > 512) TC.AddMessage("Grass resolution is higher than 513, keep in mind that Auto generate will be too slow to work in realtime.");
  424. }
  425. }
  426. public void ApplySettings()
  427. {
  428. if (applyChanges == ApplyChanges.Terrain) terrains[terrainSelect].ApplySettings(terrains[terrainSelect], settingsEditor);
  429. else if (applyChanges == ApplyChanges.TerrainArea) ApplySettingsTerrainArea();
  430. }
  431. public void ApplySettingsTerrainArea()
  432. {
  433. for (int i = 0; i < terrains.Count; i++) terrains[i].ApplySettings(terrains[terrainSelect], settingsEditor);
  434. }
  435. public void ApplySplatTextures(TCUnityTerrain sTerrain)
  436. {
  437. for (int i = 0; i < terrains.Count; i++) terrains[i].ApplySplatTextures(sTerrain);
  438. }
  439. public void GetSplatTextures()
  440. {
  441. for (int i = 0; i < terrains.Count; i++) terrains[i].GetSplatTextures();
  442. }
  443. public void ApplyTrees()
  444. {
  445. for (int i = 0; i < terrains.Count; i++) terrains[i].ApplyTrees(terrains[terrainSelect]);
  446. }
  447. public void GetTrees()
  448. {
  449. for (int i = 0; i < terrains.Count; i++) terrains[i].GetTrees();
  450. }
  451. public void ApplyGrass() { for (int i = 0; i < terrains.Count; i++) terrains[i].ApplyGrass(terrains[terrainSelect]); }
  452. public void GetGrass() { for (int i = 0; i < terrains.Count; i++) terrains[i].GetGrass(); }
  453. public void ResetHeightmap() { for (int i = 0; i < terrains.Count; i++) terrains[i].ResetHeightmap(); }
  454. public void ResetSplatmap() { for (int i = 0; i < terrains.Count; i++) terrains[i].ResetSplatmap(); }
  455. public void ResetTrees() { for (int i = 0; i < terrains.Count; i++) terrains[i].ResetTrees(); }
  456. public void ResetGrass() { for (int i = 0; i < terrains.Count; i++) terrains[i].ResetGrass(); }
  457. public void ResetObjects() { for (int i = 0; i < terrains.Count; i++) terrains[i].ResetObjects(); }
  458. }
  459. }