InTerra_Data.cs 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505
  1. //==========================================================
  2. //-------------| INTERRA |---------------
  3. //==========================================================
  4. //-------------| 4.4.0 |---------------
  5. //==========================================================
  6. //-------------| © INEFFABILIS ARCANUM |---------------
  7. //==========================================================
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10. using System.Linq;
  11. using System.IO;
  12. #if UNITY_EDITOR
  13. using UnityEditor;
  14. using UnityEngine.Rendering;
  15. #endif
  16. #if USING_HDRP
  17. using UnityEngine.Rendering.HighDefinition;
  18. #endif
  19. #if USING_URP
  20. using UnityEngine.Rendering.Universal;
  21. #endif
  22. namespace InTerra
  23. {
  24. public static class InTerra_Data
  25. {
  26. public const string ObjectShaderName = "InTerra/Built-in/Object into Terrain Integration";
  27. public const string DiffuseObjectShaderName = "InTerra/Built-in/Diffuse/Object into Terrain Integration (Diffuse)";
  28. public const string URPObjectShaderName = "InTerra/URP/Object into Terrain Integration";
  29. public const string HDRPObjectShaderName = "InTerra/HDRP/Object into Terrain Integration";
  30. public const string HDRPObjectTessellationShaderName = "InTerra/HDRP Tessellation/Object into Terrain Integration Tessellation";
  31. public const string TerrainShaderName = "InTerra/Built-in/Terrain (Standard With Features)";
  32. public const string DiffuseTerrainShaderName = "InTerra/Built-in/Diffuse/Terrain (Diffuse With Features)";
  33. public const string URPTerrainShaderName = "InTerra/URP/Terrain (Lit with Features)";
  34. public const string HDRPTerrainShaderName = "InTerra/HDRP/Terrain (Lit with Features)";
  35. public const string HDRPTerrainTessellationShaderName = "InTerra/HDRP Tessellation/Terrain (Lit with Features)";
  36. public const string MeshTerrainShaderName = "InTerra/Built-in/Mesh Terrain (Standard)";
  37. public const string DiffuseMeshTerrainShaderName = "InTerra/Built-in/Diffuse/Mesh Terrain (Diffuse)";
  38. public const string URPMeshTerrainShaderName = "InTerra/URP/Mesh Terrain";
  39. public const string HDRPMeshTerrainShaderName = "InTerra/HDRP/Mesh Terrain";
  40. public const string HDRPMeshTerrainTessellationShaderName = "InTerra/HDRP Tessellation/Mesh Terrain Tessellation";
  41. public const string TessellationShaderFolder = "InTerra/HDRP Tessellation";
  42. static readonly string[] TerrainToObjectsTextureProperties = {
  43. "_TerrainColorTintTexture",
  44. "_TerrainNormalTintTexture",
  45. "_TrackDetailTexture",
  46. "_TrackDetailNormalTexture"};
  47. static readonly string[] TerrainToObjectsFloats = {
  48. "_HeightTransition",
  49. "_Distance_HeightTransition",
  50. "_HT_distance_scale",
  51. "_HT_cover",
  52. "_TriplanarOneToAllSteep",
  53. "_TriplanarSharpness",
  54. "_TerrainColorTintStrenght",
  55. "_TerrainNormalTintStrenght",
  56. "_HeightmapBlending",
  57. "_Terrain_Parallax",
  58. "_Tracks",
  59. "_MipMapLevel",
  60. "_TrackAO",
  61. "_TrackDetailNormalStrenght",
  62. "_TrackNormalStrenght",
  63. "_TrackHeightOffset",
  64. "_TrackHeightTransition",
  65. "_ParallaxTrackAffineSteps",
  66. "_ParallaxTrackSteps",
  67. "_TrackEdgeNormals",
  68. "_TrackEdgeSharpness",
  69. "_Gamma",
  70. "_WorldMapping"};
  71. static readonly string[] TerrainToObjectsTessellationProperties = {
  72. "_TessellationFactorMinDistance",
  73. "_TessellationFactorMaxDistance",
  74. "_Tessellation_HeightTransition",
  75. "_TessellationShadowQuality",
  76. "_TrackTessallationHeightTransition",
  77. "_TrackTessallationHeightOffset"};
  78. static readonly string[] TerrainToObjectsVectorProperties = {
  79. "_HT_distance",
  80. "_TerrainNormalTintDistance",
  81. "_MipMapFade"};
  82. static readonly string[] TerrainToObjectsKeywords = {"_TERRAIN_DISTANCEBLEND"};
  83. const string UpdaterName = "InTerra_UpdateAndCheck";
  84. static public GameObject Updater;
  85. static InTerra_UpdateAndCheck UpdateScript;
  86. static Camera TrackCamera;
  87. static Vector3 TrackCameraForwardVec;
  88. static Vector3 TrackCameraPositon;
  89. static float TracksUpdateTimeCount;
  90. static bool TracksCameraUpdate;
  91. public static bool initTrack;
  92. static MaterialPropertyBlock mtb = new MaterialPropertyBlock();
  93. #if UNITY_EDITOR
  94. static string InTerraPath;
  95. static bool GlobalKeywordsCheck;
  96. const int DEFINE_MASKMAP_LineNumber = 1;
  97. const int DEFINE_NORMAL_MASK_LineNumber = 2;
  98. const int DEFINE_HEIGTH_ONLY_LineNumber = 3;
  99. const int RESTRICT_NORMALMAP_LineNumber = 5;
  100. const int RESTRICT_HEIGHTBLEND_LineNumber = 6;
  101. const int RESTRICT_TERR_PARALAX_LineNumber = 7;
  102. const int RESTRICT_TRACKS_LineNumber = 8;
  103. const int RESTRICT_OBJ_PARALLAX_LineNumber = 10;
  104. const int RESTRICT_PUDDLES_LineNumber = 12;
  105. #if USING_URP
  106. const int UNITY_VERSION_LineNumber = 13;
  107. #endif
  108. #if !(USING_URP || USING_HDRP)
  109. const int EIGHT_LAYERS_PASS_LineNumber = 13;
  110. #endif
  111. #endif
  112. #if USING_HDRP
  113. static Texture2DArray splatArray16;
  114. #endif
  115. public static void UpdateTerrainData(bool UpdateDictionary)
  116. {
  117. Terrain[] terrains = Terrain.activeTerrains;
  118. List<MeshRenderer> meshTerrainsList = GetUpdaterScript().MeshTerrainsList;
  119. if (terrains.Length > 0 || (meshTerrainsList != null && meshTerrainsList.Count > 0))
  120. {
  121. DictionaryMaterialTerrain materialTerrain = GetUpdaterScript().MaterialTerrain;
  122. DictionaryMaterialMeshTerrain materialMeshTerrain = GetUpdaterScript().MaterialMeshTerrain;
  123. meshTerrainsList.Clear();
  124. //===== DICTIONARY OF MATERIALS WITH INTERRA SHADERS AND SUM POSITIONS OF RENDERERS WITH THAT MATERIAL ======
  125. if (UpdateDictionary)
  126. {
  127. Dictionary<Material, Vector3> matPos = new Dictionary<Material, Vector3>();
  128. #if UNITY_2023_1_OR_NEWER
  129. MeshRenderer[] renderers = Object.FindObjectsByType<MeshRenderer>(FindObjectsSortMode.None);
  130. #else
  131. MeshRenderer[] renderers = Object.FindObjectsOfType<MeshRenderer>();
  132. #endif
  133. foreach (MeshRenderer rend in renderers)
  134. {
  135. if (rend != null && rend.bounds != null)
  136. {
  137. foreach (Material mat in rend.sharedMaterials)
  138. {
  139. if (CheckObjectShader(mat))
  140. {
  141. if (!matPos.ContainsKey(mat))
  142. {
  143. matPos.Add(mat, new Vector3(rend.bounds.center.x, rend.bounds.center.z, 1));
  144. }
  145. else
  146. {
  147. Vector3 sumPos = matPos[mat];
  148. sumPos.x += rend.bounds.center.x;
  149. sumPos.y += rend.bounds.center.z;
  150. sumPos.z += 1;
  151. matPos[mat] = sumPos;
  152. }
  153. }
  154. if (CheckMeshTerrainShader(mat))
  155. {
  156. if (!meshTerrainsList.Contains(rend))
  157. {
  158. meshTerrainsList.Add(rend);
  159. }
  160. }
  161. }
  162. }
  163. }
  164. //===================== DICTIONARY OF MATERIALS AND TERRAINS WHERE ARE PLACED =========================
  165. Dictionary<Material, Terrain> tempMatTerDict = CopyMaterialTerrainDictionary(materialTerrain);
  166. Dictionary<Material, MeshRenderer> tempMatMeshTerDict = CopyMaterialMeshDictionary(materialMeshTerrain);
  167. materialTerrain.Clear();
  168. materialMeshTerrain.Clear();
  169. foreach (Material mat in matPos.Keys)
  170. {
  171. Vector2 averagePos = matPos[mat] / matPos[mat].z;
  172. foreach (Terrain terrain in terrains)
  173. {
  174. if (!materialTerrain.ContainsKey(mat))
  175. {
  176. if (mat.GetFloat("_CustomTerrainSelection") > 0 && tempMatTerDict.ContainsKey(mat))
  177. {
  178. materialTerrain.Add(mat, tempMatTerDict[mat]);
  179. }
  180. else
  181. {
  182. if (CheckPosition(terrain, averagePos))
  183. {
  184. materialTerrain.Add(mat, terrain);
  185. }
  186. }
  187. }
  188. if (CheckTerrainShaderContains(terrain, "InTerra/HDRP"))
  189. {
  190. terrain.materialTemplate.renderQueue = 2225;
  191. }
  192. }
  193. //===================== MESH TERRAINS =======================
  194. foreach (MeshRenderer meshTerrain in meshTerrainsList)
  195. {
  196. if (!materialMeshTerrain.ContainsKey(mat))
  197. {
  198. if (mat.GetFloat("_CustomTerrainSelection") == 1 && mat.HasProperty("_MeshTerrain") && mat.GetFloat("_MeshTerrain") == 1 && tempMatMeshTerDict.ContainsKey(mat))
  199. {
  200. materialMeshTerrain.Add(mat, tempMatMeshTerDict[mat]);
  201. }
  202. else if (mat.GetFloat("_CustomTerrainSelection") == 0)
  203. {
  204. if (CheckMeshTerrainPosition(meshTerrain, averagePos))
  205. {
  206. materialMeshTerrain.Add(mat, meshTerrain);
  207. }
  208. }
  209. }
  210. InTerra_MeshTerrainData meshTerrainData = meshTerrain.GetComponent<InTerra_MeshTerrainData>();
  211. if (meshTerrainData != null)
  212. {
  213. TerrainLayer[] tl = meshTerrainData.TerrainLayers;
  214. SetMeshTerrainPositionAndSize(meshTerrain.sharedMaterial, meshTerrain);
  215. int layers = 8;
  216. #if USING_HDRP
  217. if (meshTerrain.sharedMaterial.IsKeywordEnabled("_LAYERS_SIXTEEN"))
  218. {
  219. if (DiffuseTextureArrayCheckSize(tl) && DiffuseTextureArrayCheckFormat(tl))
  220. {
  221. DiffuseTextureArrays16(tl, meshTerrain.sharedMaterial);
  222. }
  223. else
  224. {
  225. splatArray16 = new Texture2DArray(1, 1, 16, TextureFormat.RGBA32, true);
  226. }
  227. if (NormalMapTextureArrayCheckSize(tl) && NormalMapTextureArrayCheckFormat(tl))
  228. {
  229. NormalTextureArrays16(tl, meshTerrain.sharedMaterial);
  230. }
  231. layers = 16;
  232. }
  233. #endif
  234. for (int i = 0; i < tl.Length && i < layers; i++)
  235. {
  236. TerrainLaeyrDataToMaterial(meshTerrainData.TerrainLayers[i], i, meshTerrain.sharedMaterial);
  237. }
  238. }
  239. }
  240. }
  241. }
  242. //================================================================================
  243. //--------------------| SET TERRAINS DATA TO MATERIALS |--------------------
  244. //================================================================================
  245. foreach (Material mat in materialTerrain.Keys)
  246. {
  247. Terrain terrain = materialTerrain[mat];
  248. if (terrain != null && terrain.materialTemplate != null && CheckObjectShader(mat))
  249. {
  250. if (!(mat.IsKeywordEnabled("_LAYERS_ONE") && mat.IsKeywordEnabled("_LAYERS_TWO")))
  251. {
  252. if (terrain.terrainData.alphamapTextureCount > 1)
  253. {
  254. SetKeyword(mat, "_LAYERS_EIGHT", terrain.materialTemplate.IsKeywordEnabled("_LAYERS_EIGHT"));
  255. #if USING_HDRP
  256. SetKeyword(mat, "_LAYERS_SIXTEEN", terrain.materialTemplate.IsKeywordEnabled("_LAYERS_SIXTEEN"));
  257. #endif
  258. }
  259. }
  260. Vector4 heightScale = new Vector4(terrain.terrainData.heightmapScale.x, terrain.terrainData.heightmapScale.y / (32766.0f / 65535.0f), terrain.terrainData.heightmapScale.z, terrain.terrainData.heightmapScale.y);
  261. SetTerrainDataToMaterials(terrain.terrainData.size, terrain.transform.position, heightScale, terrain.terrainData.heightmapTexture, terrain.terrainData.alphamapTextures, terrain.materialTemplate, terrain.terrainData.terrainLayers, mat);
  262. }
  263. }
  264. foreach (Material mat in materialMeshTerrain.Keys)
  265. {
  266. InTerra_MeshTerrainData meshTerrainData = materialMeshTerrain[mat].GetComponent<InTerra_MeshTerrainData>();
  267. if (meshTerrainData != null)
  268. {
  269. Material meshTerrainMaterial = materialMeshTerrain[mat].sharedMaterial;
  270. #if USING_HDRP
  271. Texture2D[] controlmaps = new Texture2D[] { meshTerrainData.ControlMap,
  272. meshTerrainData.ControlMap1,
  273. meshTerrainData.ControlMap2,
  274. meshTerrainData.ControlMap3 };
  275. #else
  276. Texture2D[] controlmaps = new Texture2D[] { meshTerrainData.ControlMap, meshTerrainData.ControlMap1 };
  277. #endif
  278. #if (USING_URP || USING_HDRP)
  279. if (!(mat.IsKeywordEnabled("_LAYERS_ONE") && mat.IsKeywordEnabled("_LAYERS_TWO")))
  280. {
  281. SetKeyword(mat, "_LAYERS_EIGHT", meshTerrainMaterial.IsKeywordEnabled("_LAYERS_EIGHT"));
  282. #if USING_HDRP
  283. SetKeyword(mat, "_LAYERS_SIXTEEN", meshTerrainMaterial.IsKeywordEnabled("_LAYERS_SIXTEEN"));
  284. #endif
  285. }
  286. #endif
  287. SetTerrainDataToMaterials(meshTerrainMaterial.GetVector("_TerrainSize"), meshTerrainMaterial.GetVector("_TerrainPosition"), meshTerrainMaterial.GetVector("_TerrainHeightmapScale"), meshTerrainMaterial.GetTexture("_TerrainHeightmapTexture"), controlmaps, meshTerrainMaterial, meshTerrainData.TerrainLayers, mat);
  288. }
  289. }
  290. }
  291. #if UNITY_EDITOR
  292. if (!CheckDefinedKeywords()) WriteDefinedKeywords();
  293. #if USING_URP
  294. URPShadersVersionAdjust();
  295. #endif
  296. #endif
  297. TerrainMaterialUpdate();
  298. }
  299. //============================================================================
  300. //-------------------------| FUNCTIONS |-------------------------
  301. //============================================================================
  302. public static bool CheckPosition(Terrain terrain, Vector2 position)
  303. {
  304. return terrain != null && terrain.terrainData != null
  305. && terrain.GetPosition().x <= position.x && (terrain.GetPosition().x + terrain.terrainData.size.x) > position.x
  306. && terrain.GetPosition().z <= position.y && (terrain.GetPosition().z + terrain.terrainData.size.z) > position.y;
  307. }
  308. public static bool CheckMeshTerrainPosition(MeshRenderer terrain, Vector2 position)
  309. {
  310. return terrain != null
  311. && terrain.bounds.min.x <= position.x && (terrain.bounds.min.x + terrain.bounds.size.x) > position.x
  312. && terrain.bounds.min.z <= position.y && (terrain.bounds.min.z + terrain.bounds.size.z) > position.y;
  313. }
  314. public static bool CheckObjectShader(Material mat)
  315. {
  316. return mat && mat.shader && mat.shader.name != null
  317. && (mat.shader.name == ObjectShaderName
  318. || mat.shader.name == DiffuseObjectShaderName
  319. || mat.shader.name == URPObjectShaderName
  320. || mat.shader.name == HDRPObjectShaderName
  321. || mat.shader.name == HDRPObjectTessellationShaderName);
  322. }
  323. public static bool CheckTerrainShader(Material mat)
  324. {
  325. return mat && mat.shader && mat.shader.name != null
  326. && (mat.shader.name == TerrainShaderName
  327. || mat.shader.name == DiffuseTerrainShaderName
  328. || mat.shader.name == URPTerrainShaderName
  329. || mat.shader.name.Contains(HDRPTerrainShaderName)
  330. || mat.shader.name.Contains(HDRPTerrainTessellationShaderName));
  331. }
  332. public static bool CheckTerrainShaderContains(Terrain terrain, string name)
  333. {
  334. return terrain
  335. && terrain.materialTemplate
  336. && terrain.materialTemplate.shader
  337. && terrain.materialTemplate.shader.name != null
  338. && terrain.materialTemplate.shader.name.Contains(name);
  339. }
  340. public static bool CheckMeshTerrainShader(Material mat)
  341. {
  342. return mat && mat.shader && mat.shader.name != null
  343. && (mat.shader.name == MeshTerrainShaderName
  344. || mat.shader.name == DiffuseMeshTerrainShaderName
  345. || mat.shader.name == URPMeshTerrainShaderName
  346. || mat.shader.name.Contains(HDRPMeshTerrainShaderName)
  347. || mat.shader.name.Contains(HDRPMeshTerrainTessellationShaderName));
  348. }
  349. public static void SetTerrainDataToMaterials( Vector3 terrainSize, Vector3 terrainPosition, Vector4 heightmapScale, Texture heightmap, Texture2D[] controlMaps, Material terrainMaterial, TerrainLayer[] tl, Material objectMaterial)
  350. {
  351. objectMaterial.SetVector("_TerrainSize", terrainSize);
  352. objectMaterial.SetVector("_TerrainPosition", terrainPosition);
  353. objectMaterial.SetVector("_TerrainHeightmapScale", heightmapScale);
  354. objectMaterial.SetTexture("_TerrainHeightmapTexture", heightmap);
  355. if (CheckTerrainShader(terrainMaterial) || CheckMeshTerrainShader(terrainMaterial))
  356. {
  357. TerrainKeywordsToMaterial(terrainMaterial, objectMaterial, TerrainToObjectsKeywords);
  358. SetTerrainFloatsToMaterial(terrainMaterial, objectMaterial, TerrainToObjectsFloats);
  359. SetTerrainTextureToMaterial(terrainMaterial, objectMaterial, TerrainToObjectsTextureProperties);
  360. SetTerrainVectorsToMaterial(terrainMaterial, objectMaterial, TerrainToObjectsVectorProperties);
  361. if (objectMaterial.shader.name == HDRPObjectTessellationShaderName && terrainMaterial.shader.name.Contains(TessellationShaderFolder))
  362. {
  363. float terrainMaxDisplacement = terrainMaterial.GetFloat("_TessellationMaxDisplacement");
  364. float objectMaxDisplacement = objectMaterial.GetFloat("_TessellationObjMaxDisplacement");
  365. objectMaterial.SetFloat("_TessellationMaxDisplacement", terrainMaxDisplacement > objectMaxDisplacement ? terrainMaxDisplacement : objectMaxDisplacement);
  366. SetTerrainFloatsToMaterial(terrainMaterial, objectMaterial, TerrainToObjectsTessellationProperties);
  367. }
  368. }
  369. else
  370. {
  371. #if (USING_HDRP || USING_URP)
  372. DisableKeywords(objectMaterial, TerrainToObjectsKeywords);
  373. if (terrainMaterial.IsKeywordEnabled("_TERRAIN_BLEND_HEIGHT")) objectMaterial.SetFloat("_HeightmapBlending", 1); else objectMaterial.SetFloat("_HeightmapBlending", 0);
  374. objectMaterial.SetFloat("_HeightTransition", 60 - 60 * terrainMaterial.GetFloat("_HeightTransition"));
  375. #else
  376. DisableKeywords(objectMaterial, TerrainToObjectsKeywords);
  377. #endif
  378. }
  379. //----------- ONE LAYER ------------
  380. if (objectMaterial.IsKeywordEnabled("_LAYERS_ONE"))
  381. {
  382. #if UNITY_EDITOR //The TerrainLayers in Editor are referenced by GUID, in Build by TerrainLayers array index
  383. TerrainLayer terainLayer = TerrainLayerFromGUID(objectMaterial, "TerrainLayerGUID_1");
  384. TerrainLaeyrDataToMaterial(terainLayer, 0, objectMaterial);
  385. #else
  386. int layerIndex1 = (int)objectMaterial.GetFloat("_LayerIndex1");
  387. CheckLayerIndex(tl, 0, objectMaterial, ref layerIndex1);
  388. TerrainLaeyrDataToMaterial(tl[layerIndex1], 0, objectMaterial);
  389. #endif
  390. }
  391. //----------- TWO LAYERS ------------
  392. else if (objectMaterial.IsKeywordEnabled("_LAYERS_TWO"))
  393. {
  394. #if UNITY_EDITOR
  395. TerrainLayer terainLayer1 = TerrainLayerFromGUID(objectMaterial, "TerrainLayerGUID_1");
  396. TerrainLayer terainLayer2 = TerrainLayerFromGUID(objectMaterial, "TerrainLayerGUID_2");
  397. TerrainLaeyrDataToMaterial(terainLayer1, 0, objectMaterial);
  398. TerrainLaeyrDataToMaterial(terainLayer2, 1, objectMaterial);
  399. int layerIndex1 = tl.ToList().IndexOf(terainLayer1);
  400. int layerIndex2 = tl.ToList().IndexOf(terainLayer2);
  401. #else
  402. int layerIndex1 = (int)objectMaterial.GetFloat("_LayerIndex1");
  403. int layerIndex2 = (int)objectMaterial.GetFloat("_LayerIndex2");
  404. CheckLayerIndex(tl, 0, objectMaterial, ref layerIndex1);
  405. CheckLayerIndex(tl, 1, objectMaterial, ref layerIndex2);
  406. TerrainLaeyrDataToMaterial(tl[layerIndex1], 0, objectMaterial);
  407. TerrainLaeyrDataToMaterial(tl[layerIndex2], 1, objectMaterial);
  408. #endif
  409. objectMaterial.SetFloat("_ControlNumber", layerIndex1 % 4);
  410. if (controlMaps.Length > layerIndex1 / 4) objectMaterial.SetTexture("_Control", controlMaps[layerIndex1 / 4]);
  411. if (layerIndex1 > 3 || layerIndex2 > 3) objectMaterial.SetFloat("_HeightmapBlending", 0);
  412. }
  413. //----------- ONE PASS ------------
  414. else
  415. {
  416. int passNumber = (int)objectMaterial.GetFloat("_PassNumber");
  417. int layersNumber = 4;
  418. if (EightLayersEnabled(objectMaterial))
  419. {
  420. passNumber = 0;
  421. layersNumber = 8;
  422. }
  423. #if USING_HDRP
  424. else if(objectMaterial.IsKeywordEnabled("_LAYERS_SIXTEEN"))
  425. {
  426. passNumber = 0;
  427. layersNumber = 16;
  428. if (DiffuseTextureArrayCheckSize(tl) && DiffuseTextureArrayCheckFormat(tl))
  429. {
  430. DiffuseTextureArrays16(tl, objectMaterial);
  431. }
  432. else
  433. {
  434. splatArray16 = new Texture2DArray(1, 1, 16, TextureFormat.RGBA32, true);
  435. }
  436. if (NormalMapTextureArrayCheckSize(tl) && NormalMapTextureArrayCheckFormat(tl))
  437. {
  438. NormalTextureArrays16(tl, objectMaterial);
  439. }
  440. if (controlMaps.Length > 2) objectMaterial.SetTexture("_Control2", controlMaps[2]);
  441. if (controlMaps.Length > 3) objectMaterial.SetTexture("_Control3", controlMaps[3]);
  442. }
  443. #endif
  444. for (int i = 0; (i + (passNumber * layersNumber)) < tl.Length && i < layersNumber; i++)
  445. {
  446. TerrainLaeyrDataToMaterial(tl[i + (passNumber * layersNumber)], i, objectMaterial);
  447. }
  448. if (EightLayersEnabled(objectMaterial) || objectMaterial.IsKeywordEnabled("_LAYERS_SIXTEEN"))
  449. {
  450. if (controlMaps.Length > 0) objectMaterial.SetTexture("_Control", controlMaps[0]);
  451. if (controlMaps.Length > 1) objectMaterial.SetTexture("_Control1", controlMaps[1]);
  452. }
  453. else
  454. {
  455. if (controlMaps.Length > passNumber) objectMaterial.SetTexture("_Control", controlMaps[passNumber]);
  456. }
  457. if (passNumber > 0) objectMaterial.SetFloat("_HeightmapBlending", 0);
  458. }
  459. if ((objectMaterial.shader.name != DiffuseObjectShaderName) && objectMaterial.GetFloat("_DisableTerrainParallax") == 1)
  460. {
  461. objectMaterial.SetFloat("_Terrain_Parallax", 0.0f);
  462. }
  463. if (objectMaterial.GetFloat("_DisableDistanceBlending") == 1)
  464. {
  465. objectMaterial.DisableKeyword("_TERRAIN_DISTANCEBLEND");
  466. }
  467. if (objectMaterial.shader.name == DiffuseObjectShaderName)
  468. {
  469. if (objectMaterial.GetTexture("_BumpMap")) { objectMaterial.EnableKeyword("_OBJECT_NORMALMAP"); } else { objectMaterial.DisableKeyword("_OBJECT_NORMALMAP"); }
  470. }
  471. }
  472. static Dictionary<Material, Terrain> CopyMaterialTerrainDictionary(Dictionary<Material, Terrain> matTerDict)
  473. {
  474. Dictionary<Material, Terrain> tempMatTerDict = new Dictionary<Material, Terrain>();
  475. foreach (Material mt in matTerDict.Keys)
  476. {
  477. if (!tempMatTerDict.ContainsKey(mt))
  478. {
  479. tempMatTerDict.Add(mt, matTerDict[mt]);
  480. }
  481. }
  482. return tempMatTerDict;
  483. }
  484. static Dictionary<Material, MeshRenderer> CopyMaterialMeshDictionary(Dictionary<Material, MeshRenderer> matMeshDict)
  485. {
  486. Dictionary<Material, MeshRenderer> tempMatMeshDict = new Dictionary<Material, MeshRenderer>();
  487. foreach (Material mt in matMeshDict.Keys)
  488. {
  489. if (!tempMatMeshDict.ContainsKey(mt))
  490. {
  491. tempMatMeshDict.Add(mt, matMeshDict[mt]);
  492. }
  493. }
  494. return tempMatMeshDict;
  495. }
  496. #if UNITY_EDITOR
  497. public static TerrainLayer TerrainLayerFromGUID(Material mat, string tag)
  498. {
  499. return (TerrainLayer)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(mat.GetTag(tag, false)), typeof(TerrainLayer));
  500. }
  501. public static TerrainData TerrainDataFromGUID(Material mat, string tag)
  502. {
  503. return (TerrainData)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(mat.GetTag(tag, false)), typeof(TerrainData));
  504. }
  505. #endif
  506. #if UNITY_EDITOR
  507. public static void TextureAlphaSmoothness(TerrainLayer tl)
  508. {
  509. if (tl)
  510. {
  511. TextureImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(tl.diffuseTexture)) as TextureImporter;
  512. if (importer && importer.DoesSourceTextureHaveAlpha())
  513. {
  514. tl.smoothness = 1;
  515. }
  516. }
  517. }
  518. #endif
  519. public static void TerrainLaeyrDataToMaterial(TerrainLayer tl, int n, Material mat)
  520. {
  521. #if UNITY_EDITOR
  522. TextureAlphaSmoothness(tl);
  523. #endif
  524. mat.SetTexture("_Splat" + n.ToString(), tl ? tl.diffuseTexture : null);
  525. mat.SetTexture("_Normal" + n.ToString(), tl ? tl.normalMapTexture : null);
  526. mat.SetTexture("_Mask" + n.ToString(), tl ? tl.maskMapTexture : null);
  527. mat.SetVector("_SplatUV" + n.ToString(), tl ? new Vector4(tl.tileSize.x, tl.tileSize.y, tl.tileOffset.x, tl.tileOffset.y) : new Vector4(1, 1, 0, 0));
  528. mat.SetVector("_MaskMapRemapScale" + n.ToString(), tl ? tl.maskMapRemapMax - tl.maskMapRemapMin : new Vector4(1, 1, 1, 1));
  529. mat.SetVector("_MaskMapRemapOffset" + n.ToString(), tl ? tl.maskMapRemapMin : new Vector4(0, 0, 0, 0));
  530. mat.SetVector("_DiffuseRemapScale" + n.ToString(), tl ? tl.diffuseRemapMax : new Vector4(1, 1, 1, 1));
  531. mat.SetVector("_DiffuseRemapOffset" + n.ToString(), tl ? tl.diffuseRemapMin : new Vector4(0, 0, 0, 0));
  532. mat.SetFloat("_Smoothness" + n.ToString(), tl ? tl.smoothness : 0.0f);
  533. mat.SetFloat("_Metallic" + n.ToString(), tl ? tl.metallic : 0.0f);
  534. mat.SetFloat("_NormalScale" + n.ToString(), tl ? tl.normalScale : 0.0f);
  535. mat.SetColor("_Specular" + n.ToString(), tl ? tl.specular : new Color(0, 0, 0, 0));
  536. mat.SetFloat("_LayerHasMask" + n.ToString(), tl ? (float)(tl.maskMapTexture ? 1.0 : 0.0) : (float)0.0);
  537. }
  538. public static void TerrainLaeyrDataToTerrain(Vector3 size, TerrainLayer tl, int n, MaterialPropertyBlock mtb)
  539. {
  540. #if UNITY_EDITOR
  541. TextureAlphaSmoothness(tl);
  542. #endif
  543. mtb.SetTexture("_Splat" + n.ToString(), tl && tl.diffuseTexture ? tl.diffuseTexture : Texture2D.whiteTexture);
  544. mtb.SetTexture("_Normal" + n.ToString(), tl && tl.normalMapTexture ? tl.normalMapTexture : Texture2D.normalTexture);
  545. mtb.SetTexture("_Mask" + n.ToString(), tl && tl.maskMapTexture ? tl.maskMapTexture : Texture2D.linearGrayTexture);
  546. mtb.SetVector("_Splat" + n.ToString() + "_ST", tl ? new Vector4(size.x / tl.tileSize.x, size.z / tl.tileSize.y, tl.tileOffset.x, tl.tileOffset.y) : new Vector4(1, 1, 0, 0));
  547. mtb.SetVector("_MaskMapRemapScale" + n.ToString(), tl ? tl.maskMapRemapMax - tl.maskMapRemapMin : new Vector4(1, 1, 1, 1));
  548. mtb.SetVector("_MaskMapRemapOffset" + n.ToString(), tl ? tl.maskMapRemapMin : new Vector4(0, 0, 0, 0));
  549. mtb.SetVector("_DiffuseRemapScale" + n.ToString(), tl ? tl.diffuseRemapMax - tl.diffuseRemapMin : new Vector4(1, 1, 1, 1));
  550. mtb.SetVector("_DiffuseRemapOffset" + n.ToString(), tl ? tl.diffuseRemapMin : new Vector4(0, 0, 0, 0));
  551. mtb.SetFloat("_NormalScale" + n.ToString(), tl ? tl.normalScale : 1);
  552. mtb.SetFloat("_Smoothness" + n.ToString(), tl ? tl.smoothness : 0);
  553. mtb.SetFloat("_Metallic" + n.ToString(), tl ? tl.metallic : 0);
  554. mtb.SetColor("_Specular" + n.ToString(), tl ? tl.specular : new Color(0, 0, 0, 0));
  555. mtb.SetFloat("_LayerHasMask" + n.ToString(), tl ? (float)(tl.maskMapTexture ? 1.0 : 0.0) : (float)0.0);
  556. mtb.SetVector("_TerrainSizeXZPosY", new Vector3(size.x, size.z, 0.0f));
  557. }
  558. public static void CheckLayerIndex(TerrainLayer[] layers, int n, Material mat, ref int layerIndex)
  559. {
  560. bool diffuse = mat.shader.name == DiffuseObjectShaderName;
  561. foreach (TerrainLayer tl in layers)
  562. {
  563. bool equal = tl && mat.GetTexture("_Splat" + n.ToString()) == tl.diffuseTexture
  564. && mat.GetTexture("_Normal" + n.ToString()) == tl.normalMapTexture
  565. && mat.GetVector("_TerrainNormalScale")[n] == tl.normalScale
  566. && mat.GetTexture("_Mask" + n.ToString()) == tl.maskMapTexture
  567. && mat.GetVector("_SplatUV" + n.ToString()) == new Vector4(tl.tileSize.x, tl.tileSize.y, tl.tileOffset.x, tl.tileOffset.y)
  568. && mat.GetVector("_MaskMapRemapScale" + n.ToString()) == tl.maskMapRemapMax - tl.maskMapRemapMin
  569. && mat.GetVector("_MaskMapRemapOffset" + n.ToString()) == tl.maskMapRemapMin
  570. && mat.GetVector("_DiffuseRemapScale" + n.ToString()) == tl.diffuseRemapMax
  571. && mat.GetVector("_DiffuseRemapOffset" + n.ToString()) == tl.diffuseRemapMin;
  572. bool equalMetallicSmooth = diffuse || tl && mat.GetVector("_TerrainMetallic")[n] == tl.metallic
  573. && mat.GetVector("_TerrainSmoothness")[n] == tl.smoothness;
  574. if (equal && equalMetallicSmooth)
  575. {
  576. layerIndex = layers.ToList().IndexOf(tl);
  577. mat.SetFloat("_LayerIndex" + (n + 1).ToString(), layerIndex);
  578. }
  579. }
  580. }
  581. static void SetTerrainFloatsToMaterial(Material terrainMaterial, Material objectMaterial, string[] properties)
  582. {
  583. foreach (string prop in properties)
  584. {
  585. objectMaterial.SetFloat(prop, terrainMaterial.GetFloat(prop));
  586. }
  587. }
  588. static void SetTerrainVectorsToMaterial(Material terrainMaterial, Material objectMaterial, string[] vectors)
  589. {
  590. foreach (string vec in vectors)
  591. {
  592. objectMaterial.SetVector(vec, terrainMaterial.GetVector(vec));
  593. }
  594. }
  595. static void SetTerrainTextureToMaterial(Material terrainMaterial, Material objectMaterial, string[] textures)
  596. {
  597. foreach (string texture in textures)
  598. {
  599. objectMaterial.SetTexture(texture, terrainMaterial.GetTexture(texture));
  600. objectMaterial.SetTextureScale(texture, terrainMaterial.GetTextureScale(texture));
  601. objectMaterial.SetTextureOffset(texture, terrainMaterial.GetTextureOffset(texture));
  602. }
  603. }
  604. static void TerrainKeywordsToMaterial(Material terrainMaterial, Material objectMaterial, string[] keywords)
  605. {
  606. foreach (string keyword in keywords)
  607. {
  608. if (terrainMaterial.IsKeywordEnabled(keyword))
  609. {
  610. objectMaterial.EnableKeyword(keyword);
  611. }
  612. else
  613. {
  614. objectMaterial.DisableKeyword(keyword);
  615. }
  616. }
  617. }
  618. static void DisableKeywords(Material mat, string[] keywords)
  619. {
  620. foreach (string keyword in keywords)
  621. {
  622. mat.DisableKeyword(keyword);
  623. }
  624. }
  625. public static InTerra_UpdateAndCheck GetUpdaterScript()
  626. {
  627. if (UpdateScript == null)
  628. {
  629. if (!Updater)
  630. {
  631. if (!GameObject.Find(UpdaterName))
  632. {
  633. Updater = new GameObject(UpdaterName);
  634. Updater.AddComponent<InTerra_UpdateAndCheck>();
  635. Updater.hideFlags = HideFlags.HideInInspector;
  636. Updater.hideFlags = HideFlags.HideInHierarchy;
  637. }
  638. else
  639. {
  640. Updater = GameObject.Find(UpdaterName);
  641. }
  642. }
  643. UpdateScript = Updater.GetComponent<InTerra_UpdateAndCheck>();
  644. }
  645. return (UpdateScript);
  646. }
  647. public static InTerra_GlobalData GetGlobalData()
  648. {
  649. if (GetUpdaterScript().GlobalData == null)
  650. {
  651. #if UNITY_EDITOR
  652. if (Resources.Load<InTerra_GlobalData>("InTerra_GlobalData") == null)
  653. {
  654. if (!Directory.Exists(Path.Combine(GetInTerraPath(), "Resources")))
  655. {
  656. AssetDatabase.CreateFolder(GetInTerraPath(), "Resources");
  657. }
  658. InTerra_GlobalData globalData = ScriptableObject.CreateInstance<InTerra_GlobalData>();
  659. AssetDatabase.CreateAsset(globalData, GetInTerraPath() + "/Resources/InTerra_GlobalData.asset");
  660. AssetDatabase.SaveAssets();
  661. }
  662. #endif
  663. GetUpdaterScript().GlobalData = Resources.Load<InTerra_GlobalData>("InTerra_GlobalData");
  664. }
  665. return GetUpdaterScript().GlobalData;
  666. }
  667. public static void TracksUpdate()
  668. {
  669. if (Updater != null)
  670. {
  671. if (TrackCamera == null)
  672. {
  673. if (!Updater.TryGetComponent<Camera>(out Camera c))
  674. {
  675. TrackCamera = Updater.AddComponent<Camera>();
  676. InTerra_TracksCameraSettings.SetTrackCamera(Updater.GetComponent<Camera>());
  677. }
  678. else
  679. {
  680. TrackCamera = Updater.GetComponent<Camera>();
  681. }
  682. }
  683. else
  684. {
  685. TracksUpdateTimeCount += Time.deltaTime;
  686. if (!TracksCameraUpdate)
  687. {
  688. EnableTracksCamera(false);
  689. }
  690. else
  691. {
  692. TracksCameraUpdate = false;
  693. TracksUpdateTimeCount = 0;
  694. }
  695. if ((TracksUpdateTimeCount >= GetGlobalData().trackUpdateTime) || !initTrack)
  696. {
  697. #if USING_HDRP || USING_URP
  698. TrackCamera.enabled = true;
  699. #endif
  700. initTrack = true;
  701. TracksCameraUpdate = true;
  702. EnableTracksCamera(true);
  703. #if UNITY_EDITOR
  704. if (GetUpdaterScript().TrackTexture.height != GetGlobalData().trackTextureSize) CreateTrackRenderTexture();
  705. if (TrackCamera.cullingMask != 1 << GetGlobalData().trackLayer) TrackCamera.cullingMask = 1 << GetGlobalData().trackLayer;
  706. var view = SceneView.lastActiveSceneView;
  707. if (view != null && EditorWindow.focusedWindow != null && EditorWindow.focusedWindow.ToString() == " (UnityEditor.SceneView)" && UnityEditorInternal.InternalEditorUtility.isApplicationActive)
  708. {
  709. TrackCameraPositon = view.camera.transform.position;
  710. TrackCameraForwardVec = view.camera.transform.forward;
  711. }
  712. else if (EditorWindow.focusedWindow != null && EditorWindow.focusedWindow.ToString() == " (UnityEditor.GameView)" )
  713. {
  714. TrackCameraForwardVec = Camera.main.transform.forward;
  715. TrackCameraPositon = Camera.main.transform.position;
  716. }
  717. #else
  718. TrackCameraForwardVec = Camera.main.transform.forward;
  719. TrackCameraPositon = Camera.main.transform.position;
  720. #endif
  721. float trackArea = GetGlobalData().trackArea;
  722. if (GetUpdaterScript().TrackTexture == null) CreateTrackRenderTexture();
  723. Vector3 tcPos = TrackCameraPositon + TrackCameraForwardVec * Mathf.Round((trackArea * 0.5f));
  724. float roundIndex = trackArea / (GetGlobalData().trackTextureSize * 0.2f);
  725. tcPos.x = Mathf.Round(tcPos.x / roundIndex) * roundIndex;
  726. tcPos.y = Mathf.Round(tcPos.y / roundIndex) * roundIndex;
  727. tcPos.z = Mathf.Round(tcPos.z / roundIndex) * roundIndex;
  728. Updater.transform.position = new Vector3(tcPos.x, TracksStampYPosition() - 100.0f, tcPos.z);
  729. Shader.SetGlobalVector("_InTerra_TrackPosition", tcPos);
  730. Shader.SetGlobalFloat("_InTerra_TrackArea", trackArea);
  731. Shader.SetGlobalTexture("_InTerra_TrackTexture", GetUpdaterScript().TrackTexture);
  732. TrackCamera.targetTexture = GetUpdaterScript().TrackTexture;
  733. TrackCamera.orthographicSize = trackArea * 0.5f;
  734. }
  735. }
  736. }
  737. }
  738. public static float TracksStampYPosition()
  739. {
  740. float positionY = -100.0f;
  741. if (Terrain.activeTerrain != null)
  742. {
  743. positionY = Terrain.activeTerrain.GetPosition().y - 10.0f;
  744. }
  745. else if (GetUpdaterScript().MeshTerrainsList.Count > 0)
  746. {
  747. positionY = GetUpdaterScript().MeshTerrainsList[0].bounds.min.y - 10.0f;
  748. }
  749. return positionY - GetUpdaterScript().TrackDepthIndex;
  750. }
  751. private static void EnableTracksCamera(bool enable)
  752. {
  753. #if USING_HDRP
  754. if (TrackCamera.TryGetComponent<HDAdditionalCameraData>(out var cam))
  755. {
  756. cam.fullscreenPassthrough = !enable;
  757. }
  758. #elif USING_URP
  759. if (TrackCamera.TryGetComponent<UniversalAdditionalCameraData>(out var cam))
  760. {
  761. cam.renderType = enable ? CameraRenderType.Base : CameraRenderType.Overlay;
  762. }
  763. #else
  764. TrackCamera.enabled = enable;
  765. #endif
  766. }
  767. public static void CheckAndUpdate()
  768. {
  769. Terrain[] terrains = Terrain.activeTerrains;
  770. if (GetUpdaterScript() == null) return;
  771. var meshTerrainList = GetUpdaterScript().MeshTerrainsList;
  772. if (terrains.Length > 0 || (meshTerrainList != null && meshTerrainList.Count > 0))
  773. {
  774. UpdateScript = GetUpdaterScript();
  775. DictionaryMaterialTerrain materialTerrain = UpdateScript.MaterialTerrain;
  776. if (materialTerrain != null && materialTerrain.Count > 0)
  777. {
  778. Material mat = materialTerrain.Keys.First();
  779. if (mat && materialTerrain[mat] && !mat.GetTexture("_TerrainHeightmapTexture") && materialTerrain[mat] && materialTerrain[mat].terrainData.heightmapTexture.IsCreated())
  780. {
  781. UpdateTerrainData(InTerra_Setting.DictionaryUpdate);
  782. }
  783. }
  784. else if (!UpdateScript.FirstInit)
  785. {
  786. if (!InTerra_Setting.DisableAllAutoUpdates) UpdateTerrainData(true);
  787. UpdateScript.FirstInit = true;
  788. }
  789. #if UNITY_EDITOR
  790. if (!GlobalKeywordsCheck)
  791. {
  792. if (!CheckDefinedKeywords()) WriteDefinedKeywords();
  793. GlobalKeywordsCheck = true;
  794. #if USING_URP
  795. URPShadersVersionAdjust();
  796. #endif
  797. }
  798. #endif
  799. #if USING_HDRP
  800. if(GetUpdaterScript().TextureArrayCheck && splatArray16 == null)
  801. {
  802. UpdateTerrainData(InTerra_Setting.DictionaryUpdate);
  803. }
  804. #endif
  805. }
  806. if (GetUpdaterScript().TracksEnabled)
  807. {
  808. TracksUpdate();
  809. }
  810. else
  811. {
  812. if (Updater.TryGetComponent<Camera>(out Camera cam) && cam.enabled)
  813. {
  814. cam.enabled = false;
  815. }
  816. }
  817. }
  818. static public void CreateTrackRenderTexture()
  819. {
  820. if(GetUpdaterScript().TrackTexture != null)
  821. {
  822. GetUpdaterScript().TrackTexture.Release();
  823. }
  824. int tracksTexSize = GetGlobalData().trackTextureSize;
  825. GetUpdaterScript().TrackTexture = new RenderTexture(tracksTexSize, tracksTexSize, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) { name = "TrackTexture", enableRandomWrite = true};
  826. GetUpdaterScript().TrackTexture.Create();
  827. }
  828. public static bool TracksFadingEnabled()
  829. {
  830. return GetUpdaterScript().TracksFading;
  831. }
  832. public static void SetTracksFading(bool enable)
  833. {
  834. GetUpdaterScript().TracksFading = enable;
  835. }
  836. public static void SetTracksFadingTime(float time)
  837. {
  838. GetUpdaterScript().TracksFadingTime = time;
  839. }
  840. public static bool EightLayersEnabled(Material mat)
  841. {
  842. #if !(USING_URP || USING_HDRP)
  843. return GetGlobalData().eightLayersPass;
  844. #else
  845. return mat.IsKeywordEnabled("_LAYERS_EIGHT");
  846. #endif
  847. }
  848. #if UNITY_EDITOR
  849. static public void WriteDefinedKeywords()
  850. {
  851. if (File.Exists(GetKeywordsPath()))
  852. {
  853. string[] lines = File.ReadAllLines(GetKeywordsPath());
  854. InTerra_GlobalData data = GetGlobalData();
  855. lines[DEFINE_MASKMAP_LineNumber] = DefineKeywordLine(data.maskMapMode == 1, "_TERRAIN_MASK_MAPS");
  856. lines[DEFINE_NORMAL_MASK_LineNumber] = DefineKeywordLine(data.maskMapMode == 2, "_TERRAIN_NORMAL_IN_MASK");
  857. lines[DEFINE_HEIGTH_ONLY_LineNumber] = DefineKeywordLine(data.maskMapMode == 3, "_TERRAIN_MASK_HEIGHTMAP_ONLY");
  858. lines[RESTRICT_NORMALMAP_LineNumber] = DefineKeywordLine(!data.disableNormalmap, "_NORMALMAPS");
  859. lines[RESTRICT_HEIGHTBLEND_LineNumber] = DefineKeywordLine(!data.disableHeightmapBlending, "_TERRAIN_BLEND_HEIGHT");
  860. lines[RESTRICT_TERR_PARALAX_LineNumber] = DefineKeywordLine(!data.disableTerrainParallax, "_TERRAIN_PARALLAX");
  861. lines[RESTRICT_TRACKS_LineNumber] = DefineKeywordLine(!data.disableTracks, "_TRACKS");
  862. lines[RESTRICT_OBJ_PARALLAX_LineNumber] = DefineKeywordLine(!data.disableObjectParallax, "_OBJECT_PARALLAX");
  863. lines[RESTRICT_PUDDLES_LineNumber] = DefineKeywordLine(!data.disablePuddles, "_PUDDLES");
  864. #if !(USING_URP || USING_HDRP)
  865. lines[EIGHT_LAYERS_PASS_LineNumber] = DefineKeywordLine(data.eightLayersPass, "_LAYERS_EIGHT");
  866. #endif
  867. File.WriteAllLines(GetKeywordsPath(), lines);
  868. EditorApplication.delayCall += () =>
  869. {
  870. File.WriteAllLines(GetKeywordsPath(), lines);
  871. EditorApplication.delayCall += () =>
  872. {
  873. AssetImporter ai = AssetImporter.GetAtPath(GetKeywordsPath());
  874. ai.SaveAndReimport();
  875. };
  876. };
  877. }
  878. }
  879. static public bool CheckDefinedKeywords()
  880. {
  881. InTerra_GlobalData data = GetGlobalData();
  882. return
  883. #if !(USING_URP || USING_HDRP)
  884. DefinedKeyword(EIGHT_LAYERS_PASS_LineNumber) == (data.eightLayersPass) &&
  885. #endif
  886. DefinedKeyword(DEFINE_MASKMAP_LineNumber) == (data.maskMapMode == 1) &&
  887. DefinedKeyword(DEFINE_NORMAL_MASK_LineNumber) == (data.maskMapMode == 2) &&
  888. DefinedKeyword(DEFINE_HEIGTH_ONLY_LineNumber) == (data.maskMapMode == 3) &&
  889. DefinedKeyword(RESTRICT_NORMALMAP_LineNumber) != data.disableNormalmap &&
  890. DefinedKeyword(RESTRICT_HEIGHTBLEND_LineNumber) != data.disableHeightmapBlending &&
  891. DefinedKeyword(RESTRICT_TERR_PARALAX_LineNumber) != data.disableTerrainParallax &&
  892. DefinedKeyword(RESTRICT_TRACKS_LineNumber) != data.disableTracks &&
  893. DefinedKeyword(RESTRICT_OBJ_PARALLAX_LineNumber) != data.disableObjectParallax &&
  894. DefinedKeyword(RESTRICT_PUDDLES_LineNumber) != data.disablePuddles;
  895. }
  896. #if USING_URP
  897. static public void URPShadersVersionAdjust()
  898. {
  899. if (File.Exists(GetKeywordsPath()))
  900. {
  901. string[] globalLines = File.ReadAllLines(GetKeywordsPath());
  902. #if UNITY_6000_1_OR_NEWER
  903. globalLines[UNITY_VERSION_LineNumber] = "#define UNITY_6000_1_OR_NEWER";
  904. #elif UNITY_2022_2_OR_NEWER
  905. globalLines[UNITY_VERSION_LineNumber] = "#define UNITY_2022_2_OR_NEWER";
  906. #else
  907. globalLines[UNITY_VERSION_LineNumber] = " ";
  908. #endif
  909. if(File.ReadAllLines(GetKeywordsPath())[UNITY_VERSION_LineNumber] != globalLines[UNITY_VERSION_LineNumber])
  910. {
  911. EditorApplication.delayCall += () =>
  912. {
  913. File.WriteAllLines(GetKeywordsPath(), globalLines);
  914. EditorApplication.delayCall += () =>
  915. {
  916. AssetImporter ai = AssetImporter.GetAtPath(GetKeywordsPath());
  917. ai.SaveAndReimport();
  918. };
  919. };
  920. }
  921. }
  922. }
  923. #endif
  924. public static string GetInTerraPath()
  925. {
  926. if(string.IsNullOrEmpty(InTerraPath) || !Directory.Exists(InTerraPath))
  927. {
  928. string[] guids = AssetDatabase.FindAssets($"t:script InTerra_Data");
  929. if (guids == null || guids.Length == 0) return null;
  930. string relativePath = AssetDatabase.GUIDToAssetPath(guids[0]);
  931. InTerraPath = Path.GetDirectoryName(Path.GetDirectoryName(relativePath));
  932. }
  933. return InTerraPath;
  934. }
  935. public static string GetKeywordsPath()
  936. {
  937. #if USING_HDRP
  938. string hdrpGlobal = Path.Combine(GetInTerraPath(), "HDRP", "Shaders", "InTerra_HDRP_DefinedGlobalKeywords.hlsl");
  939. if (File.Exists(hdrpGlobal))
  940. { return hdrpGlobal; }
  941. else
  942. { //There was a typo in folder name in some versions, but updating package will not update the old name of folder, therfore there is a folowing alternative path.
  943. return Path.Combine(GetInTerraPath(), "HRDP", "Shaders", "InTerra_HDRP_DefinedGlobalKeywords.hlsl");
  944. }
  945. #elif USING_URP
  946. return Path.Combine(GetInTerraPath(), "URP", "Shaders", "InTerra_URP_DefinedGlobalKeywords.hlsl");
  947. #else
  948. return Path.Combine(GetInTerraPath(), "Built-in", "Shaders", "InTerra_DefinedGlobalKeywords.cginc");
  949. #endif
  950. }
  951. static string DefineKeywordLine(bool set, string keyword)
  952. {
  953. return (set ? "#define " : "#undef ") + keyword;
  954. }
  955. public static bool DefinedKeyword(int line)
  956. {
  957. if (!File.Exists(GetKeywordsPath())) return false;
  958. string[] definedKeywordsLines = File.ReadAllLines(GetKeywordsPath());
  959. bool defined;
  960. if (definedKeywordsLines[line].Contains("define"))
  961. {
  962. defined = true;
  963. }
  964. else
  965. {
  966. defined = false;
  967. }
  968. return defined;
  969. }
  970. #endif
  971. #if USING_HDRP
  972. public static bool DiffuseTextureArrayCheckFormat(TerrainLayer[] tl)
  973. {
  974. bool okFormat = true;
  975. if (tl[0] && tl[0].diffuseTexture)
  976. {
  977. for (int i = 1; i < tl.Length && i < 16; i++)
  978. {
  979. if (tl[i] && tl[i].diffuseTexture != null)
  980. {
  981. okFormat = tl[0].diffuseTexture.format == tl[i].diffuseTexture.format ? okFormat : false;
  982. }
  983. }
  984. }
  985. else
  986. {
  987. okFormat = false;
  988. }
  989. return okFormat;
  990. }
  991. public static bool DiffuseTextureArrayCheckSize(TerrainLayer[] tl)
  992. {
  993. bool okSize = true;
  994. if (tl[0] && tl[0].diffuseTexture)
  995. {
  996. for (int i = 1; i < tl.Length && i < 16; i++)
  997. {
  998. if (tl[i] && tl[i].diffuseTexture != null)
  999. {
  1000. okSize = tl[0].diffuseTexture.width == tl[i].diffuseTexture.width ? okSize : false;
  1001. okSize = tl[0].diffuseTexture.height == tl[i].diffuseTexture.height ? okSize : false;
  1002. }
  1003. }
  1004. }
  1005. else
  1006. {
  1007. okSize = false;
  1008. }
  1009. return okSize;
  1010. }
  1011. public static bool NormalMapTextureArrayCheckFormat(TerrainLayer[] tl)
  1012. {
  1013. bool okFormat = true;
  1014. if (tl[0] && tl[0].normalMapTexture)
  1015. {
  1016. for (int i = 1; i < tl.Length && i < 16; i++)
  1017. {
  1018. if (tl[i] && tl[i].normalMapTexture != null)
  1019. {
  1020. okFormat = tl[0].normalMapTexture.format == tl[i].normalMapTexture.format ? okFormat : false;
  1021. }
  1022. }
  1023. }
  1024. else
  1025. {
  1026. okFormat = false;
  1027. }
  1028. return okFormat;
  1029. }
  1030. public static bool NormalMapTextureArrayCheckSize(TerrainLayer[] tl)
  1031. {
  1032. bool okSize = true;
  1033. if (tl[0] && tl[0].normalMapTexture)
  1034. {
  1035. for (int i = 1; i < tl.Length && i < 16; i++)
  1036. {
  1037. if (tl[i] && tl[i].normalMapTexture != null)
  1038. {
  1039. okSize = tl[0].normalMapTexture.width == tl[i].normalMapTexture.width ? okSize : false;
  1040. okSize = tl[0].normalMapTexture.height == tl[i].normalMapTexture.height ? okSize : false;
  1041. }
  1042. }
  1043. }
  1044. else
  1045. {
  1046. okSize = false;
  1047. }
  1048. return okSize;
  1049. }
  1050. public static void DiffuseTextureArrays16(TerrainLayer[] tl, Material mat)
  1051. {
  1052. if (tl[0])
  1053. {
  1054. int dWidth = tl[0].diffuseTexture.width;
  1055. int dHeight = tl[0].diffuseTexture.height;
  1056. Texture2DArray splatArray = new Texture2DArray(dWidth, dHeight, 16, tl[0].diffuseTexture.format, true);
  1057. for (int i = 0; i < tl.Length && i < 16; i++)
  1058. {
  1059. if (tl[i] && tl[i].diffuseTexture != null)
  1060. {
  1061. for (int mip = 0; mip < tl[i].diffuseTexture.mipmapCount; ++mip)
  1062. {
  1063. Graphics.CopyTexture(tl[i].diffuseTexture, 0, mip, splatArray, i, mip);
  1064. }
  1065. }
  1066. }
  1067. mat.SetTexture("_SplatArray16", splatArray);
  1068. if (splatArray16 == null) splatArray16 = splatArray;
  1069. }
  1070. }
  1071. public static void NormalTextureArrays16(TerrainLayer[] tl, Material mat)
  1072. {
  1073. if (tl[0])
  1074. {
  1075. int nWidth = tl[0].normalMapTexture.width;
  1076. int nHeight = tl[0].normalMapTexture.height;
  1077. Texture2DArray normalArray = new Texture2DArray(nWidth, nHeight, 16, tl[0].normalMapTexture.format, true);
  1078. for (int i = 0; i < tl.Length && i < 16; i++)
  1079. {
  1080. if (tl[i] && tl[i].normalMapTexture != null)
  1081. {
  1082. for (int mip = 0; mip < tl[i].normalMapTexture.mipmapCount; ++mip)
  1083. {
  1084. Graphics.CopyTexture(tl[i].normalMapTexture, 0, mip, normalArray, i, mip);
  1085. }
  1086. }
  1087. }
  1088. mat.SetTexture("_NormalArray16", normalArray);
  1089. }
  1090. }
  1091. #endif
  1092. public static void TerrainMaterialUpdate()
  1093. {
  1094. Terrain[] terrains = Terrain.activeTerrains;
  1095. bool tracksEnabled = false;
  1096. #if USING_HDRP
  1097. bool textureArrayCheck = false;
  1098. #endif
  1099. foreach (Terrain terrain in terrains)
  1100. {
  1101. if (terrain && terrain.terrainData && terrain.materialTemplate && CheckTerrainShader(terrain.materialTemplate))
  1102. {
  1103. terrain.materialTemplate.SetVector("_TerrainSizeXZPosY", new Vector3(terrain.terrainData.size.x, terrain.terrainData.size.z, terrain.transform.position.y));
  1104. if(terrain.materialTemplate.GetFloat("_Tracks") == 1)
  1105. {
  1106. tracksEnabled = true;
  1107. #if UNITY_EDITOR
  1108. terrain.materialTemplate.SetFloat("_Gamma", (PlayerSettings.colorSpace == ColorSpace.Gamma ? 1.0f : 0.0f));
  1109. #endif
  1110. }
  1111. #if USING_HDRP
  1112. if (terrain.materialTemplate.IsKeywordEnabled("_LAYERS_SIXTEEN"))
  1113. {
  1114. textureArrayCheck = true;
  1115. }
  1116. #endif
  1117. }
  1118. mtb.Clear();
  1119. mtb.SetFloat("_NumLayersCount", terrain.terrainData.alphamapLayers);
  1120. #if !USING_HDRP
  1121. if (EightLayersEnabled(terrain.materialTemplate))
  1122. {
  1123. GameObject terrainGO = terrain.transform.root.gameObject;
  1124. if (!terrainGO.TryGetComponent<InTerra_TerrainData>(out var itd))
  1125. {
  1126. terrainGO.AddComponent<InTerra_TerrainData>();
  1127. }
  1128. }
  1129. #endif
  1130. }
  1131. foreach (var meshTerrain in GetUpdaterScript().MeshTerrainsList)
  1132. {
  1133. if (meshTerrain != null && CheckMeshTerrainShader(meshTerrain.sharedMaterial) && meshTerrain.bounds != null && meshTerrain.transform)
  1134. {
  1135. meshTerrain.sharedMaterial.SetVector("_TerrainSizeXZPosY", new Vector3(meshTerrain.bounds.size.x, meshTerrain.bounds.size.z, meshTerrain.transform.position.y));
  1136. if(meshTerrain.sharedMaterial.GetFloat("_Tracks") == 1)
  1137. {
  1138. tracksEnabled = true;
  1139. }
  1140. #if USING_HDRP
  1141. if (meshTerrain.sharedMaterial.IsKeywordEnabled("_LAYERS_SIXTEEN"))
  1142. {
  1143. textureArrayCheck = true;
  1144. }
  1145. #endif
  1146. }
  1147. }
  1148. if(GetUpdaterScript().TracksEnabled != tracksEnabled)
  1149. {
  1150. GetUpdaterScript().TracksEnabled = tracksEnabled;
  1151. #if UNITY_EDITOR
  1152. EditorUtility.SetDirty(GetUpdaterScript());
  1153. #endif
  1154. }
  1155. #if USING_HDRP
  1156. if(GetUpdaterScript().TextureArrayCheck != textureArrayCheck)
  1157. {
  1158. GetUpdaterScript().TextureArrayCheck = textureArrayCheck;
  1159. #if UNITY_EDITOR
  1160. EditorUtility.SetDirty(GetUpdaterScript());
  1161. #endif
  1162. }
  1163. #endif
  1164. if (GetUpdaterScript().SetSceneWetnessValues)
  1165. {
  1166. Shader.SetGlobalFloat("_InTerra_GlobalWetness", GetUpdaterScript().GlobalWetness);
  1167. Shader.SetGlobalVector("_InTerra_GlobalPuddles", GetUpdaterScript().GlobalPuddles);
  1168. Shader.SetGlobalVector("_InTerra_GlobalRaindropRipples", GetUpdaterScript().GlobalRaindropRipples);
  1169. Shader.SetGlobalVector("_InTerra_GlobalRaindropsDistance", GetUpdaterScript().GlobalRaindropDistance);
  1170. }
  1171. }
  1172. public static void SetMeshTerrainPositionAndSize(Material mat, MeshRenderer meshTerrain)
  1173. {
  1174. List<MeshRenderer> meshTerrainsList = GetUpdaterScript().MeshTerrainsList;
  1175. meshTerrain.TryGetComponent<InTerra_MeshTerrainData>(out var mtd);
  1176. if (meshTerrainsList.Count > 1)
  1177. {
  1178. Vector3 positonMin = meshTerrain.bounds.min;
  1179. Vector3 positonMax = meshTerrain.bounds.max;
  1180. if (mtd && mat.GetFloat("_HeightmapBase") == 0)
  1181. {
  1182. positonMin.y = meshTerrain.transform.position.y;
  1183. }
  1184. foreach (var mt in meshTerrainsList)
  1185. {
  1186. if(mt && mt.sharedMaterial == mat)
  1187. {
  1188. positonMin.x = mt.bounds.min.x < positonMin.x ? mt.bounds.min.x : positonMin.x;
  1189. positonMin.z = mt.bounds.min.z < positonMin.z ? mt.bounds.min.z : positonMin.z;
  1190. switch (mat.GetFloat("_HeightmapBase"))
  1191. {
  1192. case 0:
  1193. positonMin.y = mt.transform.position.y < positonMin.y ? mt.transform.position.y : positonMin.y;
  1194. break;
  1195. case 1:
  1196. positonMin.y = mt.bounds.min.y < positonMin.y ? mt.bounds.min.y : positonMin.y;
  1197. break;
  1198. case 2:
  1199. positonMin.y = mat.GetFloat("_HeightmapBaseCustom");
  1200. break;
  1201. }
  1202. positonMax.x = mt.bounds.max.x > positonMax.x ? mt.bounds.max.x : positonMax.x;
  1203. positonMax.y = mt.bounds.max.y > positonMax.y ? mt.bounds.max.y : positonMax.y;
  1204. positonMax.z = mt.bounds.max.z > positonMax.z ? mt.bounds.max.z : positonMax.z;
  1205. }
  1206. }
  1207. mat.SetVector("_TerrainSize", new Vector3(positonMax.x - positonMin.x, positonMax.y - positonMin.y, positonMax.z - positonMin.z));
  1208. mat.SetVector("_TerrainPosition", positonMin);
  1209. }
  1210. else
  1211. {
  1212. mat.SetVector("_TerrainSize", meshTerrain.bounds.size);
  1213. Vector3 positonMin = meshTerrain.bounds.min;
  1214. switch (mat.GetFloat("_HeightmapBase"))
  1215. {
  1216. case 0:
  1217. positonMin.y = meshTerrain.transform.position.y;
  1218. break;
  1219. case 1:
  1220. positonMin.y = meshTerrain.bounds.min.y;
  1221. break;
  1222. case 2:
  1223. positonMin.y = mat.GetFloat("_HeightmapBaseCustom");
  1224. break;
  1225. }
  1226. mat.SetVector("_TerrainPosition", positonMin);
  1227. }
  1228. }
  1229. static void SetKeyword(Material mat, string name, bool set)
  1230. {
  1231. if (set) mat.EnableKeyword(name); else mat.DisableKeyword(name);
  1232. }
  1233. #if UNITY_EDITOR
  1234. #if UNITY_2020_1_OR_NEWER
  1235. public static void CenterOnMainWin(this UnityEditor.EditorWindow aWin)
  1236. {
  1237. var main = EditorGUIUtility.GetMainWindowPosition();
  1238. var pos = aWin.position;
  1239. float w = (main.width - pos.width) * 0.5f;
  1240. float h = (main.height - pos.height) * 0.5f;
  1241. pos.x = main.x + w;
  1242. pos.y = main.y + h;
  1243. aWin.position = pos;
  1244. }
  1245. #else
  1246. public static System.Type[] GetAllDerivedTypes(this System.AppDomain aAppDomain, System.Type aType)
  1247. {
  1248. var result = new List<System.Type>();
  1249. var assemblies = aAppDomain.GetAssemblies();
  1250. foreach (var assembly in assemblies)
  1251. {
  1252. var types = assembly.GetTypes();
  1253. foreach (var type in types)
  1254. {
  1255. if (type.IsSubclassOf(aType))
  1256. result.Add(type);
  1257. }
  1258. }
  1259. return result.ToArray();
  1260. }
  1261. public static Rect GetEditorMainWindowPos()
  1262. {
  1263. var containerWinType = System.AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ScriptableObject)).Where(t => t.Name == "ContainerWindow").FirstOrDefault();
  1264. if (containerWinType == null)
  1265. throw new System.MissingMemberException("Can't find internal type ContainerWindow. Maybe something has changed inside Unity");
  1266. var showModeField = containerWinType.GetField("m_ShowMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  1267. var positionProperty = containerWinType.GetProperty("position", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
  1268. if (showModeField == null || positionProperty == null)
  1269. throw new System.MissingFieldException("Can't find internal fields 'm_ShowMode' or 'position'. Maybe something has changed inside Unity");
  1270. var windows = Resources.FindObjectsOfTypeAll(containerWinType);
  1271. foreach (var win in windows)
  1272. {
  1273. var showmode = (int)showModeField.GetValue(win);
  1274. if (showmode == 4) // main window
  1275. {
  1276. var pos = (Rect)positionProperty.GetValue(win, null);
  1277. return pos;
  1278. }
  1279. }
  1280. throw new System.NotSupportedException("Can't find internal main window. Maybe something has changed inside Unity");
  1281. }
  1282. public static void CenterOnMainWin(this UnityEditor.EditorWindow aWin)
  1283. {
  1284. var main = GetEditorMainWindowPos();
  1285. var pos = aWin.position;
  1286. float w = (main.width - pos.width) * 0.5f;
  1287. float h = (main.height - pos.height) * 0.5f;
  1288. pos.x = main.x + w;
  1289. pos.y = main.y + h;
  1290. aWin.position = pos;
  1291. }
  1292. #endif
  1293. #endif
  1294. }
  1295. //The Serialized Dictionary is based on christophfranke123 code from this page https://answers.unity.com/questions/460727/how-to-serialize-dictionary-with-unity-serializati.html
  1296. [System.Serializable]
  1297. public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
  1298. {
  1299. [SerializeField]
  1300. private List<TKey> keys = new List<TKey>();
  1301. [SerializeField]
  1302. private List<TValue> values = new List<TValue>();
  1303. // save the dictionary to lists
  1304. public void OnBeforeSerialize()
  1305. {
  1306. keys.Clear();
  1307. values.Clear();
  1308. foreach (KeyValuePair<TKey, TValue> pair in this)
  1309. {
  1310. keys.Add(pair.Key);
  1311. values.Add(pair.Value);
  1312. }
  1313. }
  1314. // load dictionary from lists
  1315. public void OnAfterDeserialize()
  1316. {
  1317. if (this != null)
  1318. {
  1319. this.Clear();
  1320. if (keys.Count != values.Count)
  1321. throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable."));
  1322. for (int i = 0; i < keys.Count; i++)
  1323. this.Add(keys[i], values[i]);
  1324. }
  1325. }
  1326. }
  1327. }