Add Unity3D projects
This commit is contained in:
@ -0,0 +1,106 @@
|
||||
#region "Imports"
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
|
||||
namespace RoadArchitect
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class RoadTerrain : MonoBehaviour
|
||||
{
|
||||
#region "Vars"
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private int uID = -1;
|
||||
|
||||
public int UID { get { return uID; } }
|
||||
|
||||
[HideInInspector]
|
||||
public Terrain terrain;
|
||||
|
||||
//Splat map:
|
||||
public int splatResoWidth = 1024;
|
||||
public int splatResoHeight = 1024;
|
||||
public Color splatBackground = new Color(0f, 0f, 0f, 1f);
|
||||
public Color splatForeground = new Color(1f, 1f, 1f, 1f);
|
||||
public float splatWidth = 30f;
|
||||
public bool isSplatSkipBridges = false;
|
||||
public bool isSplatSkipTunnels = false;
|
||||
public bool isSplatSingleRoad = false;
|
||||
public int splatSingleChoiceIndex = 0;
|
||||
public string roadSingleChoiceUID = "";
|
||||
#endregion
|
||||
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
CheckID();
|
||||
if (!terrain)
|
||||
{
|
||||
terrain = transform.gameObject.GetComponent<Terrain>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Check for unique id and assign terrain </summary>
|
||||
public void CheckID()
|
||||
{
|
||||
if (uID < 0)
|
||||
{
|
||||
uID = GetNewID();
|
||||
}
|
||||
if (!terrain)
|
||||
{
|
||||
terrain = transform.gameObject.GetComponent<Terrain>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Return new id preventing terrain id duplication </summary>
|
||||
private int GetNewID()
|
||||
{
|
||||
Object[] allTerrainObjs = GameObject.FindObjectsOfType<RoadTerrain>();
|
||||
List<int> allIDS = new List<int>(allTerrainObjs.Length);
|
||||
foreach (RoadTerrain Terrain in allTerrainObjs)
|
||||
{
|
||||
if (Terrain.UID > 0)
|
||||
{
|
||||
allIDS.Add(Terrain.UID);
|
||||
}
|
||||
}
|
||||
|
||||
bool isNotDone = true;
|
||||
int spamChecker = 0;
|
||||
int spamCheckerMax = allIDS.Count + 64;
|
||||
int random;
|
||||
while (isNotDone)
|
||||
{
|
||||
if (spamChecker > spamCheckerMax)
|
||||
{
|
||||
Debug.LogError("Failed to generate terrainID");
|
||||
break;
|
||||
}
|
||||
random = Random.Range(1, 2000000000);
|
||||
if (!allIDS.Contains(random))
|
||||
{
|
||||
isNotDone = false;
|
||||
return random;
|
||||
}
|
||||
spamChecker += 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
CheckID();
|
||||
if (!terrain)
|
||||
{
|
||||
terrain = transform.gameObject.GetComponent<Terrain>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81fe195562332d04ead2688a86c7325b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -0,0 +1,645 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace RoadArchitect
|
||||
{
|
||||
public static class Terraforming
|
||||
{
|
||||
public class TempTerrainData
|
||||
{
|
||||
public int HM;
|
||||
public int HMHeight;
|
||||
public float[,] heights;
|
||||
public bool[,] tHeights;
|
||||
|
||||
public float HMRatio;
|
||||
public float MetersPerHM = 0f;
|
||||
|
||||
//Heights:
|
||||
public ushort[] cX;
|
||||
public ushort[] cY;
|
||||
public float[] cH;
|
||||
public float[] oldH;
|
||||
public int Count = 0;
|
||||
public int TerrainMaxIndex;
|
||||
|
||||
//Details:
|
||||
public int DetailLayersCount;
|
||||
|
||||
public List<ushort> MainDetailsX;
|
||||
public List<ushort> MainDetailsY;
|
||||
|
||||
public List<List<ushort>> DetailsX;
|
||||
public List<List<ushort>> DetailsY;
|
||||
public List<List<ushort>> OldDetailsValue;
|
||||
//public Dictionary<int,int[,]> DetailValues;
|
||||
public int[] detailsCount;
|
||||
public float DetailToHeightRatio;
|
||||
|
||||
|
||||
//public Dictionary<int,bool[,]> DetailHasProcessed;
|
||||
|
||||
public HashSet<int> DetailHasProcessed;
|
||||
|
||||
//public List<List<bool>> OldDetailsValue;
|
||||
|
||||
public int DetailMaxIndex;
|
||||
public HashSet<int> DetailLayersSkip;
|
||||
|
||||
//Trees
|
||||
public List<TreeInstance> TreesCurrent;
|
||||
public List<TreeInstance> TreesOld;
|
||||
public int treesCount;
|
||||
public int TreeSize;
|
||||
|
||||
public Vector3 TerrainSize;
|
||||
public Vector3 TerrainPos;
|
||||
public int uID;
|
||||
|
||||
|
||||
public void Nullify()
|
||||
{
|
||||
heights = null;
|
||||
tHeights = null;
|
||||
cX = null;
|
||||
cY = null;
|
||||
cH = null;
|
||||
oldH = null;
|
||||
//DetailsX = null;
|
||||
//DetailsY = null;
|
||||
//DetailValues = null;
|
||||
OldDetailsValue = null;
|
||||
//DetailsI = null;
|
||||
TreesCurrent = null;
|
||||
TreesOld = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Checks all terrains and adds RoadTerrain if necessary </summary>
|
||||
private static void CheckAllTerrains()
|
||||
{
|
||||
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
|
||||
RoadTerrain TID;
|
||||
GameObject terrainObj;
|
||||
foreach (Terrain terrain in allTerrains)
|
||||
{
|
||||
terrainObj = terrain.transform.gameObject;
|
||||
TID = terrainObj.GetComponent<RoadTerrain>();
|
||||
if (TID == null)
|
||||
{
|
||||
TID = terrainObj.AddComponent<RoadTerrain>();
|
||||
}
|
||||
TID.CheckID();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Checks if every Terrain uses a RoadTerrain script and set it to 0 on y </summary>
|
||||
public static void CheckAllTerrainsHeight0()
|
||||
{
|
||||
CheckAllTerrains();
|
||||
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
|
||||
foreach (Terrain terrain in allTerrains)
|
||||
{
|
||||
if (!RootUtils.IsApproximately(terrain.transform.position.y, 0f, 0.0001f))
|
||||
{
|
||||
Vector3 tVect = terrain.transform.position;
|
||||
tVect.y = 0f;
|
||||
terrain.transform.position = tVect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Stores terrain infos and starts terrain calculations </summary>
|
||||
public static void ProcessRoadTerrainHook1(SplineC _spline, Road _road, bool _isMultithreaded = true)
|
||||
{
|
||||
ProcessRoadTerrainHook1Do(ref _spline, ref _road, _isMultithreaded);
|
||||
}
|
||||
|
||||
|
||||
private static void ProcessRoadTerrainHook1Do(ref SplineC _spline, ref Road _road, bool _isMultithreaded)
|
||||
{
|
||||
RootUtils.StartProfiling(_road, "ProcessRoadTerrainHook1");
|
||||
//First lets make sure all terrains have a RoadTerrain script:
|
||||
CheckAllTerrains();
|
||||
|
||||
//Reset the terrain:
|
||||
RootUtils.StartProfiling(_road, "TerrainsReset");
|
||||
TerrainsReset(_road);
|
||||
RootUtils.EndProfiling(_road);
|
||||
|
||||
float heightDistance = _road.matchHeightsDistance;
|
||||
//float treeDistance = _road.clearTreesDistance;
|
||||
float detailDistance = _road.clearDetailsDistance;
|
||||
|
||||
Dictionary<Terrain, TempTerrainData> TempTerrainDict = new Dictionary<Terrain, TempTerrainData>();
|
||||
//Populate dictionary:
|
||||
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
|
||||
RoadTerrain TID;
|
||||
int aSize = 0;
|
||||
int dSize = 0;
|
||||
TempTerrainData TTD;
|
||||
bool isContaining = false;
|
||||
Construction2DRect tRect = null;
|
||||
//Construction2DRect rRect = null;
|
||||
|
||||
|
||||
foreach (Terrain terrain in allTerrains)
|
||||
{
|
||||
if (terrain.terrainData == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tRect = GetTerrainBounds(terrain);
|
||||
isContaining = false;
|
||||
//Debug.Log(terrain.transform.name + " bounds: " + tRect.ToStringRA());
|
||||
//Debug.Log(" Road bounds: " + tSpline.RoadV0 + "," + tSpline.RoadV1 + "," + tSpline.RoadV2 + "," + tSpline.RoadV3);
|
||||
|
||||
// Check if the terrain overlaps with a part of the spline
|
||||
if (isContaining != true && tRect.Contains(ref _spline.RoadV0))
|
||||
{
|
||||
isContaining = true;
|
||||
}
|
||||
else if (isContaining != true && tRect.Contains(ref _spline.RoadV1))
|
||||
{
|
||||
isContaining = true;
|
||||
}
|
||||
else if (isContaining != true && tRect.Contains(ref _spline.RoadV2))
|
||||
{
|
||||
isContaining = true;
|
||||
}
|
||||
else if (isContaining != true && tRect.Contains(ref _spline.RoadV3))
|
||||
{
|
||||
isContaining = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nodeCount = _road.spline.GetNodeCount();
|
||||
Vector2 tVect2D_321 = default(Vector2);
|
||||
for (int index = 0; index < nodeCount; index++)
|
||||
{
|
||||
tVect2D_321 = new Vector2(_road.spline.nodes[index].pos.x, _road.spline.nodes[index].pos.z);
|
||||
if (tRect.Contains(ref tVect2D_321))
|
||||
{
|
||||
isContaining = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isContaining)
|
||||
{
|
||||
float tDef = 5f / _spline.distance;
|
||||
Vector2 x2D = default(Vector2);
|
||||
Vector3 x3D = default(Vector3);
|
||||
for (float index = 0f; index <= 1f; index += tDef)
|
||||
{
|
||||
x3D = _spline.GetSplineValue(index);
|
||||
x2D = new Vector2(x3D.x, x3D.z);
|
||||
if (tRect.Contains(ref x2D))
|
||||
{
|
||||
isContaining = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//rRect = new RoadUtility.Construction2DRect(tSpline.RoadV0,tSpline.RoadV1,tSpline.RoadV2,tSpline.RoadV3);
|
||||
|
||||
|
||||
if (isContaining && !TempTerrainDict.ContainsKey(terrain))
|
||||
{
|
||||
TTD = new TempTerrainData();
|
||||
TTD.HM = terrain.terrainData.heightmapResolution;
|
||||
TTD.HMHeight = terrain.terrainData.heightmapResolution;
|
||||
TTD.heights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution);
|
||||
TTD.HMRatio = TTD.HM / terrain.terrainData.size.x;
|
||||
TTD.MetersPerHM = terrain.terrainData.size.x / terrain.terrainData.heightmapResolution;
|
||||
float DetailRatio = terrain.terrainData.detailResolution / terrain.terrainData.size.x;
|
||||
|
||||
//Heights:
|
||||
RootUtils.StartProfiling(_road, "Heights");
|
||||
if (_road.isHeightModificationEnabled)
|
||||
{
|
||||
aSize = (int)_spline.distance * ((int)(heightDistance * 1.65f * TTD.HMRatio) + 2);
|
||||
if (aSize > (terrain.terrainData.heightmapResolution * terrain.terrainData.heightmapResolution))
|
||||
{
|
||||
aSize = terrain.terrainData.heightmapResolution * terrain.terrainData.heightmapResolution;
|
||||
}
|
||||
TTD.cX = new ushort[aSize];
|
||||
TTD.cY = new ushort[aSize];
|
||||
TTD.oldH = new float[aSize];
|
||||
TTD.cH = new float[aSize];
|
||||
TTD.Count = 0;
|
||||
TTD.TerrainMaxIndex = terrain.terrainData.heightmapResolution;
|
||||
TTD.TerrainSize = terrain.terrainData.size;
|
||||
TTD.TerrainPos = terrain.transform.position;
|
||||
TTD.tHeights = new bool[terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution];
|
||||
TID = terrain.transform.gameObject.GetComponent<RoadTerrain>();
|
||||
if (TID != null)
|
||||
{
|
||||
TTD.uID = TID.UID;
|
||||
TempTerrainDict.Add(terrain, TTD);
|
||||
}
|
||||
}
|
||||
|
||||
//Details:
|
||||
RootUtils.EndStartProfiling(_road, "Details");
|
||||
if (_road.isDetailModificationEnabled)
|
||||
{
|
||||
//TTD.DetailValues = new Dictionary<int, int[,]>();
|
||||
TTD.DetailLayersCount = terrain.terrainData.detailPrototypes.Length;
|
||||
//TTD.DetailHasProcessed = new Dictionary<int, bool[,]>();
|
||||
TTD.DetailHasProcessed = new HashSet<int>();
|
||||
TTD.MainDetailsX = new List<ushort>();
|
||||
TTD.MainDetailsY = new List<ushort>();
|
||||
TTD.detailsCount = new int[TTD.DetailLayersCount];
|
||||
TTD.DetailToHeightRatio = (float)((float)terrain.terrainData.detailResolution) / ((float)terrain.terrainData.heightmapResolution);
|
||||
TTD.DetailMaxIndex = terrain.terrainData.detailResolution;
|
||||
TTD.DetailLayersSkip = new HashSet<int>();
|
||||
|
||||
// Get all of layer zero.
|
||||
//int[] mMinMaxDetailEntryCount = new int[TTD.DetailLayersCount];
|
||||
//RootUtils.StartProfiling(_road, "DetailValues");
|
||||
//Vector3 bVect = default(Vector3);
|
||||
//Vector2 bVect2D = default(Vector2);
|
||||
//int DetailRes = tTerrain.terrainData.detailResolution;
|
||||
//for(int i=0;i<TTD.DetailLayersCount;i++)
|
||||
//{
|
||||
// int[,] tInts = tTerrain.terrainData.GetDetailLayer(0,0,tTerrain.terrainData.detailWidth,tTerrain.terrainData.detailHeight,i);
|
||||
// int Length1 = tInts.GetLength(0);
|
||||
// int Length2 = tInts.GetLength(1);
|
||||
// for (int y=0;y < Length1;y++)
|
||||
// {
|
||||
// for (int x=0;x < Length2;x++)
|
||||
// {
|
||||
// if(tInts[x,y] > 0)
|
||||
// {
|
||||
// bVect = new Vector3(((float)y/(float)DetailRes) * TTD.TerrainSize.x,0f,((float)x/(float)DetailRes) * TTD.TerrainSize.z);
|
||||
// bVect = tTerrain.transform.TransformPoint(bVect);
|
||||
// bVect2D = new Vector2(bVect.z,bVect.x);
|
||||
// if(rRect.Contains(ref bVect2D))
|
||||
// {
|
||||
// mMinMaxDetailEntryCount[i] += 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if(mMinMaxDetailEntryCount[i] < 1)
|
||||
// {
|
||||
// TTD.DetailLayersSkip.Add(i);
|
||||
// tInts = null;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// TTD.DetailValues.Add(i,tInts);
|
||||
// TTD.DetailHasProcessed.Add(i,new bool[tTerrain.terrainData.detailWidth,tTerrain.terrainData.detailHeight]);
|
||||
// }
|
||||
// }
|
||||
//RootUtils.EndProfiling(_road);
|
||||
|
||||
|
||||
dSize = (int)_spline.distance * ((int)(detailDistance * 3f * DetailRatio) + 2);
|
||||
if (dSize > (terrain.terrainData.detailResolution * terrain.terrainData.detailResolution))
|
||||
{
|
||||
dSize = terrain.terrainData.detailResolution * terrain.terrainData.detailResolution;
|
||||
}
|
||||
|
||||
//TTD.DetailsX = new List<ushort[]>();
|
||||
//TTD.DetailsY = new List<ushort[]>();
|
||||
//TTD.OldDetailsValue = new List<ushort[]>();
|
||||
TTD.DetailsX = new List<List<ushort>>();
|
||||
TTD.DetailsY = new List<List<ushort>>();
|
||||
TTD.OldDetailsValue = new List<List<ushort>>();
|
||||
//TTD.DetailHasProcessed = new List<List<bool>>();
|
||||
|
||||
for (int index = 0; index < TTD.DetailLayersCount; index++)
|
||||
{
|
||||
//if(TTD.DetailLayersSkip.Contains(index))
|
||||
//{
|
||||
// TTD.DetailsX.Add(new ushort[0]);
|
||||
// TTD.DetailsY.Add(new ushort[0]);
|
||||
// TTD.OldDetailsValue.Add(new ushort[0]);
|
||||
// continue;
|
||||
//}
|
||||
//int detailentrycount = (int)((float)mMinMaxDetailEntryCount[index] * 1.5f);
|
||||
//int d_temp_Size = dSize;
|
||||
//if(d_temp_Size > detailentrycount)
|
||||
//{
|
||||
// d_temp_Size = detailentrycount;
|
||||
//}
|
||||
//if(d_temp_Size < 1)
|
||||
//{
|
||||
// d_temp_Size = 1;
|
||||
//}
|
||||
//if(d_temp_Size > (tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution))
|
||||
//{
|
||||
// d_temp_Size = tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution;
|
||||
//}
|
||||
//
|
||||
//TTD.DetailsX.Add(new ushort[d_temp_Size]);
|
||||
//TTD.DetailsY.Add(new ushort[d_temp_Size]);
|
||||
//TTD.OldDetailsValue.Add(new ushort[d_temp_Size]);
|
||||
|
||||
TTD.DetailsX.Add(new List<ushort>());
|
||||
TTD.DetailsY.Add(new List<ushort>());
|
||||
TTD.OldDetailsValue.Add(new List<ushort>());
|
||||
}
|
||||
|
||||
|
||||
//TTD.DetailsX = new ushort[TTD.DetailLayersCount,dSize];
|
||||
//TTD.DetailsY = new ushort[TTD.DetailLayersCount,dSize];
|
||||
//TTD.OldDetailsValue = new ushort[TTD.DetailLayersCount,dSize];
|
||||
}
|
||||
|
||||
//Trees:
|
||||
RootUtils.EndStartProfiling(_road, "Trees");
|
||||
if (_road.isTreeModificationEnabled)
|
||||
{
|
||||
TTD.TreesCurrent = new List<TreeInstance>(terrain.terrainData.treeInstances);
|
||||
TTD.TreeSize = TTD.TreesCurrent.Count;
|
||||
TTD.treesCount = 0;
|
||||
TTD.TreesOld = new List<TreeInstance>();
|
||||
}
|
||||
RootUtils.EndProfiling(_road);
|
||||
}
|
||||
}
|
||||
|
||||
//Figure out relevant TTD to spline:
|
||||
List<TempTerrainData> EditorTTDList = new List<TempTerrainData>();
|
||||
if (TempTerrainDict != null)
|
||||
{
|
||||
foreach (Terrain tTerrain in allTerrains)
|
||||
{
|
||||
if (TempTerrainDict.ContainsKey(tTerrain))
|
||||
{
|
||||
EditorTTDList.Add(TempTerrainDict[tTerrain]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RootUtils.EndProfiling(_road);
|
||||
|
||||
//Start job now, for each relevant TTD:
|
||||
_road.SetEditorTerrainCalcs(ref EditorTTDList);
|
||||
if (_isMultithreaded)
|
||||
{
|
||||
Threading.TerrainCalcs terrainJob = new Threading.TerrainCalcs();
|
||||
terrainJob.Setup(ref EditorTTDList, _spline, _road);
|
||||
_road.TerrainCalcsJob = terrainJob;
|
||||
terrainJob.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Threading.TerrainCalcsStatic.RunMe(ref EditorTTDList, _spline, _road);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns an 2D rect of the terrain </summary>
|
||||
public static Construction2DRect GetTerrainBounds(Terrain _terrain)
|
||||
{
|
||||
float terrainWidth = _terrain.terrainData.size.x;
|
||||
float terrainLength = _terrain.terrainData.size.z;
|
||||
//Vector3 tPos = tTerrain.transform.TransformPoint(tTerrain.transform.position);
|
||||
|
||||
Vector3 X0 = new Vector3(0f, 0f, 0f);
|
||||
Vector3 X1 = new Vector3(terrainWidth, 0f, 0f);
|
||||
Vector3 X2 = new Vector3(terrainWidth, 0f, terrainLength);
|
||||
Vector3 X3 = new Vector3(0f, 0f, terrainLength);
|
||||
|
||||
X0 = _terrain.transform.TransformPoint(X0);
|
||||
X1 = _terrain.transform.TransformPoint(X1);
|
||||
X2 = _terrain.transform.TransformPoint(X2);
|
||||
X3 = _terrain.transform.TransformPoint(X3);
|
||||
|
||||
Vector2 P0 = new Vector2(X0.x, X0.z);
|
||||
Vector2 P1 = new Vector2(X1.x, X1.z);
|
||||
Vector2 P2 = new Vector2(X2.x, X2.z);
|
||||
Vector2 P3 = new Vector2(X3.x, X3.z);
|
||||
|
||||
|
||||
//OLD CODE:
|
||||
//Vector2 P0 = new Vector2(0f, 0f);
|
||||
//Vector2 P1 = new Vector2(terrainWidth, 0f);
|
||||
//Vector2 P2 = new Vector2(terrainWidth, terrainLength);
|
||||
//Vector2 P3 = new Vector2(0f, terrainLength);
|
||||
|
||||
//P0 = tTerrain.transform.TransformPoint(P0);
|
||||
//P1 = tTerrain.transform.TransformPoint(P1);
|
||||
//P2 = tTerrain.transform.TransformPoint(P2);
|
||||
//P3 = tTerrain.transform.TransformPoint(P3);
|
||||
|
||||
return new Construction2DRect(P0, P1, P2, P3, _terrain.transform.position.y);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Assign calculated values to terrains </summary>
|
||||
public static void ProcessRoadTerrainHook2(SplineC _spline, ref List<TempTerrainData> _TTDList)
|
||||
{
|
||||
RootUtils.StartProfiling(_spline.road, "ProcessRoadTerrainHook2");
|
||||
ProcessRoadTerrainHook2Do(ref _spline, ref _TTDList);
|
||||
RootUtils.EndProfiling(_spline.road);
|
||||
}
|
||||
|
||||
|
||||
private static void ProcessRoadTerrainHook2Do(ref SplineC _spline, ref List<TempTerrainData> _TTDList)
|
||||
{
|
||||
if (!_spline.road.isTreeModificationEnabled && !_spline.road.isHeightModificationEnabled && !_spline.road.isDetailModificationEnabled)
|
||||
{
|
||||
//Exit if no mod taking place.
|
||||
return;
|
||||
}
|
||||
Object[] TIDs = GameObject.FindObjectsOfType<RoadTerrain>();
|
||||
Terrain terrain;
|
||||
int[,] tDetails = null;
|
||||
int IntBufferX = 0;
|
||||
int IntBufferY = 0;
|
||||
int tVal = 0;
|
||||
foreach (TempTerrainData TTD in _TTDList)
|
||||
{
|
||||
foreach (RoadTerrain TID in TIDs)
|
||||
{
|
||||
if (TID.UID != TTD.uID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
terrain = TID.transform.gameObject.GetComponent<Terrain>();
|
||||
if (terrain == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//Details:
|
||||
if (_spline.road.isDetailModificationEnabled)
|
||||
{
|
||||
for (int index = 0; index < TTD.DetailLayersCount; index++)
|
||||
{
|
||||
//if(TTD.DetailLayersSkip.Contains(i) || TTD.DetailValues[i] == null)
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
//if(TTD.DetailsI[i] > 0)
|
||||
//{
|
||||
// tTerrain.terrainData.SetDetailLayer(0, 0, i, TTD.DetailValues[i]);
|
||||
//}
|
||||
|
||||
if (TTD.DetailLayersSkip.Contains(index) || TTD.MainDetailsX == null || TTD.MainDetailsX.Count < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tDetails = terrain.terrainData.GetDetailLayer(0, 0, TTD.DetailMaxIndex, TTD.DetailMaxIndex, index);
|
||||
|
||||
int MaxCount = TTD.MainDetailsX.Count;
|
||||
for (int j = 0; j < MaxCount; j++)
|
||||
{
|
||||
IntBufferX = TTD.MainDetailsX[j];
|
||||
IntBufferY = TTD.MainDetailsY[j];
|
||||
tVal = tDetails[IntBufferX, IntBufferY];
|
||||
if (tVal > 0)
|
||||
{
|
||||
TTD.DetailsX[index].Add((ushort)IntBufferX);
|
||||
TTD.DetailsY[index].Add((ushort)IntBufferY);
|
||||
TTD.OldDetailsValue[index].Add((ushort)tVal);
|
||||
tDetails[IntBufferX, IntBufferY] = 0;
|
||||
}
|
||||
}
|
||||
TTD.detailsCount[index] = TTD.DetailsX[index].Count;
|
||||
|
||||
terrain.terrainData.SetDetailLayer(0, 0, index, tDetails);
|
||||
tDetails = null;
|
||||
TTD.DetailHasProcessed = null;
|
||||
}
|
||||
TTD.MainDetailsX = null;
|
||||
TTD.MainDetailsY = null;
|
||||
System.GC.Collect();
|
||||
}
|
||||
//Trees:
|
||||
if (_spline.road.isTreeModificationEnabled && TTD.TreesCurrent != null && TTD.treesCount > 0)
|
||||
{
|
||||
terrain.terrainData.treeInstances = TTD.TreesCurrent.ToArray();
|
||||
}
|
||||
//Heights:
|
||||
if (_spline.road.isHeightModificationEnabled && TTD.heights != null && TTD.Count > 0)
|
||||
{
|
||||
//Do heights last to trigger collisions and stuff properly:
|
||||
terrain.terrainData.SetHeights(0, 0, TTD.heights);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void TerrainsReset(Road _road)
|
||||
{
|
||||
if (_road.TerrainHistory == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_road.TerrainHistory.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Object[] TIDs = GameObject.FindObjectsOfType<RoadTerrain>();
|
||||
float[,] heights;
|
||||
int[,] tDetails;
|
||||
int ArrayCount;
|
||||
foreach (TerrainHistoryMaker TH in _road.TerrainHistory)
|
||||
{
|
||||
Terrain terrain = null;
|
||||
foreach (RoadTerrain TID in TIDs)
|
||||
{
|
||||
if (TID.UID == TH.terrainID)
|
||||
{
|
||||
terrain = TID.terrain;
|
||||
}
|
||||
}
|
||||
if (!terrain)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TH.heightmapResolution != terrain.terrainData.heightmapResolution)
|
||||
{
|
||||
TH.Nullify();
|
||||
continue;
|
||||
}
|
||||
|
||||
//Heights:
|
||||
if (TH.x1 != null)
|
||||
{
|
||||
heights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution);
|
||||
ArrayCount = TH.Count;
|
||||
for (int index = 0; index < ArrayCount; index++)
|
||||
{
|
||||
heights[TH.x1[index], TH.y1[index]] = TH.height[index];
|
||||
}
|
||||
terrain.terrainData.SetHeights(0, 0, heights);
|
||||
}
|
||||
//Details:
|
||||
if (TH.detailsCount != null && TH.detailsX != null && TH.detailsY != null && TH.detailsOldValue != null)
|
||||
{
|
||||
int RealLayerCount = terrain.terrainData.detailPrototypes.Length;
|
||||
int StartIndex = 0;
|
||||
int EndIndex = 0;
|
||||
for (int index = 0; index < TH.detailLayersCount; index++)
|
||||
{
|
||||
if (index >= RealLayerCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (TH.detailsX.Length <= index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (TH.detailsY.Length <= index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (TH.detailsX.Length < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tDetails = terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailWidth, terrain.terrainData.detailHeight, index);
|
||||
ArrayCount = TH.detailsCount[index];
|
||||
if (ArrayCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
EndIndex += ArrayCount;
|
||||
for (int j = StartIndex; j < EndIndex; j++)
|
||||
{
|
||||
tDetails[TH.detailsX[j], TH.detailsY[j]] = TH.detailsOldValue[j];
|
||||
}
|
||||
StartIndex = EndIndex;
|
||||
terrain.terrainData.SetDetailLayer(0, 0, index, tDetails);
|
||||
tDetails = null;
|
||||
}
|
||||
}
|
||||
//Trees:
|
||||
TreeInstance[] xTress = TH.MakeTrees();
|
||||
if (xTress != null)
|
||||
{
|
||||
ArrayCount = xTress.Length;
|
||||
if (ArrayCount > 0 && TH.oldTrees != null)
|
||||
{
|
||||
int TerrainTreeCount = terrain.terrainData.treeInstances.Length;
|
||||
TreeInstance[] tTrees = new TreeInstance[ArrayCount + TerrainTreeCount];
|
||||
System.Array.Copy(terrain.terrainData.treeInstances, 0, tTrees, 0, TerrainTreeCount);
|
||||
System.Array.Copy(xTress, 0, tTrees, TerrainTreeCount, ArrayCount);
|
||||
terrain.terrainData.treeInstances = tTrees;
|
||||
}
|
||||
xTress = null;
|
||||
}
|
||||
}
|
||||
System.GC.Collect();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89d78ed7b18900c4cb9d282113f97801
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efa1287a39e985c40892386ab840d9e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace RoadArchitect.Threading
|
||||
{
|
||||
public class TerrainCalcs : ThreadedJob
|
||||
{
|
||||
private object handle = new object();
|
||||
private List<Terraforming.TempTerrainData> TTDList;
|
||||
private SplineC spline;
|
||||
private Road road;
|
||||
|
||||
|
||||
public void Setup(ref List<Terraforming.TempTerrainData> _TTDList, SplineC _tSpline, Road _tRoad)
|
||||
{
|
||||
TTDList = _TTDList;
|
||||
spline = _tSpline;
|
||||
road = _tRoad;
|
||||
}
|
||||
|
||||
|
||||
protected override void ThreadFunction()
|
||||
{
|
||||
float Step = (road.roadDefinition * 0.4f) / spline.distance;
|
||||
if (Step > 2f)
|
||||
{
|
||||
Step = 2f;
|
||||
}
|
||||
if (Step < 1f)
|
||||
{
|
||||
Step = 1f;
|
||||
}
|
||||
//float tDistance = tRoad.RoadWidth()*2f;
|
||||
|
||||
//Vector3 tVect, POS;
|
||||
foreach (Terraforming.TempTerrainData TTD in TTDList)
|
||||
{
|
||||
//float PrevHeight = 0f;
|
||||
//float FinalMax = 1f;
|
||||
//float StartMin = 0f;
|
||||
//if(tSpline.bSpecialEndControlNode)
|
||||
//{
|
||||
// FinalMax = tSpline.mNodes[tSpline.GetNodeCount()-2].tTime;
|
||||
//}
|
||||
//if(tSpline.bSpecialStartControlNode)
|
||||
//{
|
||||
// StartMin = tSpline.mNodes[1].tTime;
|
||||
//}
|
||||
|
||||
//if(tRoad.opt_MatchTerrain)
|
||||
//{
|
||||
try
|
||||
{
|
||||
TerraformingThreaded.DoRects(spline, TTD);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
lock (handle)
|
||||
{
|
||||
road.isEditorError = true;
|
||||
road.exceptionError = e;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// for(float i=StartMin;i<=FinalMax;i+=Step)
|
||||
// {
|
||||
// if(tSpline.IsInBridgeTerrain(i))
|
||||
// {
|
||||
// float tFloat = tSpline.GetBridgeEnd(i);
|
||||
// if(IsApproximately(tFloat,1f,0.00001f) || tFloat > 1f)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if(tFloat < 0f)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// i = tFloat;
|
||||
// }
|
||||
// tSpline.GetSplineValue_Both(i,out tVect,out POS);
|
||||
// PrevHeight = TerraformingThreaded.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight);
|
||||
// tSpline.HeightHistory.Add(new KeyValuePair<float,float>(i,PrevHeight*TTD.TerrainSize.y));
|
||||
// }
|
||||
//
|
||||
// for(int i=0;i<TTD.cI;i++)
|
||||
// {
|
||||
// TTD.heights[TTD.cX[i],TTD.cY[i]] = TTD.cH[i];
|
||||
// }
|
||||
//}
|
||||
}
|
||||
spline.HeightHistory.Sort(CompareKeys);
|
||||
IsDone = true;
|
||||
}
|
||||
|
||||
|
||||
private int CompareKeys(KeyValuePair<float, float> _a, KeyValuePair<float, float> _b)
|
||||
{
|
||||
return _a.Key.CompareTo(_b.Key);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c40fe5dd65fa96c44b2efba54af237e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace RoadArchitect.Threading
|
||||
{
|
||||
public static class TerrainCalcsStatic
|
||||
{
|
||||
public static void RunMe(ref List<Terraforming.TempTerrainData> _TTDList, SplineC _spline, Road _road)
|
||||
{
|
||||
float Step = (_road.roadDefinition * 0.4f) / _spline.distance;
|
||||
if (Step > 2f)
|
||||
{
|
||||
Step = 2f;
|
||||
}
|
||||
if (Step < 1f)
|
||||
{
|
||||
Step = 1f;
|
||||
}
|
||||
//float tDistance = tRoad.RoadWidth()*2f;
|
||||
|
||||
//Vector3 tVect,POS;
|
||||
|
||||
foreach (Terraforming.TempTerrainData TTD in _TTDList)
|
||||
{
|
||||
//float PrevHeight = 0f;
|
||||
//float FinalMax = 1f;
|
||||
//float StartMin = 0f;
|
||||
//if(tSpline.bSpecialEndControlNode)
|
||||
//{
|
||||
// FinalMax = tSpline.mNodes[tSpline.GetNodeCount()-2].tTime;
|
||||
//}
|
||||
//if(tSpline.bSpecialStartControlNode)
|
||||
//{
|
||||
// StartMin = tSpline.mNodes[1].tTime;
|
||||
//}
|
||||
|
||||
//if(tRoad.opt_MatchTerrain)
|
||||
//{
|
||||
RootUtils.StartProfiling(_road, "DoRects");
|
||||
TerraformingThreaded.DoRects(_spline, TTD);
|
||||
RootUtils.EndProfiling(_road);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// for(float i=StartMin;i<=FinalMax;i+=Step)
|
||||
// {
|
||||
// if(tSpline.IsInBridgeTerrain(i))
|
||||
// {
|
||||
// float tFloat = tSpline.GetBridgeEnd(i);
|
||||
// if(IsApproximately(tFloat,1f,0.00001f) || tFloat > 1f)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if(tFloat < 0f)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// i = tFloat;
|
||||
// }
|
||||
// tSpline.GetSplineValue_Both(i,out tVect,out POS);
|
||||
// PrevHeight = TerraformingThreaded.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight);
|
||||
// tSpline.HeightHistory.Add(new KeyValuePair<float,float>(i,PrevHeight*TTD.TerrainSize.y));
|
||||
// }
|
||||
//
|
||||
// for(int i=0;i<TTD.cI;i++)
|
||||
// {
|
||||
// TTD.heights[TTD.cX[i],TTD.cY[i]] = TTD.cH[i];
|
||||
// }
|
||||
//}
|
||||
}
|
||||
_spline.HeightHistory.Sort(Compare1);
|
||||
}
|
||||
|
||||
|
||||
private static int Compare1(KeyValuePair<float, float> _a, KeyValuePair<float, float> _b)
|
||||
{
|
||||
return _a.Key.CompareTo(_b.Key);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e03104c3c44082e4da5eb3d5c69816e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,182 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace RoadArchitect
|
||||
{
|
||||
[System.Serializable]
|
||||
public class TerrainHistoryMaker
|
||||
{
|
||||
#region "Vars"
|
||||
public int terrainID;
|
||||
public int heightmapResolution;
|
||||
//Heights:
|
||||
public int[] x1;
|
||||
public int[] y1;
|
||||
public float[] height;
|
||||
public int Count;
|
||||
//Details:
|
||||
public int detailLayersCount;
|
||||
public int[] detailsCount;
|
||||
public int[] detailsX;
|
||||
public int[] detailsY;
|
||||
public int[] detailsOldValue;
|
||||
|
||||
//Trees:
|
||||
public TerrainTreeInstance[] oldTrees;
|
||||
public int treesCount;
|
||||
#endregion
|
||||
|
||||
|
||||
public void Nullify()
|
||||
{
|
||||
//Heights:
|
||||
x1 = null;
|
||||
y1 = null;
|
||||
height = null;
|
||||
detailsX = null;
|
||||
detailsY = null;
|
||||
detailsOldValue = null;
|
||||
detailsCount = null;
|
||||
//Trees:
|
||||
oldTrees = null;
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class TerrainTreeInstance
|
||||
{
|
||||
public float colorR;
|
||||
public float colorG;
|
||||
public float colorB;
|
||||
public float colorA;
|
||||
public float heightScale;
|
||||
public float lightmapColorR;
|
||||
public float lightmapColorG;
|
||||
public float lightmapColorB;
|
||||
public float lightmapColorA;
|
||||
public float positionX;
|
||||
public float positionY;
|
||||
public float positionZ;
|
||||
public int prototypeIndex;
|
||||
public float widthScale;
|
||||
// 4 bytes for int and float
|
||||
//56 Bytes
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Stores _trees into oldTrees </summary>
|
||||
public void MakeRATrees(ref List<TreeInstance> _trees)
|
||||
{
|
||||
int tSize = _trees.Count;
|
||||
oldTrees = new TerrainTreeInstance[tSize];
|
||||
TerrainTreeInstance tTree = null;
|
||||
TreeInstance xTree;
|
||||
for (int index = 0; index < tSize; index++)
|
||||
{
|
||||
xTree = _trees[index];
|
||||
tTree = new TerrainTreeInstance();
|
||||
tTree.colorR = xTree.color.r;
|
||||
tTree.colorG = xTree.color.g;
|
||||
tTree.colorB = xTree.color.b;
|
||||
tTree.colorA = xTree.color.a;
|
||||
tTree.heightScale = xTree.heightScale;
|
||||
tTree.lightmapColorR = xTree.lightmapColor.r;
|
||||
tTree.lightmapColorG = xTree.lightmapColor.g;
|
||||
tTree.lightmapColorB = xTree.lightmapColor.b;
|
||||
tTree.lightmapColorA = xTree.lightmapColor.a;
|
||||
tTree.positionX = xTree.position.x;
|
||||
tTree.positionY = xTree.position.y;
|
||||
tTree.positionZ = xTree.position.z;
|
||||
tTree.prototypeIndex = xTree.prototypeIndex;
|
||||
tTree.widthScale = xTree.widthScale;
|
||||
oldTrees[index] = tTree;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns a new tree array copy of oldTrees </summary>
|
||||
public TreeInstance[] MakeTrees()
|
||||
{
|
||||
if (oldTrees == null || oldTrees.Length < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int tSize = oldTrees.Length;
|
||||
TreeInstance[] tTrees = new TreeInstance[tSize];
|
||||
TerrainTreeInstance tTree = null;
|
||||
TreeInstance xTree;
|
||||
for (int index = 0; index < tSize; index++)
|
||||
{
|
||||
tTree = oldTrees[index];
|
||||
xTree = new TreeInstance();
|
||||
xTree.color = new Color(tTree.colorR, tTree.colorG, tTree.colorB, tTree.colorA);
|
||||
xTree.heightScale = tTree.heightScale;
|
||||
xTree.lightmapColor = new Color(tTree.lightmapColorR, tTree.lightmapColorG, tTree.lightmapColorB, tTree.lightmapColorA);
|
||||
xTree.position = new Vector3(tTree.positionX, tTree.positionY, tTree.positionZ);
|
||||
xTree.prototypeIndex = tTree.prototypeIndex;
|
||||
xTree.widthScale = tTree.widthScale;
|
||||
tTrees[index] = xTree;
|
||||
}
|
||||
return tTrees;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns size of this terrain history </summary>
|
||||
public int GetSize()
|
||||
{
|
||||
int tSize = 4;
|
||||
if (x1 != null)
|
||||
{
|
||||
tSize += (x1.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
if (y1 != null)
|
||||
{
|
||||
tSize += (y1.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
if (height != null)
|
||||
{
|
||||
tSize += (height.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
tSize += 4;
|
||||
tSize += 1;
|
||||
//Details:
|
||||
tSize += 4;
|
||||
if (detailsX != null)
|
||||
{
|
||||
tSize += (detailsX.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
if (detailsY != null)
|
||||
{
|
||||
tSize += (detailsY.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
if (detailsOldValue != null)
|
||||
{
|
||||
tSize += (detailsOldValue.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
if (detailsCount != null)
|
||||
{
|
||||
tSize += (detailsCount.Length * 4);
|
||||
tSize += 20;
|
||||
}
|
||||
tSize += 1;
|
||||
//Trees:
|
||||
if (oldTrees != null)
|
||||
{
|
||||
tSize += (oldTrees.Length * 56);
|
||||
tSize += 20;
|
||||
}
|
||||
tSize += 4;
|
||||
tSize += 1;
|
||||
tSize += 1;
|
||||
|
||||
return tSize;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b93fdfdbd7881e14992a0b530762a8b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,154 @@
|
||||
#region "Imports"
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Runtime.Serialization;
|
||||
#endregion
|
||||
|
||||
|
||||
namespace RoadArchitect
|
||||
{
|
||||
public static class TerrainHistoryUtility
|
||||
{
|
||||
//http://forum.unity3d.com/threads/32647-C-Sharp-Binary-Serialization
|
||||
//http://answers.unity3d.com/questions/363477/c-how-to-setup-a-binary-serialization.html
|
||||
|
||||
// === This is required to guarantee a fixed serialization assembly name, which Unity likes to randomize on each compile
|
||||
// Do not change this
|
||||
public sealed class VersionDeserializationBinder : SerializationBinder
|
||||
{
|
||||
public override System.Type BindToType(string assemblyName, string typeName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(assemblyName) && !string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
System.Type typeToDeserialize = null;
|
||||
assemblyName = System.Reflection.Assembly.GetExecutingAssembly().FullName;
|
||||
// The following line of code returns the type.
|
||||
typeToDeserialize = System.Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
|
||||
return typeToDeserialize;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Saves the Terrain History to disk </summary>
|
||||
public static void SaveTerrainHistory(List<TerrainHistoryMaker> _obj, Road _road)
|
||||
{
|
||||
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
|
||||
if (string.IsNullOrEmpty(path) || path.Length < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Stream stream = File.Open(path, FileMode.Create);
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
bformatter.Binder = new VersionDeserializationBinder();
|
||||
bformatter.Serialize(stream, _obj);
|
||||
_road.TerrainHistoryByteSize = (stream.Length * 0.001f).ToString("n0") + " kb";
|
||||
stream.Close();
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Deletes the Terrain History from disk </summary>
|
||||
public static void DeleteTerrainHistory(Road _road)
|
||||
{
|
||||
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Loads the Terrain History from disk </summary>
|
||||
public static List<TerrainHistoryMaker> LoadTerrainHistory(Road _road)
|
||||
{
|
||||
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
|
||||
if (string.IsNullOrEmpty(path) || path.Length < 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<TerrainHistoryMaker> result;
|
||||
Stream stream = File.Open(path, FileMode.Open);
|
||||
BinaryFormatter bFormatter = new BinaryFormatter();
|
||||
bFormatter.Binder = new VersionDeserializationBinder();
|
||||
|
||||
result = (List<TerrainHistoryMaker>)bFormatter.Deserialize(stream);
|
||||
|
||||
stream.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Generates the Terrain History file name </summary>
|
||||
private static string GetRoadTHFilename(ref Road _road)
|
||||
{
|
||||
string sceneName;
|
||||
|
||||
sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
|
||||
sceneName = sceneName.Replace("/", "");
|
||||
sceneName = sceneName.Replace(".", "");
|
||||
string roadName = _road.roadSystem.transform.name.Replace("RoadArchitectSystem", "RAS") + "-" + _road.transform.name;
|
||||
return sceneName + "-" + roadName + ".th";
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns the path to the RoadArchitect folder where Terrain History is saved </summary>
|
||||
public static string GetDirBase()
|
||||
{
|
||||
return UnityEngine.Application.dataPath.Replace("/Assets", "/RoadArchitect/");
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns the path where Terrain History is saved </summary>
|
||||
public static string GetTHDir()
|
||||
{
|
||||
string path = GetDirBase() + "TerrainHistory/";
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Checks if RoadArchitect folder exists </summary>
|
||||
public static string CheckRoadArchitectDirectory()
|
||||
{
|
||||
string path = GetDirBase();
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
return path + "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Returns RoadArchitect/TerrainHistory path or empty </summary>
|
||||
public static string CheckNonAssetDirTH()
|
||||
{
|
||||
CheckRoadArchitectDirectory();
|
||||
|
||||
string path = GetTHDir();
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73b4fdcab871f09489dfe60aabc98fc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user