Firstborn/Assets/AwesomeTechnologies/VegetationStudioPro/Runtime/TerrainSystemPro/TerrainSystemPro.cs

392 lines
18 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using AwesomeTechnologies.VegetationStudio;
using UnityEngine;
using AwesomeTechnologies.VegetationSystem;
using AwesomeTechnologies.VegetationSystem.Biomes;
using Unity.Jobs;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_2018_3_OR_NEWER
using System.IO;
#endif
namespace AwesomeTechnologies.TerrainSystem
{
public partial class TerrainSystemPro : MonoBehaviour
{
public VegetationSystemPro VegetationSystemPro;
public int CurrentTabIndex;
public int VegetationPackageIndex;
public int VegetationPackageTextureIndex;
public bool ShowCurvesMenu = true;
public bool ShowNoiseMenu = true;
// ReSharper disable once UnusedMember.Local
void Reset()
{
VegetationSystemPro = GetComponent<VegetationSystemPro>();
}
List<IVegetationStudioTerrain> GetOverlapTerrainList(Bounds updateBounds)
{
List<IVegetationStudioTerrain> overlapTerrainList = new List<IVegetationStudioTerrain>();
for (int i = 0; i <= VegetationSystemPro.VegetationStudioTerrainList.Count - 1; i++)
{
if (VegetationSystemPro.VegetationStudioTerrainList[i]
.NeedsSplatMapUpdate(updateBounds))
{
overlapTerrainList.Add(VegetationSystemPro.VegetationStudioTerrainList[i]);
}
}
return overlapTerrainList;
}
void PrepareTextureCurves()
{
for (int i = 0; i <= VegetationSystemPro.VegetationPackageProList.Count - 1; i++)
{
VegetationSystemPro.VegetationPackageProList[i].PrepareNativeArrayTextureCurves();
}
}
void DisposeTextureCurves()
{
for (int i = 0; i <= VegetationSystemPro.VegetationPackageProList.Count - 1; i++)
{
VegetationSystemPro.VegetationPackageProList[i].DisposeNativeArrayTextureCurves();
}
}
public Texture2D GetTerrainTexture(int index)
{
for (int i = 0; i <= VegetationSystemPro.VegetationStudioTerrainList.Count - 1; i++)
{
IVegetationStudioTerrain iVegetationStudioTerrain = VegetationSystemPro.VegetationStudioTerrainList[i];
if (iVegetationStudioTerrain.HasTerrainTextures())
{
return iVegetationStudioTerrain.GetTerrainTexture(index);
}
}
return null;
}
public void GetSplatPrototypesFromTerrain(VegetationPackagePro vegetationPackage)
{
for (int i = 0; i <= VegetationSystemPro.VegetationStudioTerrainList.Count - 1; i++)
{
IVegetationStudioTerrain iVegetationStudioTerrain = VegetationSystemPro.VegetationStudioTerrainList[i];
if (iVegetationStudioTerrain.HasTerrainTextures())
{
#if UNITY_2018_3_OR_NEWER
TerrainLayer[] terrainLayers = iVegetationStudioTerrain.GetTerrainLayers();
for (int j = 0; j <= vegetationPackage.TerrainTextureList.Count - 1; j++)
{
if (j < terrainLayers.Length)
{
vegetationPackage.TerrainTextureList[j].Texture = terrainLayers[j].diffuseTexture;
vegetationPackage.TerrainTextureList[j].TextureNormals = terrainLayers[j].normalMapTexture;
vegetationPackage.TerrainTextureList[j].Offset = terrainLayers[j].tileOffset;
vegetationPackage.TerrainTextureList[j].TileSize = terrainLayers[j].tileSize;
}
}
break;
#else
SplatPrototype[] splatPrototypes = iVegetationStudioTerrain.GetSplatPrototypes();
for (int j = 0; j <= vegetationPackage.TerrainTextureList.Count - 1; j++)
{
if (j < splatPrototypes.Length)
{
vegetationPackage.TerrainTextureList[j].Texture = splatPrototypes[j].texture;
vegetationPackage.TerrainTextureList[j].TextureNormals = splatPrototypes[j].normalMap;
vegetationPackage.TerrainTextureList[j].Offset = splatPrototypes[j].tileOffset;
vegetationPackage.TerrainTextureList[j].TileSize = splatPrototypes[j].tileSize;
}
}
break;
#endif
}
}
}
public void SetSplatPrototypes(VegetationPackagePro vegetationPackage)
{
#if UNITY_2018_3_OR_NEWER
TerrainLayer[] terrainLayers = new TerrainLayer[vegetationPackage.TerrainTextureList.Count];
for (int i = 0; i <= vegetationPackage.TerrainTextureList.Count - 1; i++)
{
TerrainTextureInfo terrainTextureInfo = vegetationPackage.TerrainTextureList[i];
TerrainLayer terrainLayer = terrainTextureInfo.TerrainLayer;
if (terrainLayer == null)
{
terrainLayer = new TerrainLayer
{
diffuseTexture = terrainTextureInfo.Texture,
normalMapTexture = terrainTextureInfo.TextureNormals,
tileSize = terrainTextureInfo.TileSize,
tileOffset = terrainTextureInfo.Offset
};
#if UNITY_EDITOR
if (!Application.isPlaying)
{
terrainLayer = SaveTerrainLayer(terrainLayer,vegetationPackage);
}
EditorUtility.SetDirty(vegetationPackage);
#endif
terrainTextureInfo.TerrainLayer = terrainLayer;
}
else
{
terrainLayer.diffuseTexture = terrainTextureInfo.Texture;
terrainLayer.normalMapTexture = terrainTextureInfo.TextureNormals;
terrainLayer.tileSize = terrainTextureInfo.TileSize;
terrainLayer.tileOffset = terrainTextureInfo.Offset;
#if UNITY_EDITOR
EditorUtility.SetDirty(terrainLayer);
#endif
}
terrainLayers[i] = terrainLayer;
}
for (int i = 0; i <= VegetationSystemPro.VegetationStudioTerrainList.Count - 1; i++)
{
IVegetationStudioTerrain iVegetationStudioTerrain = VegetationSystemPro.VegetationStudioTerrainList[i];
if (iVegetationStudioTerrain.HasTerrainTextures())
{
iVegetationStudioTerrain.SetTerrainLayers(terrainLayers);
}
}
#else
SplatPrototype[] splatPrototypes = new SplatPrototype[vegetationPackage.TerrainTextureList.Count];
for (int i = 0; i <= vegetationPackage.TerrainTextureList.Count - 1; i++)
{
TerrainTextureInfo terrainTextureInfo = vegetationPackage.TerrainTextureList[i];
SplatPrototype splatPrototype = new SplatPrototype
{
texture = terrainTextureInfo.Texture,
normalMap = terrainTextureInfo.TextureNormals,
tileSize = terrainTextureInfo.TileSize,
tileOffset = terrainTextureInfo.Offset
};
splatPrototypes[i] = splatPrototype;
}
for (int i = 0; i <= VegetationSystemPro.VegetationStudioTerrainList.Count - 1; i++)
{
IVegetationStudioTerrain iVegetationStudioTerrain = VegetationSystemPro.VegetationStudioTerrainList[i];
if (iVegetationStudioTerrain.HasTerrainTextures())
{
iVegetationStudioTerrain.SetSplatPrototypes(splatPrototypes);
}
}
#endif
}
#if UNITY_2018_3_OR_NEWER
private TerrainLayer SaveTerrainLayer(TerrainLayer terrainLayer, VegetationPackagePro vegetationPackagePro)
{
#if UNITY_EDITOR
if (!vegetationPackagePro) return terrainLayer;
string terrainDataPath = AssetDatabase.GetAssetPath(vegetationPackagePro);
var directory = Path.GetDirectoryName(terrainDataPath);
var filename = Path.GetFileNameWithoutExtension(terrainDataPath);
var folderName = filename + "_TerrainLayers";
if (!AssetDatabase.IsValidFolder(directory + "/" + folderName))
AssetDatabase.CreateFolder(directory, folderName);
terrainDataPath = terrainDataPath.Replace(".asset", "");
string newTerrainLayerDataPath = directory + "/" + folderName + "/_TerrainLayer_" + Guid.NewGuid().ToString() + ".asset";
AssetDatabase.CreateAsset(terrainLayer, newTerrainLayerDataPath);
AssetDatabase.SaveAssets();
return AssetDatabase.LoadAssetAtPath<TerrainLayer>(newTerrainLayerDataPath);
#else
return null;
#endif
}
#endif
public void GenerateSplatMap(bool clearLockedTextures, IVegetationStudioTerrain iVegetationStudioTerrain)
{
if (!VegetationSystemPro) return;
VegetationSystemPro.ClearCache(iVegetationStudioTerrain.TerrainBounds);
PrepareTextureCurves();
float worldspaceMinHeight = VegetationSystemPro.VegetationSystemBounds.center.y -
VegetationSystemPro.VegetationSystemBounds.extents.y;
float worldspaceSeaLevel = worldspaceMinHeight + VegetationSystemPro.SeaLevel;
float worldspaceMaxHeight = VegetationSystemPro.VegetationSystemBounds.center.y +
VegetationSystemPro.VegetationSystemBounds.extents.y;
float heightCurveSampleHeight = worldspaceMaxHeight - worldspaceSeaLevel;
VegetationPackagePro defaultBiomeVegetationPackagePro =
VegetationSystemPro.GetVegetationPackageFromBiome(BiomeType.Default);
if (defaultBiomeVegetationPackagePro == null)
{
Debug.LogWarning("You need a default biome in order to generate splatmaps. ");
return;
}
iVegetationStudioTerrain.PrepareSplatmapGeneration(clearLockedTextures);
iVegetationStudioTerrain.GenerateSplatMapBiome(VegetationSystemPro.VegetationSystemBounds,
BiomeType.Default, null, defaultBiomeVegetationPackagePro.TerrainTextureSettingsList,
heightCurveSampleHeight, worldspaceSeaLevel, clearLockedTextures);
List<BiomeType> additionalBiomeList = VegetationSystemPro.GetAdditionalBiomeList();
List<VegetationPackagePro> additionalVegetationPackageList = new List<VegetationPackagePro>();
for (int i = 0; i <= additionalBiomeList.Count - 1; i++)
{
additionalVegetationPackageList.Add(
VegetationSystemPro.GetVegetationPackageFromBiome(additionalBiomeList[i]));
}
BiomeSortOrderComparer biomeSortOrderComparer = new BiomeSortOrderComparer();
additionalVegetationPackageList.Sort(biomeSortOrderComparer);
for (int i = 0; i <= additionalVegetationPackageList.Count - 1; i++)
{
VegetationPackagePro currentVegetationPackagePro = additionalVegetationPackageList[i];
if (!currentVegetationPackagePro.GenerateBiomeSplamap) continue;
List<PolygonBiomeMask> biomeMaskList = VegetationStudioManager.GetBiomeMasks(currentVegetationPackagePro.BiomeType);
iVegetationStudioTerrain.GenerateSplatMapBiome(VegetationSystemPro.VegetationSystemBounds,
currentVegetationPackagePro.BiomeType, biomeMaskList, currentVegetationPackagePro.TerrainTextureSettingsList, heightCurveSampleHeight, worldspaceSeaLevel,clearLockedTextures);
}
JobHandle.ScheduleBatchedJobs();
iVegetationStudioTerrain.CompleteSplatmapGeneration();
DisposeTextureCurves();
}
public void GenerateSplatMap(bool clearLockedTextures)
{
List<IVegetationStudioTerrain> overlapTerrainList = GetOverlapTerrainList(VegetationSystemPro.VegetationSystemBounds);
int terrainCount = overlapTerrainList.Count;
for (int i = 0; i <= overlapTerrainList.Count - 1; i++)
{
#if UNITY_EDITOR
EditorUtility.DisplayProgressBar("Generate splatmap",
"Terrain " + (i + 1) + "/" + terrainCount, (i + 1) / (float) terrainCount);
#endif
GenerateSplatMap(clearLockedTextures, overlapTerrainList[i]);
GC.Collect();
}
#if UNITY_EDITOR
EditorUtility.ClearProgressBar();
#endif
}
public void GenerateSplatMapParallel(bool clearLockedTextures)
{
if (!VegetationSystemPro) return;
VegetationSystemPro.ClearCache();
List<IVegetationStudioTerrain> overlapTerrainList =
GetOverlapTerrainList(VegetationSystemPro.VegetationSystemBounds);
PrepareTextureCurves();
float worldspaceMinHeight = VegetationSystemPro.VegetationSystemBounds.center.y -
VegetationSystemPro.VegetationSystemBounds.extents.y;
float worldspaceSeaLevel = worldspaceMinHeight + VegetationSystemPro.SeaLevel;
float worldspaceMaxHeight = VegetationSystemPro.VegetationSystemBounds.center.y +
VegetationSystemPro.VegetationSystemBounds.extents.y;
float heightCurveSampleHeight = worldspaceMaxHeight - worldspaceSeaLevel;
VegetationPackagePro defaultBiomeVegetationPackagePro =
VegetationSystemPro.GetVegetationPackageFromBiome(BiomeType.Default);
if (defaultBiomeVegetationPackagePro == null)
{
Debug.LogWarning("You need a default biome in order to generate splatmaps. ");
return;
}
int terrainCount = overlapTerrainList.Count;
for (int i = 0; i <= overlapTerrainList.Count - 1; i++)
{
overlapTerrainList[i].PrepareSplatmapGeneration(clearLockedTextures);
#if UNITY_EDITOR
EditorUtility.DisplayProgressBar("Prepare generation",
"Terrain " + (i + 1) + "/" + terrainCount, (i + 1) / (float) terrainCount);
#endif
}
for (int i = 0; i <= overlapTerrainList.Count - 1; i++)
{
overlapTerrainList[i].GenerateSplatMapBiome(VegetationSystemPro.VegetationSystemBounds,
BiomeType.Default, null, defaultBiomeVegetationPackagePro.TerrainTextureSettingsList, heightCurveSampleHeight, worldspaceSeaLevel,clearLockedTextures);
#if UNITY_EDITOR
EditorUtility.DisplayProgressBar("Generating default biome",
"Terrain " + (i + 1) + "/" + terrainCount, (i + 1) / (float) terrainCount);
#endif
}
List<BiomeType> additionalBiomeList = VegetationSystemPro.GetAdditionalBiomeList();
List<VegetationPackagePro> additionalVegetationPackageList = new List<VegetationPackagePro>();
for (int i = 0; i <= additionalBiomeList.Count - 1; i++)
{
additionalVegetationPackageList.Add(
VegetationSystemPro.GetVegetationPackageFromBiome(additionalBiomeList[i]));
}
BiomeSortOrderComparer biomeSortOrderComparer = new BiomeSortOrderComparer();
additionalVegetationPackageList.Sort(biomeSortOrderComparer);
for (int i = 0; i <= additionalVegetationPackageList.Count - 1; i++)
{
VegetationPackagePro currentVegetationPackagePro = additionalVegetationPackageList[i];
if (!currentVegetationPackagePro.GenerateBiomeSplamap) continue;
List<PolygonBiomeMask> biomeMaskList = VegetationStudioManager.GetBiomeMasks(currentVegetationPackagePro.BiomeType);
for (int j = 0; j <= overlapTerrainList.Count - 1; j++)
{
overlapTerrainList[j].GenerateSplatMapBiome(VegetationSystemPro.VegetationSystemBounds,
currentVegetationPackagePro.BiomeType, biomeMaskList, currentVegetationPackagePro.TerrainTextureSettingsList, heightCurveSampleHeight, worldspaceSeaLevel,clearLockedTextures);
}
}
JobHandle.ScheduleBatchedJobs();
for (int i = 0; i <= overlapTerrainList.Count - 1; i++)
{
#if UNITY_EDITOR
EditorUtility.DisplayProgressBar("Updating terrain",
"Terrain " + (i + 1) + "/" + terrainCount, (i + 1) / (float) terrainCount);
#endif
overlapTerrainList[i].CompleteSplatmapGeneration();
}
#if UNITY_EDITOR
EditorUtility.ClearProgressBar();
#endif
DisposeTextureCurves();
}
}
}