403 lines
11 KiB
C#
403 lines
11 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
namespace TT_TerrainTools
|
|
{
|
|
public class TT_Terrain9Patch : MonoBehaviour
|
|
{
|
|
public enum EFixMode
|
|
{
|
|
AVERAGE = 0,
|
|
READ_FROM_CENTER = 1,
|
|
READ_FROM_BORDERS = 2
|
|
}
|
|
|
|
public Terrain Center;
|
|
|
|
public Terrain XPositve;
|
|
|
|
public Terrain XNegative;
|
|
|
|
public Terrain ZPositve;
|
|
|
|
public Terrain ZNegative;
|
|
|
|
public Terrain XPositiveZPositve;
|
|
|
|
public Terrain XNegativeZNegative;
|
|
|
|
public Terrain XNegativeZPositve;
|
|
|
|
public Terrain XPositiveZNegative;
|
|
|
|
public bool IsTerrainDataClonedOnAwake;
|
|
|
|
public bool IsTerrainDataClonedOnStart;
|
|
|
|
public void FixAllBorders(EFixMode p_mode)
|
|
{
|
|
FixBorders(p_mode, true, true, true, true, true);
|
|
}
|
|
|
|
public void FixBorders(EFixMode p_mode, bool p_isFixCenter, bool p_isFixXPositive, bool p_isFixXNegative, bool p_isFixZPositive, bool p_isFixZNegative)
|
|
{
|
|
float p_fade;
|
|
switch (p_mode)
|
|
{
|
|
case EFixMode.AVERAGE:
|
|
p_fade = 0.5f;
|
|
break;
|
|
case EFixMode.READ_FROM_CENTER:
|
|
p_fade = 0f;
|
|
break;
|
|
default:
|
|
p_fade = 1f;
|
|
break;
|
|
}
|
|
if (p_isFixCenter)
|
|
{
|
|
if (Center != null && XPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(Center, XPositve, TT_TerrainHelpers.EDirection.RIGHT, TT_TerrainHelpers.EDirection.LEFT, p_fade);
|
|
}
|
|
if (Center != null && XNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(Center, XNegative, TT_TerrainHelpers.EDirection.LEFT, TT_TerrainHelpers.EDirection.RIGHT, p_fade);
|
|
}
|
|
if (Center != null && ZPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(Center, ZPositve, TT_TerrainHelpers.EDirection.TOP, TT_TerrainHelpers.EDirection.BOTTOM, p_fade);
|
|
}
|
|
if (Center != null && ZNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(Center, ZNegative, TT_TerrainHelpers.EDirection.BOTTOM, TT_TerrainHelpers.EDirection.TOP, p_fade);
|
|
}
|
|
}
|
|
if (p_isFixXPositive)
|
|
{
|
|
if (XPositve != null && XPositiveZPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(XPositve, XPositiveZPositve, TT_TerrainHelpers.EDirection.TOP, TT_TerrainHelpers.EDirection.BOTTOM, p_fade);
|
|
}
|
|
if (XPositve != null && XPositiveZNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(XPositve, XPositiveZNegative, TT_TerrainHelpers.EDirection.BOTTOM, TT_TerrainHelpers.EDirection.TOP, p_fade);
|
|
}
|
|
}
|
|
if (p_isFixXNegative)
|
|
{
|
|
if (XNegative != null && XNegativeZPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(XNegative, XNegativeZPositve, TT_TerrainHelpers.EDirection.TOP, TT_TerrainHelpers.EDirection.BOTTOM, p_fade);
|
|
}
|
|
if (XNegative != null && XNegativeZNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(XNegative, XNegativeZNegative, TT_TerrainHelpers.EDirection.BOTTOM, TT_TerrainHelpers.EDirection.TOP, p_fade);
|
|
}
|
|
}
|
|
if (p_isFixZPositive)
|
|
{
|
|
if (ZPositve != null && XPositiveZPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(ZPositve, XPositiveZPositve, TT_TerrainHelpers.EDirection.RIGHT, TT_TerrainHelpers.EDirection.LEFT, p_fade);
|
|
}
|
|
if (ZPositve != null && XNegativeZPositve != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(ZPositve, XNegativeZPositve, TT_TerrainHelpers.EDirection.LEFT, TT_TerrainHelpers.EDirection.RIGHT, p_fade);
|
|
}
|
|
}
|
|
if (p_isFixZNegative)
|
|
{
|
|
if (ZNegative != null && XPositiveZNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(ZNegative, XPositiveZNegative, TT_TerrainHelpers.EDirection.RIGHT, TT_TerrainHelpers.EDirection.LEFT, p_fade);
|
|
}
|
|
if (ZNegative != null && XNegativeZNegative != null)
|
|
{
|
|
TT_TerrainHelpers.FixBorders(ZNegative, XNegativeZNegative, TT_TerrainHelpers.EDirection.LEFT, TT_TerrainHelpers.EDirection.RIGHT, p_fade);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetNeighbors()
|
|
{
|
|
CrashCheck();
|
|
if (Center != null)
|
|
{
|
|
Center.SetNeighbors(XNegative, ZPositve, XPositve, ZNegative);
|
|
}
|
|
if (XPositve != null)
|
|
{
|
|
XPositve.SetNeighbors(Center, XPositiveZPositve, null, XPositiveZNegative);
|
|
}
|
|
if (XNegative != null)
|
|
{
|
|
XNegative.SetNeighbors(null, XNegativeZPositve, Center, XNegativeZNegative);
|
|
}
|
|
if (ZPositve != null)
|
|
{
|
|
ZPositve.SetNeighbors(XNegativeZPositve, null, XPositiveZPositve, Center);
|
|
}
|
|
if (ZNegative != null)
|
|
{
|
|
ZNegative.SetNeighbors(XNegativeZNegative, Center, XPositiveZNegative, null);
|
|
}
|
|
if (XPositiveZPositve != null)
|
|
{
|
|
XPositiveZPositve.SetNeighbors(ZPositve, null, null, XPositve);
|
|
}
|
|
if (XNegativeZNegative != null)
|
|
{
|
|
XNegativeZNegative.SetNeighbors(null, XNegative, ZNegative, null);
|
|
}
|
|
if (XNegativeZPositve != null)
|
|
{
|
|
XNegativeZPositve.SetNeighbors(null, null, ZPositve, XNegative);
|
|
}
|
|
if (XPositiveZNegative != null)
|
|
{
|
|
XPositiveZNegative.SetNeighbors(ZNegative, XPositve, null, null);
|
|
}
|
|
}
|
|
|
|
public void RemoveNeighbors()
|
|
{
|
|
if (Center != null)
|
|
{
|
|
Center.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XPositve != null)
|
|
{
|
|
XPositve.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XNegative != null)
|
|
{
|
|
XNegative.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (ZPositve != null)
|
|
{
|
|
ZPositve.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (ZNegative != null)
|
|
{
|
|
ZNegative.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XPositiveZPositve != null)
|
|
{
|
|
XPositiveZPositve.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XNegativeZNegative != null)
|
|
{
|
|
XNegativeZNegative.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XNegativeZPositve != null)
|
|
{
|
|
XNegativeZPositve.SetNeighbors(null, null, null, null);
|
|
}
|
|
if (XPositiveZNegative != null)
|
|
{
|
|
XPositiveZNegative.SetNeighbors(null, null, null, null);
|
|
}
|
|
}
|
|
|
|
public void CrashCheck()
|
|
{
|
|
bool flag = false;
|
|
int num = 1;
|
|
int num2 = -1;
|
|
if (Center != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != Center.terrainData.heightmapResolution;
|
|
num2 = Center.terrainData.heightmapResolution;
|
|
}
|
|
if (XPositve != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XPositve.terrainData.heightmapResolution;
|
|
num2 = XPositve.terrainData.heightmapResolution;
|
|
}
|
|
if (XNegative != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XNegative.terrainData.heightmapResolution;
|
|
num2 = XNegative.terrainData.heightmapResolution;
|
|
}
|
|
if (ZPositve != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != ZPositve.terrainData.heightmapResolution;
|
|
num2 = ZPositve.terrainData.heightmapResolution;
|
|
}
|
|
if (ZNegative != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != ZNegative.terrainData.heightmapResolution;
|
|
num2 = ZNegative.terrainData.heightmapResolution;
|
|
}
|
|
if (XPositiveZPositve != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XPositiveZPositve.terrainData.heightmapResolution;
|
|
num2 = XPositiveZPositve.terrainData.heightmapResolution;
|
|
}
|
|
if (XNegativeZNegative != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XNegativeZNegative.terrainData.heightmapResolution;
|
|
num2 = XNegativeZNegative.terrainData.heightmapResolution;
|
|
}
|
|
if (XNegativeZPositve != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XNegativeZPositve.terrainData.heightmapResolution;
|
|
num2 = XNegativeZPositve.terrainData.heightmapResolution;
|
|
}
|
|
if (XPositiveZNegative != null)
|
|
{
|
|
num++;
|
|
flag |= num2 != -1 && num2 != XPositiveZNegative.terrainData.heightmapResolution;
|
|
num2 = XPositiveZNegative.terrainData.heightmapResolution;
|
|
}
|
|
if (num >= 3 && flag)
|
|
{
|
|
Debug.LogWarning("The Unity Engine has a 'Terrain.SetNeighbors' critical bug that leads to a crash in the editor and at runtime!\nYour terrain constellation seems to allow this bug. However, I have not found a 100% reproduction way. I only know that if the terrains have different 'heightmapResolution', then the crash is possible (not guaranteed only possible).\nThe next code line will break the execution, remove it if you encounter no problems. I have decided to insert this line to make sure that you will see this warning and know that there is a possible issue. Also the current implementation of the TT_TerrainTools does not allow your terrains to have different heightmapResolutions if you want to snap the terrain borders to each other.");
|
|
Debug.Break();
|
|
if (Center != null)
|
|
{
|
|
Center.enabled = false;
|
|
}
|
|
if (XPositve != null)
|
|
{
|
|
XPositve.enabled = false;
|
|
}
|
|
if (XNegative != null)
|
|
{
|
|
XNegative.enabled = false;
|
|
}
|
|
if (ZPositve != null)
|
|
{
|
|
ZPositve.enabled = false;
|
|
}
|
|
if (ZNegative != null)
|
|
{
|
|
ZNegative.enabled = false;
|
|
}
|
|
if (XPositiveZPositve != null)
|
|
{
|
|
XPositiveZPositve.enabled = false;
|
|
}
|
|
if (XNegativeZNegative != null)
|
|
{
|
|
XNegativeZNegative.enabled = false;
|
|
}
|
|
if (XNegativeZPositve != null)
|
|
{
|
|
XNegativeZPositve.enabled = false;
|
|
}
|
|
if (XPositiveZNegative != null)
|
|
{
|
|
XPositiveZNegative.enabled = false;
|
|
}
|
|
StartCoroutine(CrashCheckReenable());
|
|
}
|
|
}
|
|
|
|
public IEnumerator CrashCheckReenable()
|
|
{
|
|
yield return new WaitForEndOfFrame();
|
|
yield return new WaitForEndOfFrame();
|
|
if (Center != null)
|
|
{
|
|
Center.enabled = true;
|
|
}
|
|
if (XPositve != null)
|
|
{
|
|
XPositve.enabled = true;
|
|
}
|
|
if (XNegative != null)
|
|
{
|
|
XNegative.enabled = true;
|
|
}
|
|
if (ZPositve != null)
|
|
{
|
|
ZPositve.enabled = true;
|
|
}
|
|
if (ZNegative != null)
|
|
{
|
|
ZNegative.enabled = true;
|
|
}
|
|
if (XPositiveZPositve != null)
|
|
{
|
|
XPositiveZPositve.enabled = true;
|
|
}
|
|
if (XNegativeZNegative != null)
|
|
{
|
|
XNegativeZNegative.enabled = true;
|
|
}
|
|
if (XNegativeZPositve != null)
|
|
{
|
|
XNegativeZPositve.enabled = true;
|
|
}
|
|
if (XPositiveZNegative != null)
|
|
{
|
|
XPositiveZNegative.enabled = true;
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
if (IsTerrainDataClonedOnAwake)
|
|
{
|
|
CloneTerrainData();
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (IsTerrainDataClonedOnAwake && IsTerrainDataClonedOnStart)
|
|
{
|
|
Debug.LogError("TT_Terrain9Patch: IsTerrainDataClonedOnAwake and IsTerrainDataClonedOnStart are set to true! Terrain data was cloned on awake...");
|
|
}
|
|
else if (IsTerrainDataClonedOnStart)
|
|
{
|
|
CloneTerrainData();
|
|
}
|
|
SetNeighbors();
|
|
}
|
|
|
|
private void CloneTerrainData()
|
|
{
|
|
CloneTerrainData(Center);
|
|
CloneTerrainData(XPositve);
|
|
CloneTerrainData(XNegative);
|
|
CloneTerrainData(ZPositve);
|
|
CloneTerrainData(ZNegative);
|
|
CloneTerrainData(XPositiveZPositve);
|
|
CloneTerrainData(XNegativeZNegative);
|
|
CloneTerrainData(XNegativeZPositve);
|
|
CloneTerrainData(XPositiveZNegative);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
RemoveNeighbors();
|
|
}
|
|
|
|
private void CloneTerrainData(Terrain p_terrain)
|
|
{
|
|
if (p_terrain != null)
|
|
{
|
|
p_terrain.enabled = false;
|
|
p_terrain.terrainData = Object.Instantiate(p_terrain.terrainData);
|
|
if (p_terrain.GetComponent<TerrainCollider>() != null)
|
|
{
|
|
p_terrain.GetComponent<TerrainCollider>().terrainData = p_terrain.terrainData;
|
|
}
|
|
p_terrain.Flush();
|
|
p_terrain.enabled = true;
|
|
}
|
|
}
|
|
}
|
|
}
|