diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..213b46df --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog +All notable changes to this RoadArchitect project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [Version: 1.8_FH] - 2019.02.10 +### Improvements +- Added some FH_Tag Optimizable as comments, since there is a way to further optimize the Code tagged by this +- Added a few Lines of comments to the code, to get a better idea of what the code does + +### Changed +- Changed some Layouts of the Scripts +- Changed some Vars in Scripts to better reflect their purpose + +### Added +- Added a few Regions to some Scripts + +###Fixed +- Fixed embeddedt/RoadArchitect/issues/4 + +## [Version: 1.7.5a_FH] - 2019.01.31 +### Changed +- Changed most Layouts of the Scripts +- Changed some Vars in Scripts to better reflect their purpose + +## [Version 1.7] - 2018.07.16 +### Changed +- Adds support for Unity 2018.x +- Updates to unit tests +- No further Informations given at this point + +## [Version 1.6] - 2017.02.28 +### Changed +- Initial Release +- No further Informations given at this point \ No newline at end of file diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta new file mode 100644 index 00000000..0c0897b8 --- /dev/null +++ b/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 82263ce59907a4c45acd2234af48e7e9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/GSDEditorProgressWindow.cs b/Editor/GSDEditorProgressWindow.cs index d9f2e99e..431b5507 100755 --- a/Editor/GSDEditorProgressWindow.cs +++ b/Editor/GSDEditorProgressWindow.cs @@ -1,54 +1,63 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif -using UnityEngine; - -/// -/// Used for progress information for other areas of RA. -/// -public class GSDEditorProgressWindow : EditorWindow -{ - float secs = 10.0f; - float startVal = 0f; - float progress = 0f; - -#if UNITY_EDITOR - static void Init() - { - GSDEditorProgressWindow window = (GSDEditorProgressWindow)EditorWindow.GetWindow(typeof(GSDEditorProgressWindow)); - window.Show(); - } -#endif - -#if UNITY_EDITOR - void OnGUI() - { - secs = EditorGUILayout.FloatField("Time to wait:", secs); - if (GUILayout.Button("Display bar")) - { - if (secs < 1) - { - Debug.LogError("Seconds should be bigger than 1"); - return; - } - startVal = (float)EditorApplication.timeSinceStartup; - } - - if (progress < secs) - EditorUtility.DisplayProgressBar( - "Simple Progress Bar", - "Shows a progress bar for the given seconds", - progress / secs); - else - EditorUtility.ClearProgressBar(); - - progress = (float)(EditorApplication.timeSinceStartup - startVal); - } - - - void OnInspectorUpdate() - { - Repaint(); - } -#endif +#region "Imports" +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +#endregion + + +/// +/// Used for progress information for other areas of RA. +/// +public class GSDEditorProgressWindow : EditorWindow +{ + float secs = 10.0f; + float startVal = 0f; + float progress = 0f; + + +#if UNITY_EDITOR + static void Init() + { + GSDEditorProgressWindow window = (GSDEditorProgressWindow) EditorWindow.GetWindow(typeof(GSDEditorProgressWindow)); + window.Show(); + } +#endif + + +#if UNITY_EDITOR + void OnGUI() + { + secs = EditorGUILayout.FloatField("Time to wait:", secs); + if (GUILayout.Button("Display bar")) + { + if (secs < 1) + { + Debug.LogError("Seconds should be bigger than 1"); + return; + } + startVal = (float) EditorApplication.timeSinceStartup; + } + + if (progress < secs) + { + EditorUtility.DisplayProgressBar( + "Simple Progress Bar", + "Shows a progress bar for the given seconds", + progress / secs); + } + else + { + EditorUtility.ClearProgressBar(); + } + + progress = (float) (EditorApplication.timeSinceStartup - startVal); + } + + + void OnInspectorUpdate() + { + Repaint(); + } +#endif } \ No newline at end of file diff --git a/Editor/GSDHelpWindow.cs b/Editor/GSDHelpWindow.cs index 83c79070..87aa3014 100755 --- a/Editor/GSDHelpWindow.cs +++ b/Editor/GSDHelpWindow.cs @@ -1,37 +1,40 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -#endregion -public class GSDHelpWindow : EditorWindow -{ - void OnGUI() - { - EditorStyles.label.wordWrap = true; - EditorStyles.miniLabel.wordWrap = true; - - EditorGUILayout.LabelField("Road Architect Help", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Please visit the online manual for help."); - GUILayout.Space(4f); - - if (GUILayout.Button("Click here to open online manual", EditorStyles.miniButton, GUILayout.Width(300f))) - { - Application.OpenURL("http://microgsd.com/Support.aspx"); - } - - EditorGUILayout.LabelField("http://microgsd.com/Support.aspx", EditorStyles.miniLabel); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Please visit the online manual for help.", EditorStyles.miniLabel); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Please visit our unity forum thread or contact support@microgsd.com with any questions or comments.", EditorStyles.miniLabel); - } - - #region "Init" - public void Initialize() - { - Rect fRect = new Rect(340, 170, 420, 180); - position = fRect; - Show(); - titleContent.text = "Help Info"; - } - #endregion +#region "Imports" +using UnityEngine; +using UnityEditor; +#endregion + + +public class GSDHelpWindow : EditorWindow +{ + void OnGUI() + { + EditorStyles.label.wordWrap = true; + EditorStyles.miniLabel.wordWrap = true; + + EditorGUILayout.LabelField("Road Architect Help", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Please visit the online manual for help."); + GUILayout.Space(4f); + + if (GUILayout.Button("Click here to open online manual", EditorStyles.miniButton, GUILayout.Width(300f))) + { + Application.OpenURL("http://microgsd.com/Support.aspx"); + } + + EditorGUILayout.LabelField("http://microgsd.com/Support.aspx", EditorStyles.miniLabel); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Please visit the online manual for help.", EditorStyles.miniLabel); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Please visit our unity forum thread or contact support@microgsd.com with any questions or comments.", EditorStyles.miniLabel); + } + + + #region "Init" + public void Initialize() + { + Rect fRect = new Rect(340, 170, 420, 180); + position = fRect; + Show(); + titleContent.text = "Help Info"; + } + #endregion } \ No newline at end of file diff --git a/Editor/GSDNotification.cs b/Editor/GSDNotification.cs index 2a9b548a..5f7e3039 100755 --- a/Editor/GSDNotification.cs +++ b/Editor/GSDNotification.cs @@ -1,29 +1,35 @@ -using UnityEngine; -using UnityEditor; -using System.Collections; - -/// -/// Used for notifications in other areas of RA. -/// -public class GSDNotification : EditorWindow -{ - string notification = "This is a Notification"; - static void Initialize() - { - GSDNotification window = EditorWindow.GetWindow(); - window.Show(); - } - - void OnGUI() - { - notification = EditorGUILayout.TextField(notification); - if (GUILayout.Button("Show Notification")) - { - this.ShowNotification(new GUIContent(notification)); - } - if (GUILayout.Button("Remove Notification")) - { - this.RemoveNotification(); - } - } +#region Imports +using UnityEngine; +using UnityEditor; +using System.Collections; +#endregion + + +/// +/// Used for notifications in other areas of RA. +/// +public class GSDNotification : EditorWindow +{ + string notification = "This is a Notification"; + + + static void Initialize() + { + GSDNotification window = EditorWindow.GetWindow(); + window.Show(); + } + + + void OnGUI() + { + notification = EditorGUILayout.TextField(notification); + if (GUILayout.Button("Show Notification")) + { + this.ShowNotification(new GUIContent(notification)); + } + if (GUILayout.Button("Remove Notification")) + { + this.RemoveNotification(); + } + } } \ No newline at end of file diff --git a/Editor/GSDObjExporter.cs b/Editor/GSDObjExporter.cs index 838cbb0c..2bef8ad1 100755 --- a/Editor/GSDObjExporter.cs +++ b/Editor/GSDObjExporter.cs @@ -1,364 +1,394 @@ -/* -Based on ObjExporter.cs, this "wrapper" lets you export to .OBJ directly from the editor menu. - -This should be put in your "Editor"-folder. Use by selecting the objects you want to export, and select -the appropriate menu item from "Custom->Export". Exported models are put in a folder called -"ExportedObj" in the root of your Unity-project. Textures should also be copied and placed in the -same folder. -N.B. there may be a bug so if the custom option doesn't come up refer to this thread -http://answers.unity3d.com/questions/317951/how-to-use-editorobjexporter-obj-saving-script-fro.html -http://wiki.unity3d.com/index.php?title=ObjExporter -http://wiki.unity3d.com/index.php/User:KeliHlodversson -*/ - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System; - -struct ObjMaterial -{ - public string name; - public string textureName; -} - -public class GSDObjExporter : ScriptableObject -{ - private static int vertexOffset = 0; - private static int normalOffset = 0; - private static int uvOffset = 0; - - - //User should probably be able to change this. It is currently left as an excercise for - //the reader. - private static string targetFolder = "ExportedObj"; - - private static string MeshToString(MeshFilter mf, Dictionary materialList) - { - Mesh m = mf.sharedMesh; - Renderer rend = mf.GetComponent(); - //Material[] mats = mf.renderer.sharedMaterials; - Material[] mats = rend.sharedMaterials; - - StringBuilder sb = new StringBuilder(); - - sb.Append("g ").Append(mf.name).Append("\n"); - foreach (Vector3 lv in m.vertices) - { - Vector3 wv = mf.transform.TransformPoint(lv); - - //This is sort of ugly - inverting x-component since we're in - //a different coordinate system than "everyone" is "used to". - sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); - } - sb.Append("\n"); - - foreach (Vector3 lv in m.normals) - { - Vector3 wv = mf.transform.TransformDirection(lv); - - sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); - } - sb.Append("\n"); - - foreach (Vector3 v in m.uv) - { - sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); - } - - for (int material = 0; material < m.subMeshCount; material++) - { - sb.Append("\n"); - sb.Append("usemtl ").Append(mats[material].name).Append("\n"); - sb.Append("usemap ").Append(mats[material].name).Append("\n"); - - //See if this material is already in the materiallist. - try - { - ObjMaterial objMaterial = new ObjMaterial(); - - objMaterial.name = mats[material].name; - - if (mats[material].mainTexture) - objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); - else - objMaterial.textureName = null; - - materialList.Add(objMaterial.name, objMaterial); - } - catch (ArgumentException) - { - //Already in the dictionary - } - - - int[] triangles = m.GetTriangles(material); - for (int i = 0; i < triangles.Length; i += 3) - { - //Because we inverted the x-component, we also needed to alter the triangle winding. - sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", - triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); - } - } - - vertexOffset += m.vertices.Length; - normalOffset += m.normals.Length; - uvOffset += m.uv.Length; - - return sb.ToString(); - } - - private static void Clear() - { - vertexOffset = 0; - normalOffset = 0; - uvOffset = 0; - } - - private static Dictionary PrepareFileWrite() - { - Clear(); - - return new Dictionary(); - } - - private static void MaterialsToFile(Dictionary materialList, string folder, string filename) - { - using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".mtl")) - { - foreach (KeyValuePair kvp in materialList) - { - sw.Write("\n"); - sw.Write("newmtl {0}\n", kvp.Key); - sw.Write("Ka 0.6 0.6 0.6\n"); - sw.Write("Kd 0.6 0.6 0.6\n"); - sw.Write("Ks 0.9 0.9 0.9\n"); - sw.Write("d 1.0\n"); - sw.Write("Ns 0.0\n"); - sw.Write("illum 2\n"); - - if (kvp.Value.textureName != null) - { - string destinationFile = kvp.Value.textureName; - - - int stripIndex = destinationFile.LastIndexOf('/');//FIXME: Should be Path.PathSeparator; - - if (stripIndex >= 0) - destinationFile = destinationFile.Substring(stripIndex + 1).Trim(); - - - string relativeFile = destinationFile; - - destinationFile = folder + "/" + destinationFile; - - // Debug.Log("Copying texture from " + kvp.Value.textureName + " to " + destinationFile); - - try - { - //Copy the source file - File.Copy(kvp.Value.textureName, destinationFile); - } - catch - { - - } - - - sw.Write("map_Kd {0}", relativeFile); - } - - sw.Write("\n\n\n"); - } - } - } - - private static void MeshToFile(MeshFilter mf, string folder, string filename) - { - Dictionary materialList = PrepareFileWrite(); - - using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")) - { - sw.Write("mtllib ./" + filename + ".mtl\n"); - - sw.Write(MeshToString(mf, materialList)); - } - - MaterialsToFile(materialList, folder, filename); - } - - private static void MeshesToFile(MeshFilter[] mf, string folder, string filename) - { - Dictionary materialList = PrepareFileWrite(); - - using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")) - { - sw.Write("mtllib ./" + filename + ".mtl\n"); - - for (int i = 0; i < mf.Length; i++) - { - sw.Write(MeshToString(mf[i], materialList)); - } - } - - MaterialsToFile(materialList, folder, filename); - } - - private static bool CreateTargetFolder() - { - try - { - System.IO.Directory.CreateDirectory(targetFolder); - } - catch - { - EditorUtility.DisplayDialog("Error!", "Failed to create target folder!", ""); - return false; - } - - return true; - } - - [MenuItem("Window/Road Architect/Export/Export all MeshFilters in selection to separate OBJs")] - static void ExportSelectionToSeparate() - { - if (!CreateTargetFolder()) - return; - - Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); - - if (selection.Length == 0) - { - EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); - return; - } - - int exportedObjects = 0; - - for (int i = 0; i < selection.Length; i++) - { - Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter)); - - for (int m = 0; m < meshfilter.Length; m++) - { - exportedObjects++; - MeshToFile((MeshFilter)meshfilter[m], targetFolder, selection[i].name + "_" + i + "_" + m); - } - } - - if (exportedObjects > 0) - EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects", ""); - else - EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); - } - - [MenuItem("Window/Road Architect/Export/Export whole selection to single OBJ")] - static void ExportWholeSelectionToSingle() - { - if (!CreateTargetFolder()) - return; - - - Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); - - if (selection.Length == 0) - { - EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); - return; - } - - int exportedObjects = 0; - - ArrayList mfList = new ArrayList(); - - for (int i = 0; i < selection.Length; i++) - { - Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter)); - - for (int m = 0; m < meshfilter.Length; m++) - { - exportedObjects++; - mfList.Add(meshfilter[m]); - } - } - - if (exportedObjects > 0) - { - MeshFilter[] mf = new MeshFilter[mfList.Count]; - - for (int i = 0; i < mfList.Count; i++) - { - mf[i] = (MeshFilter)mfList[i]; - } - - - string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; - //string filename = EditorApplication.currentScene + "_" + exportedObjects; - string filename = tSceneName + "_" + exportedObjects; - - int stripIndex = filename.LastIndexOf('/');//FIXME: Should be Path.PathSeparator - - if (stripIndex >= 0) - filename = filename.Substring(stripIndex + 1).Trim(); - - MeshesToFile(mf, targetFolder, filename); - - - EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects to " + filename, ""); - } - else - EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); - } - - - - [MenuItem("Window/Road Architect/Export/Export each selected to single OBJ")] - static void ExportEachSelectionToSingle() - { - if (!CreateTargetFolder()) - return; - - Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); - - if (selection.Length == 0) - { - EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); - return; - } - - int exportedObjects = 0; - - - for (int i = 0; i < selection.Length; i++) - { - Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter)); - - MeshFilter[] mf = new MeshFilter[meshfilter.Length]; - - for (int m = 0; m < meshfilter.Length; m++) - { - exportedObjects++; - mf[m] = (MeshFilter)meshfilter[m]; - } - - MeshesToFile(mf, targetFolder, selection[i].name + "_" + i); - } - - if (exportedObjects > 0) - { - EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects", ""); - } - else - EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); - } - - - [MenuItem("Window/Road Architect/Export/Exporters by Hrafnkell Freyr Hlooversson from Unity3D wiki")] - static void DoNothing1() - { - Application.OpenURL("http://wiki.unity3d.com/index.php?title=ObjExporter"); - } +/* +Based on ObjExporter.cs, this "wrapper" lets you export to .OBJ directly from the editor menu. + +This should be put in your "Editor"-folder. Use by selecting the objects you want to export, and select +the appropriate menu item from "Custom->Export". Exported models are put in a folder called +"ExportedObj" in the root of your Unity-project. Textures should also be copied and placed in the +same folder. +N.B. there may be a bug so if the custom option doesn't come up refer to this thread +http://answers.unity3d.com/questions/317951/how-to-use-editorobjexporter-obj-saving-script-fro.html +http://wiki.unity3d.com/index.php?title=ObjExporter +http://wiki.unity3d.com/index.php/User:KeliHlodversson +*/ + + +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System; +#endregion + + +struct ObjMaterial +{ + public string name; + public string textureName; +} + + +public class GSDObjExporter : ScriptableObject +{ + private static int vertexOffset = 0; + private static int normalOffset = 0; + private static int uvOffset = 0; + + + //User should probably be able to change this. It is currently left as an excercise for + //the reader. + private static string targetFolder = "ExportedObj"; + + + private static string MeshToString(MeshFilter mf, Dictionary materialList) + { + Mesh m = mf.sharedMesh; + Renderer rend = mf.GetComponent(); + //Material[] mats = mf.renderer.sharedMaterials; + Material[] mats = rend.sharedMaterials; + + StringBuilder sb = new StringBuilder(); + + sb.Append("g ").Append(mf.name).Append("\n"); + foreach (Vector3 lv in m.vertices) + { + Vector3 wv = mf.transform.TransformPoint(lv); + + //This is sort of ugly - inverting x-component since we're in + //a different coordinate system than "everyone" is "used to". + sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); + } + sb.Append("\n"); + + foreach (Vector3 lv in m.normals) + { + Vector3 wv = mf.transform.TransformDirection(lv); + + sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); + } + sb.Append("\n"); + + foreach (Vector3 v in m.uv) + { + sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); + } + + for (int material = 0; material < m.subMeshCount; material++) + { + sb.Append("\n"); + sb.Append("usemtl ").Append(mats[material].name).Append("\n"); + sb.Append("usemap ").Append(mats[material].name).Append("\n"); + + //See if this material is already in the materiallist. + try + { + ObjMaterial objMaterial = new ObjMaterial(); + + objMaterial.name = mats[material].name; + + if (mats[material].mainTexture) + objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); + else + objMaterial.textureName = null; + + materialList.Add(objMaterial.name, objMaterial); + } + catch (ArgumentException) + { + //Already in the dictionary + } + + + int[] triangles = m.GetTriangles(material); + for (int index = 0; index < triangles.Length; index += 3) + { + //Because we inverted the x-component, we also needed to alter the triangle winding. + sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", + triangles[index] + 1 + vertexOffset, triangles[index + 1] + 1 + normalOffset, triangles[index + 2] + 1 + uvOffset)); + } + } + + vertexOffset += m.vertices.Length; + normalOffset += m.normals.Length; + uvOffset += m.uv.Length; + + return sb.ToString(); + } + + + private static void Clear() + { + vertexOffset = 0; + normalOffset = 0; + uvOffset = 0; + } + + + private static Dictionary PrepareFileWrite() + { + Clear(); + + return new Dictionary(); + } + + + private static void MaterialsToFile(Dictionary materialList, string folder, string filename) + { + using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".mtl")) + { + foreach (KeyValuePair kvp in materialList) + { + sw.Write("\n"); + sw.Write("newmtl {0}\n", kvp.Key); + sw.Write("Ka 0.6 0.6 0.6\n"); + sw.Write("Kd 0.6 0.6 0.6\n"); + sw.Write("Ks 0.9 0.9 0.9\n"); + sw.Write("d 1.0\n"); + sw.Write("Ns 0.0\n"); + sw.Write("illum 2\n"); + + if (kvp.Value.textureName != null) + { + string destinationFile = kvp.Value.textureName; + + + int stripIndex = destinationFile.LastIndexOf('/');//FIXME: Should be Path.PathSeparator; + + if (stripIndex >= 0) + { + destinationFile = destinationFile.Substring(stripIndex + 1).Trim(); + } + + + string relativeFile = destinationFile; + + destinationFile = folder + "/" + destinationFile; + + // Debug.Log("Copying texture from " + kvp.Value.textureName + " to " + destinationFile); + + try + { + //Copy the source file + File.Copy(kvp.Value.textureName, destinationFile); + } + catch + { + + } + + + sw.Write("map_Kd {0}", relativeFile); + } + + sw.Write("\n\n\n"); + } + } + } + + + private static void MeshToFile(MeshFilter mf, string folder, string filename) + { + Dictionary materialList = PrepareFileWrite(); + + using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")) + { + sw.Write("mtllib ./" + filename + ".mtl\n"); + + sw.Write(MeshToString(mf, materialList)); + } + + MaterialsToFile(materialList, folder, filename); + } + + + private static void MeshesToFile(MeshFilter[] mf, string folder, string filename) + { + Dictionary materialList = PrepareFileWrite(); + + using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")) + { + sw.Write("mtllib ./" + filename + ".mtl\n"); + + for (int index = 0; index < mf.Length; index++) + { + sw.Write(MeshToString(mf[index], materialList)); + } + } + + MaterialsToFile(materialList, folder, filename); + } + + + private static bool CreateTargetFolder() + { + try + { + System.IO.Directory.CreateDirectory(targetFolder); + } + catch + { + EditorUtility.DisplayDialog("Error!", "Failed to create target folder!", ""); + return false; + } + + return true; + } + + + [MenuItem("Window/Road Architect/Export/Export all MeshFilters in selection to separate OBJs")] + static void ExportSelectionToSeparate() + { + if (!CreateTargetFolder()) + { + return; + } + + Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); + + if (selection.Length == 0) + { + EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); + return; + } + + int exportedObjects = 0; + + for (int index = 0; index < selection.Length; index++) + { + Component[] meshfilter = selection[index].GetComponentsInChildren(typeof(MeshFilter)); + + for (int m = 0; m < meshfilter.Length; m++) + { + exportedObjects++; + MeshToFile((MeshFilter) meshfilter[m], targetFolder, selection[index].name + "_" + index + "_" + m); + } + } + + if (exportedObjects > 0) + { + EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects", ""); + } + else + { + EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); + } + } + + + [MenuItem("Window/Road Architect/Export/Export whole selection to single OBJ")] + static void ExportWholeSelectionToSingle() + { + if (!CreateTargetFolder()) + { + return; + } + + + Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); + + if (selection.Length == 0) + { + EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); + return; + } + + int exportedObjects = 0; + + ArrayList mfList = new ArrayList(); + + for (int index = 0; index < selection.Length; index++) + { + Component[] meshfilter = selection[index].GetComponentsInChildren(typeof(MeshFilter)); + + for (int m = 0; m < meshfilter.Length; m++) + { + exportedObjects++; + mfList.Add(meshfilter[m]); + } + } + + if (exportedObjects > 0) + { + MeshFilter[] mf = new MeshFilter[mfList.Count]; + + for (int index = 0; index < mfList.Count; index++) + { + mf[index] = (MeshFilter) mfList[index]; + } + + + string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; + //string filename = EditorApplication.currentScene + "_" + exportedObjects; + string filename = tSceneName + "_" + exportedObjects; + + int stripIndex = filename.LastIndexOf('/');//FIXME: Should be Path.PathSeparator + + if (stripIndex >= 0) + { + filename = filename.Substring(stripIndex + 1).Trim(); + } + + MeshesToFile(mf, targetFolder, filename); + + + EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects to " + filename, ""); + } + else + EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); + } + + + + [MenuItem("Window/Road Architect/Export/Export each selected to single OBJ")] + static void ExportEachSelectionToSingle() + { + if (!CreateTargetFolder()) + { + return; + } + + Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab); + + if (selection.Length == 0) + { + EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", ""); + return; + } + + int exportedObjects = 0; + + + for (int index = 0; index < selection.Length; index++) + { + Component[] meshfilter = selection[index].GetComponentsInChildren(typeof(MeshFilter)); + + MeshFilter[] mf = new MeshFilter[meshfilter.Length]; + + for (int m = 0; m < meshfilter.Length; m++) + { + exportedObjects++; + mf[m] = (MeshFilter) meshfilter[m]; + } + + MeshesToFile(mf, targetFolder, selection[index].name + "_" + index); + } + + if (exportedObjects > 0) + { + EditorUtility.DisplayDialog("Objects exported", "Exported " + exportedObjects + " objects", ""); + } + else + { + EditorUtility.DisplayDialog("Objects not exported", "Make sure at least some of your selected objects have mesh filters!", ""); + } + } + + + [MenuItem("Window/Road Architect/Export/Exporters by Hrafnkell Freyr Hlooversson from Unity3D wiki")] + static void DoNothing1() + { + Application.OpenURL("http://wiki.unity3d.com/index.php?title=ObjExporter"); + } } \ No newline at end of file diff --git a/Editor/GSDRoadEditor.cs b/Editor/GSDRoadEditor.cs index ba148f69..4f85d8f8 100755 --- a/Editor/GSDRoadEditor.cs +++ b/Editor/GSDRoadEditor.cs @@ -1,1445 +1,1522 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -using System.Collections; -using GSD.Roads; -using GSD; -[CustomEditor(typeof(GSDRoad))] -#endregion -public class GSDRoadEditor : Editor -{ - - private static string[] RoadMaterialDropdownEnumDesc = new string[]{ - "Asphalt", - "Dirt", - "Brick", - "Cobblestone" - }; - - - protected GSDRoad RS { get { return (GSDRoad)target; } } - - //Serialized properties: - SerializedProperty t_opt_GizmosEnabled; - SerializedProperty t_opt_Lanes; - SerializedProperty t_opt_LaneWidth; - SerializedProperty t_opt_bShouldersEnabled; - SerializedProperty t_opt_ShoulderWidth; - SerializedProperty t_opt_RoadDefinition; - SerializedProperty t_opt_UseDefaultMaterials; - SerializedProperty t_opt_bMaxGradeEnabled; - SerializedProperty t_opt_MaxGrade; - SerializedProperty t_opt_bMultithreading; - SerializedProperty t_opt_bSaveMeshes; - SerializedProperty t_opt_TerrainSubtract_Match; - SerializedProperty t_opt_MagnitudeThreshold; - SerializedProperty t_opt_HeightModEnabled; - SerializedProperty t_opt_DetailModEnabled; - SerializedProperty t_opt_TreeModEnabled; - SerializedProperty t_opt_MatchHeightsDistance; - SerializedProperty t_opt_ClearDetailsDistance; - SerializedProperty t_opt_ClearDetailsDistanceHeight; - SerializedProperty t_opt_ClearTreesDistance; - SerializedProperty t_opt_ClearTreesDistanceHeight; - SerializedProperty t_opt_SaveTerrainHistoryOnDisk; - SerializedProperty t_opt_bRoadCuts; - SerializedProperty t_opt_bDynamicCuts; - SerializedProperty t_opt_bShoulderCuts; - SerializedProperty t_bEditorCameraRotate; - SerializedProperty t_EditorCameraMetersPerSecond; - SerializedProperty t_opt_bUseMeshColliders; - SerializedProperty t_opt_tRoadMaterialDropdown; - SerializedProperty t_opt_bIsStatic; - SerializedProperty t_opt_bIsLightmapped; - - SerializedProperty t_RoadMaterial1; - SerializedProperty t_RoadMaterial2; - SerializedProperty t_RoadMaterial3; - SerializedProperty t_RoadMaterial4; - SerializedProperty t_RoadMaterialMarker1; - SerializedProperty t_RoadMaterialMarker2; - SerializedProperty t_RoadMaterialMarker3; - SerializedProperty t_RoadMaterialMarker4; - SerializedProperty t_ShoulderMaterial1; - SerializedProperty t_ShoulderMaterial2; - SerializedProperty t_ShoulderMaterial3; - SerializedProperty t_ShoulderMaterial4; - SerializedProperty t_ShoulderMaterialMarker1; - SerializedProperty t_ShoulderMaterialMarker2; - SerializedProperty t_ShoulderMaterialMarker3; - SerializedProperty t_ShoulderMaterialMarker4; - SerializedProperty t_RoadPhysicMaterial; - SerializedProperty t_ShoulderPhysicMaterial; - - //Editor only variables: - string status = "Show help"; - const string tOnlineHelpDesc = "Visit the online manual for the most effective help."; - bool bShowCutsHelp = false; - bool bShowMatsHelp = false; - bool bShowHelpRoad = false; - bool bShowHelpTerrain = false; - bool bShowCameraHelp = false; - GUIStyle GSDLoadButton = null; - bool bResetTH = false; - public enum tempEnum { Two, Four, Six }; - Texture btnRefreshText = null; - Texture btnDeleteText = null; - Texture btnRefreshTextReal = null; - tempEnum LanesEnum = tempEnum.Two; - tempEnum tLanesEnum = tempEnum.Two; - private static string[] tempEnumDescriptions = new string[]{ - "Two", - "Four", - "Six" - }; - GUIStyle WarningLabelStyle; - Texture2D WarningLabelBG; - GUIStyle GSDImageButton = null; - GUIStyle GSDMaybeButton = null; - bool bHasInit = false; - Texture2D LoadBtnBG = null; - Texture2D LoadBtnBGGlow = null; - - //Buffers: - //float TempChangeChecker = 0f; - //bool bMatChange = false; - bool bNeedRoadUpdate = false; - bool bSetDefaultMats = false; - bool bApplyMatsCheck = false; - bool t_bApplyMatsCheck = false; - - private void OnEnable() - { - t_opt_GizmosEnabled = serializedObject.FindProperty("opt_GizmosEnabled"); - t_opt_Lanes = serializedObject.FindProperty("opt_Lanes"); - t_opt_LaneWidth = serializedObject.FindProperty("opt_LaneWidth"); - t_opt_bShouldersEnabled = serializedObject.FindProperty("opt_bShouldersEnabled"); - t_opt_ShoulderWidth = serializedObject.FindProperty("opt_ShoulderWidth"); - t_opt_RoadDefinition = serializedObject.FindProperty("opt_RoadDefinition"); - t_opt_UseDefaultMaterials = serializedObject.FindProperty("opt_UseDefaultMaterials"); - t_opt_bMaxGradeEnabled = serializedObject.FindProperty("opt_bMaxGradeEnabled"); - t_opt_MaxGrade = serializedObject.FindProperty("opt_MaxGrade"); - t_opt_bMultithreading = serializedObject.FindProperty("opt_bMultithreading"); - t_opt_bSaveMeshes = serializedObject.FindProperty("opt_bSaveMeshes"); - t_opt_TerrainSubtract_Match = serializedObject.FindProperty("opt_TerrainSubtract_Match"); - t_opt_MagnitudeThreshold = serializedObject.FindProperty("opt_MagnitudeThreshold"); - t_opt_HeightModEnabled = serializedObject.FindProperty("opt_HeightModEnabled"); - t_opt_DetailModEnabled = serializedObject.FindProperty("opt_DetailModEnabled"); - t_opt_TreeModEnabled = serializedObject.FindProperty("opt_TreeModEnabled"); - t_opt_MatchHeightsDistance = serializedObject.FindProperty("opt_MatchHeightsDistance"); - t_opt_ClearDetailsDistance = serializedObject.FindProperty("opt_ClearDetailsDistance"); - t_opt_ClearDetailsDistanceHeight = serializedObject.FindProperty("opt_ClearDetailsDistanceHeight"); - t_opt_ClearTreesDistance = serializedObject.FindProperty("opt_ClearTreesDistance"); - t_opt_ClearTreesDistanceHeight = serializedObject.FindProperty("opt_ClearTreesDistanceHeight"); - t_opt_SaveTerrainHistoryOnDisk = serializedObject.FindProperty("opt_SaveTerrainHistoryOnDisk"); - t_opt_bRoadCuts = serializedObject.FindProperty("opt_bRoadCuts"); - t_opt_bDynamicCuts = serializedObject.FindProperty("opt_bDynamicCuts"); - t_opt_bShoulderCuts = serializedObject.FindProperty("opt_bShoulderCuts"); - t_bEditorCameraRotate = serializedObject.FindProperty("bEditorCameraRotate"); - t_EditorCameraMetersPerSecond = serializedObject.FindProperty("EditorCameraMetersPerSecond"); - t_opt_bUseMeshColliders = serializedObject.FindProperty("opt_bUseMeshColliders"); - t_opt_tRoadMaterialDropdown = serializedObject.FindProperty("opt_tRoadMaterialDropdown"); - t_opt_bIsStatic = serializedObject.FindProperty("opt_bIsStatic"); - t_opt_bIsLightmapped = serializedObject.FindProperty("opt_bIsLightmapped"); - - t_RoadMaterial1 = serializedObject.FindProperty("RoadMaterial1"); - t_RoadMaterial2 = serializedObject.FindProperty("RoadMaterial2"); - t_RoadMaterial3 = serializedObject.FindProperty("RoadMaterial3"); - t_RoadMaterial4 = serializedObject.FindProperty("RoadMaterial4"); - t_RoadMaterialMarker1 = serializedObject.FindProperty("RoadMaterialMarker1"); - t_RoadMaterialMarker2 = serializedObject.FindProperty("RoadMaterialMarker2"); - t_RoadMaterialMarker3 = serializedObject.FindProperty("RoadMaterialMarker3"); - t_RoadMaterialMarker4 = serializedObject.FindProperty("RoadMaterialMarker4"); - t_ShoulderMaterial1 = serializedObject.FindProperty("ShoulderMaterial1"); - t_ShoulderMaterial2 = serializedObject.FindProperty("ShoulderMaterial2"); - t_ShoulderMaterial3 = serializedObject.FindProperty("ShoulderMaterial3"); - t_ShoulderMaterial4 = serializedObject.FindProperty("ShoulderMaterial4"); - t_ShoulderMaterialMarker1 = serializedObject.FindProperty("ShoulderMaterialMarker1"); - t_ShoulderMaterialMarker2 = serializedObject.FindProperty("ShoulderMaterialMarker2"); - t_ShoulderMaterialMarker3 = serializedObject.FindProperty("ShoulderMaterialMarker3"); - t_ShoulderMaterialMarker4 = serializedObject.FindProperty("ShoulderMaterialMarker4"); - t_RoadPhysicMaterial = serializedObject.FindProperty("RoadPhysicMaterial"); - t_ShoulderPhysicMaterial = serializedObject.FindProperty("ShoulderPhysicMaterial"); - } - - void Init() - { - bHasInit = true; - EditorStyles.label.wordWrap = true; - - if (WarningLabelBG == null) - { - WarningLabelBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/WarningLabelBG.png", typeof(Texture2D)) as Texture2D; - } - if (btnRefreshText == null) - { - btnRefreshText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; - } - if (btnRefreshTextReal == null) - { - btnRefreshTextReal = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh.png", typeof(Texture)) as Texture; - } - if (LoadBtnBG == null) - { - LoadBtnBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBGGlow == null) - { - LoadBtnBGGlow = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; - } - if (btnDeleteText == null) - { - btnDeleteText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; - } - - if (WarningLabelStyle == null) - { - WarningLabelStyle = new GUIStyle(GUI.skin.textArea); - WarningLabelStyle.normal.textColor = Color.red; - WarningLabelStyle.active.textColor = Color.red; - WarningLabelStyle.hover.textColor = Color.red; - WarningLabelStyle.normal.background = WarningLabelBG; - WarningLabelStyle.active.background = WarningLabelBG; - WarningLabelStyle.hover.background = WarningLabelBG; - WarningLabelStyle.padding = new RectOffset(8, 8, 8, 8); - } - - if (GSDImageButton == null) - { - GSDImageButton = new GUIStyle(GUI.skin.button); - GSDImageButton.contentOffset = new Vector2(0f, 0f); - GSDImageButton.border = new RectOffset(0, 0, 0, 0); - GSDImageButton.fixedHeight = 16f; - GSDImageButton.padding = new RectOffset(0, 0, 0, 0); - GSDImageButton.normal.background = null; - } - - if (GSDLoadButton == null) - { - GSDLoadButton = new GUIStyle(GUI.skin.button); - GSDLoadButton.contentOffset = new Vector2(0f, 1f); - GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDLoadButton.normal.background = LoadBtnBG; - GSDLoadButton.active.background = LoadBtnBGGlow; - GSDLoadButton.focused.background = LoadBtnBGGlow; - GSDLoadButton.hover.background = LoadBtnBGGlow; - GSDLoadButton.fixedHeight = 16f; - GSDLoadButton.fixedWidth = 128f; - } - - if (GSDMaybeButton == null) - { - GSDMaybeButton = new GUIStyle(GUI.skin.button); - GSDMaybeButton.normal.textColor = new Color(0f, 0f, 0f, 1f); - } - } - - public override void OnInspectorGUI() - { - if (Event.current.type == EventType.ValidateCommand) - { - switch (Event.current.commandName) - { - case "UndoRedoPerformed": - TriggerRoadUpdate(); - break; - } - } - - serializedObject.Update(); - - bNeedRoadUpdate = false; - bSetDefaultMats = false; - //Graphic null checks: - if (!bHasInit) { Init(); } - - - - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(RS.transform.name, EditorStyles.boldLabel); - if (GUILayout.Button("Update road", GSDLoadButton)) - { - RS.EditorUpdateMe = true; - } - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.LabelField("Hold ctrl and click terrain to add nodes."); - EditorGUILayout.LabelField("Hold shift and click terrain to insert nodes."); - EditorGUILayout.LabelField("Select nodes on spline to add objects."); - EditorGUILayout.LabelField("Road options:"); - - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - //Option: Gizmos input: - t_opt_GizmosEnabled.boolValue = EditorGUILayout.Toggle("Gizmos: ", RS.opt_GizmosEnabled); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - - //Option: Lane count: - if (RS.opt_Lanes == 2) - { - LanesEnum = tempEnum.Two; - } - else if (RS.opt_Lanes == 4) - { - LanesEnum = tempEnum.Four; - } - else - { - LanesEnum = tempEnum.Six; - } - tLanesEnum = (tempEnum)EditorGUILayout.Popup("Lanes: ", (int)LanesEnum, tempEnumDescriptions); - if (tLanesEnum == tempEnum.Two) - { - t_opt_Lanes.intValue = 2; - } - else if (tLanesEnum == tempEnum.Four) - { - t_opt_Lanes.intValue = 4; - } - else if (tLanesEnum == tempEnum.Six) - { - t_opt_Lanes.intValue = 6; - } - - //Option: Lane and road width: - EditorGUILayout.BeginHorizontal(); - t_opt_LaneWidth.floatValue = EditorGUILayout.FloatField("Lane width:", RS.opt_LaneWidth); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_LaneWidth.floatValue = 5f; - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.LabelField("Road width: " + RS.RoadWidth().ToString("F1") + " meters"); - - //Option: Shoulders enabled: - t_opt_bShouldersEnabled.boolValue = EditorGUILayout.Toggle("Shoulders enabled:", RS.opt_bShouldersEnabled); - - //Option: Shoulders width: - if (RS.opt_bShouldersEnabled) - { - EditorGUILayout.BeginHorizontal(); - t_opt_ShoulderWidth.floatValue = EditorGUILayout.FloatField("Shoulders width:", RS.opt_ShoulderWidth); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_ShoulderWidth.floatValue = 3f; - } - EditorGUILayout.EndHorizontal(); - } - - //Option: Road definition: - EditorGUILayout.BeginHorizontal(); - t_opt_RoadDefinition.floatValue = EditorGUILayout.FloatField("Road definition:", RS.opt_RoadDefinition); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_RoadDefinition.floatValue = 5f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Use default materials: - t_opt_UseDefaultMaterials.boolValue = EditorGUILayout.Toggle("Use default materials:", RS.opt_UseDefaultMaterials); - - //Dropdown: - if (RS.opt_UseDefaultMaterials) - { - int Old = (int)RS.opt_tRoadMaterialDropdown; - t_opt_tRoadMaterialDropdown.enumValueIndex = (int)EditorGUILayout.Popup("Road material: ", (int)RS.opt_tRoadMaterialDropdown, RoadMaterialDropdownEnumDesc, GUILayout.Width(250f)); - if (t_opt_tRoadMaterialDropdown.enumValueIndex != Old) - { - if (t_opt_tRoadMaterialDropdown.enumValueIndex > 0) - { - t_opt_bShouldersEnabled.boolValue = false; - } - else - { - t_opt_bShouldersEnabled.boolValue = true; - } - } - } - - //Option: Max grade enabled: - t_opt_bMaxGradeEnabled.boolValue = EditorGUILayout.Toggle("Max grade enforced: ", RS.opt_bMaxGradeEnabled); - - //Option: Max grade value: - if (RS.opt_bMaxGradeEnabled) - { - EditorGUILayout.BeginHorizontal(); - t_opt_MaxGrade.floatValue = EditorGUILayout.Slider("Max road grade: ", RS.opt_MaxGrade, 0f, 1f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_MaxGrade.floatValue = 0.08f; - } - EditorGUILayout.EndHorizontal(); - } - - //Mesh colliders: - if (RS.GSDRS != null) - { - t_opt_bUseMeshColliders.boolValue = EditorGUILayout.Toggle("Use mesh colliders: ", RS.opt_bUseMeshColliders); - } - - //Option: Multi-threading option: workaround for UAS submission rules: - if (RS.GSDRS.opt_bMultithreading != RS.opt_bMultithreading) - { - RS.GSDRS.opt_bMultithreading = RS.opt_bMultithreading; - RS.GSDRS.UpdateAllRoads_MultiThreadOptions(); - } - if (RS.GSDRS != null) - { - t_opt_bMultithreading.boolValue = EditorGUILayout.Toggle("Multithreading: ", RS.GSDRS.opt_bMultithreading); - } - - //Static: - if (RS.GSDRS != null) - { - t_opt_bIsStatic.boolValue = EditorGUILayout.Toggle("Static: ", RS.opt_bIsStatic); - } - - //Used for lightmapping: - if (RS.GSDRS != null) - { - t_opt_bIsLightmapped.boolValue = EditorGUILayout.Toggle("Lightmapped: ", RS.opt_bIsLightmapped); - } - - //Option: Save meshes as unity assets options: - if (RS.GSDRS.opt_bSaveMeshes != RS.opt_bSaveMeshes) - { - RS.GSDRS.opt_bSaveMeshes = RS.opt_bSaveMeshes; - RS.GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); - } - if (RS.GSDRS != null) - { - t_opt_bSaveMeshes.boolValue = EditorGUILayout.Toggle("Save mesh assets: ", RS.GSDRS.opt_bSaveMeshes); - } - if (RS.GSDRS.opt_bSaveMeshes) - { - GUILayout.Label("WARNING: Saving meshes as assets is very slow and can increase road generation time by several minutes.", WarningLabelStyle); - } - - if (GUILayout.Button("Duplicate road", EditorStyles.miniButton, GUILayout.Width(120f))) - { - RS.DuplicateRoad(); - } - - - bShowHelpRoad = EditorGUILayout.Foldout(bShowHelpRoad, status); - if (bShowHelpRoad) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Road options quick help:", EditorStyles.boldLabel); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); - - GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Gizmos:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Enable or disable most gizmos for this road. Disable mesh collider gizmos via the unity menu if necessary or desired.", EditorStyles.miniLabel); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Lanes:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Select the number of lanes for this road."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Lane width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Modify the width per lane, in meters."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Road width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Displays the road width without considering shoulders, in meters."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Shoulders enabled:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Enables or disables shoulders."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Shoulders width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Modify the width of shoulders, in meters."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Road definition: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The meter spacing between mesh triangles on the road and shoulder."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Use default materials: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("When enabled will use default materials for the road system, allowing certain aspects of generation to automatically determine the correct materials to utilize."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Max grade enforced: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("When enabled enforces a maximum grade on a per node basis."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Max road grade: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The maximum road grade allowed on a per node basis."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Multithreading:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("When enabled allows for multi-threaded road generation."); - EditorGUILayout.EndVertical(); GUILayout.Space(4f); EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Save mesh assets:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("When enabled saves all generated meshes as .asset files."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - EditorGUILayout.EndVertical(); - - EditorGUILayout.LabelField("Terrain options:"); - EditorGUILayout.BeginVertical("box"); - - //Option: Terrain subtraction: - EditorGUILayout.BeginHorizontal(); - t_opt_TerrainSubtract_Match.floatValue = EditorGUILayout.Slider("Terrain subtraction: ", RS.opt_TerrainSubtract_Match, 0.01f, 1f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_TerrainSubtract_Match.floatValue = 0.01f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Spline magnitude limit: - EditorGUILayout.BeginHorizontal(); - t_opt_MagnitudeThreshold.floatValue = EditorGUILayout.Slider("Spline magnitude limit: ", RS.opt_MagnitudeThreshold, 128f, 8192f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_MagnitudeThreshold.floatValue = 300f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Height modification - t_opt_HeightModEnabled.boolValue = EditorGUILayout.Toggle("Height modification: ", RS.opt_HeightModEnabled); - - //Option: Active detail removal - t_opt_DetailModEnabled.boolValue = EditorGUILayout.Toggle("Active detail removal: ", RS.opt_DetailModEnabled); - - //Option: Active tree removal - t_opt_TreeModEnabled.boolValue = EditorGUILayout.Toggle("Active tree removal: ", RS.opt_TreeModEnabled); - - //Option: heights width - if (RS.opt_HeightModEnabled) - { - EditorGUILayout.BeginHorizontal(); - t_opt_MatchHeightsDistance.floatValue = EditorGUILayout.Slider("Heights match width: ", RS.opt_MatchHeightsDistance, 0.01f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_MatchHeightsDistance.floatValue = 50f; - } - EditorGUILayout.EndHorizontal(); - } - - //Option: details width and height - if (RS.opt_DetailModEnabled) - { - EditorGUILayout.BeginHorizontal(); - t_opt_ClearDetailsDistance.floatValue = EditorGUILayout.Slider("Details clear width: ", RS.opt_ClearDetailsDistance, 0.01f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_ClearDetailsDistance.floatValue = 30f; - } - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - t_opt_ClearDetailsDistanceHeight.floatValue = EditorGUILayout.Slider("Details clear height: ", RS.opt_ClearDetailsDistanceHeight, 0.01f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_ClearDetailsDistanceHeight.floatValue = 5f; - } - - EditorGUILayout.EndHorizontal(); - } - - //Option: tree widths and height - if (RS.opt_TreeModEnabled) - { - EditorGUILayout.BeginHorizontal(); - t_opt_ClearTreesDistance.floatValue = EditorGUILayout.Slider("Trees clear width: ", RS.opt_ClearTreesDistance, 0.01f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_ClearTreesDistance.floatValue = 30f; - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - t_opt_ClearTreesDistanceHeight.floatValue = EditorGUILayout.Slider("Trees clear height: ", RS.opt_ClearTreesDistanceHeight, 0.01f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_ClearTreesDistanceHeight.floatValue = 50f; - } - EditorGUILayout.EndHorizontal(); - } - - - //Option: terrain history save type: - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Store terrain history separate from scene:"); - t_opt_SaveTerrainHistoryOnDisk.boolValue = EditorGUILayout.Toggle(RS.opt_SaveTerrainHistoryOnDisk, GUILayout.Width(50f)); - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.LabelField("Terrain history size: " + RS.TerrainHistoryByteSize); - - bShowHelpTerrain = EditorGUILayout.Foldout(bShowHelpTerrain, status); - if (bShowHelpTerrain) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Terrain options quick help:", EditorStyles.boldLabel); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); - EditorGUILayout.LabelField("Terrain subtraction: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("This value, in meters, will be subtracted from the terrain match height to prevent z-fighting."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Spline magnitude limit: ", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Limits the magnitude of the spline nodes. Lower limit is better for typical roads with node seperation of around 100 to 300 meters. Higher limits will allow for less tension when using very spread out nodes."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Height Modification:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Enables or disables height matching for the terrain."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Active detail removal:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Enables or disables active detail removal. Memory intensive on large terrains with large amounts of details. Recommended to not use this option and instead remove details and trees via splat maps with other addons."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Active tree removal:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Enables or disables active tree removal. Memory intensive on large terrains with large amounts of trees. Recommended to not use this option and instead remove details and trees via splat maps with other addons."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Heights match width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The distance to the left and right of the road in which terrain heights will be matched to the road."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Details clear width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The distance between the road and detail, width wise, in which details will be removed."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Details clear height:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The distance between the road and detail, height wise, in which details will be removed."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Tree clear width:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The distance between the road and tree, width wise, in which trees will be removed."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Tree clear height:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("The distance between the road and tree, height wise, in which trees will be removed."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Store terrain history separate from scene:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("If enabled, stores the terrain history immediately on disk after use, saving memory while in editor."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Terrain history size:", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Shows the size, in kilobytes, of the terrain history in memory or on disk."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - } - EditorGUILayout.EndVertical(); - - - - GUILayout.Label("Road and shoulder splitting:"); - EditorGUILayout.BeginVertical("box"); - GUILayout.Space(4f); - - //Option: road cuts: - if (!RS.opt_bDynamicCuts) - { - EditorGUILayout.BeginHorizontal(); - t_opt_bRoadCuts.boolValue = EditorGUILayout.Toggle("Auto split road: ", RS.opt_bRoadCuts); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_bDynamicCuts.boolValue = false; - t_opt_bRoadCuts.boolValue = true; - t_opt_bShoulderCuts.boolValue = true; - } - EditorGUILayout.EndHorizontal(); - - if (RS.opt_bShouldersEnabled) - { - t_opt_bShoulderCuts.boolValue = EditorGUILayout.Toggle("Auto split shoulders: ", RS.opt_bShoulderCuts); - } - } - else - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Manual road splitting: true"); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_opt_bDynamicCuts.boolValue = false; - t_opt_bRoadCuts.boolValue = true; - t_opt_bShoulderCuts.boolValue = true; - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.LabelField("Manual shoulder splitting: true"); - } - t_opt_bDynamicCuts.boolValue = EditorGUILayout.Toggle("Manual splitting: ", RS.opt_bDynamicCuts); - - - bShowCutsHelp = EditorGUILayout.Foldout(bShowCutsHelp, status); - if (bShowCutsHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Road splitting quick help:", EditorStyles.boldLabel); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); - - EditorGUILayout.LabelField("Typically auto-split will be the best choice for performance and other reasons."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Choosing split options will split the road/shoulder up into pieces mirroring the locations of nodes."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Splitting allows for more detailed and flexible road texturing options such as passing sections, other different road lines per section, road debris and more."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Choosing split options may also speed up mesh collider collision calculations if bounds calculations are involved."); - GUILayout.Space(4f); - - EditorGUILayout.LabelField("Which splitting option to choose?", EditorStyles.boldLabel); - EditorGUILayout.LabelField("Choose no splitting if you desire a single material set for this entire road and your game experiences no collison processing slowdowns from one large mesh collider. This option will create less game objects than automatic and manual splitting."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Choose automatic road and shoulder splitting if you desire multiple materials (such as yellow double lines for certain sections and white dotted for others) for this road and or your game experiences collision processing slowdowns from one large mesh collider."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Choose manual road and shoulder splitting if you desire the same as automatic splitting and desire more freedom over the process. This option will result in less gameobjects and larger mesh colliders when compared to automatic splitting."); - GUILayout.Space(4f); - - - Line(); - EditorGUILayout.LabelField("Manual splitting information: "); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Choosing manual splitting will force the user to select individual nodes to cut instead of the cuts being performed automatically. This option is recommended if bigger mesh colliders do not cause a slowdown in performance, as it lowers the overall gameobject count."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Manual splitting will not split up the mesh colliders like automatic cuts, so the colliders may get large & complex and cost more CPU to process collisions. If this option is chosen, please verify your game's collision processing speed and if you run into long collision processing times split more road sections"); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Example usages of manual splitting"); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Example hill: Goal is to have double yellow no passing lines on a two lane road but only while the road is near or on the hill. " + - "Pick nodes on either sides of the hill and mark both as road cut. Everything between these two nodes will be its own section, " + - "allowing you to apply double yellow no passing lines for just the hill."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Example mountains: In the mountains, the road is curvy and the grade is high. " + - "There's a flat straight spot that you want to allow passing in, by marking the road with white dotted passing lines. " + - "At the beginning of the flat straight section, mark the node as road cut. Now at the end of the flat straight section, mark this node as road cut. " + - "This will create a road section between the two nodes, allowing you to apply white dotted passing lines for just the flat straight section."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - else - { - GUILayout.Space(4f); - } - EditorGUILayout.EndVertical(); - - - //Camera: - EditorGUILayout.LabelField("Editor camera travel:"); - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - - //Option: Editor camera meters per sec - t_EditorCameraMetersPerSecond.floatValue = EditorGUILayout.Slider("Camera meters/sec:", RS.EditorCameraMetersPerSecond, 1f, 512f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_EditorCameraMetersPerSecond.floatValue = 60f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Editor camera auto rotate: - t_bEditorCameraRotate.boolValue = EditorGUILayout.Toggle("Camera auto rotate: ", RS.bEditorCameraRotate); - if (RS.EditorPlayCamera == null) - { - RS.EditorCameraSetSingle(); - } - RS.EditorPlayCamera = (Camera)EditorGUILayout.ObjectField("Editor play camera:", RS.EditorPlayCamera, typeof(Camera), true); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Reset", GUILayout.Width(70f))) - { - RS.QuitEditorCamera(); - RS.DoEditorCameraLoop(); - } - if (GUILayout.Button("<<", GUILayout.Width(40f))) - { - RS.EditorCameraPos -= 0.1f; - RS.DoEditorCameraLoop(); - } - if (RS.bEditorCameraMoving == true) - { - if (GUILayout.Button("Pause", GUILayout.Width(70f))) - { - RS.bEditorCameraMoving = false; - } - } - else - { - if (GUILayout.Button("Play", GUILayout.Width(70f))) - { - RS.bEditorCameraMoving = true; - } - } - if (GUILayout.Button(">>", GUILayout.Width(40f))) - { - RS.EditorCameraPos += 0.1f; - RS.DoEditorCameraLoop(); - } - EditorGUILayout.EndHorizontal(); - - GUILayout.Space(4); - bShowCameraHelp = EditorGUILayout.Foldout(bShowCameraHelp, status); - if (bShowCameraHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Editor camera quick help:", EditorStyles.boldLabel); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); - EditorGUILayout.LabelField("Use this section to travel along the road while in the editor sceneview."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Camera meters/sec is the speed at which the camera moves along the road."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Auto rotate will automatically rotate the camera to look forward at the current road's tangent. Note: You can still zoom in and out with the camera with this option selected."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Note: Materials act differently in the editor scene view compared to actual gameplay. Try the game camera if the materials are z fighting and having other issues."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - EditorGUILayout.EndVertical(); - - GUILayout.Label("Materials:"); - EditorGUILayout.BeginVertical("box"); - //Road material defaults: - - EditorGUILayout.BeginHorizontal(); - GUILayout.Label("Road base material(s) defaults:"); - //Option: Set mats to defaults: - bSetDefaultMats = false; - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - bSetDefaultMats = true; - } - EditorGUILayout.EndHorizontal(); - // EditorGUILayout.PropertyField (t_RoadMaterial1, new GUIContent (" Mat #1: ")); - // if(RS.RoadMaterial1 != null){ EditorGUILayout.PropertyField (t_RoadMaterial2, new GUIContent (" Mat #2: ")); } - // if(RS.RoadMaterial2 != null){EditorGUILayout.PropertyField (t_RoadMaterial3, new GUIContent (" Mat #3: ")); } - // if(RS.RoadMaterial3 != null){EditorGUILayout.PropertyField (t_RoadMaterial4, new GUIContent (" Mat #4: ")); } - - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterial1, new GUIContent(" Mat #1: ")); - if (RS.RoadMaterial1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterial1 = null; } - EditorGUILayout.EndHorizontal(); - if (RS.RoadMaterial1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterial2, new GUIContent(" Mat #2: ")); - if (RS.RoadMaterial2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterial2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.RoadMaterial1 != null && RS.RoadMaterial2 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterial3, new GUIContent(" Mat #3: ")); - if (RS.RoadMaterial3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterial3 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.RoadMaterial1 != null && RS.RoadMaterial2 != null && RS.RoadMaterial3 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterial4, new GUIContent(" Mat #4: ")); - if (RS.RoadMaterial4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterial4 = null; } - EditorGUILayout.EndHorizontal(); - } - - - - - - - // //Road marker material defaults: - GUILayout.Label("Road marker material(s) defaults:"); - // EditorGUILayout.PropertyField (t_RoadMaterialMarker1, new GUIContent (" Mat #1: ")); - // if(RS.RoadMaterialMarker1 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker2, new GUIContent (" Mat #2: ")); } - // if(RS.RoadMaterialMarker2 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker3, new GUIContent (" Mat #3: ")); } - // if(RS.RoadMaterialMarker3 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker4, new GUIContent (" Mat #4: ")); } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterialMarker1, new GUIContent(" Mat #1: ")); - if (RS.RoadMaterialMarker1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterialMarker1 = null; } - EditorGUILayout.EndHorizontal(); - if (RS.RoadMaterialMarker1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterialMarker2, new GUIContent(" Mat #2: ")); - if (RS.RoadMaterialMarker2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterialMarker2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.RoadMaterialMarker1 != null && RS.RoadMaterialMarker2 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterialMarker3, new GUIContent(" Mat #3: ")); - if (RS.RoadMaterialMarker3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterialMarker3 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.RoadMaterialMarker1 != null && RS.RoadMaterialMarker2 != null && RS.RoadMaterialMarker3 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_RoadMaterialMarker4, new GUIContent(" Mat #4: ")); - if (RS.RoadMaterialMarker4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.RoadMaterialMarker4 = null; } - EditorGUILayout.EndHorizontal(); - } - - - - - // //Shoulder material defaults: - if (RS.opt_bShouldersEnabled) - { - GUILayout.Label("Shoulder base material(s) defaults:"); - // EditorGUILayout.PropertyField (t_ShoulderMaterial1, new GUIContent (" Mat #1: ")); - // if(RS.ShoulderMaterial1 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial2, new GUIContent (" Mat #2: ")); } - // if(RS.ShoulderMaterial2 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial3, new GUIContent (" Mat #3: ")); } - // if(RS.ShoulderMaterial3 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial4, new GUIContent (" Mat #4: ")); } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterial1, new GUIContent(" Mat #1: ")); - if (RS.ShoulderMaterial1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterial1 = null; } - EditorGUILayout.EndHorizontal(); - if (RS.ShoulderMaterial1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterial2, new GUIContent(" Mat #2: ")); - if (RS.ShoulderMaterial2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterial2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.ShoulderMaterial1 != null && RS.ShoulderMaterial2 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterial3, new GUIContent(" Mat #3: ")); - if (RS.ShoulderMaterial3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterial3 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.ShoulderMaterial1 != null && RS.ShoulderMaterial2 != null && RS.ShoulderMaterial3 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterial4, new GUIContent(" Mat #4: ")); - if (RS.ShoulderMaterial4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterial4 = null; } - EditorGUILayout.EndHorizontal(); - } - } - - - - - // //Shoulder marker material defaults: - if (RS.opt_bShouldersEnabled) - { - GUILayout.Label("Shoulder marker material(s) defaults:"); - // EditorGUILayout.PropertyField (t_ShoulderMaterialMarker1, new GUIContent (" Mat #1: ")); - // if(RS.ShoulderMaterialMarker1 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker2, new GUIContent (" Mat #2: ")); } - // if(RS.ShoulderMaterialMarker2 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker3, new GUIContent (" Mat #3: ")); } - // if(RS.ShoulderMaterialMarker3 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker4, new GUIContent (" Mat #4: ")); } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterialMarker1, new GUIContent(" Mat #1: ")); - if (RS.ShoulderMaterialMarker1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterialMarker1 = null; } - EditorGUILayout.EndHorizontal(); - if (RS.ShoulderMaterialMarker1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterialMarker2, new GUIContent(" Mat #2: ")); - if (RS.ShoulderMaterialMarker2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterialMarker2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.ShoulderMaterialMarker1 != null && RS.ShoulderMaterialMarker2 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterialMarker3, new GUIContent(" Mat #3: ")); - if (RS.ShoulderMaterialMarker3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterialMarker3 = null; } - EditorGUILayout.EndHorizontal(); - } - if (RS.ShoulderMaterialMarker1 != null && RS.ShoulderMaterialMarker2 != null && RS.ShoulderMaterialMarker3 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_ShoulderMaterialMarker4, new GUIContent(" Mat #4: ")); - if (RS.ShoulderMaterialMarker4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { RS.ShoulderMaterialMarker4 = null; } - EditorGUILayout.EndHorizontal(); - } - } - - - - //Physics materials: - GUILayout.Label("Physics materials defaults:"); - //Option: physical road mat: - // t_RoadPhysicMaterial.serializedObject = (PhysicMaterial)EditorGUILayout.ObjectField(" Road mat: ",RS.RoadPhysicMaterial,typeof(PhysicMaterial),false); - EditorGUILayout.PropertyField(t_RoadPhysicMaterial, new GUIContent("Road phys mat: ")); - - - //Option: physical shoulder mat: - // t_ShoulderPhysicMaterial.serializedObject = (PhysicMaterial)EditorGUILayout.ObjectField(" Shoulder mat: ",RS.ShoulderPhysicMaterial,typeof(PhysicMaterial),false); - EditorGUILayout.PropertyField(t_ShoulderPhysicMaterial, new GUIContent("Shoulder phys mat: ")); - - - GUILayout.Space(4); - EditorGUILayout.BeginHorizontal(); - //Option: Apply above materials to entire road: - EditorGUILayout.LabelField("Apply above materials to entire road:"); - bApplyMatsCheck = EditorGUILayout.Toggle(bApplyMatsCheck, GUILayout.Width(20f)); - if (GUILayout.Button("Apply", EditorStyles.miniButton, GUILayout.Width(60f))) - { - if (bApplyMatsCheck) - { - t_bApplyMatsCheck = true; - } - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.LabelField("Applying will overwrite any saved cuts' material(s)."); - - //Help toggle for materials - GUILayout.Space(4); - bShowMatsHelp = EditorGUILayout.Foldout(bShowMatsHelp, status); - if (bShowMatsHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("These default materials will be applied by default to their respective generated meshes. If using split roads and or shoulders, you can specific specific materials to use on them (on the mesh renderers of the cuts) and they will be used instead of the default materials listed above."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Road base material is UV mapped on a world vector basis for seamless tiles."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Road marker material is UV mapped to fit roads. Use these materials to place road lines and other road texture details. Note: if using road cuts, these are the materials which will be placed by default at the initial generation."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Shoulder base material is UV mapped on a world vector basis for seamless tiles."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Shoulder marker material is UV mapped on a world vector basis for seamless tiles. For intended use with transparent shadow receiving shaders. Marker materials are applied, optionally, on shoulder cuts."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("The physical material for road will be used on all road colliders. The physical material for shoulder will be used on all shoulder colliders. If using road and or shoulder cuts, you can specficy unique physics materials which will be used instead of the default physics materials."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Apply above materials button will clear all saved materials on the roads and all road and shoulder meshes will use the materials listed above."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - EditorGUILayout.EndVertical(); - - //Reset terrain history: - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Reset road's terrain history:"); - bResetTH = EditorGUILayout.Toggle(bResetTH, GUILayout.Width(20f)); - if (bResetTH) - { - if (GUILayout.Button("Reset") && bResetTH) - { - RS.ConstructRoad_ResetTerrainHistory(); - bResetTH = false; - } - } - else - { - if (GUILayout.Button("Check to reset", GSDMaybeButton) && bResetTH) - { - RS.ConstructRoad_ResetTerrainHistory(); - bResetTH = false; - } - } - EditorGUILayout.EndHorizontal(); - - if (bResetTH) - { - EditorGUILayout.LabelField("WARNING: This option can't be undone! Only reset the terrain history if you have changed terrain resolution data such as heightmap or detail resolutions. A rare event may occur when editing and compiling this addon's scripts that a terrain history reset may be necessary. Treat this reset as a last resort.", WarningLabelStyle); - } - GUILayout.Space(6f); - - - EditorGUILayout.LabelField("Statistics:"); - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Length: " + RS.GSDSpline.distance.ToString("F1") + " meters"); - EditorGUILayout.LabelField("Total nodes: " + RS.MostRecentNodeCount.ToString()); - EditorGUILayout.EndVertical(); - - bool bGizmoChange = false; - bool bLaneChange = false; - bool bMultithreadChange = false; - bool bSaveMeshChange = false; - bool bTerrainHistoryChange = false; - bool bEditorCameraSpeedChange = false; - - if (GUI.changed) - { - //Option pre-handle: Gizmos: - if (t_opt_GizmosEnabled.boolValue != RS.opt_GizmosEnabled) - { - bGizmoChange = true; - RS.Wireframes_Toggle(); - SceneView.RepaintAll(); - } - //Option pre-handle: Lane count: - if (t_opt_Lanes.intValue != RS.opt_Lanes) - { - bNeedRoadUpdate = true; - bLaneChange = true; - } - - //Option pre-handle for multithread and save mesh: - if (RS.GSDRS != null) - { - if (t_opt_bMultithreading.boolValue != RS.GSDRS.opt_bMultithreading) - { - RS.GSDRS.opt_bMultithreading = t_opt_bMultithreading.boolValue; - bMultithreadChange = true; - } - if (t_opt_bSaveMeshes.boolValue != RS.GSDRS.opt_bSaveMeshes) - { - RS.GSDRS.opt_bSaveMeshes = t_opt_bSaveMeshes.boolValue; - bSaveMeshChange = true; - } - } - - //Option pre-handle for terrain history: - if (t_opt_SaveTerrainHistoryOnDisk.boolValue != RS.opt_SaveTerrainHistoryOnDisk) - { - bTerrainHistoryChange = true; - } - - //Option pre-handle for editor camera speed: - if (!GSDRootUtil.IsApproximately(t_EditorCameraMetersPerSecond.floatValue, RS.EditorCameraMetersPerSecond, 0.001f)) - { - bEditorCameraSpeedChange = true; - } - - //Apply serialization: - serializedObject.ApplyModifiedProperties(); - - - //Handle after effects: - if (bGizmoChange) - { - RS.Wireframes_Toggle(); - SceneView.RepaintAll(); - } - - - //Option: Lane count: - if (bLaneChange) - { - if (RS.opt_UseDefaultMaterials) - { - RS.GSDSpline.ClearAllRoadCuts(); - RS.SetDefaultMats(); - RS.SetAllCutsToCurrentMaterials(); - } - } - - //Option: Multithreading - if (bMultithreadChange) - { - RS.GSDRS.UpdateAllRoads_MultiThreadOptions(); - } - - //Option: Save meshes as unity assets options: - if (bSaveMeshChange) - { - RS.GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); - } - - //Option: terrain history save type: - if (bTerrainHistoryChange) - { - if (RS.opt_SaveTerrainHistoryOnDisk) - { - RS.ConstructRoad_StoreTerrainHistory(true); - } - else - { - RS.ConstructRoad_LoadTerrainHistory(true); - } - } - - //Option: Editor camera meters per sec - if (bEditorCameraSpeedChange) - { - RS.ChangeEditorCameraMetersPerSec(); - } - - //Update road: - if (bNeedRoadUpdate) - { - RS.GSDSpline.Setup_Trigger(); - } - - //Option: Set mats to defaults: - if (bSetDefaultMats) - { - RS.SetDefaultMats(); - RS.SetAllCutsToCurrentMaterials(); - } - - //Option: Apply above materials to entire road: - if (t_bApplyMatsCheck) - { - t_bApplyMatsCheck = false; - bApplyMatsCheck = false; - RS.SetAllCutsToCurrentMaterials(); - } - - EditorUtility.SetDirty(target); - } - } - - public void OnSceneGUI() - { - Event current = Event.current; - int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - - if (current.alt == true) { return; } - - if (Selection.Contains(RS.transform.gameObject) && Selection.objects.Length > 1) - { - SetSelectionToRoad(); - } - - // Handle Ctrl and Shift when road is selected - if (Selection.activeGameObject == RS.transform.gameObject) - { - RS.Editor_bSelected = true; - // Only handle MouseMove and MouseDrag events - if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag) - { - if (current.control) - { - Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); - RaycastHit hitInfo; - if (Physics.Raycast(worldRay, out hitInfo)) - { - /* There used to be a check for whether this was a terrain */ - RS.Editor_MousePos = hitInfo.point; - RS.Editor_MouseTerrainHit = true; - if (RS.GSDSpline && RS.GSDSpline.PreviewSpline) - { - //Debug.Log("Drawing new node"); - if (RS.GSDSpline.PreviewSpline.mNodes == null || RS.GSDSpline.PreviewSpline.mNodes.Count < 1) { RS.GSDSpline.Setup(); } - RS.GSDSpline.PreviewSpline.MousePos = hitInfo.point; - RS.GSDSpline.PreviewSpline.bGizmoDraw = true; - SceneView.RepaintAll(); - } - } - - GUI.changed = true; - } - else if (current.shift) - { - Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); - RaycastHit hitInfo; - if (Physics.Raycast(worldRay, out hitInfo)) - { - /* Used to check for terrain */ - // if(hitInfo.collider.transform.name.ToLower().Contains("terrain")){ - RS.Editor_MousePos = hitInfo.point; - RS.Editor_MouseTerrainHit = true; - if (RS.GSDSpline && RS.GSDSpline.PreviewSplineInsert) - { - if (RS.GSDSpline.PreviewSplineInsert.mNodes == null || RS.GSDSpline.PreviewSplineInsert.mNodes.Count < 1) { RS.GSDSpline.PreviewSplineInsert.DetermineInsertNodes(); } - RS.GSDSpline.PreviewSplineInsert.MousePos = hitInfo.point; - RS.GSDSpline.PreviewSplineInsert.bGizmoDraw = true; - RS.GSDSpline.PreviewSplineInsert.UpdateActionNode(); - SceneView.RepaintAll(); - } - //}else{ - // RS.Editor_MouseTerrainHit = false; - //} - } - - GUI.changed = true; - } - else - { - if (RS.Editor_MouseTerrainHit) { RS.Editor_MouseTerrainHit = false; GUI.changed = true; } - if (RS.GSDSpline && RS.GSDSpline.PreviewSpline) - { - //Debug.Log("not drawing new node"); - RS.GSDSpline.PreviewSpline.bGizmoDraw = false; - } - if (RS.GSDSpline && RS.GSDSpline.PreviewSplineInsert) - { - //Debug.Log("not drawing insert node"); - RS.GSDSpline.PreviewSplineInsert.bGizmoDraw = false; - } - } - } - } - else - { - RS.Editor_bSelected = false; - if (RS.GSDSpline.PreviewSpline) - { - RS.GSDSpline.PreviewSpline.bGizmoDraw = false; - } - } - - - - if (current.shift && RS.GSDSpline.PreviewSpline != null) { RS.GSDSpline.PreviewSpline.bGizmoDraw = false; } - bool bUsed = false; - if (current.control) - { - if (Event.current.type == EventType.MouseDown) - { - //Left click: - if (Event.current.button == 0) - { - if (RS.Editor_MouseTerrainHit) - { - // if((EditorApplication.timeSinceStartup - RS.GSDSpline.EditorOnly_LastNode_TimeSinceStartup) > 0.05){ - // RS.GSDSpline.EditorOnly_LastNode_TimeSinceStartup = EditorApplication.timeSinceStartup; - Event.current.Use(); - GSDConstruction.CreateNode(RS); - bUsed = true; - // } - } - else - { - Debug.Log("Invalid surface for new node. Must be terrain."); - } - } - } - } - else if (current.shift) - { - if (Event.current.type == EventType.MouseDown) - { - //Left click: - if (Event.current.button == 0) - { - if (RS.Editor_MouseTerrainHit) - { - Event.current.Use(); - GSDConstruction.InsertNode(RS); - bUsed = true; - } - else - { - Debug.Log("Invalid surface for insertion node. Must be terrain."); - } - } - } - } - - - if (current.type == EventType.ValidateCommand) - { - switch (current.commandName) - { - case "UndoRedoPerformed": - TriggerRoadUpdate(); - break; - } - } - - if (Selection.activeGameObject == RS.transform.gameObject) - { - if (current.keyCode == KeyCode.F5) - { - TriggerRoadUpdate(); - } - } - - - - if (bUsed) - { - SetSelectionToRoad(); - switch (current.type) - { - case EventType.Layout: - HandleUtility.AddDefaultControl(controlID); - break; - } - } - - if (GUI.changed) - { - EditorUtility.SetDirty(RS); - } - } - - - private void TriggerRoadUpdate() - { - if (RS != null) - { - RS.EditorUpdateMe = true; - } - } - - void SetSelectionToRoad() - { - GameObject[] tObjs = new GameObject[1]; - tObjs[0] = RS.transform.gameObject; - Selection.objects = tObjs; - } - - #region "Progress bar" - /// - /// Creates progress bar. - /// - /// - /// Value of the progress bar. - /// - /// - /// Label of the progress bar. - /// - void GSDProgressBar(float tV, string tL) - { - // Get a rect for the progress bar using the same margins as a textfield: - Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField"); - EditorGUI.ProgressBar(rect, tV, tL); - EditorGUILayout.Space(); - } - #endregion - - void Line() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar - GUILayout.Space(4f); - } - - void LineSmall() - { - GUILayout.Space(1f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar - GUILayout.Space(1f); - } - - -} +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections; +using GSD.Roads; +using GSD; +#endregion + + +[CustomEditor(typeof(GSDRoad))] +public class GSDRoadEditor : Editor +{ + + private static string[] RoadMaterialDropdownEnumDesc = new string[]{ + "Asphalt", + "Dirt", + "Brick", + "Cobblestone" + }; + + + protected GSDRoad RS { get { return (GSDRoad) target; } } + + //Serialized properties: + SerializedProperty t_opt_GizmosEnabled; + SerializedProperty t_opt_Lanes; + SerializedProperty t_opt_LaneWidth; + SerializedProperty t_opt_bShouldersEnabled; + SerializedProperty t_opt_ShoulderWidth; + SerializedProperty t_opt_RoadDefinition; + SerializedProperty t_opt_UseDefaultMaterials; + SerializedProperty t_opt_bMaxGradeEnabled; + SerializedProperty t_opt_MaxGrade; + SerializedProperty t_opt_bMultithreading; + SerializedProperty t_opt_bSaveMeshes; + SerializedProperty t_opt_TerrainSubtract_Match; + SerializedProperty t_opt_MagnitudeThreshold; + SerializedProperty t_opt_HeightModEnabled; + SerializedProperty t_opt_DetailModEnabled; + SerializedProperty t_opt_TreeModEnabled; + SerializedProperty t_opt_MatchHeightsDistance; + SerializedProperty t_opt_ClearDetailsDistance; + SerializedProperty t_opt_ClearDetailsDistanceHeight; + SerializedProperty t_opt_ClearTreesDistance; + SerializedProperty t_opt_ClearTreesDistanceHeight; + SerializedProperty t_opt_SaveTerrainHistoryOnDisk; + SerializedProperty t_opt_bRoadCuts; + SerializedProperty t_opt_bDynamicCuts; + SerializedProperty t_opt_bShoulderCuts; + SerializedProperty t_bEditorCameraRotate; + SerializedProperty t_EditorCameraMetersPerSecond; + SerializedProperty t_opt_bUseMeshColliders; + SerializedProperty t_opt_tRoadMaterialDropdown; + SerializedProperty t_opt_bIsStatic; + SerializedProperty t_opt_bIsLightmapped; + + SerializedProperty t_RoadMaterial1; + SerializedProperty t_RoadMaterial2; + SerializedProperty t_RoadMaterial3; + SerializedProperty t_RoadMaterial4; + SerializedProperty t_RoadMaterialMarker1; + SerializedProperty t_RoadMaterialMarker2; + SerializedProperty t_RoadMaterialMarker3; + SerializedProperty t_RoadMaterialMarker4; + SerializedProperty t_ShoulderMaterial1; + SerializedProperty t_ShoulderMaterial2; + SerializedProperty t_ShoulderMaterial3; + SerializedProperty t_ShoulderMaterial4; + SerializedProperty t_ShoulderMaterialMarker1; + SerializedProperty t_ShoulderMaterialMarker2; + SerializedProperty t_ShoulderMaterialMarker3; + SerializedProperty t_ShoulderMaterialMarker4; + SerializedProperty t_RoadPhysicMaterial; + SerializedProperty t_ShoulderPhysicMaterial; + + //Editor only variables: + string status = "Show help"; + const string tOnlineHelpDesc = "Visit the online manual for the most effective help."; + bool bShowCutsHelp = false; + bool bShowMatsHelp = false; + bool bShowHelpRoad = false; + bool bShowHelpTerrain = false; + bool bShowCameraHelp = false; + GUIStyle GSDLoadButton = null; + bool bResetTH = false; + public enum tempEnum { Two, Four, Six }; + Texture btnRefreshText = null; + Texture btnDeleteText = null; + Texture btnRefreshTextReal = null; + tempEnum LanesEnum = tempEnum.Two; + tempEnum tLanesEnum = tempEnum.Two; + + private static string[] tempEnumDescriptions = new string[]{ + "Two", + "Four", + "Six" + }; + + GUIStyle WarningLabelStyle; + Texture2D WarningLabelBG; + GUIStyle GSDImageButton = null; + GUIStyle GSDMaybeButton = null; + bool bHasInit = false; + Texture2D LoadBtnBG = null; + Texture2D LoadBtnBGGlow = null; + + //Buffers: + //float TempChangeChecker = 0f; + //bool bMatChange = false; + bool bNeedRoadUpdate = false; + bool bSetDefaultMats = false; + bool bApplyMatsCheck = false; + bool t_bApplyMatsCheck = false; + + + private void OnEnable() + { + t_opt_GizmosEnabled = serializedObject.FindProperty("opt_GizmosEnabled"); + t_opt_Lanes = serializedObject.FindProperty("opt_Lanes"); + t_opt_LaneWidth = serializedObject.FindProperty("opt_LaneWidth"); + t_opt_bShouldersEnabled = serializedObject.FindProperty("opt_bShouldersEnabled"); + t_opt_ShoulderWidth = serializedObject.FindProperty("opt_ShoulderWidth"); + t_opt_RoadDefinition = serializedObject.FindProperty("opt_RoadDefinition"); + t_opt_UseDefaultMaterials = serializedObject.FindProperty("opt_UseDefaultMaterials"); + t_opt_bMaxGradeEnabled = serializedObject.FindProperty("opt_bMaxGradeEnabled"); + t_opt_MaxGrade = serializedObject.FindProperty("opt_MaxGrade"); + t_opt_bMultithreading = serializedObject.FindProperty("opt_bMultithreading"); + t_opt_bSaveMeshes = serializedObject.FindProperty("opt_bSaveMeshes"); + t_opt_TerrainSubtract_Match = serializedObject.FindProperty("opt_TerrainSubtract_Match"); + t_opt_MagnitudeThreshold = serializedObject.FindProperty("opt_MagnitudeThreshold"); + t_opt_HeightModEnabled = serializedObject.FindProperty("opt_HeightModEnabled"); + t_opt_DetailModEnabled = serializedObject.FindProperty("opt_DetailModEnabled"); + t_opt_TreeModEnabled = serializedObject.FindProperty("opt_TreeModEnabled"); + t_opt_MatchHeightsDistance = serializedObject.FindProperty("opt_MatchHeightsDistance"); + t_opt_ClearDetailsDistance = serializedObject.FindProperty("opt_ClearDetailsDistance"); + t_opt_ClearDetailsDistanceHeight = serializedObject.FindProperty("opt_ClearDetailsDistanceHeight"); + t_opt_ClearTreesDistance = serializedObject.FindProperty("opt_ClearTreesDistance"); + t_opt_ClearTreesDistanceHeight = serializedObject.FindProperty("opt_ClearTreesDistanceHeight"); + t_opt_SaveTerrainHistoryOnDisk = serializedObject.FindProperty("opt_SaveTerrainHistoryOnDisk"); + t_opt_bRoadCuts = serializedObject.FindProperty("opt_bRoadCuts"); + t_opt_bDynamicCuts = serializedObject.FindProperty("opt_bDynamicCuts"); + t_opt_bShoulderCuts = serializedObject.FindProperty("opt_bShoulderCuts"); + t_bEditorCameraRotate = serializedObject.FindProperty("bEditorCameraRotate"); + t_EditorCameraMetersPerSecond = serializedObject.FindProperty("EditorCameraMetersPerSecond"); + t_opt_bUseMeshColliders = serializedObject.FindProperty("opt_bUseMeshColliders"); + t_opt_tRoadMaterialDropdown = serializedObject.FindProperty("opt_tRoadMaterialDropdown"); + t_opt_bIsStatic = serializedObject.FindProperty("opt_bIsStatic"); + t_opt_bIsLightmapped = serializedObject.FindProperty("opt_bIsLightmapped"); + + t_RoadMaterial1 = serializedObject.FindProperty("RoadMaterial1"); + t_RoadMaterial2 = serializedObject.FindProperty("RoadMaterial2"); + t_RoadMaterial3 = serializedObject.FindProperty("RoadMaterial3"); + t_RoadMaterial4 = serializedObject.FindProperty("RoadMaterial4"); + t_RoadMaterialMarker1 = serializedObject.FindProperty("RoadMaterialMarker1"); + t_RoadMaterialMarker2 = serializedObject.FindProperty("RoadMaterialMarker2"); + t_RoadMaterialMarker3 = serializedObject.FindProperty("RoadMaterialMarker3"); + t_RoadMaterialMarker4 = serializedObject.FindProperty("RoadMaterialMarker4"); + t_ShoulderMaterial1 = serializedObject.FindProperty("ShoulderMaterial1"); + t_ShoulderMaterial2 = serializedObject.FindProperty("ShoulderMaterial2"); + t_ShoulderMaterial3 = serializedObject.FindProperty("ShoulderMaterial3"); + t_ShoulderMaterial4 = serializedObject.FindProperty("ShoulderMaterial4"); + t_ShoulderMaterialMarker1 = serializedObject.FindProperty("ShoulderMaterialMarker1"); + t_ShoulderMaterialMarker2 = serializedObject.FindProperty("ShoulderMaterialMarker2"); + t_ShoulderMaterialMarker3 = serializedObject.FindProperty("ShoulderMaterialMarker3"); + t_ShoulderMaterialMarker4 = serializedObject.FindProperty("ShoulderMaterialMarker4"); + t_RoadPhysicMaterial = serializedObject.FindProperty("RoadPhysicMaterial"); + t_ShoulderPhysicMaterial = serializedObject.FindProperty("ShoulderPhysicMaterial"); + } + + + void Init() + { + bHasInit = true; + EditorStyles.label.wordWrap = true; + + if (WarningLabelBG == null) + { + WarningLabelBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/WarningLabelBG.png", typeof(Texture2D)) as Texture2D; + } + if (btnRefreshText == null) + { + btnRefreshText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; + } + if (btnRefreshTextReal == null) + { + btnRefreshTextReal = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh.png", typeof(Texture)) as Texture; + } + if (LoadBtnBG == null) + { + LoadBtnBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBGGlow == null) + { + LoadBtnBGGlow = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; + } + if (btnDeleteText == null) + { + btnDeleteText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; + } + + if (WarningLabelStyle == null) + { + WarningLabelStyle = new GUIStyle(GUI.skin.textArea); + WarningLabelStyle.normal.textColor = Color.red; + WarningLabelStyle.active.textColor = Color.red; + WarningLabelStyle.hover.textColor = Color.red; + WarningLabelStyle.normal.background = WarningLabelBG; + WarningLabelStyle.active.background = WarningLabelBG; + WarningLabelStyle.hover.background = WarningLabelBG; + WarningLabelStyle.padding = new RectOffset(8, 8, 8, 8); + } + + if (GSDImageButton == null) + { + GSDImageButton = new GUIStyle(GUI.skin.button); + GSDImageButton.contentOffset = new Vector2(0f, 0f); + GSDImageButton.border = new RectOffset(0, 0, 0, 0); + GSDImageButton.fixedHeight = 16f; + GSDImageButton.padding = new RectOffset(0, 0, 0, 0); + GSDImageButton.normal.background = null; + } + + if (GSDLoadButton == null) + { + GSDLoadButton = new GUIStyle(GUI.skin.button); + GSDLoadButton.contentOffset = new Vector2(0f, 1f); + GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDLoadButton.normal.background = LoadBtnBG; + GSDLoadButton.active.background = LoadBtnBGGlow; + GSDLoadButton.focused.background = LoadBtnBGGlow; + GSDLoadButton.hover.background = LoadBtnBGGlow; + GSDLoadButton.fixedHeight = 16f; + GSDLoadButton.fixedWidth = 128f; + } + + if (GSDMaybeButton == null) + { + GSDMaybeButton = new GUIStyle(GUI.skin.button); + GSDMaybeButton.normal.textColor = new Color(0f, 0f, 0f, 1f); + } + } + + + public override void OnInspectorGUI() + { + if (Event.current.type == EventType.ValidateCommand) + { + switch (Event.current.commandName) + { + case "UndoRedoPerformed": + TriggerRoadUpdate(); + break; + } + } + + serializedObject.Update(); + + bNeedRoadUpdate = false; + bSetDefaultMats = false; + //Graphic null checks: + if (!bHasInit) + { + Init(); + } + + + + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(RS.transform.name, EditorStyles.boldLabel); + if (GUILayout.Button("Update road", GSDLoadButton)) + { + RS.EditorUpdateMe = true; + } + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.LabelField("Hold ctrl and click terrain to add nodes."); + EditorGUILayout.LabelField("Hold shift and click terrain to insert nodes."); + EditorGUILayout.LabelField("Select nodes on spline to add objects."); + EditorGUILayout.LabelField("Road options:"); + + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + //Option: Gizmos input: + t_opt_GizmosEnabled.boolValue = EditorGUILayout.Toggle("Gizmos: ", RS.opt_GizmosEnabled); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + + //Option: Lane count: + if (RS.opt_Lanes == 2) + { + LanesEnum = tempEnum.Two; + } + else if (RS.opt_Lanes == 4) + { + LanesEnum = tempEnum.Four; + } + else + { + LanesEnum = tempEnum.Six; + } + tLanesEnum = (tempEnum) EditorGUILayout.Popup("Lanes: ", (int) LanesEnum, tempEnumDescriptions); + if (tLanesEnum == tempEnum.Two) + { + t_opt_Lanes.intValue = 2; + } + else if (tLanesEnum == tempEnum.Four) + { + t_opt_Lanes.intValue = 4; + } + else if (tLanesEnum == tempEnum.Six) + { + t_opt_Lanes.intValue = 6; + } + + //Option: Lane and road width: + EditorGUILayout.BeginHorizontal(); + t_opt_LaneWidth.floatValue = EditorGUILayout.FloatField("Lane width:", RS.opt_LaneWidth); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_LaneWidth.floatValue = 5f; + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.LabelField("Road width: " + RS.RoadWidth().ToString("F1") + " meters"); + + //Option: Shoulders enabled: + t_opt_bShouldersEnabled.boolValue = EditorGUILayout.Toggle("Shoulders enabled:", RS.opt_bShouldersEnabled); + + //Option: Shoulders width: + if (RS.opt_bShouldersEnabled) + { + EditorGUILayout.BeginHorizontal(); + t_opt_ShoulderWidth.floatValue = EditorGUILayout.FloatField("Shoulders width:", RS.opt_ShoulderWidth); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_ShoulderWidth.floatValue = 3f; + } + EditorGUILayout.EndHorizontal(); + } + + //Option: Road definition: + EditorGUILayout.BeginHorizontal(); + t_opt_RoadDefinition.floatValue = EditorGUILayout.FloatField("Road definition:", RS.opt_RoadDefinition); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_RoadDefinition.floatValue = 5f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Use default materials: + t_opt_UseDefaultMaterials.boolValue = EditorGUILayout.Toggle("Use default materials:", RS.opt_UseDefaultMaterials); + + //Dropdown: + if (RS.opt_UseDefaultMaterials) + { + int Old = (int) RS.opt_tRoadMaterialDropdown; + t_opt_tRoadMaterialDropdown.enumValueIndex = (int) EditorGUILayout.Popup("Road material: ", (int) RS.opt_tRoadMaterialDropdown, RoadMaterialDropdownEnumDesc, GUILayout.Width(250f)); + if (t_opt_tRoadMaterialDropdown.enumValueIndex != Old) + { + if (t_opt_tRoadMaterialDropdown.enumValueIndex > 0) + { + t_opt_bShouldersEnabled.boolValue = false; + } + else + { + t_opt_bShouldersEnabled.boolValue = true; + } + } + } + + //Option: Max grade enabled: + t_opt_bMaxGradeEnabled.boolValue = EditorGUILayout.Toggle("Max grade enforced: ", RS.opt_bMaxGradeEnabled); + + //Option: Max grade value: + if (RS.opt_bMaxGradeEnabled) + { + EditorGUILayout.BeginHorizontal(); + t_opt_MaxGrade.floatValue = EditorGUILayout.Slider("Max road grade: ", RS.opt_MaxGrade, 0f, 1f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_MaxGrade.floatValue = 0.08f; + } + EditorGUILayout.EndHorizontal(); + } + + //Mesh colliders: + if (RS.GSDRS != null) + { + t_opt_bUseMeshColliders.boolValue = EditorGUILayout.Toggle("Use mesh colliders: ", RS.opt_bUseMeshColliders); + } + + //Option: Multi-threading option: workaround for UAS submission rules: + if (RS.GSDRS.opt_bMultithreading != RS.opt_bMultithreading) + { + RS.GSDRS.opt_bMultithreading = RS.opt_bMultithreading; + RS.GSDRS.UpdateAllRoads_MultiThreadOptions(); + } + if (RS.GSDRS != null) + { + t_opt_bMultithreading.boolValue = EditorGUILayout.Toggle("Multithreading: ", RS.GSDRS.opt_bMultithreading); + } + + //Static: + if (RS.GSDRS != null) + { + t_opt_bIsStatic.boolValue = EditorGUILayout.Toggle("Static: ", RS.opt_bIsStatic); + } + + //Used for lightmapping: + if (RS.GSDRS != null) + { + t_opt_bIsLightmapped.boolValue = EditorGUILayout.Toggle("Lightmapped: ", RS.opt_bIsLightmapped); + } + + //Option: Save meshes as unity assets options: + if (RS.GSDRS.opt_bSaveMeshes != RS.opt_bSaveMeshes) + { + RS.GSDRS.opt_bSaveMeshes = RS.opt_bSaveMeshes; + RS.GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); + } + if (RS.GSDRS != null) + { + t_opt_bSaveMeshes.boolValue = EditorGUILayout.Toggle("Save mesh assets: ", RS.GSDRS.opt_bSaveMeshes); + } + if (RS.GSDRS.opt_bSaveMeshes) + { + GUILayout.Label("WARNING: Saving meshes as assets is very slow and can increase road generation time by several minutes.", WarningLabelStyle); + } + + if (GUILayout.Button("Duplicate road", EditorStyles.miniButton, GUILayout.Width(120f))) + { + RS.DuplicateRoad(); + } + + + bShowHelpRoad = EditorGUILayout.Foldout(bShowHelpRoad, status); + if (bShowHelpRoad) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Road options quick help:", EditorStyles.boldLabel); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); + + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Gizmos:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Enable or disable most gizmos for this road. Disable mesh collider gizmos via the unity menu if necessary or desired.", EditorStyles.miniLabel); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Lanes:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Select the number of lanes for this road."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Lane width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Modify the width per lane, in meters."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Road width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Displays the road width without considering shoulders, in meters."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Shoulders enabled:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Enables or disables shoulders."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Shoulders width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Modify the width of shoulders, in meters."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Road definition: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The meter spacing between mesh triangles on the road and shoulder."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Use default materials: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("When enabled will use default materials for the road system, allowing certain aspects of generation to automatically determine the correct materials to utilize."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Max grade enforced: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("When enabled enforces a maximum grade on a per node basis."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Max road grade: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The maximum road grade allowed on a per node basis."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Multithreading:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("When enabled allows for multi-threaded road generation."); + EditorGUILayout.EndVertical(); + GUILayout.Space(4f); + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Save mesh assets:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("When enabled saves all generated meshes as .asset files."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.LabelField("Terrain options:"); + EditorGUILayout.BeginVertical("box"); + + //Option: Terrain subtraction: + EditorGUILayout.BeginHorizontal(); + t_opt_TerrainSubtract_Match.floatValue = EditorGUILayout.Slider("Terrain subtraction: ", RS.opt_TerrainSubtract_Match, 0.01f, 1f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_TerrainSubtract_Match.floatValue = 0.01f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Spline magnitude limit: + EditorGUILayout.BeginHorizontal(); + t_opt_MagnitudeThreshold.floatValue = EditorGUILayout.Slider("Spline magnitude limit: ", RS.opt_MagnitudeThreshold, 128f, 8192f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_MagnitudeThreshold.floatValue = 300f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Height modification + t_opt_HeightModEnabled.boolValue = EditorGUILayout.Toggle("Height modification: ", RS.opt_HeightModEnabled); + + //Option: Active detail removal + t_opt_DetailModEnabled.boolValue = EditorGUILayout.Toggle("Active detail removal: ", RS.opt_DetailModEnabled); + + //Option: Active tree removal + t_opt_TreeModEnabled.boolValue = EditorGUILayout.Toggle("Active tree removal: ", RS.opt_TreeModEnabled); + + //Option: heights width + if (RS.opt_HeightModEnabled) + { + EditorGUILayout.BeginHorizontal(); + t_opt_MatchHeightsDistance.floatValue = EditorGUILayout.Slider("Heights match width: ", RS.opt_MatchHeightsDistance, 0.01f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_MatchHeightsDistance.floatValue = 50f; + } + EditorGUILayout.EndHorizontal(); + } + + //Option: details width and height + if (RS.opt_DetailModEnabled) + { + EditorGUILayout.BeginHorizontal(); + t_opt_ClearDetailsDistance.floatValue = EditorGUILayout.Slider("Details clear width: ", RS.opt_ClearDetailsDistance, 0.01f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_ClearDetailsDistance.floatValue = 30f; + } + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + t_opt_ClearDetailsDistanceHeight.floatValue = EditorGUILayout.Slider("Details clear height: ", RS.opt_ClearDetailsDistanceHeight, 0.01f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_ClearDetailsDistanceHeight.floatValue = 5f; + } + + EditorGUILayout.EndHorizontal(); + } + + //Option: tree widths and height + if (RS.opt_TreeModEnabled) + { + EditorGUILayout.BeginHorizontal(); + t_opt_ClearTreesDistance.floatValue = EditorGUILayout.Slider("Trees clear width: ", RS.opt_ClearTreesDistance, 0.01f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_ClearTreesDistance.floatValue = 30f; + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + t_opt_ClearTreesDistanceHeight.floatValue = EditorGUILayout.Slider("Trees clear height: ", RS.opt_ClearTreesDistanceHeight, 0.01f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_ClearTreesDistanceHeight.floatValue = 50f; + } + EditorGUILayout.EndHorizontal(); + } + + + //Option: terrain history save type: + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Store terrain history separate from scene:"); + t_opt_SaveTerrainHistoryOnDisk.boolValue = EditorGUILayout.Toggle(RS.opt_SaveTerrainHistoryOnDisk, GUILayout.Width(50f)); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.LabelField("Terrain history size: " + RS.TerrainHistoryByteSize); + + bShowHelpTerrain = EditorGUILayout.Foldout(bShowHelpTerrain, status); + if (bShowHelpTerrain) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Terrain options quick help:", EditorStyles.boldLabel); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); + EditorGUILayout.LabelField("Terrain subtraction: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("This value, in meters, will be subtracted from the terrain match height to prevent z-fighting."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Spline magnitude limit: ", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Limits the magnitude of the spline nodes. Lower limit is better for typical roads with node seperation of around 100 to 300 meters. Higher limits will allow for less tension when using very spread out nodes."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Height Modification:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Enables or disables height matching for the terrain."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Active detail removal:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Enables or disables active detail removal. Memory intensive on large terrains with large amounts of details. Recommended to not use this option and instead remove details and trees via splat maps with other addons."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Active tree removal:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Enables or disables active tree removal. Memory intensive on large terrains with large amounts of trees. Recommended to not use this option and instead remove details and trees via splat maps with other addons."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Heights match width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The distance to the left and right of the road in which terrain heights will be matched to the road."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Details clear width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The distance between the road and detail, width wise, in which details will be removed."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Details clear height:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The distance between the road and detail, height wise, in which details will be removed."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Tree clear width:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The distance between the road and tree, width wise, in which trees will be removed."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Tree clear height:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("The distance between the road and tree, height wise, in which trees will be removed."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Store terrain history separate from scene:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("If enabled, stores the terrain history immediately on disk after use, saving memory while in editor."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Terrain history size:", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Shows the size, in kilobytes, of the terrain history in memory or on disk."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + + + + GUILayout.Label("Road and shoulder splitting:"); + EditorGUILayout.BeginVertical("box"); + GUILayout.Space(4f); + + //Option: road cuts: + if (!RS.opt_bDynamicCuts) + { + EditorGUILayout.BeginHorizontal(); + t_opt_bRoadCuts.boolValue = EditorGUILayout.Toggle("Auto split road: ", RS.opt_bRoadCuts); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_bDynamicCuts.boolValue = false; + t_opt_bRoadCuts.boolValue = true; + t_opt_bShoulderCuts.boolValue = true; + } + EditorGUILayout.EndHorizontal(); + + if (RS.opt_bShouldersEnabled) + { + t_opt_bShoulderCuts.boolValue = EditorGUILayout.Toggle("Auto split shoulders: ", RS.opt_bShoulderCuts); + } + } + else + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Manual road splitting: true"); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_bDynamicCuts.boolValue = false; + t_opt_bRoadCuts.boolValue = true; + t_opt_bShoulderCuts.boolValue = true; + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.LabelField("Manual shoulder splitting: true"); + } + t_opt_bDynamicCuts.boolValue = EditorGUILayout.Toggle("Manual splitting: ", RS.opt_bDynamicCuts); + + + bShowCutsHelp = EditorGUILayout.Foldout(bShowCutsHelp, status); + if (bShowCutsHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Road splitting quick help:", EditorStyles.boldLabel); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); + + EditorGUILayout.LabelField("Typically auto-split will be the best choice for performance and other reasons."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Choosing split options will split the road/shoulder up into pieces mirroring the locations of nodes."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Splitting allows for more detailed and flexible road texturing options such as passing sections, other different road lines per section, road debris and more."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Choosing split options may also speed up mesh collider collision calculations if bounds calculations are involved."); + GUILayout.Space(4f); + + EditorGUILayout.LabelField("Which splitting option to choose?", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Choose no splitting if you desire a single material set for this entire road and your game experiences no collison processing slowdowns from one large mesh collider. This option will create less game objects than automatic and manual splitting."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Choose automatic road and shoulder splitting if you desire multiple materials (such as yellow double lines for certain sections and white dotted for others) for this road and or your game experiences collision processing slowdowns from one large mesh collider."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Choose manual road and shoulder splitting if you desire the same as automatic splitting and desire more freedom over the process. This option will result in less gameobjects and larger mesh colliders when compared to automatic splitting."); + GUILayout.Space(4f); + + + Line(); + EditorGUILayout.LabelField("Manual splitting information: "); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Choosing manual splitting will force the user to select individual nodes to cut instead of the cuts being performed automatically. This option is recommended if bigger mesh colliders do not cause a slowdown in performance, as it lowers the overall gameobject count."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Manual splitting will not split up the mesh colliders like automatic cuts, so the colliders may get large & complex and cost more CPU to process collisions. If this option is chosen, please verify your game's collision processing speed and if you run into long collision processing times split more road sections"); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Example usages of manual splitting"); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Example hill: Goal is to have double yellow no passing lines on a two lane road but only while the road is near or on the hill. " + + "Pick nodes on either sides of the hill and mark both as road cut. Everything between these two nodes will be its own section, " + + "allowing you to apply double yellow no passing lines for just the hill."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Example mountains: In the mountains, the road is curvy and the grade is high. " + + "There's a flat straight spot that you want to allow passing in, by marking the road with white dotted passing lines. " + + "At the beginning of the flat straight section, mark the node as road cut. Now at the end of the flat straight section, mark this node as road cut. " + + "This will create a road section between the two nodes, allowing you to apply white dotted passing lines for just the flat straight section."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + else + { + GUILayout.Space(4f); + } + EditorGUILayout.EndVertical(); + + + //Camera: + EditorGUILayout.LabelField("Editor camera travel:"); + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + + //Option: Editor camera meters per sec + t_EditorCameraMetersPerSecond.floatValue = EditorGUILayout.Slider("Camera meters/sec:", RS.EditorCameraMetersPerSecond, 1f, 512f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_EditorCameraMetersPerSecond.floatValue = 60f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Editor camera auto rotate: + t_bEditorCameraRotate.boolValue = EditorGUILayout.Toggle("Camera auto rotate: ", RS.bEditorCameraRotate); + if (RS.EditorPlayCamera == null) + { + RS.EditorCameraSetSingle(); + } + RS.EditorPlayCamera = (Camera) EditorGUILayout.ObjectField("Editor play camera:", RS.EditorPlayCamera, typeof(Camera), true); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Reset", GUILayout.Width(70f))) + { + RS.QuitEditorCamera(); + RS.DoEditorCameraLoop(); + } + if (GUILayout.Button("<<", GUILayout.Width(40f))) + { + RS.EditorCameraPos -= 0.1f; + RS.DoEditorCameraLoop(); + } + if (RS.bEditorCameraMoving == true) + { + if (GUILayout.Button("Pause", GUILayout.Width(70f))) + { + RS.bEditorCameraMoving = false; + } + } + else + { + if (GUILayout.Button("Play", GUILayout.Width(70f))) + { + RS.bEditorCameraMoving = true; + } + } + if (GUILayout.Button(">>", GUILayout.Width(40f))) + { + RS.EditorCameraPos += 0.1f; + RS.DoEditorCameraLoop(); + } + EditorGUILayout.EndHorizontal(); + + GUILayout.Space(4); + bShowCameraHelp = EditorGUILayout.Foldout(bShowCameraHelp, status); + if (bShowCameraHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Editor camera quick help:", EditorStyles.boldLabel); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.HelpBox(tOnlineHelpDesc, MessageType.Info); + EditorGUILayout.LabelField("Use this section to travel along the road while in the editor sceneview."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Camera meters/sec is the speed at which the camera moves along the road."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Auto rotate will automatically rotate the camera to look forward at the current road's tangent. Note: You can still zoom in and out with the camera with this option selected."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Note: Materials act differently in the editor scene view compared to actual gameplay. Try the game camera if the materials are z fighting and having other issues."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + + GUILayout.Label("Materials:"); + EditorGUILayout.BeginVertical("box"); + //Road material defaults: + + EditorGUILayout.BeginHorizontal(); + GUILayout.Label("Road base material(s) defaults:"); + //Option: Set mats to defaults: + bSetDefaultMats = false; + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + bSetDefaultMats = true; + } + EditorGUILayout.EndHorizontal(); + // EditorGUILayout.PropertyField (t_RoadMaterial1, new GUIContent (" Mat #1: ")); + // if(RS.RoadMaterial1 != null){ EditorGUILayout.PropertyField (t_RoadMaterial2, new GUIContent (" Mat #2: ")); } + // if(RS.RoadMaterial2 != null){EditorGUILayout.PropertyField (t_RoadMaterial3, new GUIContent (" Mat #3: ")); } + // if(RS.RoadMaterial3 != null){EditorGUILayout.PropertyField (t_RoadMaterial4, new GUIContent (" Mat #4: ")); } + + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterial1, new GUIContent(" Mat #1: ")); + if (RS.RoadMaterial1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.RoadMaterial1 = null; } + EditorGUILayout.EndHorizontal(); + if (RS.RoadMaterial1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterial2, new GUIContent(" Mat #2: ")); + if (RS.RoadMaterial2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { RS.RoadMaterial2 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.RoadMaterial1 != null && RS.RoadMaterial2 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterial3, new GUIContent(" Mat #3: ")); + if (RS.RoadMaterial3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { RS.RoadMaterial3 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.RoadMaterial1 != null && RS.RoadMaterial2 != null && RS.RoadMaterial3 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterial4, new GUIContent(" Mat #4: ")); + if (RS.RoadMaterial4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { RS.RoadMaterial4 = null; } + EditorGUILayout.EndHorizontal(); + } + + + + + // //Road marker material defaults: + GUILayout.Label("Road marker material(s) defaults:"); + // EditorGUILayout.PropertyField (t_RoadMaterialMarker1, new GUIContent (" Mat #1: ")); + // if(RS.RoadMaterialMarker1 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker2, new GUIContent (" Mat #2: ")); } + // if(RS.RoadMaterialMarker2 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker3, new GUIContent (" Mat #3: ")); } + // if(RS.RoadMaterialMarker3 != null){EditorGUILayout.PropertyField (t_RoadMaterialMarker4, new GUIContent (" Mat #4: ")); } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterialMarker1, new GUIContent(" Mat #1: ")); + if (RS.RoadMaterialMarker1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.RoadMaterialMarker1 = null; } + EditorGUILayout.EndHorizontal(); + if (RS.RoadMaterialMarker1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterialMarker2, new GUIContent(" Mat #2: ")); + if (RS.RoadMaterialMarker2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.RoadMaterialMarker2 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.RoadMaterialMarker1 != null && RS.RoadMaterialMarker2 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterialMarker3, new GUIContent(" Mat #3: ")); + if (RS.RoadMaterialMarker3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.RoadMaterialMarker3 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.RoadMaterialMarker1 != null && RS.RoadMaterialMarker2 != null && RS.RoadMaterialMarker3 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_RoadMaterialMarker4, new GUIContent(" Mat #4: ")); + if (RS.RoadMaterialMarker4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.RoadMaterialMarker4 = null; } + EditorGUILayout.EndHorizontal(); + } + + + + + // //Shoulder material defaults: + if (RS.opt_bShouldersEnabled) + { + GUILayout.Label("Shoulder base material(s) defaults:"); + // EditorGUILayout.PropertyField (t_ShoulderMaterial1, new GUIContent (" Mat #1: ")); + // if(RS.ShoulderMaterial1 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial2, new GUIContent (" Mat #2: ")); } + // if(RS.ShoulderMaterial2 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial3, new GUIContent (" Mat #3: ")); } + // if(RS.ShoulderMaterial3 != null){EditorGUILayout.PropertyField (t_ShoulderMaterial4, new GUIContent (" Mat #4: ")); } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterial1, new GUIContent(" Mat #1: ")); + if (RS.ShoulderMaterial1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterial1 = null; } + EditorGUILayout.EndHorizontal(); + if (RS.ShoulderMaterial1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterial2, new GUIContent(" Mat #2: ")); + if (RS.ShoulderMaterial2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { RS.ShoulderMaterial2 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.ShoulderMaterial1 != null && RS.ShoulderMaterial2 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterial3, new GUIContent(" Mat #3: ")); + if (RS.ShoulderMaterial3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterial3 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.ShoulderMaterial1 != null && RS.ShoulderMaterial2 != null && RS.ShoulderMaterial3 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterial4, new GUIContent(" Mat #4: ")); + if (RS.ShoulderMaterial4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterial4 = null; } + EditorGUILayout.EndHorizontal(); + } + } + + + + + // //Shoulder marker material defaults: + if (RS.opt_bShouldersEnabled) + { + GUILayout.Label("Shoulder marker material(s) defaults:"); + // EditorGUILayout.PropertyField (t_ShoulderMaterialMarker1, new GUIContent (" Mat #1: ")); + // if(RS.ShoulderMaterialMarker1 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker2, new GUIContent (" Mat #2: ")); } + // if(RS.ShoulderMaterialMarker2 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker3, new GUIContent (" Mat #3: ")); } + // if(RS.ShoulderMaterialMarker3 != null){EditorGUILayout.PropertyField (t_ShoulderMaterialMarker4, new GUIContent (" Mat #4: ")); } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterialMarker1, new GUIContent(" Mat #1: ")); + if (RS.ShoulderMaterialMarker1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterialMarker1 = null; } + EditorGUILayout.EndHorizontal(); + if (RS.ShoulderMaterialMarker1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterialMarker2, new GUIContent(" Mat #2: ")); + if (RS.ShoulderMaterialMarker2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { RS.ShoulderMaterialMarker2 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.ShoulderMaterialMarker1 != null && RS.ShoulderMaterialMarker2 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterialMarker3, new GUIContent(" Mat #3: ")); + if (RS.ShoulderMaterialMarker3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterialMarker3 = null; } + EditorGUILayout.EndHorizontal(); + } + if (RS.ShoulderMaterialMarker1 != null && RS.ShoulderMaterialMarker2 != null && RS.ShoulderMaterialMarker3 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_ShoulderMaterialMarker4, new GUIContent(" Mat #4: ")); + if (RS.ShoulderMaterialMarker4 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + RS.ShoulderMaterialMarker4 = null; } + EditorGUILayout.EndHorizontal(); + } + } + + + + //Physics materials: + GUILayout.Label("Physics materials defaults:"); + //Option: physical road mat: + // t_RoadPhysicMaterial.serializedObject = (PhysicMaterial)EditorGUILayout.ObjectField(" Road mat: ",RS.RoadPhysicMaterial,typeof(PhysicMaterial),false); + EditorGUILayout.PropertyField(t_RoadPhysicMaterial, new GUIContent("Road phys mat: ")); + + + //Option: physical shoulder mat: + // t_ShoulderPhysicMaterial.serializedObject = (PhysicMaterial)EditorGUILayout.ObjectField(" Shoulder mat: ",RS.ShoulderPhysicMaterial,typeof(PhysicMaterial),false); + EditorGUILayout.PropertyField(t_ShoulderPhysicMaterial, new GUIContent("Shoulder phys mat: ")); + + + GUILayout.Space(4); + EditorGUILayout.BeginHorizontal(); + //Option: Apply above materials to entire road: + EditorGUILayout.LabelField("Apply above materials to entire road:"); + bApplyMatsCheck = EditorGUILayout.Toggle(bApplyMatsCheck, GUILayout.Width(20f)); + if (GUILayout.Button("Apply", EditorStyles.miniButton, GUILayout.Width(60f))) + { + if (bApplyMatsCheck) + { + t_bApplyMatsCheck = true; + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.LabelField("Applying will overwrite any saved cuts' material(s)."); + + //Help toggle for materials + GUILayout.Space(4); + bShowMatsHelp = EditorGUILayout.Foldout(bShowMatsHelp, status); + if (bShowMatsHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("These default materials will be applied by default to their respective generated meshes. If using split roads and or shoulders, you can specific specific materials to use on them (on the mesh renderers of the cuts) and they will be used instead of the default materials listed above."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Road base material is UV mapped on a world vector basis for seamless tiles."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Road marker material is UV mapped to fit roads. Use these materials to place road lines and other road texture details. Note: if using road cuts, these are the materials which will be placed by default at the initial generation."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Shoulder base material is UV mapped on a world vector basis for seamless tiles."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Shoulder marker material is UV mapped on a world vector basis for seamless tiles. For intended use with transparent shadow receiving shaders. Marker materials are applied, optionally, on shoulder cuts."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("The physical material for road will be used on all road colliders. The physical material for shoulder will be used on all shoulder colliders. If using road and or shoulder cuts, you can specficy unique physics materials which will be used instead of the default physics materials."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Apply above materials button will clear all saved materials on the roads and all road and shoulder meshes will use the materials listed above."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + + //Reset terrain history: + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Reset road's terrain history:"); + bResetTH = EditorGUILayout.Toggle(bResetTH, GUILayout.Width(20f)); + if (bResetTH) + { + if (GUILayout.Button("Reset") && bResetTH) + { + RS.ConstructRoad_ResetTerrainHistory(); + bResetTH = false; + } + } + else + { + if (GUILayout.Button("Check to reset", GSDMaybeButton) && bResetTH) + { + RS.ConstructRoad_ResetTerrainHistory(); + bResetTH = false; + } + } + EditorGUILayout.EndHorizontal(); + + if (bResetTH) + { + EditorGUILayout.LabelField("WARNING: This option can't be undone! Only reset the terrain history if you have changed terrain resolution data such as heightmap or detail resolutions. A rare event may occur when editing and compiling this addon's scripts that a terrain history reset may be necessary. Treat this reset as a last resort.", WarningLabelStyle); + } + GUILayout.Space(6f); + + + EditorGUILayout.LabelField("Statistics:"); + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Length: " + RS.GSDSpline.distance.ToString("F1") + " meters"); + EditorGUILayout.LabelField("Total nodes: " + RS.MostRecentNodeCount.ToString()); + EditorGUILayout.EndVertical(); + + bool bGizmoChange = false; + bool bLaneChange = false; + bool bMultithreadChange = false; + bool bSaveMeshChange = false; + bool bTerrainHistoryChange = false; + bool bEditorCameraSpeedChange = false; + + if (GUI.changed) + { + //Option pre-handle: Gizmos: + if (t_opt_GizmosEnabled.boolValue != RS.opt_GizmosEnabled) + { + bGizmoChange = true; + RS.Wireframes_Toggle(); + SceneView.RepaintAll(); + } + //Option pre-handle: Lane count: + if (t_opt_Lanes.intValue != RS.opt_Lanes) + { + bNeedRoadUpdate = true; + bLaneChange = true; + } + + //Option pre-handle for multithread and save mesh: + if (RS.GSDRS != null) + { + if (t_opt_bMultithreading.boolValue != RS.GSDRS.opt_bMultithreading) + { + RS.GSDRS.opt_bMultithreading = t_opt_bMultithreading.boolValue; + bMultithreadChange = true; + } + if (t_opt_bSaveMeshes.boolValue != RS.GSDRS.opt_bSaveMeshes) + { + RS.GSDRS.opt_bSaveMeshes = t_opt_bSaveMeshes.boolValue; + bSaveMeshChange = true; + } + } + + //Option pre-handle for terrain history: + if (t_opt_SaveTerrainHistoryOnDisk.boolValue != RS.opt_SaveTerrainHistoryOnDisk) + { + bTerrainHistoryChange = true; + } + + //Option pre-handle for editor camera speed: + if (!GSDRootUtil.IsApproximately(t_EditorCameraMetersPerSecond.floatValue, RS.EditorCameraMetersPerSecond, 0.001f)) + { + bEditorCameraSpeedChange = true; + } + + //Apply serialization: + serializedObject.ApplyModifiedProperties(); + + + //Handle after effects: + if (bGizmoChange) + { + RS.Wireframes_Toggle(); + SceneView.RepaintAll(); + } + + + //Option: Lane count: + if (bLaneChange) + { + if (RS.opt_UseDefaultMaterials) + { + RS.GSDSpline.ClearAllRoadCuts(); + RS.SetDefaultMats(); + RS.SetAllCutsToCurrentMaterials(); + } + } + + //Option: Multithreading + if (bMultithreadChange) + { + RS.GSDRS.UpdateAllRoads_MultiThreadOptions(); + } + + //Option: Save meshes as unity assets options: + if (bSaveMeshChange) + { + RS.GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); + } + + //Option: terrain history save type: + if (bTerrainHistoryChange) + { + if (RS.opt_SaveTerrainHistoryOnDisk) + { + RS.ConstructRoad_StoreTerrainHistory(true); + } + else + { + RS.ConstructRoad_LoadTerrainHistory(true); + } + } + + //Option: Editor camera meters per sec + if (bEditorCameraSpeedChange) + { + RS.ChangeEditorCameraMetersPerSec(); + } + + //Update road: + if (bNeedRoadUpdate) + { + RS.GSDSpline.Setup_Trigger(); + } + + //Option: Set mats to defaults: + if (bSetDefaultMats) + { + RS.SetDefaultMats(); + RS.SetAllCutsToCurrentMaterials(); + } + + //Option: Apply above materials to entire road: + if (t_bApplyMatsCheck) + { + t_bApplyMatsCheck = false; + bApplyMatsCheck = false; + RS.SetAllCutsToCurrentMaterials(); + } + + EditorUtility.SetDirty(target); + } + } + + + public void OnSceneGUI() + { + Event current = Event.current; + int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); + + if (current.alt == true) + { + return; + } + + if (Selection.Contains(RS.transform.gameObject) && Selection.objects.Length > 1) + { + SetSelectionToRoad(); + } + + // Handle Ctrl and Shift when road is selected + if (Selection.activeGameObject == RS.transform.gameObject) + { + RS.Editor_bSelected = true; + // Only handle MouseMove and MouseDrag events + if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag) + { + if (current.control) + { + Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); + RaycastHit hitInfo; + if (Physics.Raycast(worldRay, out hitInfo)) + { + /* There used to be a check for whether this was a terrain */ + RS.Editor_MousePos = hitInfo.point; + RS.Editor_MouseTerrainHit = true; + if (RS.GSDSpline && RS.GSDSpline.PreviewSpline) + { + //Debug.Log("Drawing new node"); + if (RS.GSDSpline.PreviewSpline.mNodes == null || RS.GSDSpline.PreviewSpline.mNodes.Count < 1) + { + RS.GSDSpline.Setup(); } + RS.GSDSpline.PreviewSpline.MousePos = hitInfo.point; + RS.GSDSpline.PreviewSpline.bGizmoDraw = true; + SceneView.RepaintAll(); + } + } + + GUI.changed = true; + } + else if (current.shift) + { + Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); + RaycastHit hitInfo; + if (Physics.Raycast(worldRay, out hitInfo)) + { + /* Used to check for terrain */ + // if(hitInfo.collider.transform.name.ToLower().Contains("terrain")){ + RS.Editor_MousePos = hitInfo.point; + RS.Editor_MouseTerrainHit = true; + if (RS.GSDSpline && RS.GSDSpline.PreviewSplineInsert) + { + if (RS.GSDSpline.PreviewSplineInsert.mNodes == null || RS.GSDSpline.PreviewSplineInsert.mNodes.Count < 1) + { + RS.GSDSpline.PreviewSplineInsert.DetermineInsertNodes(); } + RS.GSDSpline.PreviewSplineInsert.MousePos = hitInfo.point; + RS.GSDSpline.PreviewSplineInsert.bGizmoDraw = true; + RS.GSDSpline.PreviewSplineInsert.UpdateActionNode(); + SceneView.RepaintAll(); + } + //}else{ + // RS.Editor_MouseTerrainHit = false; + //} + } + + GUI.changed = true; + } + else + { + if (RS.Editor_MouseTerrainHit) + { + RS.Editor_MouseTerrainHit = false; + GUI.changed = true; + } + if (RS.GSDSpline && RS.GSDSpline.PreviewSpline) + { + //Debug.Log("not drawing new node"); + RS.GSDSpline.PreviewSpline.bGizmoDraw = false; + } + if (RS.GSDSpline && RS.GSDSpline.PreviewSplineInsert) + { + //Debug.Log("not drawing insert node"); + RS.GSDSpline.PreviewSplineInsert.bGizmoDraw = false; + } + } + } + } + else + { + RS.Editor_bSelected = false; + if (RS.GSDSpline.PreviewSpline) + { + RS.GSDSpline.PreviewSpline.bGizmoDraw = false; + } + } + + + + if (current.shift && RS.GSDSpline.PreviewSpline != null) + { + RS.GSDSpline.PreviewSpline.bGizmoDraw = false; + } + bool bUsed = false; + if (current.control) + { + if (Event.current.type == EventType.MouseDown) + { + //Left click: + if (Event.current.button == 0) + { + if (RS.Editor_MouseTerrainHit) + { + // if((EditorApplication.timeSinceStartup - RS.GSDSpline.EditorOnly_LastNode_TimeSinceStartup) > 0.05){ + // RS.GSDSpline.EditorOnly_LastNode_TimeSinceStartup = EditorApplication.timeSinceStartup; + Event.current.Use(); + GSDConstruction.CreateNode(RS); + bUsed = true; + // } + } + else + { + Debug.Log("Invalid surface for new node. Must be terrain."); + } + } + } + } + else if (current.shift) + { + if (Event.current.type == EventType.MouseDown) + { + //Left click: + if (Event.current.button == 0) + { + if (RS.Editor_MouseTerrainHit) + { + Event.current.Use(); + GSDConstruction.InsertNode(RS); + bUsed = true; + } + else + { + Debug.Log("Invalid surface for insertion node. Must be terrain."); + } + } + } + } + + + if (current.type == EventType.ValidateCommand) + { + switch (current.commandName) + { + case "UndoRedoPerformed": + TriggerRoadUpdate(); + break; + } + } + + if (Selection.activeGameObject == RS.transform.gameObject) + { + if (current.keyCode == KeyCode.F5) + { + TriggerRoadUpdate(); + } + } + + + + if (bUsed) + { + SetSelectionToRoad(); + switch (current.type) + { + case EventType.Layout: + HandleUtility.AddDefaultControl(controlID); + break; + } + } + + if (GUI.changed) + { + EditorUtility.SetDirty(RS); + } + } + + + private void TriggerRoadUpdate() + { + if (RS != null) + { + RS.EditorUpdateMe = true; + } + } + + + void SetSelectionToRoad() + { + GameObject[] tObjs = new GameObject[1]; + tObjs[0] = RS.transform.gameObject; + Selection.objects = tObjs; + } + + + #region "Progress bar" + /// + /// Creates progress bar. + /// + /// + /// Value of the progress bar. + /// + /// + /// Label of the progress bar. + /// + void GSDProgressBar(float tV, string tL) + { + // Get a rect for the progress bar using the same margins as a textfield: + Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField"); + EditorGUI.ProgressBar(rect, tV, tL); + EditorGUILayout.Space(); + } + #endregion + + + // FH_Tag Optimizable + void Line() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar + GUILayout.Space(4f); + } + + + void LineSmall() + { + GUILayout.Space(1f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar + GUILayout.Space(1f); + } + // FH_Tag Optimizable +} \ No newline at end of file diff --git a/Editor/GSDRoadIntersectionEditor.cs b/Editor/GSDRoadIntersectionEditor.cs index 36e938a4..ff15efe1 100755 --- a/Editor/GSDRoadIntersectionEditor.cs +++ b/Editor/GSDRoadIntersectionEditor.cs @@ -1,1035 +1,1221 @@ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using GSD; - -[CustomEditor(typeof(GSDRoadIntersection))] -public class GSDRoadIntersectionEditor : Editor -{ - protected GSDRoadIntersection tInter { get { return (GSDRoadIntersection)target; } } - - SerializedProperty t_opt_AutoUpdateIntersections; - SerializedProperty t_bDrawGizmo; - SerializedProperty t_bLeftTurnYieldOnGreen; - SerializedProperty t_opt_FixedTime_RegularLightLength; - SerializedProperty t_opt_FixedTime_LeftTurnLightLength; - SerializedProperty t_opt_FixedTime_AllRedLightLength; - SerializedProperty t_opt_FixedTime_YellowLightLength; - SerializedProperty t_bTrafficPoleStreetLight; - SerializedProperty t_bTrafficLightGray; - SerializedProperty t_bRegularPoleAlignment; - SerializedProperty t_bLightsEnabled; - SerializedProperty t_StreetLight_Range; - SerializedProperty t_StreetLight_Intensity; - SerializedProperty t_StreetLight_Color; - SerializedProperty t_ScalingSense; - SerializedProperty t_GradeMod; - SerializedProperty t_bUseDefaultMaterials; - SerializedProperty t_MarkerCenter1; - SerializedProperty t_MarkerCenter2; - SerializedProperty t_MarkerCenter3; - SerializedProperty t_MarkerExt_Stretch1; - SerializedProperty t_MarkerExt_Stretch2; - SerializedProperty t_MarkerExt_Stretch3; - SerializedProperty t_MarkerExt_Tiled1; - SerializedProperty t_MarkerExt_Tiled2; - SerializedProperty t_MarkerExt_Tiled3; - SerializedProperty t_Lane0Mat1; - SerializedProperty t_Lane0Mat2; - SerializedProperty t_Lane1Mat1; - SerializedProperty t_Lane1Mat2; - SerializedProperty t_Lane2Mat1; - SerializedProperty t_Lane2Mat2; - SerializedProperty t_Lane3Mat1; - SerializedProperty t_Lane3Mat2; - SerializedProperty t_rType; - SerializedProperty t_iStopType; - SerializedProperty t_lType; - - #region "Editor only variables" - //Editor only variables - const bool bDebug = false; - bool bShowMarkerStretch = false; - bool bShowMarkerTiled = false; - bool bShowMarkerCenter = false; - bool bShowTLSense = false; - bool bShowTLPole = false; - bool bShowLightHelp = false; - bool bShowLanes = false; - bool bGradeCorrect = false; - bool bShowDefaultMatHelp = false; - bool bShowHelpLeftTurnGreen = false; - string status = "Show help"; - - GUIStyle GSDImageButton = null; - Texture btnRefreshText = null; - Texture btnDeleteText = null; - - private static string[] rTypeDescriptions = new string[]{ - "No turn lanes", - "Left turn lane only", - "Both left and right turn lanes" - }; - - private static string[] rTypeDescriptions_3Way = new string[]{ - "No turn lanes", - "Left turn lane only" - }; - - private static string[] iStopTypeEnumDescriptions = new string[]{ - "Stop signs", - "Traffic lights", - "None" -// "Traffic lights #2" - }; - - private static string[] iTrafficLightSequenceTypeDesc = new string[]{ - "Fixed time", - "Other" - }; - - const string HelpText1 = "Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking."; - - //Checkers: - Texture2D LoadBtnBG = null; - Texture2D LoadBtnBGGlow = null; - - GUIStyle GSDLoadButton = null; - bool bHasInit = false; - #endregion - - private void OnEnable() - { - t_opt_AutoUpdateIntersections = serializedObject.FindProperty("opt_AutoUpdateIntersections"); - t_bDrawGizmo = serializedObject.FindProperty("bDrawGizmo"); - t_bLeftTurnYieldOnGreen = serializedObject.FindProperty("bLeftTurnYieldOnGreen"); - t_opt_FixedTime_RegularLightLength = serializedObject.FindProperty("opt_FixedTime_RegularLightLength"); - t_opt_FixedTime_LeftTurnLightLength = serializedObject.FindProperty("opt_FixedTime_LeftTurnLightLength"); - t_opt_FixedTime_AllRedLightLength = serializedObject.FindProperty("opt_FixedTime_AllRedLightLength"); - t_opt_FixedTime_YellowLightLength = serializedObject.FindProperty("opt_FixedTime_YellowLightLength"); - t_bTrafficPoleStreetLight = serializedObject.FindProperty("bTrafficPoleStreetLight"); - t_bTrafficLightGray = serializedObject.FindProperty("bTrafficLightGray"); - t_bRegularPoleAlignment = serializedObject.FindProperty("bRegularPoleAlignment"); - t_bLightsEnabled = serializedObject.FindProperty("bLightsEnabled"); - t_StreetLight_Range = serializedObject.FindProperty("StreetLight_Range"); - t_StreetLight_Intensity = serializedObject.FindProperty("StreetLight_Intensity"); - t_StreetLight_Color = serializedObject.FindProperty("StreetLight_Color"); - t_ScalingSense = serializedObject.FindProperty("ScalingSense"); - t_GradeMod = serializedObject.FindProperty("GradeMod"); - t_bUseDefaultMaterials = serializedObject.FindProperty("bUseDefaultMaterials"); - t_MarkerCenter1 = serializedObject.FindProperty("MarkerCenter1"); - t_MarkerCenter2 = serializedObject.FindProperty("MarkerCenter2"); - t_MarkerCenter3 = serializedObject.FindProperty("MarkerCenter3"); - t_MarkerExt_Stretch1 = serializedObject.FindProperty("MarkerExt_Stretch1"); - t_MarkerExt_Stretch2 = serializedObject.FindProperty("MarkerExt_Stretch2"); - t_MarkerExt_Stretch3 = serializedObject.FindProperty("MarkerExt_Stretch3"); - t_MarkerExt_Tiled1 = serializedObject.FindProperty("MarkerExt_Tiled1"); - t_MarkerExt_Tiled2 = serializedObject.FindProperty("MarkerExt_Tiled2"); - t_MarkerExt_Tiled3 = serializedObject.FindProperty("MarkerExt_Tiled3"); - t_Lane0Mat1 = serializedObject.FindProperty("Lane0Mat1"); - t_Lane0Mat2 = serializedObject.FindProperty("Lane0Mat2"); - t_Lane1Mat1 = serializedObject.FindProperty("Lane1Mat1"); - t_Lane1Mat2 = serializedObject.FindProperty("Lane1Mat2"); - t_Lane2Mat1 = serializedObject.FindProperty("Lane2Mat1"); - t_Lane2Mat2 = serializedObject.FindProperty("Lane2Mat2"); - t_Lane3Mat1 = serializedObject.FindProperty("Lane3Mat1"); - t_Lane3Mat2 = serializedObject.FindProperty("Lane3Mat2"); - t_rType = serializedObject.FindProperty("rType"); - t_iStopType = serializedObject.FindProperty("iStopType"); - t_lType = serializedObject.FindProperty("lType"); - } - - public override void OnInspectorGUI() - { - if (Event.current.type == EventType.ValidateCommand) - { - switch (Event.current.commandName) - { - case "UndoRedoPerformed": - TriggerRoadUpdate(true); - break; - } - } - - serializedObject.Update(); - - //Graphic null checks: - if (!bHasInit) { Init(); } - - Line(); - EditorGUILayout.BeginHorizontal(); - { - GSDRoad road1 = tInter.Node1.GSDSpline.transform.parent.GetComponent(); - GSDRoad road2 = tInter.Node2.GSDSpline.transform.parent.GetComponent(); - EditorGUILayout.LabelField("First road: " + road1.name + " node: " + tInter.Node1.name); - EditorGUILayout.LabelField("Second road: " + road2.name + " node: " + tInter.Node2.name); - } - EditorGUILayout.EndHorizontal(); - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Intersection options", EditorStyles.boldLabel); - if (GUILayout.Button("Update intersection", GSDLoadButton)) - { - TriggerRoadUpdate(true); - } - EditorGUILayout.EndHorizontal(); - - //Option: Auto update: - t_opt_AutoUpdateIntersections.boolValue = EditorGUILayout.Toggle("Auto-update:", tInter.opt_AutoUpdateIntersections); - - //Option: Gizmo: - t_bDrawGizmo.boolValue = EditorGUILayout.Toggle("Gizmo:", tInter.bDrawGizmo); - - //UI: - EditorGUILayout.BeginHorizontal(); - if (tInter.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) - { - EditorGUILayout.LabelField("Intersection type: 3 way"); - } - else - { - EditorGUILayout.LabelField("Intersection type: 4 way"); - } - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - Line(); - EditorGUILayout.BeginVertical(); - if (GUILayout.Button("Access objects on first road node")) - { - Selection.objects = new Object[1] { tInter.Node1 }; - } - if (GUILayout.Button("Access objects on second road node")) - { - Selection.objects = new Object[1] { tInter.Node2 }; - } - EditorGUILayout.EndVertical(); - //Option: Intersection turn lane options - Line(); - EditorGUILayout.LabelField("Intersection turn lane options:"); - if (tInter.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) - { - t_rType.enumValueIndex = (int)EditorGUILayout.Popup((int)tInter.rType, rTypeDescriptions_3Way); - } - else - { - t_rType.enumValueIndex = (int)EditorGUILayout.Popup((int)tInter.rType, rTypeDescriptions); - } - - //Option: Left yield on green: - if (tInter.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - t_bLeftTurnYieldOnGreen.boolValue = EditorGUILayout.Toggle("Left yield on green: ", tInter.bLeftTurnYieldOnGreen); - - bShowHelpLeftTurnGreen = EditorGUILayout.Foldout(bShowHelpLeftTurnGreen, status); - if (bShowHelpLeftTurnGreen) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Left yield on green: If checked, replaces the standard 3-light left turn light with a five-light yield on green left turn signal structure and sign."); - EditorGUILayout.EndVertical(); - } - } - Line(); - - - //Option: Intersection stop type: - t_iStopType.enumValueIndex = (int)EditorGUILayout.Popup("Intersection stop type:", (int)tInter.iStopType, iStopTypeEnumDescriptions); - - - if (tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - //Option: Traffic light timing type: - t_lType.enumValueIndex = (int)EditorGUILayout.Popup("Traffic light timing:", (int)tInter.lType, iTrafficLightSequenceTypeDesc); - - //Options: Traffic fixed light timings: - if (tInter.lType == GSDRoadIntersection.LightTypeEnum.Timed) - { - EditorGUILayout.LabelField("Traffic light fixed time lengths (in seconds):"); - EditorGUILayout.BeginHorizontal(); - t_opt_FixedTime_RegularLightLength.floatValue = EditorGUILayout.Slider("Green length: ", tInter.opt_FixedTime_RegularLightLength, 0.1f, 180f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) { t_opt_FixedTime_RegularLightLength.floatValue = 30f; } - EditorGUILayout.EndHorizontal(); - - if (tInter.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - EditorGUILayout.BeginHorizontal(); - t_opt_FixedTime_LeftTurnLightLength.floatValue = EditorGUILayout.Slider("Left turn only length: ", tInter.opt_FixedTime_LeftTurnLightLength, 0.1f, 180f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) { t_opt_FixedTime_LeftTurnLightLength.floatValue = 10f; } - EditorGUILayout.EndHorizontal(); - } - - EditorGUILayout.BeginHorizontal(); - t_opt_FixedTime_AllRedLightLength.floatValue = EditorGUILayout.Slider("All red length: ", tInter.opt_FixedTime_AllRedLightLength, 0.1f, 180f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) { t_opt_FixedTime_AllRedLightLength.floatValue = 1f; } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - t_opt_FixedTime_YellowLightLength.floatValue = EditorGUILayout.Slider("Yellow light length: ", tInter.opt_FixedTime_YellowLightLength, 0.1f, 180f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) { t_opt_FixedTime_YellowLightLength.floatValue = 3f; } - EditorGUILayout.EndHorizontal(); - } - } - - - if (tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - //Option: Traffic light poles: - Line(); - EditorGUILayout.LabelField("Traffic light poles:"); - t_bTrafficPoleStreetLight.boolValue = EditorGUILayout.Toggle("Street lights: ", tInter.bTrafficPoleStreetLight); - - //Option: Traffic light pole gray color: - t_bTrafficLightGray.boolValue = EditorGUILayout.Toggle("Gray color: ", tInter.bTrafficLightGray); - - //Option: Normal pole alignment: - t_bRegularPoleAlignment.boolValue = EditorGUILayout.Toggle("Normal pole alignment: ", tInter.bRegularPoleAlignment); - bShowTLPole = EditorGUILayout.Foldout(bShowTLPole, status); - if (bShowTLPole) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Street lights: If checked, attaches street lights to each intersection pole. Point lights optional and can be manipulated in the next option segment."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Gray color: If checked, sets the traffic light pole base materials to gray galvanized steel. If unchecked the material used is black metal paint."); - GUILayout.Space(4f); - EditorGUILayout.LabelField("Normal pole alignment: Recommended to keep this option on unless abnormal twisting of light objects is occurring. Turn this option off if the roads immediately surrounding your intersection are curved at extreme angles and cause irregular twisting of the traffic light objects. Turning this option off will attempt to align the poles perpendicular to the adjacent relevant road without any part existing over the main intersection bounds."); - EditorGUILayout.EndVertical(); - } - - //Option: Point lights enabled: - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Point lights:"); - EditorGUILayout.EndHorizontal(); - t_bLightsEnabled.boolValue = EditorGUILayout.Toggle(" Point lights enabled: ", tInter.bLightsEnabled); - - //Options: Street point light options: - if (tInter.bTrafficPoleStreetLight) - { - //Option: Street light range: - EditorGUILayout.BeginHorizontal(); - t_StreetLight_Range.floatValue = EditorGUILayout.Slider(" Street light range: ", tInter.StreetLight_Range, 1f, 128f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_StreetLight_Range.floatValue = 30f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Street light intensity: - EditorGUILayout.BeginHorizontal(); - t_StreetLight_Intensity.floatValue = EditorGUILayout.Slider(" Street light intensity: ", tInter.StreetLight_Intensity, 0f, 8f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_StreetLight_Intensity.floatValue = 1f; - } - EditorGUILayout.EndHorizontal(); - - //Option: Street light color: - EditorGUILayout.BeginHorizontal(); - t_StreetLight_Color.colorValue = EditorGUILayout.ColorField(" Street light color: ", tInter.StreetLight_Color); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_StreetLight_Color.colorValue = new Color(1f, 0.7451f, 0.27451f, 1f); ; - } - EditorGUILayout.EndHorizontal(); - } - bShowLightHelp = EditorGUILayout.Foldout(bShowLightHelp, status); - if (bShowLightHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Point lights: Enabled means that point lights for the traffic lights (and street lights, if enabled) will be turned on. This is accessible via script \"bLightsEnabled\""); - - GUILayout.Space(4f); - EditorGUILayout.LabelField("If street pole lights enabled: Street light range, intensity and color: These settings directly correlate to the standard point light settings."); - - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - Line(); - - //Option: Traffic light scaling sensitivity: - EditorGUILayout.LabelField("Traffic light scaling sensitivity: *Does not auto-update"); - EditorGUILayout.BeginHorizontal(); - t_ScalingSense.floatValue = EditorGUILayout.Slider(tInter.ScalingSense, 0f, 200f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_ScalingSense.floatValue = 170f; - } - EditorGUILayout.EndHorizontal(); GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - bShowTLSense = EditorGUILayout.Foldout(bShowTLSense, status); - if (GUILayout.Button("Manually update intersection", EditorStyles.miniButton, GUILayout.Width(170f))) - { - TriggerRoadUpdate(true); - } - EditorGUILayout.EndHorizontal(); - if (bShowTLSense) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Increasing this value will increase the scaling sensitivity relative to the size of the intersection. Higher scaling value = bigger traffic lights at further distances. Default value is 170."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - GUILayout.Space(4f); - } - - //Option: Grade correction modifier: - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Grade correction factor: *Does not auto-update"); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.BeginHorizontal(); - t_GradeMod.floatValue = EditorGUILayout.Slider(tInter.GradeMod, 0.01f, 2f); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - t_GradeMod.floatValue = 0.375f; - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.BeginHorizontal(); - bGradeCorrect = EditorGUILayout.Foldout(bGradeCorrect, status); - if (GUILayout.Button("Manually update intersection", EditorStyles.miniButton, GUILayout.Width(170f))) - { - tInter.UpdateRoads(); - } - EditorGUILayout.EndHorizontal(); - if (bGradeCorrect) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("If using extreme road grades immediately surrounding the intersection, terrain height matching errors may occur at the point of road expansion leading to the intersection."); - EditorGUILayout.LabelField("Raise this value if you see terrain poking through the road at the road expansion areas."); - EditorGUILayout.LabelField("Lower this value if you are not using road mesh colliders and notice dips at the expansion points."); - EditorGUILayout.LabelField("Default value is 0.375 meters, which is the maximum value for a linear range of 0% to 20% grade."); - EditorGUILayout.LabelField("Recommended to keep grades and angles small leading up to intersections."); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets settings to default."); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - } - - //Option: Use default materials: - Line(); - t_bUseDefaultMaterials.boolValue = EditorGUILayout.Toggle("Use default materials:", tInter.bUseDefaultMaterials); - bShowDefaultMatHelp = EditorGUILayout.Foldout(bShowDefaultMatHelp, status); - if (bShowDefaultMatHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Checking this option will reset all materials for this intersection and use the default intersection materials that come with this addon."); - EditorGUILayout.EndVertical(); - } - - - Line(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Center marker material(s):"); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tInter.ResetMaterials_Center(); - } - EditorGUILayout.EndHorizontal(); GUILayout.Space(4f); - //Options: Center materials: - // EditorGUILayout.BeginHorizontal(); - // EditorGUILayout.PropertyField (t_MarkerCenter1, new GUIContent ("Center material #1:")); - // if(tInter.MarkerCenter1 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter1 = null; } - // EditorGUILayout.EndHorizontal(); - // if(tInter.MarkerCenter1 != null){ - // EditorGUILayout.BeginHorizontal(); - // EditorGUILayout.PropertyField (t_MarkerCenter2, new GUIContent ("Center material #2:")); - // if(tInter.MarkerCenter2 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter2 = null; } - // EditorGUILayout.EndHorizontal(); - // if(tInter.MarkerCenter2 != null){ - // EditorGUILayout.BeginHorizontal(); - // EditorGUILayout.PropertyField (t_MarkerCenter3, new GUIContent ("Center material #3:")); - // if(tInter.MarkerCenter3 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter3 = null; } - // EditorGUILayout.EndHorizontal(); - // } - // } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerCenter1, new GUIContent(" Mat #1: ")); - if (tInter.MarkerCenter1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerCenter1 = null; } - EditorGUILayout.EndHorizontal(); - - if (tInter.MarkerCenter1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerCenter2, new GUIContent(" Mat #2: ")); - if (tInter.MarkerCenter2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerCenter2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (tInter.MarkerCenter2 != null && tInter.MarkerCenter1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerCenter3, new GUIContent(" Mat #3: ")); - if (tInter.MarkerCenter3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerCenter3 = null; } - EditorGUILayout.EndHorizontal(); - } - - bShowMarkerCenter = EditorGUILayout.Foldout(bShowMarkerCenter, status); - if (bShowMarkerCenter) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Center marker materials require transparent shaders. Covers the center area of the intersection. Displayed in order #1 on bottom to #4 on top. Combine with transparent shaders which accept shadows to allow for easy marking."); - DoDefaultHelpMat(); - DoDeleteHelpMat(); - EditorGUILayout.EndVertical(); - } - Line(); - - //Options: Marker ext stretched materials: - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Exterior fitted marker material(s):"); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tInter.ResetMaterials_Ext_Stretched(); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Stretch1, new GUIContent(" Mat #1: ")); - if (tInter.MarkerExt_Stretch1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Stretch1 = null; } - EditorGUILayout.EndHorizontal(); - - if (tInter.MarkerExt_Stretch1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Stretch2, new GUIContent(" Mat #2: ")); - if (tInter.MarkerExt_Stretch2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Stretch2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (tInter.MarkerExt_Stretch2 != null && tInter.MarkerExt_Stretch1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Stretch3, new GUIContent(" Mat #3: ")); - if (tInter.MarkerExt_Stretch3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Stretch3 = null; } - EditorGUILayout.EndHorizontal(); - } - - bShowMarkerStretch = EditorGUILayout.Foldout(bShowMarkerStretch, status); - if (bShowMarkerStretch) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Fitted marker materials require transparent shaders. Covers the exterior area of the intersection with the UV's stretched to match at a 1:1 ratio. Should be use for intersection markings and any visual effects like dirt." + HelpText1); - DoDefaultHelpMat(); - DoDeleteHelpMat(); - EditorGUILayout.EndVertical(); - } - Line(); - - //Options: Marker ext tiled materials: - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Exterior tiled marker material(s):"); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tInter.ResetMaterials_Ext_Tiled(); - } - EditorGUILayout.EndHorizontal(); GUILayout.Space(4f); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Tiled1, new GUIContent(" Mat #1: ")); - if (tInter.MarkerExt_Tiled1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Tiled1 = null; } - EditorGUILayout.EndHorizontal(); - - if (tInter.MarkerExt_Tiled1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Tiled2, new GUIContent(" Mat #2: ")); - if (tInter.MarkerExt_Tiled2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Tiled2 = null; } - EditorGUILayout.EndHorizontal(); - } - if (tInter.MarkerExt_Tiled2 != null && tInter.MarkerExt_Tiled1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_MarkerExt_Tiled3, new GUIContent(" Mat #3: ")); - if (tInter.MarkerExt_Tiled3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.MarkerExt_Tiled3 = null; } - EditorGUILayout.EndHorizontal(); - } - - bShowMarkerTiled = EditorGUILayout.Foldout(bShowMarkerTiled, status); - if (bShowMarkerTiled) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Covers the exterior area of the intersection with the UV's tiled matching world coordinates. Tiled and used for road pavement textures. UV coordinates will match up seamlessly with road pavement." + HelpText1); - DoDefaultHelpMat(); - DoDeleteHelpMat(); - EditorGUILayout.EndVertical(); - } - Line(); - - //Option: Lane section 0: - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Lanes marker materials:"); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tInter.ResetMaterials_Lanes(); - } - EditorGUILayout.EndHorizontal(); GUILayout.Space(4f); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane0Mat1, new GUIContent("Lane section 0 mat #1:")); - if (tInter.Lane0Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane0Mat1 = null; } - EditorGUILayout.EndHorizontal(); - if (tInter.Lane0Mat1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane0Mat2, new GUIContent("Lane section 0 mat #2:")); - if (tInter.Lane0Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane0Mat2 = null; } - EditorGUILayout.EndHorizontal(); - } - - - //Option: Lane section 1: - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane1Mat1, new GUIContent("Lane section 1 mat #1:")); - if (tInter.Lane1Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane1Mat1 = null; } - EditorGUILayout.EndHorizontal(); - if (tInter.Lane1Mat1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane1Mat2, new GUIContent("Lane section 1 mat #2:")); - if (tInter.Lane1Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane1Mat2 = null; } - EditorGUILayout.EndHorizontal(); - } - - //Option: Lane section 2: - if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || tInter.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane2Mat1, new GUIContent("Lane section 2 mat #1:")); - if (tInter.Lane2Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane2Mat1 = null; } - EditorGUILayout.EndHorizontal(); - if (tInter.Lane2Mat1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane2Mat2, new GUIContent("Lane section 2 mat #2:")); - if (tInter.Lane2Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane2Mat2 = null; } - EditorGUILayout.EndHorizontal(); - } - } - GUILayout.Space(4f); - - //Option: Lane section 3: - if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane3Mat1, new GUIContent("Lane section 3 mat #1:")); - if (tInter.Lane3Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane3Mat1 = null; } - EditorGUILayout.EndHorizontal(); - if (tInter.Lane3Mat1 != null) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(t_Lane3Mat2, new GUIContent("Lane section 3 mat #2:")); - if (tInter.Lane3Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { tInter.Lane3Mat2 = null; } - EditorGUILayout.EndHorizontal(); - } - } - bShowLanes = EditorGUILayout.Foldout(bShowLanes, status); - if (bShowLanes) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Covers individual lane sections in the intersection. Used for high-definition line marking."); - EditorGUILayout.LabelField("Lane section 0 = Left side of the intersection where oncoming traffic travels. Use lane texture which matches the number of lanes used on the road system, with a white left line and a yellow right line."); - - if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - EditorGUILayout.LabelField("Lane section 1 = Left turn lane. Use a single lane texture with a yellow left line and a white right line."); - EditorGUILayout.LabelField("Lane section 2 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); - EditorGUILayout.LabelField("Lane section 3 = Right turn lane. Use a single lane texture with a white right line."); - } - else if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - EditorGUILayout.LabelField("Lane section 1 = Left turn lane. Use a single lane texture with a yellow left line and a white right line."); - EditorGUILayout.LabelField("Lane section 2 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); - } - else if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - EditorGUILayout.LabelField("Lane section 1 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); - } - - EditorGUILayout.LabelField(HelpText1); - DoDefaultHelpMat(); - DoDeleteHelpMat(); - EditorGUILayout.EndVertical(); - } - Line(); - - // if(bDebug){ - // Line(); - // EditorGUILayout.LabelField("Debug"); - // if(tInter.Node1 != null){ EditorGUILayout.LabelField(" Node1: " + tInter.Node1.transform.name); } else { EditorGUILayout.LabelField(" Node1: null"); } - // if(tInter.Node2 != null){ EditorGUILayout.LabelField(" Node2: " + tInter.Node2.transform.name); } else { EditorGUILayout.LabelField(" Node2: null"); } - // if(tInter.Node1 != null){ EditorGUILayout.LabelField(" UID1: " + tInter.Node1.UID); } else { EditorGUILayout.LabelField(" UID1: null"); } - // if(tInter.Node2 != null){ EditorGUILayout.LabelField(" UID2: " + tInter.Node2.UID); } else { EditorGUILayout.LabelField(" UID2: null"); } - // EditorGUILayout.LabelField(" Same spline: " + tInter.bSameSpline); - // EditorGUILayout.LabelField(" bFlipped: " + tInter.bFlipped); - // EditorGUILayout.LabelField(" IgnoreSide: " + tInter.IgnoreSide); - // EditorGUILayout.LabelField(" IgnoreCorner: " + tInter.IgnoreCorner); - // - // if(tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2){ - // if(tInter.LightsRR != null){ EditorGUILayout.LabelField(" LightsRR: " + tInter.LightsRR); } else { EditorGUILayout.LabelField(" LightsRR: null"); } - // if(tInter.LightsRR != null || tInter.LightsRR.MR_Main != null){ EditorGUILayout.LabelField(" MR_Main: " + tInter.LightsRR.MR_Main); } else { EditorGUILayout.LabelField(" LightsRR.MR_Main: null"); } - // if(tInter.LightsRR != null || tInter.LightsRR.MR_Left != null){ EditorGUILayout.LabelField(" MR_Left: " + tInter.LightsRR.MR_Left); } else { EditorGUILayout.LabelField(" LightsRR.MR_Left: null"); } - // if(tInter.LightsRR != null || tInter.LightsRR.MR_Right != null){ EditorGUILayout.LabelField(" MR_Right: " + tInter.LightsRR.MR_Right); } else { EditorGUILayout.LabelField(" LightsRR.MR_Right: null"); } - // if(tInter.LightsRL != null){ EditorGUILayout.LabelField(" LightsRL: " + tInter.LightsRL); } else { EditorGUILayout.LabelField(" LightsRL: null"); } - // if(tInter.LightsLL != null){ EditorGUILayout.LabelField(" LightsLL: " + tInter.LightsLL); } else { EditorGUILayout.LabelField(" LightsLL: null"); } - // if(tInter.LightsLR != null){ EditorGUILayout.LabelField(" LightsLR: " + tInter.LightsLR); } else { EditorGUILayout.LabelField(" LightsLR: null"); } - // } - // Line(); - // } - - - //Set change bools: - bool bToggleTrafficLightPoleColor = false; - bool bTogglePointLights = false; - bool bGizmoChange = false; - bool bMatChange = false; - bool bRoadUpdate = false; - - if (GUI.changed) - { - //Option: Gizmo: - if (t_bDrawGizmo.boolValue != tInter.bDrawGizmo) - { - bGizmoChange = true; - } - - //Option: Intersection turn lane options - if ((int)tInter.rType != t_rType.enumValueIndex) - { - bMatChange = true; - bRoadUpdate = true; - } - - //Option: Left yield on green: - if (t_bLeftTurnYieldOnGreen.boolValue != tInter.bLeftTurnYieldOnGreen) - { - bRoadUpdate = true; - } - - //Option: Intersection stop type: - if (t_iStopType.enumValueIndex != (int)tInter.iStopType) - { - bRoadUpdate = true; - } - - //Option: Traffic light poles: - if (t_bTrafficPoleStreetLight.boolValue != tInter.bTrafficPoleStreetLight) - { - bRoadUpdate = true; - } - - //Option: Traffic light pole gray color: - if (t_bTrafficLightGray.boolValue != tInter.bTrafficLightGray) - { - bToggleTrafficLightPoleColor = true; - } - - //Option: Normal pole alignment: - if (t_bRegularPoleAlignment.boolValue != tInter.bRegularPoleAlignment) - { - bRoadUpdate = true; - } - - //Option: Point lights enabled: - if (t_bLightsEnabled.boolValue != tInter.bLightsEnabled) - { - bTogglePointLights = true; - } - - //Option: Street light range: - if (!GSDRootUtil.IsApproximately(t_StreetLight_Range.floatValue, tInter.StreetLight_Range, 0.01f)) - { - bTogglePointLights = true; - } - - //Option: Street light intensity: - if (!GSDRootUtil.IsApproximately(t_StreetLight_Intensity.floatValue, tInter.StreetLight_Intensity, 0.01f)) - { - bTogglePointLights = true; - } - - //Option: Street light color: - if (t_StreetLight_Color.colorValue != tInter.StreetLight_Color) - { - bTogglePointLights = true; - } - - //Option: Use default materials: - if (t_bUseDefaultMaterials.boolValue != tInter.bUseDefaultMaterials) - { - bMatChange = true; - } - - if (t_MarkerCenter1 == null || t_MarkerCenter1.objectReferenceValue == null) { tInter.MarkerCenter1 = null; } - if (t_MarkerCenter2 == null || t_MarkerCenter2.objectReferenceValue == null) { tInter.MarkerCenter2 = null; } - if (t_MarkerCenter3 == null || t_MarkerCenter3.objectReferenceValue == null) { tInter.MarkerCenter3 = null; } - if (t_MarkerExt_Stretch1 == null || t_MarkerExt_Stretch1.objectReferenceValue == null) { tInter.MarkerExt_Stretch1 = null; } - if (t_MarkerExt_Stretch2 == null || t_MarkerExt_Stretch2.objectReferenceValue == null) { tInter.MarkerExt_Stretch2 = null; } - if (t_MarkerExt_Stretch3 == null || t_MarkerExt_Stretch3.objectReferenceValue == null) { tInter.MarkerExt_Stretch3 = null; } - if (t_MarkerExt_Tiled1 == null || t_MarkerExt_Tiled1.objectReferenceValue == null) { tInter.MarkerExt_Tiled1 = null; } - if (t_MarkerExt_Tiled2 == null || t_MarkerExt_Tiled2.objectReferenceValue == null) { tInter.MarkerExt_Tiled2 = null; } - if (t_MarkerExt_Tiled3 == null || t_MarkerExt_Tiled3.objectReferenceValue == null) { tInter.MarkerExt_Tiled3 = null; } - if (t_Lane0Mat1 == null || t_Lane0Mat1.objectReferenceValue == null) { tInter.Lane0Mat1 = null; } - if (t_Lane0Mat2 == null || t_Lane0Mat2.objectReferenceValue == null) { tInter.Lane0Mat2 = null; } - if (t_Lane1Mat1 == null || t_Lane1Mat1.objectReferenceValue == null) { tInter.Lane1Mat1 = null; } - if (t_Lane1Mat2 == null || t_Lane1Mat2.objectReferenceValue == null) { tInter.Lane1Mat2 = null; } - if (t_Lane2Mat1 == null || t_Lane2Mat1.objectReferenceValue == null) { tInter.Lane2Mat1 = null; } - if (t_Lane2Mat2 == null || t_Lane2Mat2.objectReferenceValue == null) { tInter.Lane2Mat2 = null; } - if (t_Lane3Mat1 == null || t_Lane3Mat1.objectReferenceValue == null) { tInter.Lane3Mat1 = null; } - if (t_Lane3Mat2 == null || t_Lane3Mat2.objectReferenceValue == null) { tInter.Lane3Mat2 = null; } - - if (tInter.MarkerCenter1 != null && t_MarkerCenter1.objectReferenceValue != tInter.MarkerCenter1) { bMatChange = true; } - if (tInter.MarkerCenter2 != null && t_MarkerCenter2.objectReferenceValue != tInter.MarkerCenter2) { bMatChange = true; } - if (tInter.MarkerCenter3 != null && t_MarkerCenter3.objectReferenceValue != tInter.MarkerCenter3) { bMatChange = true; } - if (tInter.MarkerExt_Stretch1 != null && t_MarkerExt_Stretch1.objectReferenceValue != tInter.MarkerExt_Stretch1) { bMatChange = true; } - if (tInter.MarkerExt_Stretch2 != null && t_MarkerExt_Stretch2.objectReferenceValue != tInter.MarkerExt_Stretch2) { bMatChange = true; } - if (tInter.MarkerExt_Stretch3 != null && t_MarkerExt_Stretch3.objectReferenceValue != tInter.MarkerExt_Stretch3) { bMatChange = true; } - if (tInter.MarkerExt_Tiled1 != null && t_MarkerExt_Tiled1.objectReferenceValue != tInter.MarkerExt_Tiled1) { bMatChange = true; } - if (tInter.MarkerExt_Tiled2 != null && t_MarkerExt_Tiled2.objectReferenceValue != tInter.MarkerExt_Tiled2) { bMatChange = true; } - if (tInter.MarkerExt_Tiled3 != null && t_MarkerExt_Tiled3.objectReferenceValue != tInter.MarkerExt_Tiled3) { bMatChange = true; } - if (tInter.Lane0Mat1 != null && t_Lane0Mat1.objectReferenceValue != tInter.Lane0Mat1) { bMatChange = true; } - if (tInter.Lane0Mat2 != null && t_Lane0Mat2.objectReferenceValue != tInter.Lane0Mat2) { bMatChange = true; } - if (tInter.Lane1Mat1 != null && t_Lane1Mat1.objectReferenceValue != tInter.Lane1Mat1) { bMatChange = true; } - if (tInter.Lane1Mat2 != null && t_Lane1Mat2.objectReferenceValue != tInter.Lane1Mat2) { bMatChange = true; } - if (tInter.Lane2Mat1 != null && t_Lane2Mat1.objectReferenceValue != tInter.Lane2Mat1) { bMatChange = true; } - if (tInter.Lane2Mat2 != null && t_Lane2Mat2.objectReferenceValue != tInter.Lane2Mat2) { bMatChange = true; } - if (tInter.Lane3Mat1 != null && t_Lane3Mat1.objectReferenceValue != tInter.Lane3Mat1) { bMatChange = true; } - if (tInter.Lane3Mat2 != null && t_Lane3Mat2.objectReferenceValue != tInter.Lane3Mat2) { bMatChange = true; } - - - //Apply changes: - serializedObject.ApplyModifiedProperties(); - - - //Apply secondary effects: - if (bGizmoChange) - { - MeshRenderer[] tMRs = tInter.transform.GetComponentsInChildren(); - int tCount = tMRs.Length; - for (int i = 0; i < tCount; i++) - { - //EditorUtility.SetSelectedWireframeHidden(tMRs[i], !tInter.bDrawGizmo); - EditorUtility.SetSelectedRenderState(tMRs[i], tInter.bDrawGizmo ? EditorSelectedRenderState.Wireframe : EditorSelectedRenderState.Hidden); - - } - SceneView.RepaintAll(); - } - - if (bTogglePointLights) - { - tInter.TogglePointLights(tInter.bLightsEnabled); - } - - if (bToggleTrafficLightPoleColor) - { - tInter.ToggleTrafficLightPoleColor(); - } - - if (bMatChange) - { - tInter.UpdateMaterials(); - if (tInter.bUseDefaultMaterials) - { - tInter.ResetMaterials_All(); - } - } - - if (bRoadUpdate) - { - TriggerRoadUpdate(); - } - - EditorUtility.SetDirty(tInter); - } - } - - public void OnSceneGUI() - { - Event current = Event.current; - int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - - // if (Event.current.type == EventType.MouseDrag && Event.current.button == 0){ - // //Update relevant splines: - // tInter.Node1.GSDSpline.Setup(); - // if(!tInter.bSameSpline){ - // tInter.Node2.GSDSpline.Setup(); - // } - // bMouseDragHasProcessed = false; - // } - // - // if(Event.current.type == EventType.MouseUp && Event.current.button == 0){ - // if(!bMouseDragHasProcessed){ - // tInter.Node1.transform.position = tInter.transform.position; - // tInter.Node2.transform.position = tInter.transform.position; - // tInter.StartCoroutine(TriggerRoadUpdate()); - // } - // bMouseDragHasProcessed = true; - // } - - if (Event.current.type == EventType.MouseUp && Event.current.button == 0) - { - if (tInter.transform.position != tInter.Node1.transform.position) - { - tInter.Node1.transform.position = tInter.transform.position; - tInter.Node2.transform.position = tInter.transform.position; - tInter.Height = tInter.transform.position.y; - TriggerRoadUpdate(); - } - } - - - - if (current.type == EventType.ValidateCommand) - { - switch (current.commandName) - { - case "UndoRedoPerformed": - TriggerRoadUpdate(true); - break; - } - } - - if (current.type == EventType.MouseDown) - { - return; - } - - if (Selection.activeGameObject == tInter.transform.gameObject) - { - if (current.keyCode == KeyCode.F5) - { - if (tInter != null && tInter.Node1 != null && tInter.Node2 != null) - { - TriggerRoadUpdate(); - } - } - } - - // switch(current.type){ - // case EventType.layout: - //// if(current.type != EventType.MouseDown){ - // HandleUtility.AddDefaultControl(controlID); - //// } - // break; - // - // } - - if (controlID == 1) - { - //Do nothing - } - if (GUI.changed) { EditorUtility.SetDirty(tInter); } - } - - private void TriggerRoadUpdate(bool bForce = false) - { - if (!bForce && !tInter.opt_AutoUpdateIntersections) { return; } - - if (tInter != null && tInter.Node1 != null && tInter.Node2 != null) - { - if (!tInter.Node1.GSDSpline.tRoad.Editor_bIsConstructing && !tInter.Node2.GSDSpline.tRoad.Editor_bIsConstructing) - { - if (!tInter.bSameSpline) - { - tInter.Node1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[1]; - tInter.Node1.GSDSpline.tRoad.PiggyBacks[0] = tInter.Node2.GSDSpline; - } - tInter.Node1.GSDSpline.tRoad.EditorUpdateMe = true; - } - } - } - - void Init() - { - EditorStyles.label.wordWrap = true; - bHasInit = true; - if (btnRefreshText == null) - { - btnRefreshText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; - } - if (btnDeleteText == null) - { - btnDeleteText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; - } - if (LoadBtnBG == null) - { - LoadBtnBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBGGlow == null) - { - LoadBtnBGGlow = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; - } - - if (GSDImageButton == null) - { - GSDImageButton = new GUIStyle(GUI.skin.button); - GSDImageButton.contentOffset = new Vector2(0f, 0f); - GSDImageButton.border = new RectOffset(0, 0, 0, 0); - GSDImageButton.fixedHeight = 16f; - GSDImageButton.padding = new RectOffset(0, 0, 0, 0); - GSDImageButton.normal.background = null; - } - if (GSDLoadButton == null) - { - GSDLoadButton = new GUIStyle(GUI.skin.button); - GSDLoadButton.contentOffset = new Vector2(0f, 1f); - GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDLoadButton.normal.background = LoadBtnBG; - GSDLoadButton.active.background = LoadBtnBGGlow; - GSDLoadButton.focused.background = LoadBtnBGGlow; - GSDLoadButton.hover.background = LoadBtnBGGlow; - GSDLoadButton.fixedHeight = 16f; - GSDLoadButton.fixedWidth = 128f; - } - } - - void DoDefaultHelpMat() - { - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Resets material(s) to default materials."); - EditorGUILayout.EndHorizontal(); - } - - void DoDeleteHelpMat() - { - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) - { - - } - EditorGUILayout.LabelField(" = Removes material(s) from intersection."); - EditorGUILayout.EndHorizontal(); - } - - void Line() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar - GUILayout.Space(4f); - } +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using GSD; +#endregion + + +[CustomEditor(typeof(GSDRoadIntersection))] +public class GSDRoadIntersectionEditor : Editor +{ + protected GSDRoadIntersection tInter { get { return (GSDRoadIntersection) target; } } + + SerializedProperty t_opt_AutoUpdateIntersections; + SerializedProperty t_bDrawGizmo; + SerializedProperty t_bLeftTurnYieldOnGreen; + SerializedProperty t_opt_FixedTime_RegularLightLength; + SerializedProperty t_opt_FixedTime_LeftTurnLightLength; + SerializedProperty t_opt_FixedTime_AllRedLightLength; + SerializedProperty t_opt_FixedTime_YellowLightLength; + SerializedProperty t_bTrafficPoleStreetLight; + SerializedProperty t_bTrafficLightGray; + SerializedProperty t_bRegularPoleAlignment; + SerializedProperty t_bLightsEnabled; + SerializedProperty t_StreetLight_Range; + SerializedProperty t_StreetLight_Intensity; + SerializedProperty t_StreetLight_Color; + SerializedProperty t_ScalingSense; + SerializedProperty t_GradeMod; + SerializedProperty t_bUseDefaultMaterials; + SerializedProperty t_MarkerCenter1; + SerializedProperty t_MarkerCenter2; + SerializedProperty t_MarkerCenter3; + SerializedProperty t_MarkerExt_Stretch1; + SerializedProperty t_MarkerExt_Stretch2; + SerializedProperty t_MarkerExt_Stretch3; + SerializedProperty t_MarkerExt_Tiled1; + SerializedProperty t_MarkerExt_Tiled2; + SerializedProperty t_MarkerExt_Tiled3; + SerializedProperty t_Lane0Mat1; + SerializedProperty t_Lane0Mat2; + SerializedProperty t_Lane1Mat1; + SerializedProperty t_Lane1Mat2; + SerializedProperty t_Lane2Mat1; + SerializedProperty t_Lane2Mat2; + SerializedProperty t_Lane3Mat1; + SerializedProperty t_Lane3Mat2; + SerializedProperty t_rType; + SerializedProperty t_iStopType; + SerializedProperty t_lType; + + + #region "Editor only variables" + //Editor only variables + const bool bDebug = false; + bool bShowMarkerStretch = false; + bool bShowMarkerTiled = false; + bool bShowMarkerCenter = false; + bool bShowTLSense = false; + bool bShowTLPole = false; + bool bShowLightHelp = false; + bool bShowLanes = false; + bool bGradeCorrect = false; + bool bShowDefaultMatHelp = false; + bool bShowHelpLeftTurnGreen = false; + string status = "Show help"; + + GUIStyle GSDImageButton = null; + Texture btnRefreshText = null; + Texture btnDeleteText = null; + + + private static string[] rTypeDescriptions = new string[]{ + "No turn lanes", + "Left turn lane only", + "Both left and right turn lanes" + }; + + + private static string[] rTypeDescriptions_3Way = new string[]{ + "No turn lanes", + "Left turn lane only" + }; + + + private static string[] iStopTypeEnumDescriptions = new string[]{ + "Stop signs", + "Traffic lights", + "None" +// "Traffic lights #2" + }; + + + private static string[] iTrafficLightSequenceTypeDesc = new string[]{ + "Fixed time", + "Other" + }; + + + const string HelpText1 = "Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking."; + + //Checkers: + Texture2D LoadBtnBG = null; + Texture2D LoadBtnBGGlow = null; + + GUIStyle GSDLoadButton = null; + bool bHasInit = false; + #endregion + + + private void OnEnable() + { + t_opt_AutoUpdateIntersections = serializedObject.FindProperty("opt_AutoUpdateIntersections"); + t_bDrawGizmo = serializedObject.FindProperty("bDrawGizmo"); + t_bLeftTurnYieldOnGreen = serializedObject.FindProperty("bLeftTurnYieldOnGreen"); + t_opt_FixedTime_RegularLightLength = serializedObject.FindProperty("opt_FixedTime_RegularLightLength"); + t_opt_FixedTime_LeftTurnLightLength = serializedObject.FindProperty("opt_FixedTime_LeftTurnLightLength"); + t_opt_FixedTime_AllRedLightLength = serializedObject.FindProperty("opt_FixedTime_AllRedLightLength"); + t_opt_FixedTime_YellowLightLength = serializedObject.FindProperty("opt_FixedTime_YellowLightLength"); + t_bTrafficPoleStreetLight = serializedObject.FindProperty("bTrafficPoleStreetLight"); + t_bTrafficLightGray = serializedObject.FindProperty("bTrafficLightGray"); + t_bRegularPoleAlignment = serializedObject.FindProperty("bRegularPoleAlignment"); + t_bLightsEnabled = serializedObject.FindProperty("bLightsEnabled"); + t_StreetLight_Range = serializedObject.FindProperty("StreetLight_Range"); + t_StreetLight_Intensity = serializedObject.FindProperty("StreetLight_Intensity"); + t_StreetLight_Color = serializedObject.FindProperty("StreetLight_Color"); + t_ScalingSense = serializedObject.FindProperty("ScalingSense"); + t_GradeMod = serializedObject.FindProperty("GradeMod"); + t_bUseDefaultMaterials = serializedObject.FindProperty("bUseDefaultMaterials"); + t_MarkerCenter1 = serializedObject.FindProperty("MarkerCenter1"); + t_MarkerCenter2 = serializedObject.FindProperty("MarkerCenter2"); + t_MarkerCenter3 = serializedObject.FindProperty("MarkerCenter3"); + t_MarkerExt_Stretch1 = serializedObject.FindProperty("MarkerExt_Stretch1"); + t_MarkerExt_Stretch2 = serializedObject.FindProperty("MarkerExt_Stretch2"); + t_MarkerExt_Stretch3 = serializedObject.FindProperty("MarkerExt_Stretch3"); + t_MarkerExt_Tiled1 = serializedObject.FindProperty("MarkerExt_Tiled1"); + t_MarkerExt_Tiled2 = serializedObject.FindProperty("MarkerExt_Tiled2"); + t_MarkerExt_Tiled3 = serializedObject.FindProperty("MarkerExt_Tiled3"); + t_Lane0Mat1 = serializedObject.FindProperty("Lane0Mat1"); + t_Lane0Mat2 = serializedObject.FindProperty("Lane0Mat2"); + t_Lane1Mat1 = serializedObject.FindProperty("Lane1Mat1"); + t_Lane1Mat2 = serializedObject.FindProperty("Lane1Mat2"); + t_Lane2Mat1 = serializedObject.FindProperty("Lane2Mat1"); + t_Lane2Mat2 = serializedObject.FindProperty("Lane2Mat2"); + t_Lane3Mat1 = serializedObject.FindProperty("Lane3Mat1"); + t_Lane3Mat2 = serializedObject.FindProperty("Lane3Mat2"); + t_rType = serializedObject.FindProperty("rType"); + t_iStopType = serializedObject.FindProperty("iStopType"); + t_lType = serializedObject.FindProperty("lType"); + } + + + public override void OnInspectorGUI() + { + if (Event.current.type == EventType.ValidateCommand) + { + switch (Event.current.commandName) + { + case "UndoRedoPerformed": + TriggerRoadUpdate(true); + break; + } + } + + serializedObject.Update(); + + //Graphic null checks: + if (!bHasInit) + { + Init(); + } + + Line(); + EditorGUILayout.BeginHorizontal(); + { + GSDRoad road1 = tInter.Node1.GSDSpline.transform.parent.GetComponent(); + GSDRoad road2 = tInter.Node2.GSDSpline.transform.parent.GetComponent(); + EditorGUILayout.LabelField("First road: " + road1.name + " node: " + tInter.Node1.name); + EditorGUILayout.LabelField("Second road: " + road2.name + " node: " + tInter.Node2.name); + } + EditorGUILayout.EndHorizontal(); + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Intersection options", EditorStyles.boldLabel); + if (GUILayout.Button("Update intersection", GSDLoadButton)) + { + TriggerRoadUpdate(true); + } + EditorGUILayout.EndHorizontal(); + + //Option: Auto update: + t_opt_AutoUpdateIntersections.boolValue = EditorGUILayout.Toggle("Auto-update:", tInter.opt_AutoUpdateIntersections); + + //Option: Gizmo: + t_bDrawGizmo.boolValue = EditorGUILayout.Toggle("Gizmo:", tInter.bDrawGizmo); + + //UI: + EditorGUILayout.BeginHorizontal(); + if (tInter.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + EditorGUILayout.LabelField("Intersection type: 3 way"); + } + else + { + EditorGUILayout.LabelField("Intersection type: 4 way"); + } + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + Line(); + EditorGUILayout.BeginVertical(); + if (GUILayout.Button("Access objects on first road node")) + { + Selection.objects = new Object[1] { tInter.Node1 }; + } + if (GUILayout.Button("Access objects on second road node")) + { + Selection.objects = new Object[1] { tInter.Node2 }; + } + EditorGUILayout.EndVertical(); + //Option: Intersection turn lane options + Line(); + EditorGUILayout.LabelField("Intersection turn lane options:"); + if (tInter.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + t_rType.enumValueIndex = (int) EditorGUILayout.Popup((int) tInter.rType, rTypeDescriptions_3Way); + } + else + { + t_rType.enumValueIndex = (int) EditorGUILayout.Popup((int) tInter.rType, rTypeDescriptions); + } + + //Option: Left yield on green: + if (tInter.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + t_bLeftTurnYieldOnGreen.boolValue = EditorGUILayout.Toggle("Left yield on green: ", tInter.bLeftTurnYieldOnGreen); + + bShowHelpLeftTurnGreen = EditorGUILayout.Foldout(bShowHelpLeftTurnGreen, status); + if (bShowHelpLeftTurnGreen) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Left yield on green: If checked, replaces the standard 3-light left turn light with a five-light yield on green left turn signal structure and sign."); + EditorGUILayout.EndVertical(); + } + } + Line(); + + + //Option: Intersection stop type: + t_iStopType.enumValueIndex = (int) EditorGUILayout.Popup("Intersection stop type:", (int) tInter.iStopType, iStopTypeEnumDescriptions); + + + if (tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + //Option: Traffic light timing type: + t_lType.enumValueIndex = (int) EditorGUILayout.Popup("Traffic light timing:", (int) tInter.lType, iTrafficLightSequenceTypeDesc); + + //Options: Traffic fixed light timings: + if (tInter.lType == GSDRoadIntersection.LightTypeEnum.Timed) + { + EditorGUILayout.LabelField("Traffic light fixed time lengths (in seconds):"); + EditorGUILayout.BeginHorizontal(); + t_opt_FixedTime_RegularLightLength.floatValue = EditorGUILayout.Slider("Green length: ", tInter.opt_FixedTime_RegularLightLength, 0.1f, 180f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_FixedTime_RegularLightLength.floatValue = 30f; + } + EditorGUILayout.EndHorizontal(); + + if (tInter.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + EditorGUILayout.BeginHorizontal(); + t_opt_FixedTime_LeftTurnLightLength.floatValue = EditorGUILayout.Slider("Left turn only length: ", tInter.opt_FixedTime_LeftTurnLightLength, 0.1f, 180f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_FixedTime_LeftTurnLightLength.floatValue = 10f; + } + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.BeginHorizontal(); + t_opt_FixedTime_AllRedLightLength.floatValue = EditorGUILayout.Slider("All red length: ", tInter.opt_FixedTime_AllRedLightLength, 0.1f, 180f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_FixedTime_AllRedLightLength.floatValue = 1f; + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + t_opt_FixedTime_YellowLightLength.floatValue = EditorGUILayout.Slider("Yellow light length: ", tInter.opt_FixedTime_YellowLightLength, 0.1f, 180f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_opt_FixedTime_YellowLightLength.floatValue = 3f; + } + EditorGUILayout.EndHorizontal(); + } + } + + + if (tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + //Option: Traffic light poles: + Line(); + EditorGUILayout.LabelField("Traffic light poles:"); + t_bTrafficPoleStreetLight.boolValue = EditorGUILayout.Toggle("Street lights: ", tInter.bTrafficPoleStreetLight); + + //Option: Traffic light pole gray color: + t_bTrafficLightGray.boolValue = EditorGUILayout.Toggle("Gray color: ", tInter.bTrafficLightGray); + + //Option: Normal pole alignment: + t_bRegularPoleAlignment.boolValue = EditorGUILayout.Toggle("Normal pole alignment: ", tInter.bRegularPoleAlignment); + bShowTLPole = EditorGUILayout.Foldout(bShowTLPole, status); + if (bShowTLPole) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Street lights: If checked, attaches street lights to each intersection pole. Point lights optional and can be manipulated in the next option segment."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Gray color: If checked, sets the traffic light pole base materials to gray galvanized steel. If unchecked the material used is black metal paint."); + GUILayout.Space(4f); + EditorGUILayout.LabelField("Normal pole alignment: Recommended to keep this option on unless abnormal twisting of light objects is occurring. Turn this option off if the roads immediately surrounding your intersection are curved at extreme angles and cause irregular twisting of the traffic light objects. Turning this option off will attempt to align the poles perpendicular to the adjacent relevant road without any part existing over the main intersection bounds."); + EditorGUILayout.EndVertical(); + } + + //Option: Point lights enabled: + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Point lights:"); + EditorGUILayout.EndHorizontal(); + t_bLightsEnabled.boolValue = EditorGUILayout.Toggle(" Point lights enabled: ", tInter.bLightsEnabled); + + //Options: Street point light options: + if (tInter.bTrafficPoleStreetLight) + { + //Option: Street light range: + EditorGUILayout.BeginHorizontal(); + t_StreetLight_Range.floatValue = EditorGUILayout.Slider(" Street light range: ", tInter.StreetLight_Range, 1f, 128f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_StreetLight_Range.floatValue = 30f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Street light intensity: + EditorGUILayout.BeginHorizontal(); + t_StreetLight_Intensity.floatValue = EditorGUILayout.Slider(" Street light intensity: ", tInter.StreetLight_Intensity, 0f, 8f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_StreetLight_Intensity.floatValue = 1f; + } + EditorGUILayout.EndHorizontal(); + + //Option: Street light color: + EditorGUILayout.BeginHorizontal(); + t_StreetLight_Color.colorValue = EditorGUILayout.ColorField(" Street light color: ", tInter.StreetLight_Color); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_StreetLight_Color.colorValue = new Color(1f, 0.7451f, 0.27451f, 1f); + ; + } + EditorGUILayout.EndHorizontal(); + } + bShowLightHelp = EditorGUILayout.Foldout(bShowLightHelp, status); + if (bShowLightHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Point lights: Enabled means that point lights for the traffic lights (and street lights, if enabled) will be turned on. This is accessible via script \"bLightsEnabled\""); + + GUILayout.Space(4f); + EditorGUILayout.LabelField("If street pole lights enabled: Street light range, intensity and color: These settings directly correlate to the standard point light settings."); + + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + Line(); + + //Option: Traffic light scaling sensitivity: + EditorGUILayout.LabelField("Traffic light scaling sensitivity: *Does not auto-update"); + EditorGUILayout.BeginHorizontal(); + t_ScalingSense.floatValue = EditorGUILayout.Slider(tInter.ScalingSense, 0f, 200f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_ScalingSense.floatValue = 170f; + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + bShowTLSense = EditorGUILayout.Foldout(bShowTLSense, status); + if (GUILayout.Button("Manually update intersection", EditorStyles.miniButton, GUILayout.Width(170f))) + { + TriggerRoadUpdate(true); + } + EditorGUILayout.EndHorizontal(); + if (bShowTLSense) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Increasing this value will increase the scaling sensitivity relative to the size of the intersection. Higher scaling value = bigger traffic lights at further distances. Default value is 170."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + GUILayout.Space(4f); + } + + //Option: Grade correction modifier: + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Grade correction factor: *Does not auto-update"); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + t_GradeMod.floatValue = EditorGUILayout.Slider(tInter.GradeMod, 0.01f, 2f); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + t_GradeMod.floatValue = 0.375f; + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + bGradeCorrect = EditorGUILayout.Foldout(bGradeCorrect, status); + if (GUILayout.Button("Manually update intersection", EditorStyles.miniButton, GUILayout.Width(170f))) + { + tInter.UpdateRoads(); + } + EditorGUILayout.EndHorizontal(); + if (bGradeCorrect) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("If using extreme road grades immediately surrounding the intersection, terrain height matching errors may occur at the point of road expansion leading to the intersection."); + EditorGUILayout.LabelField("Raise this value if you see terrain poking through the road at the road expansion areas."); + EditorGUILayout.LabelField("Lower this value if you are not using road mesh colliders and notice dips at the expansion points."); + EditorGUILayout.LabelField("Default value is 0.375 meters, which is the maximum value for a linear range of 0% to 20% grade."); + EditorGUILayout.LabelField("Recommended to keep grades and angles small leading up to intersections."); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets settings to default."); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + + //Option: Use default materials: + Line(); + t_bUseDefaultMaterials.boolValue = EditorGUILayout.Toggle("Use default materials:", tInter.bUseDefaultMaterials); + bShowDefaultMatHelp = EditorGUILayout.Foldout(bShowDefaultMatHelp, status); + if (bShowDefaultMatHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Checking this option will reset all materials for this intersection and use the default intersection materials that come with this addon."); + EditorGUILayout.EndVertical(); + } + + + Line(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Center marker material(s):"); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.ResetMaterials_Center(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + //Options: Center materials: + // EditorGUILayout.BeginHorizontal(); + // EditorGUILayout.PropertyField (t_MarkerCenter1, new GUIContent ("Center material #1:")); + // if(tInter.MarkerCenter1 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter1 = null; } + // EditorGUILayout.EndHorizontal(); + // if(tInter.MarkerCenter1 != null){ + // EditorGUILayout.BeginHorizontal(); + // EditorGUILayout.PropertyField (t_MarkerCenter2, new GUIContent ("Center material #2:")); + // if(tInter.MarkerCenter2 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter2 = null; } + // EditorGUILayout.EndHorizontal(); + // if(tInter.MarkerCenter2 != null){ + // EditorGUILayout.BeginHorizontal(); + // EditorGUILayout.PropertyField (t_MarkerCenter3, new GUIContent ("Center material #3:")); + // if(tInter.MarkerCenter3 != null && GUILayout.Button(btnDeleteText,GSDImageButton,GUILayout.Width(16f))){ t_MarkerCenter3 = null; } + // EditorGUILayout.EndHorizontal(); + // } + // } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerCenter1, new GUIContent(" Mat #1: ")); + if (tInter.MarkerCenter1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { tInter.MarkerCenter1 = null; } + EditorGUILayout.EndHorizontal(); + + if (tInter.MarkerCenter1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerCenter2, new GUIContent(" Mat #2: ")); + if (tInter.MarkerCenter2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { tInter.MarkerCenter2 = null; } + EditorGUILayout.EndHorizontal(); + } + if (tInter.MarkerCenter2 != null && tInter.MarkerCenter1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerCenter3, new GUIContent(" Mat #3: ")); + if (tInter.MarkerCenter3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { tInter.MarkerCenter3 = null; } + EditorGUILayout.EndHorizontal(); + } + + bShowMarkerCenter = EditorGUILayout.Foldout(bShowMarkerCenter, status); + if (bShowMarkerCenter) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Center marker materials require transparent shaders. Covers the center area of the intersection. Displayed in order #1 on bottom to #4 on top. Combine with transparent shaders which accept shadows to allow for easy marking."); + DoDefaultHelpMat(); + DoDeleteHelpMat(); + EditorGUILayout.EndVertical(); + } + Line(); + + //Options: Marker ext stretched materials: + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Exterior fitted marker material(s):"); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.ResetMaterials_Ext_Stretched(); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Stretch1, new GUIContent(" Mat #1: ")); + if (tInter.MarkerExt_Stretch1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Stretch1 = null; + } + EditorGUILayout.EndHorizontal(); + + if (tInter.MarkerExt_Stretch1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Stretch2, new GUIContent(" Mat #2: ")); + if (tInter.MarkerExt_Stretch2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Stretch2 = null; + } + EditorGUILayout.EndHorizontal(); + } + if (tInter.MarkerExt_Stretch2 != null && tInter.MarkerExt_Stretch1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Stretch3, new GUIContent(" Mat #3: ")); + if (tInter.MarkerExt_Stretch3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Stretch3 = null; + } + EditorGUILayout.EndHorizontal(); + } + + bShowMarkerStretch = EditorGUILayout.Foldout(bShowMarkerStretch, status); + if (bShowMarkerStretch) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Fitted marker materials require transparent shaders. Covers the exterior area of the intersection with the UV's stretched to match at a 1:1 ratio. Should be use for intersection markings and any visual effects like dirt." + HelpText1); + DoDefaultHelpMat(); + DoDeleteHelpMat(); + EditorGUILayout.EndVertical(); + } + Line(); + + //Options: Marker ext tiled materials: + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Exterior tiled marker material(s):"); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.ResetMaterials_Ext_Tiled(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Tiled1, new GUIContent(" Mat #1: ")); + if (tInter.MarkerExt_Tiled1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Tiled1 = null; + } + EditorGUILayout.EndHorizontal(); + + if (tInter.MarkerExt_Tiled1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Tiled2, new GUIContent(" Mat #2: ")); + if (tInter.MarkerExt_Tiled2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Tiled2 = null; + } + EditorGUILayout.EndHorizontal(); + } + if (tInter.MarkerExt_Tiled2 != null && tInter.MarkerExt_Tiled1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_MarkerExt_Tiled3, new GUIContent(" Mat #3: ")); + if (tInter.MarkerExt_Tiled3 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.MarkerExt_Tiled3 = null; + } + EditorGUILayout.EndHorizontal(); + } + + bShowMarkerTiled = EditorGUILayout.Foldout(bShowMarkerTiled, status); + if (bShowMarkerTiled) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Covers the exterior area of the intersection with the UV's tiled matching world coordinates. Tiled and used for road pavement textures. UV coordinates will match up seamlessly with road pavement." + HelpText1); + DoDefaultHelpMat(); + DoDeleteHelpMat(); + EditorGUILayout.EndVertical(); + } + Line(); + + //Option: Lane section 0: + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Lanes marker materials:"); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.ResetMaterials_Lanes(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane0Mat1, new GUIContent("Lane section 0 mat #1:")); + if (tInter.Lane0Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane0Mat1 = null; + } + EditorGUILayout.EndHorizontal(); + if (tInter.Lane0Mat1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane0Mat2, new GUIContent("Lane section 0 mat #2:")); + if (tInter.Lane0Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane0Mat2 = null; + } + EditorGUILayout.EndHorizontal(); + } + + + //Option: Lane section 1: + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane1Mat1, new GUIContent("Lane section 1 mat #1:")); + if (tInter.Lane1Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane1Mat1 = null; + } + EditorGUILayout.EndHorizontal(); + if (tInter.Lane1Mat1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane1Mat2, new GUIContent("Lane section 1 mat #2:")); + if (tInter.Lane1Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { tInter.Lane1Mat2 = null; } + EditorGUILayout.EndHorizontal(); + } + + //Option: Lane section 2: + if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || tInter.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane2Mat1, new GUIContent("Lane section 2 mat #1:")); + if (tInter.Lane2Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane2Mat1 = null; + } + EditorGUILayout.EndHorizontal(); + if (tInter.Lane2Mat1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane2Mat2, new GUIContent("Lane section 2 mat #2:")); + if (tInter.Lane2Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { tInter.Lane2Mat2 = null; } + EditorGUILayout.EndHorizontal(); + } + } + GUILayout.Space(4f); + + //Option: Lane section 3: + if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane3Mat1, new GUIContent("Lane section 3 mat #1:")); + if (tInter.Lane3Mat1 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane3Mat1 = null; + } + EditorGUILayout.EndHorizontal(); + if (tInter.Lane3Mat1 != null) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(t_Lane3Mat2, new GUIContent("Lane section 3 mat #2:")); + if (tInter.Lane3Mat2 != null && GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + tInter.Lane3Mat2 = null; + } + EditorGUILayout.EndHorizontal(); + } + } + bShowLanes = EditorGUILayout.Foldout(bShowLanes, status); + if (bShowLanes) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Covers individual lane sections in the intersection. Used for high-definition line marking."); + EditorGUILayout.LabelField("Lane section 0 = Left side of the intersection where oncoming traffic travels. Use lane texture which matches the number of lanes used on the road system, with a white left line and a yellow right line."); + + if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + EditorGUILayout.LabelField("Lane section 1 = Left turn lane. Use a single lane texture with a yellow left line and a white right line."); + EditorGUILayout.LabelField("Lane section 2 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); + EditorGUILayout.LabelField("Lane section 3 = Right turn lane. Use a single lane texture with a white right line."); + } + else if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + EditorGUILayout.LabelField("Lane section 1 = Left turn lane. Use a single lane texture with a yellow left line and a white right line."); + EditorGUILayout.LabelField("Lane section 2 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); + } + else if (tInter.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + EditorGUILayout.LabelField("Lane section 1 = Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line."); + } + + EditorGUILayout.LabelField(HelpText1); + DoDefaultHelpMat(); + DoDeleteHelpMat(); + EditorGUILayout.EndVertical(); + } + Line(); + + // if(bDebug){ + // Line(); + // EditorGUILayout.LabelField("Debug"); + // if(tInter.Node1 != null){ EditorGUILayout.LabelField(" Node1: " + tInter.Node1.transform.name); } else { EditorGUILayout.LabelField(" Node1: null"); } + // if(tInter.Node2 != null){ EditorGUILayout.LabelField(" Node2: " + tInter.Node2.transform.name); } else { EditorGUILayout.LabelField(" Node2: null"); } + // if(tInter.Node1 != null){ EditorGUILayout.LabelField(" UID1: " + tInter.Node1.UID); } else { EditorGUILayout.LabelField(" UID1: null"); } + // if(tInter.Node2 != null){ EditorGUILayout.LabelField(" UID2: " + tInter.Node2.UID); } else { EditorGUILayout.LabelField(" UID2: null"); } + // EditorGUILayout.LabelField(" Same spline: " + tInter.bSameSpline); + // EditorGUILayout.LabelField(" bFlipped: " + tInter.bFlipped); + // EditorGUILayout.LabelField(" IgnoreSide: " + tInter.IgnoreSide); + // EditorGUILayout.LabelField(" IgnoreCorner: " + tInter.IgnoreCorner); + // + // if(tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || tInter.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2){ + // if(tInter.LightsRR != null){ EditorGUILayout.LabelField(" LightsRR: " + tInter.LightsRR); } else { EditorGUILayout.LabelField(" LightsRR: null"); } + // if(tInter.LightsRR != null || tInter.LightsRR.MR_Main != null){ EditorGUILayout.LabelField(" MR_Main: " + tInter.LightsRR.MR_Main); } else { EditorGUILayout.LabelField(" LightsRR.MR_Main: null"); } + // if(tInter.LightsRR != null || tInter.LightsRR.MR_Left != null){ EditorGUILayout.LabelField(" MR_Left: " + tInter.LightsRR.MR_Left); } else { EditorGUILayout.LabelField(" LightsRR.MR_Left: null"); } + // if(tInter.LightsRR != null || tInter.LightsRR.MR_Right != null){ EditorGUILayout.LabelField(" MR_Right: " + tInter.LightsRR.MR_Right); } else { EditorGUILayout.LabelField(" LightsRR.MR_Right: null"); } + // if(tInter.LightsRL != null){ EditorGUILayout.LabelField(" LightsRL: " + tInter.LightsRL); } else { EditorGUILayout.LabelField(" LightsRL: null"); } + // if(tInter.LightsLL != null){ EditorGUILayout.LabelField(" LightsLL: " + tInter.LightsLL); } else { EditorGUILayout.LabelField(" LightsLL: null"); } + // if(tInter.LightsLR != null){ EditorGUILayout.LabelField(" LightsLR: " + tInter.LightsLR); } else { EditorGUILayout.LabelField(" LightsLR: null"); } + // } + // Line(); + // } + + + //Set change bools: + bool bToggleTrafficLightPoleColor = false; + bool bTogglePointLights = false; + bool bGizmoChange = false; + bool bMatChange = false; + bool bRoadUpdate = false; + + if (GUI.changed) + { + //Option: Gizmo: + if (t_bDrawGizmo.boolValue != tInter.bDrawGizmo) + { + bGizmoChange = true; + } + + //Option: Intersection turn lane options + if ((int) tInter.rType != t_rType.enumValueIndex) + { + bMatChange = true; + bRoadUpdate = true; + } + + //Option: Left yield on green: + if (t_bLeftTurnYieldOnGreen.boolValue != tInter.bLeftTurnYieldOnGreen) + { + bRoadUpdate = true; + } + + //Option: Intersection stop type: + if (t_iStopType.enumValueIndex != (int) tInter.iStopType) + { + bRoadUpdate = true; + } + + //Option: Traffic light poles: + if (t_bTrafficPoleStreetLight.boolValue != tInter.bTrafficPoleStreetLight) + { + bRoadUpdate = true; + } + + //Option: Traffic light pole gray color: + if (t_bTrafficLightGray.boolValue != tInter.bTrafficLightGray) + { + bToggleTrafficLightPoleColor = true; + } + + //Option: Normal pole alignment: + if (t_bRegularPoleAlignment.boolValue != tInter.bRegularPoleAlignment) + { + bRoadUpdate = true; + } + + //Option: Point lights enabled: + if (t_bLightsEnabled.boolValue != tInter.bLightsEnabled) + { + bTogglePointLights = true; + } + + //Option: Street light range: + if (!GSDRootUtil.IsApproximately(t_StreetLight_Range.floatValue, tInter.StreetLight_Range, 0.01f)) + { + bTogglePointLights = true; + } + + //Option: Street light intensity: + if (!GSDRootUtil.IsApproximately(t_StreetLight_Intensity.floatValue, tInter.StreetLight_Intensity, 0.01f)) + { + bTogglePointLights = true; + } + + //Option: Street light color: + if (t_StreetLight_Color.colorValue != tInter.StreetLight_Color) + { + bTogglePointLights = true; + } + + //Option: Use default materials: + if (t_bUseDefaultMaterials.boolValue != tInter.bUseDefaultMaterials) + { + bMatChange = true; + } + + if (t_MarkerCenter1 == null || t_MarkerCenter1.objectReferenceValue == null) + { + tInter.MarkerCenter1 = null; + } + if (t_MarkerCenter2 == null || t_MarkerCenter2.objectReferenceValue == null) + { + tInter.MarkerCenter2 = null; + } + if (t_MarkerCenter3 == null || t_MarkerCenter3.objectReferenceValue == null) + { + tInter.MarkerCenter3 = null; + } + if (t_MarkerExt_Stretch1 == null || t_MarkerExt_Stretch1.objectReferenceValue == null) + { + tInter.MarkerExt_Stretch1 = null; + } + if (t_MarkerExt_Stretch2 == null || t_MarkerExt_Stretch2.objectReferenceValue == null) + { + tInter.MarkerExt_Stretch2 = null; + } + if (t_MarkerExt_Stretch3 == null || t_MarkerExt_Stretch3.objectReferenceValue == null) + { + tInter.MarkerExt_Stretch3 = null; + } + if (t_MarkerExt_Tiled1 == null || t_MarkerExt_Tiled1.objectReferenceValue == null) + { + tInter.MarkerExt_Tiled1 = null; + } + if (t_MarkerExt_Tiled2 == null || t_MarkerExt_Tiled2.objectReferenceValue == null) + { + tInter.MarkerExt_Tiled2 = null; + } + if (t_MarkerExt_Tiled3 == null || t_MarkerExt_Tiled3.objectReferenceValue == null) + { + tInter.MarkerExt_Tiled3 = null; + } + if (t_Lane0Mat1 == null || t_Lane0Mat1.objectReferenceValue == null) + { + tInter.Lane0Mat1 = null; + } + if (t_Lane0Mat2 == null || t_Lane0Mat2.objectReferenceValue == null) + { + tInter.Lane0Mat2 = null; + } + if (t_Lane1Mat1 == null || t_Lane1Mat1.objectReferenceValue == null) + { + tInter.Lane1Mat1 = null; + } + if (t_Lane1Mat2 == null || t_Lane1Mat2.objectReferenceValue == null) + { + tInter.Lane1Mat2 = null; + } + if (t_Lane2Mat1 == null || t_Lane2Mat1.objectReferenceValue == null) + { + tInter.Lane2Mat1 = null; + } + if (t_Lane2Mat2 == null || t_Lane2Mat2.objectReferenceValue == null) + { + tInter.Lane2Mat2 = null; + } + if (t_Lane3Mat1 == null || t_Lane3Mat1.objectReferenceValue == null) + { + tInter.Lane3Mat1 = null; + } + if (t_Lane3Mat2 == null || t_Lane3Mat2.objectReferenceValue == null) + { + tInter.Lane3Mat2 = null; + } + + if (tInter.MarkerCenter1 != null && t_MarkerCenter1.objectReferenceValue != tInter.MarkerCenter1) + { + bMatChange = true; + } + if (tInter.MarkerCenter2 != null && t_MarkerCenter2.objectReferenceValue != tInter.MarkerCenter2) + { + bMatChange = true; + } + if (tInter.MarkerCenter3 != null && t_MarkerCenter3.objectReferenceValue != tInter.MarkerCenter3) + { + bMatChange = true; + } + if (tInter.MarkerExt_Stretch1 != null && t_MarkerExt_Stretch1.objectReferenceValue != tInter.MarkerExt_Stretch1) + { + bMatChange = true; + } + if (tInter.MarkerExt_Stretch2 != null && t_MarkerExt_Stretch2.objectReferenceValue != tInter.MarkerExt_Stretch2) + { + bMatChange = true; + } + if (tInter.MarkerExt_Stretch3 != null && t_MarkerExt_Stretch3.objectReferenceValue != tInter.MarkerExt_Stretch3) + { + bMatChange = true; + } + if (tInter.MarkerExt_Tiled1 != null && t_MarkerExt_Tiled1.objectReferenceValue != tInter.MarkerExt_Tiled1) + { + bMatChange = true; + } + if (tInter.MarkerExt_Tiled2 != null && t_MarkerExt_Tiled2.objectReferenceValue != tInter.MarkerExt_Tiled2) + { + bMatChange = true; + } + if (tInter.MarkerExt_Tiled3 != null && t_MarkerExt_Tiled3.objectReferenceValue != tInter.MarkerExt_Tiled3) + { + bMatChange = true; + } + if (tInter.Lane0Mat1 != null && t_Lane0Mat1.objectReferenceValue != tInter.Lane0Mat1) + { + bMatChange = true; + } + if (tInter.Lane0Mat2 != null && t_Lane0Mat2.objectReferenceValue != tInter.Lane0Mat2) + { + bMatChange = true; + } + if (tInter.Lane1Mat1 != null && t_Lane1Mat1.objectReferenceValue != tInter.Lane1Mat1) + { + bMatChange = true; + } + if (tInter.Lane1Mat2 != null && t_Lane1Mat2.objectReferenceValue != tInter.Lane1Mat2) + { + bMatChange = true; + } + if (tInter.Lane2Mat1 != null && t_Lane2Mat1.objectReferenceValue != tInter.Lane2Mat1) + { + bMatChange = true; + } + if (tInter.Lane2Mat2 != null && t_Lane2Mat2.objectReferenceValue != tInter.Lane2Mat2) + { + bMatChange = true; + } + if (tInter.Lane3Mat1 != null && t_Lane3Mat1.objectReferenceValue != tInter.Lane3Mat1) + { + bMatChange = true; + } + if (tInter.Lane3Mat2 != null && t_Lane3Mat2.objectReferenceValue != tInter.Lane3Mat2) + { + bMatChange = true; + } + + + //Apply changes: + serializedObject.ApplyModifiedProperties(); + + + //Apply secondary effects: + if (bGizmoChange) + { + MeshRenderer[] tMRs = tInter.transform.GetComponentsInChildren(); + int tCount = tMRs.Length; + for (int i = 0; i < tCount; i++) + { + //EditorUtility.SetSelectedWireframeHidden(tMRs[i], !tInter.bDrawGizmo); + EditorUtility.SetSelectedRenderState(tMRs[i], tInter.bDrawGizmo ? EditorSelectedRenderState.Wireframe : EditorSelectedRenderState.Hidden); + + } + SceneView.RepaintAll(); + } + + if (bTogglePointLights) + { + tInter.TogglePointLights(tInter.bLightsEnabled); + } + + if (bToggleTrafficLightPoleColor) + { + tInter.ToggleTrafficLightPoleColor(); + } + + if (bMatChange) + { + tInter.UpdateMaterials(); + if (tInter.bUseDefaultMaterials) + { + tInter.ResetMaterials_All(); + } + } + + if (bRoadUpdate) + { + TriggerRoadUpdate(); + } + + EditorUtility.SetDirty(tInter); + } + } + + + public void OnSceneGUI() + { + Event current = Event.current; + int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); + + // if (Event.current.type == EventType.MouseDrag && Event.current.button == 0){ + // //Update relevant splines: + // tInter.Node1.GSDSpline.Setup(); + // if(!tInter.bSameSpline){ + // tInter.Node2.GSDSpline.Setup(); + // } + // bMouseDragHasProcessed = false; + // } + // + // if(Event.current.type == EventType.MouseUp && Event.current.button == 0){ + // if(!bMouseDragHasProcessed){ + // tInter.Node1.transform.position = tInter.transform.position; + // tInter.Node2.transform.position = tInter.transform.position; + // tInter.StartCoroutine(TriggerRoadUpdate()); + // } + // bMouseDragHasProcessed = true; + // } + + if (Event.current.type == EventType.MouseUp && Event.current.button == 0) + { + if (tInter.transform.position != tInter.Node1.transform.position) + { + tInter.Node1.transform.position = tInter.transform.position; + tInter.Node2.transform.position = tInter.transform.position; + tInter.Height = tInter.transform.position.y; + TriggerRoadUpdate(); + } + } + + + + if (current.type == EventType.ValidateCommand) + { + switch (current.commandName) + { + case "UndoRedoPerformed": + TriggerRoadUpdate(true); + break; + } + } + + if (current.type == EventType.MouseDown) + { + return; + } + + if (Selection.activeGameObject == tInter.transform.gameObject) + { + if (current.keyCode == KeyCode.F5) + { + if (tInter != null && tInter.Node1 != null && tInter.Node2 != null) + { + TriggerRoadUpdate(); + } + } + } + + // switch(current.type){ + // case EventType.layout: + //// if(current.type != EventType.MouseDown){ + // HandleUtility.AddDefaultControl(controlID); + //// } + // break; + // + // } + + if (controlID == 1) + { + //Do nothing + } + if (GUI.changed) + { + EditorUtility.SetDirty(tInter); + } + } + + + private void TriggerRoadUpdate(bool bForce = false) + { + if (!bForce && !tInter.opt_AutoUpdateIntersections) + { + return; + } + + if (tInter != null && tInter.Node1 != null && tInter.Node2 != null) + { + if (!tInter.Node1.GSDSpline.tRoad.Editor_bIsConstructing && !tInter.Node2.GSDSpline.tRoad.Editor_bIsConstructing) + { + if (!tInter.bSameSpline) + { + tInter.Node1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[1]; + tInter.Node1.GSDSpline.tRoad.PiggyBacks[0] = tInter.Node2.GSDSpline; + } + tInter.Node1.GSDSpline.tRoad.EditorUpdateMe = true; + } + } + } + + + void Init() + { + EditorStyles.label.wordWrap = true; + bHasInit = true; + if (btnRefreshText == null) + { + btnRefreshText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; + } + if (btnDeleteText == null) + { + btnDeleteText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; + } + if (LoadBtnBG == null) + { + LoadBtnBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBGGlow == null) + { + LoadBtnBGGlow = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; + } + + if (GSDImageButton == null) + { + GSDImageButton = new GUIStyle(GUI.skin.button); + GSDImageButton.contentOffset = new Vector2(0f, 0f); + GSDImageButton.border = new RectOffset(0, 0, 0, 0); + GSDImageButton.fixedHeight = 16f; + GSDImageButton.padding = new RectOffset(0, 0, 0, 0); + GSDImageButton.normal.background = null; + } + if (GSDLoadButton == null) + { + GSDLoadButton = new GUIStyle(GUI.skin.button); + GSDLoadButton.contentOffset = new Vector2(0f, 1f); + GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDLoadButton.normal.background = LoadBtnBG; + GSDLoadButton.active.background = LoadBtnBGGlow; + GSDLoadButton.focused.background = LoadBtnBGGlow; + GSDLoadButton.hover.background = LoadBtnBGGlow; + GSDLoadButton.fixedHeight = 16f; + GSDLoadButton.fixedWidth = 128f; + } + } + + + void DoDefaultHelpMat() + { + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Resets material(s) to default materials."); + EditorGUILayout.EndHorizontal(); + } + + + void DoDeleteHelpMat() + { + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + + } + EditorGUILayout.LabelField(" = Removes material(s) from intersection."); + EditorGUILayout.EndHorizontal(); + } + + + void Line() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar + GUILayout.Space(4f); + } } \ No newline at end of file diff --git a/Editor/GSDRoadSystemEditor.cs b/Editor/GSDRoadSystemEditor.cs index 0d04ce48..483b0473 100755 --- a/Editor/GSDRoadSystemEditor.cs +++ b/Editor/GSDRoadSystemEditor.cs @@ -1,352 +1,377 @@ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using GSD; -[CustomEditor(typeof(GSDRoadSystem))] -public class GSDRoadSystemEditor : Editor -{ - //Main target for this editor file: - protected GSDRoadSystem GSDRS { get { return (GSDRoadSystem)target; } } - - //Serialized properties: - SerializedProperty bTempMultithreading; - SerializedProperty bTempSaveMeshAssets; - - //Editor only variables: - bool bUpdateGlobal_Multithread = false; - bool bUpdateGlobal_SaveMesh = false; - - // //Editor only camera variables: - // GSDRoadIntersection[] tInters = null; - // int tInterIndex = 0; - // GSDSplineN[] tBridges = null; - // int tBridgesIndex = 0; - // bool bHasBridgeInit = false; - // bool bHasInterInit = false; - // bool bHasDoneEither = false; - // bool bFlipEditorCamera = false; - // float CameraZoomFactor = 1f; - // float CameraHeightOffset = 1f; - // bool bCameraCustomRot = false; - // Vector3 CameraCustomRot = new Vector3(0.5f,0f,-0.5f); - - //Editor only graphic variables: - Texture2D LoadBtnBG = null; - Texture2D LoadBtnBGGlow = null; - GUIStyle WarningLabelStyle; - Texture2D WarningLabelBG; - GUIStyle GSDLoadButton = null; - - private void OnEnable() - { - bTempMultithreading = serializedObject.FindProperty("opt_bMultithreading"); - bTempSaveMeshAssets = serializedObject.FindProperty("opt_bSaveMeshes"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - bUpdateGlobal_Multithread = false; - bUpdateGlobal_SaveMesh = false; - EditorStyles.label.wordWrap = true; - InitChecks(); - - //Add road button: - Line(); - if (GUILayout.Button("Add road", GSDLoadButton, GUILayout.Width(128f))) - {// || GUILayout.Button(btnLoadText,GSDImageButton,GUILayout.Width(16f))){ - Selection.activeObject = GSDRS.AddRoad(); - } - Line(); - - //Multi-threading input: - EditorGUILayout.BeginHorizontal(); - bTempMultithreading.boolValue = EditorGUILayout.Toggle("Multi-threading enabled", GSDRS.opt_bMultithreading); - if (bTempMultithreading.boolValue != GSDRS.opt_bMultithreading) { bUpdateGlobal_Multithread = true; } - - //Update all roads button: - if (GUILayout.Button("Update all roads", EditorStyles.miniButton, GUILayout.Width(120f))) - { - GSDRS.UpdateAllRoads(); - } - EditorGUILayout.EndHorizontal(); - - //Save mesh assets input: - bTempSaveMeshAssets.boolValue = EditorGUILayout.Toggle("Save mesh assets: ", GSDRS.opt_bSaveMeshes); - if (bTempSaveMeshAssets.boolValue != GSDRS.opt_bSaveMeshes) { bUpdateGlobal_SaveMesh = true; } - if (GSDRS.opt_bSaveMeshes || bTempSaveMeshAssets.boolValue) - { - GUILayout.Label("WARNING: Saving meshes as assets is very slow and can increase road generation time by several minutes.", WarningLabelStyle); - } - - //Online manual button: - GUILayout.Space(4f); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - - if (GSDRS.EditorPlayCamera == null) - { - GSDRS.EditorCameraSetSingle(); - } - Line(); - - // bHasDoneEither = false; - - // //View intersection - // DoInter(); - - //View bridges - // DoBridges(); - // if(bHasDoneEither){ - // EditorGUILayout.LabelField("* Hotkeys only function when this RoadArchitectSystem object is selected", EditorStyles.miniLabel); - // } - - //Hotkey check: - DoHotKeyCheck(); - - if (GUI.changed) - { - serializedObject.ApplyModifiedProperties(); - - //Multithreading global change: - if (bUpdateGlobal_Multithread) - { - GSDRS.UpdateAllRoads_MultiThreadOptions(); - } - - //Save mesh assets global change: - if (bUpdateGlobal_SaveMesh) - { - GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); - } - } - } - - void InitChecks() - { - if (WarningLabelBG == null) - { - WarningLabelBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/WarningLabelBG.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBG == null) - { - LoadBtnBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBGGlow == null) - { - LoadBtnBGGlow = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; - } - - if (GSDLoadButton == null) - { - GSDLoadButton = new GUIStyle(GUI.skin.button); - GSDLoadButton.contentOffset = new Vector2(0f, 1f); - GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDLoadButton.normal.background = LoadBtnBG; - GSDLoadButton.active.background = LoadBtnBGGlow; - GSDLoadButton.focused.background = LoadBtnBGGlow; - GSDLoadButton.hover.background = LoadBtnBGGlow; - GSDLoadButton.fixedHeight = 16f; - GSDLoadButton.fixedWidth = 128f; - GSDLoadButton.padding = new RectOffset(0, 0, 0, 0); - } - - if (WarningLabelStyle == null) - { - WarningLabelStyle = new GUIStyle(GUI.skin.textArea); - WarningLabelStyle.normal.textColor = Color.red; - WarningLabelStyle.active.textColor = Color.red; - WarningLabelStyle.hover.textColor = Color.red; - WarningLabelStyle.normal.background = WarningLabelBG; - WarningLabelStyle.active.background = WarningLabelBG; - WarningLabelStyle.hover.background = WarningLabelBG; - WarningLabelStyle.padding = new RectOffset(8, 8, 8, 8); - } - } - - // void DoInter(){ - // //View intersection - // if(!bHasInterInit){ - // bHasInterInit = true; - // tInters = (GSDRoadIntersection[])GameObject.FindObjectsOfType(typeof(GSDRoadIntersection)); - // if(tInters == null || tInters.Length < 1){ - // tInterIndex = -1; - // tInters = null; - // } - // } - // if(tInters != null && tInters.Length > 0 && tInterIndex > -1){ - // EditorGUILayout.BeginHorizontal(); - // if(GUILayout.Button("View next intersection",GUILayout.Width(150f))){ - // IncrementIntersection(); - // } - // EditorGUILayout.LabelField("Hotkey K"); - // EditorGUILayout.EndHorizontal(); - // bHasDoneEither = true; - // } - // } - // - // void IncrementIntersection(){ - // if(tInters != null && tInters.Length > 0){ - // tInterIndex+=1; - // if(tInterIndex >= tInters.Length){ tInterIndex = 0; } - // ShowIntersection(tInterIndex); - // } - // } - // - // void DoBridges(){ - // //View bridges - // if(!bHasBridgeInit){ - // bHasBridgeInit = true; - // GSDSplineN[] tSplineN = (GSDSplineN[])GameObject.FindObjectsOfType(typeof(GSDSplineN)); - // List tSplineNList = new List(); - // foreach(GSDSplineN tNode in tSplineN){ - // if(tNode.bIsBridgeStart && tNode.bIsBridgeMatched){ - // tSplineNList.Add(tNode); - // } - // } - // tBridges = tSplineNList.ToArray(); - // tBridgesIndex = 0; - // if(tBridges == null || tBridges.Length < 1){ - // tBridgesIndex = -1; - // tBridges = null; - // } - // } - // - // if(tBridges != null && tBridges.Length > 0 && tBridgesIndex > -1){ - // EditorGUILayout.BeginHorizontal(); - // if(GUILayout.Button("View next bridge",GUILayout.Width(150f))){ - // IncrementBridge(); - // } - // EditorGUILayout.LabelField("Hotkey L"); - // EditorGUILayout.EndHorizontal(); - // if(EditorApplication.isPlaying){ - // bool bChangeChecker = EditorGUILayout.Toggle("Flip camera Y:",bFlipEditorCamera); - // if(bChangeChecker != bFlipEditorCamera){ - // bFlipEditorCamera = bChangeChecker; - // ShowBridge(tBridgesIndex); - // } - // } - // - // if(EditorApplication.isPlaying){ - // float ChangeChecker = EditorGUILayout.Slider("Zoom factor:",CameraZoomFactor,0.02f,10f); - // if(!GSDRootUtil.IsApproximately(ChangeChecker,CameraZoomFactor,0.001f)){ - // CameraZoomFactor = ChangeChecker; - // ShowBridge(tBridgesIndex); - // } - // ChangeChecker = EditorGUILayout.Slider("Height offset:",CameraHeightOffset,0f,8f); - // if(!GSDRootUtil.IsApproximately(ChangeChecker,CameraHeightOffset,0.001f)){ - // CameraHeightOffset = ChangeChecker; - // ShowBridge(tBridgesIndex); - // } - // - // bool bChangeChecker = EditorGUILayout.Toggle("Custom camera rot:",bCameraCustomRot); - // if(bChangeChecker != bCameraCustomRot){ - // bCameraCustomRot = bChangeChecker; - // ShowBridge(tBridgesIndex); - // } - // if(bCameraCustomRot){ - // Vector3 vChangeChecker = default(Vector3); - // vChangeChecker.x = EditorGUILayout.Slider("Rotation X:",CameraCustomRot.x,-1f,1f); - // vChangeChecker.z = EditorGUILayout.Slider("Rotation Z:",CameraCustomRot.z,-1f,1f); - // - // if(vChangeChecker != CameraCustomRot){ - // CameraCustomRot = vChangeChecker; - // ShowBridge(tBridgesIndex); - // } - // } - // } - // - // bHasDoneEither = true; - // } - // } - // - // void IncrementBridge(){ - // if(tBridges != null && tBridges.Length > 0){ - // tBridgesIndex+=1; - // if(tBridgesIndex >= tBridges.Length){ tBridgesIndex = 0; } - // ShowBridge(tBridgesIndex); - // } - // } - // - // void ShowIntersection(int i){ - // if(EditorApplication.isPlaying && GSDRS.EditorPlayCamera != null){ - // GSDRS.EditorPlayCamera.transform.position = tInters[i].transform.position + new Vector3(-40f,20f,-40f); - // GSDRS.EditorPlayCamera.transform.rotation = Quaternion.LookRotation(tInters[i].transform.position - (tInters[i].transform.position + new Vector3(-40f,20f,-40f))); - // }else{ - // SceneView.lastActiveSceneView.pivot = tInters[i].transform.position; - // SceneView.lastActiveSceneView.Repaint(); - // } - // } - // - // void ShowBridge(int i){ - // if(EditorApplication.isPlaying && GSDRS.EditorPlayCamera != null){ - // Vector3 tBridgePos = ((tBridges[i].pos - tBridges[i].BridgeCounterpartNode.pos)*0.5f)+tBridges[i].BridgeCounterpartNode.pos; - // float tBridgeLength = Vector3.Distance(tBridges[i].pos,tBridges[i].BridgeCounterpartNode.pos); - // - // //Rotation: - // Vector3 tCameraRot = Vector3.Cross((tBridges[i].pos - tBridges[i].BridgeCounterpartNode.pos),Vector3.up); - // if(bCameraCustomRot){ - // tCameraRot = CameraCustomRot; - // }else{ - // tCameraRot = tCameraRot.normalized; - // } - // - // //Calc offset: - // Vector3 tBridgeOffset = tCameraRot * (tBridgeLength * 0.5f * CameraZoomFactor); - // - // //Height offset: - // tBridgeOffset.y = Mathf.Lerp(20f,120f,(tBridgeLength*0.001f)) * CameraZoomFactor * CameraHeightOffset; - // - // GSDRS.EditorPlayCamera.transform.position = tBridgePos + tBridgeOffset; - // GSDRS.EditorPlayCamera.transform.rotation = Quaternion.LookRotation(tBridgePos - (tBridgePos + tBridgeOffset)); - // }else{ - // SceneView.lastActiveSceneView.pivot = tBridges[i].transform.position; - // SceneView.lastActiveSceneView.Repaint(); - // } - // } - - void Line() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar - GUILayout.Space(4f); - } - - // bool bCtrl = false; - public void OnSceneGUI() - { - DoHotKeyCheck(); - } - - void DoHotKeyCheck() - { - bool bUsed = false; - Event current = Event.current; - int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - - // if(current.type == EventType.KeyDown){ - // if(current.keyCode == KeyCode.K){ - // IncrementIntersection(); - // bUsed = true; - // }else if(current.keyCode == KeyCode.L){ - // IncrementBridge(); - // bUsed = true; - // } - // } - - if (bUsed) - { - switch (current.type) - { - case EventType.Layout: - HandleUtility.AddDefaultControl(controlID); - break; - } - } - - if (GUI.changed) { EditorUtility.SetDirty(GSDRS); } - } +#region Imports +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using GSD; +#endregion + + +[CustomEditor(typeof(GSDRoadSystem))] +public class GSDRoadSystemEditor : Editor +{ + //Main target for this editor file: + protected GSDRoadSystem GSDRS { get { return (GSDRoadSystem) target; } } + + //Serialized properties: + SerializedProperty bTempMultithreading; + SerializedProperty bTempSaveMeshAssets; + + //Editor only variables: + bool bUpdateGlobal_Multithread = false; + bool bUpdateGlobal_SaveMesh = false; + + // //Editor only camera variables: + // GSDRoadIntersection[] tInters = null; + // int tInterIndex = 0; + // GSDSplineN[] tBridges = null; + // int tBridgesIndex = 0; + // bool bHasBridgeInit = false; + // bool bHasInterInit = false; + // bool bHasDoneEither = false; + // bool bFlipEditorCamera = false; + // float CameraZoomFactor = 1f; + // float CameraHeightOffset = 1f; + // bool bCameraCustomRot = false; + // Vector3 CameraCustomRot = new Vector3(0.5f,0f,-0.5f); + + //Editor only graphic variables: + Texture2D LoadBtnBG = null; + Texture2D LoadBtnBGGlow = null; + GUIStyle WarningLabelStyle; + Texture2D WarningLabelBG; + GUIStyle GSDLoadButton = null; + + + private void OnEnable() + { + bTempMultithreading = serializedObject.FindProperty("opt_bMultithreading"); + bTempSaveMeshAssets = serializedObject.FindProperty("opt_bSaveMeshes"); + } + + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + bUpdateGlobal_Multithread = false; + bUpdateGlobal_SaveMesh = false; + EditorStyles.label.wordWrap = true; + InitChecks(); + + //Add road button: + Line(); + if (GUILayout.Button("Add road", GSDLoadButton, GUILayout.Width(128f))) + {// || GUILayout.Button(btnLoadText,GSDImageButton,GUILayout.Width(16f))){ + Selection.activeObject = GSDRS.AddRoad(); + } + Line(); + + //Multi-threading input: + EditorGUILayout.BeginHorizontal(); + bTempMultithreading.boolValue = EditorGUILayout.Toggle("Multi-threading enabled", GSDRS.opt_bMultithreading); + if (bTempMultithreading.boolValue != GSDRS.opt_bMultithreading) + { + bUpdateGlobal_Multithread = true; + } + + //Update all roads button: + if (GUILayout.Button("Update all roads", EditorStyles.miniButton, GUILayout.Width(120f))) + { + GSDRS.UpdateAllRoads(); + } + EditorGUILayout.EndHorizontal(); + + //Save mesh assets input: + bTempSaveMeshAssets.boolValue = EditorGUILayout.Toggle("Save mesh assets: ", GSDRS.opt_bSaveMeshes); + if (bTempSaveMeshAssets.boolValue != GSDRS.opt_bSaveMeshes) + { + bUpdateGlobal_SaveMesh = true; + } + if (GSDRS.opt_bSaveMeshes || bTempSaveMeshAssets.boolValue) + { + GUILayout.Label("WARNING: Saving meshes as assets is very slow and can increase road generation time by several minutes.", WarningLabelStyle); + } + + //Online manual button: + GUILayout.Space(4f); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + + if (GSDRS.EditorPlayCamera == null) + { + GSDRS.EditorCameraSetSingle(); + } + Line(); + + // bHasDoneEither = false; + + // //View intersection + // DoInter(); + + //View bridges + // DoBridges(); + // if(bHasDoneEither){ + // EditorGUILayout.LabelField("* Hotkeys only function when this RoadArchitectSystem object is selected", EditorStyles.miniLabel); + // } + + //Hotkey check: + DoHotKeyCheck(); + + if (GUI.changed) + { + serializedObject.ApplyModifiedProperties(); + + //Multithreading global change: + if (bUpdateGlobal_Multithread) + { + GSDRS.UpdateAllRoads_MultiThreadOptions(); + } + + //Save mesh assets global change: + if (bUpdateGlobal_SaveMesh) + { + GSDRS.UpdateAllRoads_SaveMeshesAsAssetsOptions(); + } + } + } + + + void InitChecks() + { + if (WarningLabelBG == null) + { + WarningLabelBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/WarningLabelBG.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBG == null) + { + LoadBtnBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBGGlow == null) + { + LoadBtnBGGlow = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/otherbg2.png", typeof(Texture2D)) as Texture2D; + } + + if (GSDLoadButton == null) + { + GSDLoadButton = new GUIStyle(GUI.skin.button); + GSDLoadButton.contentOffset = new Vector2(0f, 1f); + GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDLoadButton.normal.background = LoadBtnBG; + GSDLoadButton.active.background = LoadBtnBGGlow; + GSDLoadButton.focused.background = LoadBtnBGGlow; + GSDLoadButton.hover.background = LoadBtnBGGlow; + GSDLoadButton.fixedHeight = 16f; + GSDLoadButton.fixedWidth = 128f; + GSDLoadButton.padding = new RectOffset(0, 0, 0, 0); + } + + if (WarningLabelStyle == null) + { + WarningLabelStyle = new GUIStyle(GUI.skin.textArea); + WarningLabelStyle.normal.textColor = Color.red; + WarningLabelStyle.active.textColor = Color.red; + WarningLabelStyle.hover.textColor = Color.red; + WarningLabelStyle.normal.background = WarningLabelBG; + WarningLabelStyle.active.background = WarningLabelBG; + WarningLabelStyle.hover.background = WarningLabelBG; + WarningLabelStyle.padding = new RectOffset(8, 8, 8, 8); + } + } + + + // void DoInter(){ + // //View intersection + // if(!bHasInterInit){ + // bHasInterInit = true; + // tInters = (GSDRoadIntersection[])GameObject.FindObjectsOfType(typeof(GSDRoadIntersection)); + // if(tInters == null || tInters.Length < 1){ + // tInterIndex = -1; + // tInters = null; + // } + // } + // if(tInters != null && tInters.Length > 0 && tInterIndex > -1){ + // EditorGUILayout.BeginHorizontal(); + // if(GUILayout.Button("View next intersection",GUILayout.Width(150f))){ + // IncrementIntersection(); + // } + // EditorGUILayout.LabelField("Hotkey K"); + // EditorGUILayout.EndHorizontal(); + // bHasDoneEither = true; + // } + // } + // + // + // void IncrementIntersection(){ + // if(tInters != null && tInters.Length > 0){ + // tInterIndex+=1; + // if(tInterIndex >= tInters.Length){ tInterIndex = 0; } + // ShowIntersection(tInterIndex); + // } + // } + // + // + // void DoBridges(){ + // //View bridges + // if(!bHasBridgeInit){ + // bHasBridgeInit = true; + // GSDSplineN[] tSplineN = (GSDSplineN[])GameObject.FindObjectsOfType(typeof(GSDSplineN)); + // List tSplineNList = new List(); + // foreach(GSDSplineN tNode in tSplineN){ + // if(tNode.bIsBridgeStart && tNode.bIsBridgeMatched){ + // tSplineNList.Add(tNode); + // } + // } + // tBridges = tSplineNList.ToArray(); + // tBridgesIndex = 0; + // if(tBridges == null || tBridges.Length < 1){ + // tBridgesIndex = -1; + // tBridges = null; + // } + // } + // + // if(tBridges != null && tBridges.Length > 0 && tBridgesIndex > -1){ + // EditorGUILayout.BeginHorizontal(); + // if(GUILayout.Button("View next bridge",GUILayout.Width(150f))){ + // IncrementBridge(); + // } + // EditorGUILayout.LabelField("Hotkey L"); + // EditorGUILayout.EndHorizontal(); + // if(EditorApplication.isPlaying){ + // bool bChangeChecker = EditorGUILayout.Toggle("Flip camera Y:",bFlipEditorCamera); + // if(bChangeChecker != bFlipEditorCamera){ + // bFlipEditorCamera = bChangeChecker; + // ShowBridge(tBridgesIndex); + // } + // } + // + // if(EditorApplication.isPlaying){ + // float ChangeChecker = EditorGUILayout.Slider("Zoom factor:",CameraZoomFactor,0.02f,10f); + // if(!GSDRootUtil.IsApproximately(ChangeChecker,CameraZoomFactor,0.001f)){ + // CameraZoomFactor = ChangeChecker; + // ShowBridge(tBridgesIndex); + // } + // ChangeChecker = EditorGUILayout.Slider("Height offset:",CameraHeightOffset,0f,8f); + // if(!GSDRootUtil.IsApproximately(ChangeChecker,CameraHeightOffset,0.001f)){ + // CameraHeightOffset = ChangeChecker; + // ShowBridge(tBridgesIndex); + // } + // + // bool bChangeChecker = EditorGUILayout.Toggle("Custom camera rot:",bCameraCustomRot); + // if(bChangeChecker != bCameraCustomRot){ + // bCameraCustomRot = bChangeChecker; + // ShowBridge(tBridgesIndex); + // } + // if(bCameraCustomRot){ + // Vector3 vChangeChecker = default(Vector3); + // vChangeChecker.x = EditorGUILayout.Slider("Rotation X:",CameraCustomRot.x,-1f,1f); + // vChangeChecker.z = EditorGUILayout.Slider("Rotation Z:",CameraCustomRot.z,-1f,1f); + // + // if(vChangeChecker != CameraCustomRot){ + // CameraCustomRot = vChangeChecker; + // ShowBridge(tBridgesIndex); + // } + // } + // } + // + // bHasDoneEither = true; + // } + // } + // + // + // void IncrementBridge(){ + // if(tBridges != null && tBridges.Length > 0){ + // tBridgesIndex+=1; + // if(tBridgesIndex >= tBridges.Length){ tBridgesIndex = 0; } + // ShowBridge(tBridgesIndex); + // } + // } + // + // + // void ShowIntersection(int i){ + // if(EditorApplication.isPlaying && GSDRS.EditorPlayCamera != null){ + // GSDRS.EditorPlayCamera.transform.position = tInters[i].transform.position + new Vector3(-40f,20f,-40f); + // GSDRS.EditorPlayCamera.transform.rotation = Quaternion.LookRotation(tInters[i].transform.position - (tInters[i].transform.position + new Vector3(-40f,20f,-40f))); + // }else{ + // SceneView.lastActiveSceneView.pivot = tInters[i].transform.position; + // SceneView.lastActiveSceneView.Repaint(); + // } + // } + // + // + // void ShowBridge(int i){ + // if(EditorApplication.isPlaying && GSDRS.EditorPlayCamera != null){ + // Vector3 tBridgePos = ((tBridges[i].pos - tBridges[i].BridgeCounterpartNode.pos)*0.5f)+tBridges[i].BridgeCounterpartNode.pos; + // float tBridgeLength = Vector3.Distance(tBridges[i].pos,tBridges[i].BridgeCounterpartNode.pos); + // + // //Rotation: + // Vector3 tCameraRot = Vector3.Cross((tBridges[i].pos - tBridges[i].BridgeCounterpartNode.pos),Vector3.up); + // if(bCameraCustomRot){ + // tCameraRot = CameraCustomRot; + // }else{ + // tCameraRot = tCameraRot.normalized; + // } + // + // //Calc offset: + // Vector3 tBridgeOffset = tCameraRot * (tBridgeLength * 0.5f * CameraZoomFactor); + // + // //Height offset: + // tBridgeOffset.y = Mathf.Lerp(20f,120f,(tBridgeLength*0.001f)) * CameraZoomFactor * CameraHeightOffset; + // + // GSDRS.EditorPlayCamera.transform.position = tBridgePos + tBridgeOffset; + // GSDRS.EditorPlayCamera.transform.rotation = Quaternion.LookRotation(tBridgePos - (tBridgePos + tBridgeOffset)); + // }else{ + // SceneView.lastActiveSceneView.pivot = tBridges[i].transform.position; + // SceneView.lastActiveSceneView.Repaint(); + // } + // } + + + void Line() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar + GUILayout.Space(4f); + } + + + // bool bCtrl = false; + public void OnSceneGUI() + { + DoHotKeyCheck(); + } + + + void DoHotKeyCheck() + { + bool bUsed = false; + Event current = Event.current; + int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); + + // if(current.type == EventType.KeyDown){ + // if(current.keyCode == KeyCode.K){ + // IncrementIntersection(); + // bUsed = true; + // }else if(current.keyCode == KeyCode.L){ + // IncrementBridge(); + // bUsed = true; + // } + // } + + if (bUsed) + { + switch (current.type) + { + case EventType.Layout: + HandleUtility.AddDefaultControl(controlID); + break; + } + } + + if (GUI.changed) + { + EditorUtility.SetDirty(GSDRS); + } + } } \ No newline at end of file diff --git a/Editor/GSDRoadSystemEditorMenu.cs b/Editor/GSDRoadSystemEditorMenu.cs index 3a267e53..87f02c66 100755 --- a/Editor/GSDRoadSystemEditorMenu.cs +++ b/Editor/GSDRoadSystemEditorMenu.cs @@ -1,124 +1,133 @@ -using UnityEngine; -using UnityEditor; - -public class GSDRoadSystemEditorMenu : ScriptableObject -{ - private const bool bRoadTestCubes = false; - - /// - /// Creates the road system. - /// - [MenuItem("Window/Road Architect/Create road system")] - public static void CreateRoadSystem() - { - Object[] tObj = GameObject.FindObjectsOfType(typeof(GSDRoadSystem)); - int i = (tObj.Length + 1); - tObj = null; - - GameObject tRoadSystemObj = new GameObject("RoadArchitectSystem" + i.ToString()); - GSDRoadSystem tRoadSystem = tRoadSystemObj.AddComponent(); //Add road system component. - tRoadSystem.AddRoad(true);//Add road for new road system. - - GameObject IntersectionsMasterObject = new GameObject("Intersections"); - IntersectionsMasterObject.transform.parent = tRoadSystemObj.transform; - } - - /// - /// Add road to gameobject. Not sure if this is necessary. - /// - [MenuItem("Window/Road Architect/Add road")] - public static void AddRoad() - { - Object[] tObjs = GameObject.FindObjectsOfType(typeof(GSDRoadSystem)); - if (tObjs != null && tObjs.Length == 0) - { - CreateRoadSystem(); - return; - } - else - { - GSDRoadSystem GSDRS = (GSDRoadSystem)tObjs[0]; - Selection.activeGameObject = GSDRS.AddRoad(); - } - } - - /// - /// Updates all roads. Used when things get out of sync. - /// - [MenuItem("Window/Road Architect/Update All Roads")] - public static void UpdateAllRoads() - { - GSDRoad[] tRoadObjs = (GSDRoad[])GameObject.FindObjectsOfType(typeof(GSDRoad)); - - int RoadCount = tRoadObjs.Length; - - GSDRoad tRoad = null; - GSDSplineC[] tPiggys = null; - if (RoadCount > 1) - { - tPiggys = new GSDSplineC[RoadCount - 1]; - } - - for (int h = 0; h < RoadCount; h++) - { - tRoad = tRoadObjs[h]; - if (h > 0) - { - tPiggys[h - 1] = tRoad.GSDSpline; - } - } - - tRoad = tRoadObjs[0]; - if (tPiggys != null && tPiggys.Length > 0) - { - tRoad.PiggyBacks = tPiggys; - } - tRoad.UpdateRoad(); - } - - /// - /// Show the help screen. - /// - [MenuItem("Window/Road Architect/Help")] - public static void GSDRoadsHelp() - { - GSDHelpWindow tHelp = EditorWindow.GetWindow(); - tHelp.Initialize(); - } - - /// - /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. - /// - [MenuItem("Window/Road Architect/Testing/Run all unit tests (caution)")] - public static void TestProgram() - { - GSD.Roads.GSDUnitTests.RoadArchitectUnitTests(); - } - - /// - /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. - /// - [MenuItem("Window/Road Architect/Testing/Clean up tests (caution)")] - public static void TestCleanup() - { - GSD.Roads.GSDUnitTests.CleanupTests(); - } - - - - /// - /// Get code line count for RA project. - /// - [MenuItem("Window/Road Architect/Testing/Get line count of RA")] - public static void testCodeCount() - { - string mainDir = Application.dataPath + "/RoadArchitect/"; - string[] files = System.IO.Directory.GetFiles(mainDir, "*.cs", System.IO.SearchOption.AllDirectories); - int lineCount = 0; - foreach (string s in files) - { - lineCount += System.IO.File.ReadAllLines(s).Length; - } - Debug.Log(string.Format("{0:n0}", lineCount) + " lines of code in Road Architect."); - } +#region "Imports" +using UnityEngine; +using UnityEditor; +#endregion + + +public class GSDRoadSystemEditorMenu : ScriptableObject +{ + private const bool bRoadTestCubes = false; + + + /// + /// Creates the road system. + /// + [MenuItem("Window/Road Architect/Create road system")] + public static void CreateRoadSystem() + { + Object[] tObj = GameObject.FindObjectsOfType(typeof(GSDRoadSystem)); + int i = (tObj.Length + 1); + tObj = null; + + GameObject tRoadSystemObj = new GameObject("RoadArchitectSystem" + i.ToString()); + GSDRoadSystem tRoadSystem = tRoadSystemObj.AddComponent(); //Add road system component. + tRoadSystem.AddRoad(true);//Add road for new road system. + + GameObject IntersectionsMasterObject = new GameObject("Intersections"); + IntersectionsMasterObject.transform.parent = tRoadSystemObj.transform; + } + + + /// + /// Add road to gameobject. Not sure if this is necessary. + /// + [MenuItem("Window/Road Architect/Add road")] + public static void AddRoad() + { + Object[] tObjs = GameObject.FindObjectsOfType(typeof(GSDRoadSystem)); + if (tObjs != null && tObjs.Length == 0) + { + CreateRoadSystem(); + return; + } + else + { + GSDRoadSystem GSDRS = (GSDRoadSystem) tObjs[0]; + Selection.activeGameObject = GSDRS.AddRoad(); + } + } + + + /// + /// Updates all roads. Used when things get out of sync. + /// + [MenuItem("Window/Road Architect/Update All Roads")] + public static void UpdateAllRoads() + { + GSDRoad[] tRoadObjs = (GSDRoad[]) GameObject.FindObjectsOfType(typeof(GSDRoad)); + + int RoadCount = tRoadObjs.Length; + + GSDRoad tRoad = null; + GSDSplineC[] tPiggys = null; + if (RoadCount > 1) + { + tPiggys = new GSDSplineC[RoadCount - 1]; + } + + for (int h = 0; h < RoadCount; h++) + { + tRoad = tRoadObjs[h]; + if (h > 0) + { + tPiggys[h - 1] = tRoad.GSDSpline; + } + } + + tRoad = tRoadObjs[0]; + if (tPiggys != null && tPiggys.Length > 0) + { + tRoad.PiggyBacks = tPiggys; + } + tRoad.UpdateRoad(); + } + + + /// + /// Show the help screen. + /// + [MenuItem("Window/Road Architect/Help")] + public static void GSDRoadsHelp() + { + GSDHelpWindow tHelp = EditorWindow.GetWindow(); + tHelp.Initialize(); + } + + + /// + /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. + /// + [MenuItem("Window/Road Architect/Testing/Run all unit tests (caution)")] + public static void TestProgram() + { + GSD.Roads.GSDUnitTests.RoadArchitectUnitTests(); + } + + + /// + /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. + /// + [MenuItem("Window/Road Architect/Testing/Clean up tests (caution)")] + public static void TestCleanup() + { + GSD.Roads.GSDUnitTests.CleanupTests(); + } + + + + /// + /// Get code line count for RA project. + /// + [MenuItem("Window/Road Architect/Testing/Get line count of RA")] + public static void testCodeCount() + { + string mainDir = Application.dataPath + "/RoadArchitect/"; + string[] files = System.IO.Directory.GetFiles(mainDir, "*.cs", System.IO.SearchOption.AllDirectories); + int lineCount = 0; + foreach (string s in files) + { + lineCount += System.IO.File.ReadAllLines(s).Length; + } + Debug.Log(string.Format("{0:n0}", lineCount) + " lines of code in Road Architect."); + } } \ No newline at end of file diff --git a/Editor/GSDSaveWindow.cs b/Editor/GSDSaveWindow.cs index c0fa3b18..dd5e2dbb 100755 --- a/Editor/GSDSaveWindow.cs +++ b/Editor/GSDSaveWindow.cs @@ -1,316 +1,336 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using GSD; -#endregion -public class GSDSaveWindow : EditorWindow -{ - public enum WindowTypeEnum - { - Extrusion, - Edge, - BridgeWizard - }; - WindowTypeEnum tWindowType = WindowTypeEnum.Extrusion; - - Texture2D temp2D = null; - Texture2D temp2D_2 = null; - string ThumbString = ""; - string Desc = ""; - string tFilename = "DefaultName"; - string tDisplayName = "DefaultName"; - string tDisplayName2 = ""; - string TitleText = ""; - // string tPath = ""; - bool bFileExists = false; - bool bIsBridge = false; - // bool bIsDefault = false; - - GSD.Roads.Splination.SplinatedMeshMaker[] tSMMs = null; - GSD.Roads.EdgeObjects.EdgeObjectMaker[] tEOMs = null; - const int titleLabelHeight = 20; - - string xPath = ""; - - void OnGUI() - { - GUILayout.Space(4f); - EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel); - - temp2D_2 = (Texture2D)EditorGUILayout.ObjectField("Square thumb (optional):", temp2D, typeof(Texture2D), false); - if (temp2D_2 != temp2D) - { - temp2D = temp2D_2; - ThumbString = AssetDatabase.GetAssetPath(temp2D); - } - - if (xPath.Length < 5) - { - xPath = GSDRootUtil.Dir_GetLibrary(); - } - - EditorGUILayout.LabelField("Short description (optional):"); - Desc = EditorGUILayout.TextArea(Desc, GUILayout.Height(40f)); - tDisplayName2 = EditorGUILayout.TextField("Display name:", tDisplayName); - if (string.Compare(tDisplayName2, tDisplayName) != 0) - { - tDisplayName = tDisplayName2; - SanitizeFilename(); - - if (tWindowType == WindowTypeEnum.Edge) - { - - - if (System.IO.File.Exists(xPath + "EOM" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - else if (tWindowType == WindowTypeEnum.Extrusion) - { - if (System.IO.File.Exists(xPath + "ESO" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - else - { - if (System.IO.File.Exists(xPath + "B/" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - } - - - if (bFileExists) - { - EditorGUILayout.LabelField("File exists already!", EditorStyles.miniLabel); - if (tWindowType == WindowTypeEnum.Edge) - { - EditorGUILayout.LabelField(xPath + "EOM" + tFilename + ".gsd", EditorStyles.miniLabel); - } - else if (tWindowType == WindowTypeEnum.Extrusion) - { - EditorGUILayout.LabelField(xPath + "ESO" + tFilename + ".gsd", EditorStyles.miniLabel); - } - else - { - EditorGUILayout.LabelField(xPath + "B/" + tFilename + ".gsd", EditorStyles.miniLabel); - } - } - else - { - if (tWindowType == WindowTypeEnum.Edge) - { - EditorGUILayout.LabelField(xPath + "EOM" + tFilename + ".gsd", EditorStyles.miniLabel); - } - else if (tWindowType == WindowTypeEnum.Extrusion) - { - EditorGUILayout.LabelField(xPath + "ESO" + tFilename + ".gsd", EditorStyles.miniLabel); - } - else - { - EditorGUILayout.LabelField(xPath + "B/" + tFilename + ".gsd", EditorStyles.miniLabel); - } - } - - GUILayout.Space(4f); - - bIsBridge = EditorGUILayout.Toggle("Is bridge related:", bIsBridge); - // GUILayout.Space(4f); - // bIsDefault = EditorGUILayout.Toggle("Is GSD:",bIsDefault); - GUILayout.Space(8f); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Cancel")) - { - Close(); - } - if (tWindowType == WindowTypeEnum.Extrusion) - { - DoExtrusion(); - } - else if (tWindowType == WindowTypeEnum.Edge) - { - DoEdgeObject(); - } - else if (tWindowType == WindowTypeEnum.BridgeWizard) - { - DoBridge(); - } - - EditorGUILayout.EndHorizontal(); - } - - void DoExtrusion() - { - if (GUILayout.Button("Save extrusion")) - { - SanitizeFilename(); - tSMMs[0].bIsBridge = bIsBridge; - tSMMs[0].ThumbString = ThumbString; - tSMMs[0].Desc = Desc; - tSMMs[0].DisplayName = tDisplayName; - tSMMs[0].SaveToLibrary(tFilename, false); - Close(); - } - } - - void DoEdgeObject() - { - if (GUILayout.Button("Save edge object")) - { - SanitizeFilename(); - tEOMs[0].bIsBridge = bIsBridge; - tEOMs[0].ThumbString = ThumbString; - tEOMs[0].Desc = Desc; - tEOMs[0].DisplayName = tDisplayName; - tEOMs[0].SaveToLibrary(tFilename, false); - Close(); - } - } - - void DoBridge() - { - if (GUILayout.Button("Save group")) - { - SanitizeFilename(); - GSD.Roads.GSDRoadUtil.WizardObject WO = new GSD.Roads.GSDRoadUtil.WizardObject(); - WO.ThumbString = ThumbString; - WO.Desc = Desc; - WO.DisplayName = tDisplayName; - WO.FileName = tFilename; - WO.bIsBridge = bIsBridge; - WO.bIsDefault = false; - - GSD.Roads.GSDRoadUtil.SaveNodeObjects(ref tSMMs, ref tEOMs, ref WO); - Close(); - } - } - - void SanitizeFilename() - { - Regex rgx = new Regex("[^a-zA-Z0-9 -]"); - tFilename = rgx.Replace(tDisplayName, ""); - tFilename = tFilename.Replace(" ", "-"); - tFilename = tFilename.Replace("_", "-"); - } - - #region "Init" - public void Initialize(ref Rect tRect, WindowTypeEnum _tWindowType, GSDSplineN tNode, GSD.Roads.Splination.SplinatedMeshMaker SMM = null, GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = null) - { - int Rheight = 300; - int Rwidth = 360; - float Rx = ((float)tRect.width / 2f) - ((float)Rwidth / 2f) + tRect.x; - float Ry = ((float)tRect.height / 2f) - ((float)Rheight / 2f) + tRect.y; - - if (Rx < 0) { Rx = tRect.x; } - if (Ry < 0) { Ry = tRect.y; } - if (Rx > (tRect.width + tRect.x)) { Rx = tRect.x; } - if (Ry > (tRect.height + tRect.y)) { Ry = tRect.y; } - - Rect fRect = new Rect(Rx, Ry, Rwidth, Rheight); - - if (fRect.width < 300) - { - fRect.width = 300; - fRect.x = tRect.x; - } - if (fRect.height < 300) - { - fRect.height = 300; - fRect.y = tRect.y; - } - - position = fRect; - tWindowType = _tWindowType; - Show(); - titleContent.text = "Save"; - if (tWindowType == WindowTypeEnum.Extrusion) - { - TitleText = "Save extrusion"; - tSMMs = new GSD.Roads.Splination.SplinatedMeshMaker[1]; - tSMMs[0] = SMM; - if (SMM != null) - { - tFilename = SMM.tName; - tDisplayName = tFilename; - } - } - else if (tWindowType == WindowTypeEnum.Edge) - { - TitleText = "Save edge object"; - tEOMs = new GSD.Roads.EdgeObjects.EdgeObjectMaker[1]; - tEOMs[0] = EOM; - if (EOM != null) - { - tFilename = EOM.tName; - tDisplayName = tFilename; - } - } - else if (tWindowType == WindowTypeEnum.BridgeWizard) - { - bIsBridge = true; - tSMMs = tNode.SplinatedObjects.ToArray(); - tEOMs = tNode.EdgeObjects.ToArray(); - TitleText = "Save group"; - tFilename = "Group" + Random.Range(0, 10000).ToString(); - tDisplayName = tFilename; - } - - if (xPath.Length < 5) - { - xPath = GSDRootUtil.Dir_GetLibrary(); - } - - if (tWindowType == WindowTypeEnum.Edge) - { - if (System.IO.File.Exists(xPath + "EOM" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - else if (tWindowType == WindowTypeEnum.Extrusion) - { - if (System.IO.File.Exists(xPath + "ESO" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - else - { - if (System.IO.File.Exists(xPath + "B/" + tFilename + ".gsd")) - { - bFileExists = true; - } - else - { - bFileExists = false; - } - } - } - #endregion +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using GSD; +#endregion + + +public class GSDSaveWindow : EditorWindow +{ + public enum WindowTypeEnum + { + Extrusion, + Edge, + BridgeWizard + }; + WindowTypeEnum tWindowType = WindowTypeEnum.Extrusion; + + Texture2D temp2D = null; + Texture2D temp2D_2 = null; + string ThumbString = ""; + string Desc = ""; + string tFilename = "DefaultName"; + string tDisplayName = "DefaultName"; + string tDisplayName2 = ""; + string TitleText = ""; + // string tPath = ""; + bool bFileExists = false; + bool bIsBridge = false; + // bool bIsDefault = false; + + GSD.Roads.Splination.SplinatedMeshMaker[] tSMMs = null; + GSD.Roads.EdgeObjects.EdgeObjectMaker[] tEOMs = null; + const int titleLabelHeight = 20; + + string xPath = ""; + + + void OnGUI() + { + GUILayout.Space(4f); + EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel); + + temp2D_2 = (Texture2D) EditorGUILayout.ObjectField("Square thumb (optional):", temp2D, typeof(Texture2D), false); + if (temp2D_2 != temp2D) + { + temp2D = temp2D_2; + ThumbString = AssetDatabase.GetAssetPath(temp2D); + } + + if (xPath.Length < 5) + { + xPath = GSDRootUtil.Dir_GetLibrary(); + } + + EditorGUILayout.LabelField("Short description (optional):"); + Desc = EditorGUILayout.TextArea(Desc, GUILayout.Height(40f)); + tDisplayName2 = EditorGUILayout.TextField("Display name:", tDisplayName); + if (string.Compare(tDisplayName2, tDisplayName) != 0) + { + tDisplayName = tDisplayName2; + SanitizeFilename(); + + if (tWindowType == WindowTypeEnum.Edge) + { + + + if (System.IO.File.Exists(xPath + "EOM" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + else if (tWindowType == WindowTypeEnum.Extrusion) + { + if (System.IO.File.Exists(xPath + "ESO" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + else + { + if (System.IO.File.Exists(xPath + "B/" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + } + + + if (bFileExists) + { + EditorGUILayout.LabelField("File exists already!", EditorStyles.miniLabel); + if (tWindowType == WindowTypeEnum.Edge) + { + EditorGUILayout.LabelField(xPath + "EOM" + tFilename + ".gsd", EditorStyles.miniLabel); + } + else if (tWindowType == WindowTypeEnum.Extrusion) + { + EditorGUILayout.LabelField(xPath + "ESO" + tFilename + ".gsd", EditorStyles.miniLabel); + } + else + { + EditorGUILayout.LabelField(xPath + "B/" + tFilename + ".gsd", EditorStyles.miniLabel); + } + } + else + { + if (tWindowType == WindowTypeEnum.Edge) + { + EditorGUILayout.LabelField(xPath + "EOM" + tFilename + ".gsd", EditorStyles.miniLabel); + } + else if (tWindowType == WindowTypeEnum.Extrusion) + { + EditorGUILayout.LabelField(xPath + "ESO" + tFilename + ".gsd", EditorStyles.miniLabel); + } + else + { + EditorGUILayout.LabelField(xPath + "B/" + tFilename + ".gsd", EditorStyles.miniLabel); + } + } + + GUILayout.Space(4f); + + bIsBridge = EditorGUILayout.Toggle("Is bridge related:", bIsBridge); + // GUILayout.Space(4f); + // bIsDefault = EditorGUILayout.Toggle("Is GSD:",bIsDefault); + GUILayout.Space(8f); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Cancel")) + { + Close(); + } + if (tWindowType == WindowTypeEnum.Extrusion) + { + DoExtrusion(); + } + else if (tWindowType == WindowTypeEnum.Edge) + { + DoEdgeObject(); + } + else if (tWindowType == WindowTypeEnum.BridgeWizard) + { + DoBridge(); + } + + EditorGUILayout.EndHorizontal(); + } + + + void DoExtrusion() + { + if (GUILayout.Button("Save extrusion")) + { + SanitizeFilename(); + tSMMs[0].bIsBridge = bIsBridge; + tSMMs[0].ThumbString = ThumbString; + tSMMs[0].Desc = Desc; + tSMMs[0].DisplayName = tDisplayName; + tSMMs[0].SaveToLibrary(tFilename, false); + Close(); + } + } + + + void DoEdgeObject() + { + if (GUILayout.Button("Save edge object")) + { + SanitizeFilename(); + tEOMs[0].bIsBridge = bIsBridge; + tEOMs[0].ThumbString = ThumbString; + tEOMs[0].Desc = Desc; + tEOMs[0].DisplayName = tDisplayName; + tEOMs[0].SaveToLibrary(tFilename, false); + Close(); + } + } + + + void DoBridge() + { + if (GUILayout.Button("Save group")) + { + SanitizeFilename(); + GSD.Roads.GSDRoadUtil.WizardObject WO = new GSD.Roads.GSDRoadUtil.WizardObject(); + WO.ThumbString = ThumbString; + WO.Desc = Desc; + WO.DisplayName = tDisplayName; + WO.FileName = tFilename; + WO.bIsBridge = bIsBridge; + WO.bIsDefault = false; + + GSD.Roads.GSDRoadUtil.SaveNodeObjects(ref tSMMs, ref tEOMs, ref WO); + Close(); + } + } + + + void SanitizeFilename() + { + Regex rgx = new Regex("[^a-zA-Z0-9 -]"); + tFilename = rgx.Replace(tDisplayName, ""); + tFilename = tFilename.Replace(" ", "-"); + tFilename = tFilename.Replace("_", "-"); + } + + + #region "Init" + public void Initialize(ref Rect tRect, WindowTypeEnum _tWindowType, GSDSplineN tNode, GSD.Roads.Splination.SplinatedMeshMaker SMM = null, GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = null) + { + int Rheight = 300; + int Rwidth = 360; + float Rx = ((float) tRect.width / 2f) - ((float) Rwidth / 2f) + tRect.x; + float Ry = ((float) tRect.height / 2f) - ((float) Rheight / 2f) + tRect.y; + + if (Rx < 0) + { + Rx = tRect.x; + } + if (Ry < 0) + { + Ry = tRect.y; + } + if (Rx > (tRect.width + tRect.x)) + { + Rx = tRect.x; + } + if (Ry > (tRect.height + tRect.y)) + { + Ry = tRect.y; + } + + Rect fRect = new Rect(Rx, Ry, Rwidth, Rheight); + + if (fRect.width < 300) + { + fRect.width = 300; + fRect.x = tRect.x; + } + if (fRect.height < 300) + { + fRect.height = 300; + fRect.y = tRect.y; + } + + position = fRect; + tWindowType = _tWindowType; + Show(); + titleContent.text = "Save"; + if (tWindowType == WindowTypeEnum.Extrusion) + { + TitleText = "Save extrusion"; + tSMMs = new GSD.Roads.Splination.SplinatedMeshMaker[1]; + tSMMs[0] = SMM; + if (SMM != null) + { + tFilename = SMM.tName; + tDisplayName = tFilename; + } + } + else if (tWindowType == WindowTypeEnum.Edge) + { + TitleText = "Save edge object"; + tEOMs = new GSD.Roads.EdgeObjects.EdgeObjectMaker[1]; + tEOMs[0] = EOM; + if (EOM != null) + { + tFilename = EOM.tName; + tDisplayName = tFilename; + } + } + else if (tWindowType == WindowTypeEnum.BridgeWizard) + { + bIsBridge = true; + tSMMs = tNode.SplinatedObjects.ToArray(); + tEOMs = tNode.EdgeObjects.ToArray(); + TitleText = "Save group"; + tFilename = "Group" + Random.Range(0, 10000).ToString(); + tDisplayName = tFilename; + } + + if (xPath.Length < 5) + { + xPath = GSDRootUtil.Dir_GetLibrary(); + } + + if (tWindowType == WindowTypeEnum.Edge) + { + if (System.IO.File.Exists(xPath + "EOM" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + else if (tWindowType == WindowTypeEnum.Extrusion) + { + if (System.IO.File.Exists(xPath + "ESO" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + else + { + if (System.IO.File.Exists(xPath + "B/" + tFilename + ".gsd")) + { + bFileExists = true; + } + else + { + bFileExists = false; + } + } + } + #endregion } \ No newline at end of file diff --git a/Editor/GSDSplineCEditor.cs b/Editor/GSDSplineCEditor.cs index 8170d930..53e1b0da 100755 --- a/Editor/GSDSplineCEditor.cs +++ b/Editor/GSDSplineCEditor.cs @@ -1,23 +1,31 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -[CustomEditor(typeof(GSDSplineC))] -#endregion -public class GSDSplineCEditor : Editor -{ - protected GSDSplineC tSpline { get { return (GSDSplineC)target; } } - - int browseNode = 0; - public override void OnInspectorGUI() - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Browse to node:", EditorStyles.boldLabel); - browseNode = EditorGUILayout.IntField(browseNode); - if (GUILayout.Button("Browse")) - { - if (browseNode < tSpline.mNodes.Count) - Selection.objects = new Object[1] { tSpline.mNodes[browseNode] }; - } - EditorGUILayout.EndHorizontal(); - } +#region "Imports" +using UnityEngine; +using UnityEditor; +#endregion + + +[CustomEditor(typeof(GSDSplineC))] +public class GSDSplineCEditor : Editor +{ + protected GSDSplineC tSpline { get { return (GSDSplineC) target; } } + + int browseNode = 0; + + + public override void OnInspectorGUI() + { + #region NodeBrowser + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Browse to node:", EditorStyles.boldLabel); + browseNode = EditorGUILayout.IntField(browseNode); + if (GUILayout.Button("Browse")) + { + if (browseNode < tSpline.mNodes.Count) + { + Selection.objects = new Object[1] { tSpline.mNodes[browseNode] }; + } + } + EditorGUILayout.EndHorizontal(); + #endregion + } } \ No newline at end of file diff --git a/Editor/GSDSplineFEditor.cs b/Editor/GSDSplineFEditor.cs index 3ed4a5f8..6d2610b6 100755 --- a/Editor/GSDSplineFEditor.cs +++ b/Editor/GSDSplineFEditor.cs @@ -1,14 +1,17 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -[CustomEditor(typeof(GSDSplineF))] -#endregion -public class GSDSplineFEditor : Editor -{ - protected GSDSplineF tSpline { get { return (GSDSplineF)target; } } - - public override void OnInspectorGUI() - { - //Intentionally left empty. - } +#region "Imports" +using UnityEngine; +using UnityEditor; +#endregion + + +[CustomEditor(typeof(GSDSplineF))] +public class GSDSplineFEditor : Editor +{ + protected GSDSplineF tSpline { get { return (GSDSplineF) target; } } + + + public override void OnInspectorGUI() + { + //Intentionally left empty. + } } \ No newline at end of file diff --git a/Editor/GSDSplineIEditor.cs b/Editor/GSDSplineIEditor.cs index 70e109ce..fde8c0cb 100755 --- a/Editor/GSDSplineIEditor.cs +++ b/Editor/GSDSplineIEditor.cs @@ -1,14 +1,17 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -[CustomEditor(typeof(GSDSplineI))] -#endregion -public class GSDSplineIEditor : Editor -{ - protected GSDSplineI tSpline { get { return (GSDSplineI)target; } } - - public override void OnInspectorGUI() - { - //Intentionally left empty. - } +#region "Imports" +using UnityEngine; +using UnityEditor; +#endregion + + +[CustomEditor(typeof(GSDSplineI))] +public class GSDSplineIEditor : Editor +{ + protected GSDSplineI tSpline { get { return (GSDSplineI) target; } } + + + public override void OnInspectorGUI() + { + //Intentionally left empty. + } } \ No newline at end of file diff --git a/Editor/GSDSplineNEditor.cs b/Editor/GSDSplineNEditor.cs index b83e5e56..67513624 100755 --- a/Editor/GSDSplineNEditor.cs +++ b/Editor/GSDSplineNEditor.cs @@ -1,2336 +1,2609 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using GSD; -[CustomEditor(typeof(GSDSplineN))] -#endregion - -//===================================================== -//== NOTE THAT CUSTOM SERIALIZATION IS USED HERE == -//== SOLELY TO COMPLY WITH UNDO REQUIREMENTS == -//===================================================== - -public class GSDSplineNEditor : Editor -{ - #region "Vars" - protected GSDSplineN tNode { get { return (GSDSplineN)target; } } - const string tOnlineHelpDesc = "Visit the online manual for the most effective help."; - bool bMouseDragHasProcessed = true; - int eCount = -1; - int currentCount = 0; - public bool bSplinatedObjectHelp = false; - public bool bEdgeObjectHelp = false; - bool bRemoveAll = false; - float HorizRoadMax = 0; - - //Button icons: - Texture btnDeleteText = null; - Texture btnCopyText = null; - Texture btnSaveText = null; - Texture btnLoadText = null; - Texture btnExtrudeText = null; - Texture btnEdgeText = null; - Texture btnHelpText = null; - Texture btnRefreshText = null; - Texture btnDefaultText = null; - Texture2D LoadBtnBG = null; - Texture2D GSDTextAreaBG = null; - Texture2D LoadBtnBGGlow = null; - Texture2D ManualBG = null; - - public bool bLoadingEOS = false; - public int LoadingEOSIndex = 0; - public List LoadingEOSNames = null; - public List LoadingEOSPaths = null; - - public bool bLoadingEOM = false; - public int LoadingEOMIndex = 0; - public List LoadingEOMNames = null; - public List LoadingEOMPaths = null; - - //Checkers: - // float ChangeChecker = -1f; - // bool bChangeChecker = false; - // Vector3 vChangeChecker = default(Vector3); - // GameObject tObj = null; - // Material tMat = null; - GSD.Roads.Splination.SplinatedMeshMaker SMM = null; - - - - - public enum EndObjectsDefaultsEnum - { - None, - WarningSign1_Static, - WarningSign2_Static, - Atten_Static, - Barrel1_Static, - Barrel1_Rigid, - Barrel3_Static, - Barrel3_Rigid, - Barrel7_Static, - Barrel7_Rigid - }; - EndObjectsDefaultsEnum tEndObjectAdd = EndObjectsDefaultsEnum.None; - - private static string[] EndObjectsDefaultsEnumDesc = new string[]{ - "Quick add", - "WarningSign1", - "WarningSign2", - "Attenuator", - "1 Sand barrel Static", - "1 Sand barrel Rigid", - "3 Sand barrels Static", - "3 Sand barrels Rigid", - "7 Sand barrels Static", - "7 Sand barrels Rigid" - }; - - public enum SMMDefaultsEnum - { - None, Custom, - KRail, - WBeamR, - WBeamL, - Railing1, - Railing2, - Railing3, - Railing4, - RailingBase05m, - RailingBase1m - }; - SMMDefaultsEnum tSMMQuickAdd = SMMDefaultsEnum.None; - - public enum BridgeTopBaseDefaultsEnum - { - None, - BaseExact, - Base1MOver, - Base2MOver, - Base3MDeep, - }; - BridgeTopBaseDefaultsEnum tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; - - public enum BridgeBottomBaseDefaultsEnum - { - None, - BridgeBase6, - BridgeBase7, - BridgeBase8, - BridgeBaseGrid, - BridgeSteel, - BridgeBase2, - BridgeBase3, - BridgeBase4, - BridgeBase5, - }; - BridgeBottomBaseDefaultsEnum tBridgeBottomBaseQuickAdd = BridgeBottomBaseDefaultsEnum.None; - - public enum BridgeWizardDefaultsEnum - { - None, - ArchBridge12m, - ArchBridge24m, - ArchBridge48m, - SuspensionBridgeSmall, - SuspensionBridgeLarge, - CausewayBridge1, - CausewayBridge2, - CausewayBridge3, - CausewayBridge4, - ArchBridge1, - ArchBridge2, - ArchBridge3, - GridBridge, - SteelBeamBridge - }; - // BridgeWizardDefaultsEnum tBridgeWizardQuickAdd = BridgeWizardDefaultsEnum.None; - - - public enum HorizMatchingDefaultsEnum - { - None, - MatchCenter, - MatchRoadLeft, - MatchShoulderLeft, - MatchRoadRight, - MatchShoulderRight - }; - HorizMatchingDefaultsEnum tHorizMatching = HorizMatchingDefaultsEnum.None; - - public enum EOMDefaultsEnum { None, Custom, StreetLightSingle, StreetLightDouble }; - - //GSD.Roads.Splination.CollisionTypeEnum tCollisionTypeSpline = GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle; - //GSD.Roads.Splination.RepeatUVTypeEnum tRepeatUVType = GSD.Roads.Splination.RepeatUVTypeEnum.None; - GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = null; - - private static string[] TheAxisDescriptions_Spline = new string[]{ - "X axis", - "Z axis" - }; - - private static string[] RepeatUVTypeDescriptions_Spline = new string[]{ - "None", - "X axis", - "Y axis" - }; - - private static string[] TheCollisionTypeEnumDescSpline = new string[]{ - "None", - "Simple triangle", - "Simple trapezoid", - "Meshfilter collision mesh", - "Straight line box collider" - }; - - private string[] HorizMatchSubTypeDescriptions; - #endregion - - GUIStyle GSDImageButton = null; - GUIStyle GSDLoadButton = null; - GUIStyle GSDManualButton = null; - GUIStyle GSDUrl = null; - - bool bSceneRectSet = false; - Rect tSceneRect = default(Rect); - bool bHasInit = false; - - //Buffers: - // bool t_opt_GizmosEnabled = false; - bool t_opt_GizmosEnabled = false; - bool t_bIsBridgeStart = false; - bool t_bIsBridgeEnd = false; - bool t_bRoadCut = false; - - void Init() - { - bHasInit = true; - EditorStyles.label.wordWrap = true; - EditorStyles.miniLabel.wordWrap = true; - - if (btnDeleteText == null) - { - btnDeleteText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; - } - if (btnCopyText == null) - { - btnCopyText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/copy.png", typeof(Texture)) as Texture; - } - if (btnLoadText == null) - { - btnLoadText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/load.png", typeof(Texture)) as Texture; - } - if (btnSaveText == null) - { - btnSaveText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/save.png", typeof(Texture)) as Texture; - } - if (btnExtrudeText == null) - { - btnExtrudeText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/extrude.png", typeof(Texture)) as Texture; - } - if (btnEdgeText == null) - { - btnEdgeText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/edge.png", typeof(Texture)) as Texture; - } - if (btnHelpText == null) - { - btnHelpText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/help.png", typeof(Texture)) as Texture; - } - if (GSDTextAreaBG == null) - { - GSDTextAreaBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/popupbg.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBG == null) - { - LoadBtnBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/loadbg.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBGGlow == null) - { - LoadBtnBGGlow = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/loadbgglow.png", typeof(Texture2D)) as Texture2D; - } - if (ManualBG == null) - { - ManualBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/manualbg.png", typeof(Texture2D)) as Texture2D; - } - if (btnRefreshText == null) - { - btnRefreshText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh.png", typeof(Texture)) as Texture; - } - if (btnDefaultText == null) - { - btnDefaultText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; - } - - if (GSDImageButton == null) - { - GSDImageButton = new GUIStyle(GUI.skin.button); - GSDImageButton.contentOffset = new Vector2(0f, -2f); - GSDImageButton.border = new RectOffset(0, 0, 0, 0); - GSDImageButton.fixedHeight = 16f; - GSDImageButton.padding = new RectOffset(0, 0, 0, 0); - GSDImageButton.normal.background = null; - } - - if (GSDLoadButton == null) - { - GSDLoadButton = new GUIStyle(GUI.skin.button); - GSDLoadButton.contentOffset = new Vector2(0f, 1f); - GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDLoadButton.normal.background = LoadBtnBG; - GSDLoadButton.active.background = LoadBtnBGGlow; - GSDLoadButton.focused.background = LoadBtnBGGlow; - GSDLoadButton.hover.background = LoadBtnBGGlow; - GSDLoadButton.fixedHeight = 16f; - GSDLoadButton.fixedWidth = 128f; - GSDLoadButton.padding = new RectOffset(0, 35, 0, 0); - } - - if (GSDManualButton == null) - { - GSDManualButton = new GUIStyle(GUI.skin.button); - GSDManualButton.contentOffset = new Vector2(0f, 1f); - GSDManualButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDManualButton.normal.background = ManualBG; - GSDManualButton.fixedHeight = 16f; - GSDManualButton.fixedWidth = 128f; - } - - if (GSDUrl == null) - { - GSDUrl = new GUIStyle(GUI.skin.button); - GSDUrl.normal.textColor = new Color(0.5f, 1f, 0.5f, 1f); - } - - float tRoadWidthHalf = tNode.GSDSpline.tRoad.RoadWidth() * 0.5f; - HorizMatchSubTypeDescriptions = new string[6]; - HorizMatchSubTypeDescriptions[0] = "Select preset"; - HorizMatchSubTypeDescriptions[1] = "Match center: 0 meters"; - HorizMatchSubTypeDescriptions[2] = "Match road left edge: -" + tRoadWidthHalf.ToString("F1") + " meters"; - HorizMatchSubTypeDescriptions[4] = "Match road right edge: " + tRoadWidthHalf.ToString("F1") + " meters"; - - if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) - { - HorizMatchSubTypeDescriptions[3] = "Match shoulder left edge: -" + (tRoadWidthHalf + tNode.GSDSpline.tRoad.opt_ShoulderWidth).ToString("F1") + " meters"; - HorizMatchSubTypeDescriptions[5] = "Match shoulder right edge: " + (tRoadWidthHalf + tNode.GSDSpline.tRoad.opt_ShoulderWidth).ToString("F1") + " meters"; - } - else - { - HorizMatchSubTypeDescriptions[2] = "Match shoulder left edge: -" + tRoadWidthHalf.ToString("F1") + " meters"; - HorizMatchSubTypeDescriptions[4] = "Match shoulder right edge: " + tRoadWidthHalf.ToString("F1") + " meters"; - } - - HorizRoadMax = tNode.GSDSpline.tRoad.RoadWidth() * 20; - } - - GSDSplineN iNode1 = null; - GSDSplineN iNode2 = null; - bool bCreateIntersection = false; - public override void OnInspectorGUI() - { - if (Event.current.type == EventType.ValidateCommand) - { - switch (Event.current.commandName) - { - case "UndoRedoPerformed": - UpdateSplineObjects_OnUndo(); - break; - } - } - - if (Event.current.type != EventType.Layout && bCreateIntersection) - { - bCreateIntersection = false; - Selection.activeGameObject = GSD.Roads.GSDIntersections.CreateIntersection(iNode1, iNode2); - return; - } - - - if (Event.current.type != EventType.Layout && tNode.bQuitGUI) - { - tNode.bQuitGUI = false; - return; - } - - //Graphic null checks: - if (!bHasInit) { Init(); } - - Line(); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(tNode.EditorDisplayString, EditorStyles.boldLabel); - - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(128f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - - //Option: Gizmo options, Convoluted due to submission compliance for undo rules: - if (tNode.GSDSpline.tRoad.opt_GizmosEnabled != tNode.opt_GizmosEnabled) - { - tNode.GSDSpline.tRoad.opt_GizmosEnabled = tNode.opt_GizmosEnabled; - tNode.GSDSpline.tRoad.UpdateGizmoOptions(); - tNode.GSDSpline.tRoad.Wireframes_Toggle(); - } - t_opt_GizmosEnabled = EditorGUILayout.Toggle("Gizmos: ", tNode.GSDSpline.tRoad.opt_GizmosEnabled); - - //Option: Manual road cut: - if (tNode.idOnSpline > 0 && tNode.idOnSpline < (tNode.GSDSpline.GetNodeCount() - 1) && !tNode.bIsIntersection && !tNode.bSpecialEndNode) - { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ - if (tNode.GSDSpline.tRoad.opt_bDynamicCuts) - { - Line(); - t_bRoadCut = EditorGUILayout.Toggle("Cut road at this node: ", tNode.bRoadCut); - } - Line(); - } - - //Option: Bridge options - bool bDidBridge = false; - if (!tNode.bIsEndPoint) - { - //Bridge start: - if (!tNode.bIsBridgeEnd && tNode.CanBridgeStart()) - { - t_bIsBridgeStart = EditorGUILayout.Toggle(" Bridge start", tNode.bIsBridgeStart); - bDidBridge = true; - } - //Bridge end: - if (!tNode.bIsBridgeStart && tNode.CanBridgeEnd()) - { - t_bIsBridgeEnd = EditorGUILayout.Toggle(" Bridge end", tNode.bIsBridgeEnd); - bDidBridge = true; - } - - if (bDidBridge) - { - Line(); - } - } - - if ((Selection.objects.Length == 1 && Selection.objects[0] is GSDSplineN) || (tNode.SpecialNodeCounterpart == null && !tNode.bSpecialRoadConnPrimary)) - { - //Do extrusion and edge objects overview: - DoExtAndEdgeOverview(); - } - else - { - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Road objects")) - { - Selection.objects = new Object[1] { tNode.SpecialNodeCounterpart }; - } - EditorGUILayout.EndHorizontal(); - } - - if (tNode.bSpecialRoadConnPrimary) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Road connection:", EditorStyles.boldLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.BeginVertical(); - if (GUILayout.Button("Update road connection")) - { - GSDSplineN tNode1 = tNode.OriginalConnectionNodes[0]; - GSDSplineN tNode2 = tNode.OriginalConnectionNodes[1]; - tNode.SpecialNodeCounterpart.BreakConnection(); - tNode.GSDSpline.tRoad.UpdateRoad(); - tNode1.GSDSpline.ActivateEndNodeConnection(tNode1, tNode2); - } - if (GUILayout.Button("Break road connection")) - { - tNode.SpecialNodeCounterpart.BreakConnection(); - } - if (GUILayout.Button("Access objects on other node")) - { - Selection.objects = new Object[] { tNode.SpecialNodeCounterpart }; - } - EditorGUILayout.EndVertical(); - if (tNode.SpecialNodeCounterpart != null) - { - EditorGUILayout.LabelField(tNode.SpecialNodeCounterpart.GSDSpline.tRoad.transform.name + " to " + tNode.SpecialNodeCounterpart.SpecialNodeCounterpart.GSDSpline.tRoad.transform.name); - } - EditorGUILayout.LabelField("To break this road connection, click the \"Break road connection\" button."); - Line(); - } - - //Statistics: - DoStats(); - EditorGUILayout.EndVertical(); - - if (GUI.changed) - { - //Set snapshot for undo: - - Undo.RecordObject(tNode, "Modify node"); - - //Option: Gizmo options, Convoluted due to submission compliance for undo rules: - if (t_opt_GizmosEnabled != tNode.GSDSpline.tRoad.opt_GizmosEnabled) - { - tNode.GSDSpline.tRoad.opt_GizmosEnabled = t_opt_GizmosEnabled; - tNode.GSDSpline.tRoad.UpdateGizmoOptions(); - tNode.GSDSpline.tRoad.Wireframes_Toggle(); - SceneView.RepaintAll(); - } - - //Option: Manual cut: - if (tNode.idOnSpline > 0 && tNode.idOnSpline < (tNode.GSDSpline.GetNodeCount() - 1) && !tNode.bIsIntersection && !tNode.bSpecialEndNode) - { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ - if (tNode.GSDSpline.tRoad.opt_bDynamicCuts) - { - if (t_bRoadCut != tNode.bRoadCut) - { - tNode.bRoadCut = t_bRoadCut; - } - } - } - - //Option: Bridge options - //Bridge start: - if (!tNode.bIsEndPoint) - { - if (!tNode.bIsBridgeEnd && tNode.CanBridgeStart()) - { - if (t_bIsBridgeStart != tNode.bIsBridgeStart) - { - tNode.bIsBridgeStart = t_bIsBridgeStart; - tNode.BridgeToggleStart(); - } - } - } - //Bridge end: - if (!tNode.bIsEndPoint) - { - if (!tNode.bIsBridgeStart && tNode.CanBridgeEnd()) - { - if (t_bIsBridgeEnd != tNode.bIsBridgeEnd) - { - tNode.bIsBridgeEnd = t_bIsBridgeEnd; - tNode.BridgeToggleEnd(); - } - } - } - - UpdateSplineObjects(); - UpdateEdgeObjects(); - - EditorUtility.SetDirty(target); - } - } - - void OnSelectionChanged() - { - Repaint(); - } - - //GUIStyle SectionBG; - - void DoExtAndEdgeOverview() - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Extrusion & edge objects", EditorStyles.boldLabel); - EditorGUILayout.LabelField(""); - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (bEdgeObjectHelp) - { - bEdgeObjectHelp = EditorGUILayout.Foldout(bEdgeObjectHelp, "Hide quick help"); - } - else - { - bEdgeObjectHelp = EditorGUILayout.Foldout(bEdgeObjectHelp, "Show quick help"); - } - EditorGUILayout.LabelField(""); - - if (GUILayout.Button("Save group", EditorStyles.miniButton, GUILayout.Width(108f)) || GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) - { - GSDSaveWindow tSave = EditorWindow.GetWindow(); - if (tNode.bIsBridge) - { - tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.BridgeWizard, tNode); - } - else - { - tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.BridgeWizard, tNode); - } - } - EditorGUILayout.EndHorizontal(); - GUILayout.Space(4f); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(""); - if (GUILayout.Button("Open Wizard", GSDLoadButton, GUILayout.Width(128f))) - {// || GUILayout.Button(btnLoadText,GSDImageButton,GUILayout.Width(16f))){ - GSDWizard tWiz = EditorWindow.GetWindow(); - if (tSceneRect.x < 0) { tSceneRect.x = 0f; } - if (tSceneRect.y < 0) { tSceneRect.y = 0f; } - tWiz.xRect = tSceneRect; - if (tNode.bIsBridgeStart) - { - tWiz.Initialize(GSDWizard.WindowTypeEnum.BridgeComplete, tNode); - } - else - { - tWiz.Initialize(GSDWizard.WindowTypeEnum.Extrusion, tNode); - } - } - EditorGUILayout.EndHorizontal(); - GUILayout.Space(4f); - - if (bEdgeObjectHelp) - { - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnExtrudeText, GSDImageButton, GUILayout.Width(32f))) { } - EditorGUILayout.LabelField("= Extrusion objects", EditorStyles.miniLabel); - EditorGUILayout.LabelField(""); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.LabelField("Railings, bridge pieces, center dividers and other connected objects.", EditorStyles.miniLabel); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnEdgeText, GSDImageButton, GUILayout.Width(32f))) { } - EditorGUILayout.LabelField("= Edge objects", EditorStyles.miniLabel); - EditorGUILayout.LabelField(""); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.LabelField("Signs, street lights, bridge pillars and other unconnected road objects.", EditorStyles.miniLabel); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) { } - EditorGUILayout.LabelField("= Saves object config to library for use on other nodes.", EditorStyles.miniLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) { } - EditorGUILayout.LabelField("= Duplicates object onto current node.", EditorStyles.miniLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) { } - EditorGUILayout.LabelField("= Deletes object.", EditorStyles.miniLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) { } - EditorGUILayout.LabelField("= Refreshes object.", EditorStyles.miniLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) { } - EditorGUILayout.LabelField("= Resets setting(s) to default.", EditorStyles.miniLabel); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - Line(); - } - currentCount = 0; - - GUILayout.Space(2f); - - - //Splinated objects: - DoSplineObjects(); - - //Edge Objects: - DoEdgeObjects(); - - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(""); - if (GUILayout.Button("Add custom extrusion object", EditorStyles.miniButton)) - { - tNode.AddSplinatedObject(); - } - EditorGUILayout.EndHorizontal(); - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(""); - if (GUILayout.Button("Add custom edge object", EditorStyles.miniButton)) - { - tNode.AddEdgeObject(); - } - EditorGUILayout.EndHorizontal(); - - if (tNode.SplinatedObjects.Count > 20 || tNode.EdgeObjects.Count > 20) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(""); - bRemoveAll = EditorGUILayout.Toggle(bRemoveAll, GUILayout.Width(20f)); - if (GUILayout.Button("Remove all", EditorStyles.miniButton, GUILayout.Width(100f))) - { - if (bRemoveAll) - { - tNode.RemoveAllSplinatedObjects(); - tNode.RemoveAllEdgeObjects(); - bRemoveAll = false; - } - } - - EditorGUILayout.EndHorizontal(); - } - Line(); - } - - void DoStats() - { - EditorGUILayout.LabelField("Statistics:"); - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("Grade to next node: " + tNode.GradeToNext); - EditorGUILayout.LabelField("Grade to prev node: " + tNode.GradeToPrev); - EditorGUILayout.LabelField("Distance from start: " + tNode.tDist.ToString("F3") + " meters"); - EditorGUILayout.LabelField("% of spline: " + ((tNode.tDist / tNode.GSDSpline.distance) * 100f).ToString("F2") + "%"); - EditorGUILayout.LabelField("Parameter: " + tNode.tTime); - EditorGUILayout.LabelField("Tangent: " + tNode.tangent); - EditorGUILayout.LabelField("POS: " + tNode.pos); - EditorGUILayout.LabelField("ID on spline: " + tNode.idOnSpline); - EditorGUILayout.LabelField("Is intersection node: " + tNode.bIsIntersection); - EditorGUILayout.LabelField("Is end node: " + tNode.bIsEndPoint); - EditorGUILayout.LabelField("Is bridge start: " + tNode.bIsBridgeStart); - EditorGUILayout.LabelField("Is bridge end: " + tNode.bIsBridgeEnd); - EditorGUILayout.LabelField("Road: " + tNode.GSDSpline.tRoad.transform.name); - EditorGUILayout.LabelField("System: " + tNode.GSDSpline.tRoad.GSDRS.transform.name); - EditorGUILayout.SelectableLabel("UID: " + tNode.UID); - } - - public void DoSplineObjects() - { - if (!tNode.CanSplinate()) { return; } - if (tNode.SplinatedObjects == null) { tNode.SplinatedObjects = new List(); } - eCount = tNode.SplinatedObjects.Count; - - SMM = null; - eCount = tNode.SplinatedObjects.Count; - if (eCount == 0) { } - - for (int i = 0; i < tNode.SplinatedObjects.Count; i++) - { - currentCount += 1; - SMM = tNode.SplinatedObjects[i]; - if (SMM.EM == null) - { - SMM.EM = new GSD.Roads.Splination.SplinatedMeshMaker.SplinatedMeshEditorMaker(); - } - SMM.EM.Setup(SMM); - - //GSD.Roads.Splination.AxisTypeEnum tAxisTypeSpline = GSD.Roads.Splination.AxisTypeEnum.Z; - - EditorGUILayout.BeginVertical("TextArea"); - - if (SMM.bNeedsUpdate) { SMM.Setup(true); } - - - EditorGUILayout.BeginHorizontal(); - - SMM.bToggle = EditorGUILayout.Foldout(SMM.bToggle, "#" + currentCount.ToString() + ": " + SMM.tName); - - if (GUILayout.Button(btnExtrudeText, GSDImageButton, GUILayout.Width(32f))) - { - - } - - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.Setup(); - } - if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) - { - GSDSaveWindow tSave = EditorWindow.GetWindow(); - tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.Extrusion, tNode, SMM); - } - if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) - { - Undo.RecordObject(tNode, "Copy"); - tNode.CopySplinatedObject(ref SMM); - EditorUtility.SetDirty(tNode); - } - if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) - { - Undo.RecordObject(tNode, "Delete"); - tNode.RemoveSplinatedObject(i); - EditorUtility.SetDirty(tNode); - } - EditorGUILayout.EndHorizontal(); - if (!SMM.bToggle) { EditorGUILayout.EndVertical(); continue; } - - GUILayout.Space(8f); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("General options:"); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginVertical("box"); - - //Name: - SMM.EM.tName = EditorGUILayout.TextField("Name:", SMM.tName); - - //Game object (prefab): - SMM.EM.CurrentSplination = (GameObject)EditorGUILayout.ObjectField("Prefab:", SMM.CurrentSplination, typeof(GameObject), false); - - //Game object (prefab start cap): - SMM.EM.CurrentSplinationCap1 = (GameObject)EditorGUILayout.ObjectField("Prefab start cap:", SMM.CurrentSplinationCap1, typeof(GameObject), false); - //Prefab start cap height offset: - if (SMM.CurrentSplinationCap1 != null) - { - SMM.EM.CapHeightOffset1 = EditorGUILayout.FloatField(" Height offset:", SMM.CapHeightOffset1); - } - - //Game object (prefab end cap): - SMM.EM.CurrentSplinationCap2 = (GameObject)EditorGUILayout.ObjectField("Prefab end cap:", SMM.CurrentSplinationCap2, typeof(GameObject), false); - //Prefab end cap height offset: - if (SMM.CurrentSplinationCap2 != null) - { - SMM.EM.CapHeightOffset2 = EditorGUILayout.FloatField(" Height offset:", SMM.CapHeightOffset2); - } - - //Material overrides: - SMM.EM.bMaterialOverride = EditorGUILayout.Toggle("Material override: ", SMM.bMaterialOverride); - if (SMM.bMaterialOverride) - { - SMM.EM.SplinatedMaterial1 = (Material)EditorGUILayout.ObjectField("Override mat #1: ", SMM.SplinatedMaterial1, typeof(Material), false); - SMM.EM.SplinatedMaterial2 = (Material)EditorGUILayout.ObjectField("Override mat #2: ", SMM.SplinatedMaterial2, typeof(Material), false); - } - - //Axis: - SMM.EM.Axis = (GSD.Roads.Splination.AxisTypeEnum)EditorGUILayout.Popup("Extrusion axis: ", (int)SMM.Axis, TheAxisDescriptions_Spline, GUILayout.Width(250f)); - - //Start time: - if (SMM.StartTime < tNode.MinSplination) { SMM.StartTime = tNode.MinSplination; } - if (SMM.EndTime > tNode.MaxSplination) { SMM.EndTime = tNode.MaxSplination; } - EditorGUILayout.BeginHorizontal(); - SMM.EM.StartTime = EditorGUILayout.Slider("Start param: ", SMM.StartTime, tNode.MinSplination, tNode.MaxSplination - 0.01f); - if (GUILayout.Button("match node", EditorStyles.miniButton, GUILayout.Width(80f))) - { - SMM.EM.StartTime = tNode.tTime; - } - if (SMM.EM.StartTime >= SMM.EM.EndTime) { SMM.EM.EndTime = (SMM.EM.StartTime + 0.01f); } - EditorGUILayout.EndHorizontal(); - - //End time: - EditorGUILayout.BeginHorizontal(); - SMM.EM.EndTime = EditorGUILayout.Slider("End param: ", SMM.EndTime, SMM.StartTime, tNode.MaxSplination); - if (GUILayout.Button("match next", EditorStyles.miniButton, GUILayout.Width(80f))) - { - SMM.EM.EndTime = tNode.NextTime; - } - if (SMM.EM.StartTime >= SMM.EM.EndTime) { SMM.EM.EndTime = (SMM.EM.StartTime + 0.01f); } - EditorGUILayout.EndHorizontal(); - - //Straight line options: - if (tNode.IsStraight()) - { - if (!SMM.bIsStretch) - { - SMM.EM.bIsStretch = EditorGUILayout.Toggle("Straight line stretch:", SMM.bIsStretch); - } - else - { - EditorGUILayout.BeginVertical("box"); - SMM.EM.bIsStretch = EditorGUILayout.Toggle("Straight line stretch:", SMM.bIsStretch); - - //Stretch_UVThreshold: - SMM.EM.Stretch_UVThreshold = EditorGUILayout.Slider("UV stretch threshold:", SMM.Stretch_UVThreshold, 0.01f, 0.5f); - - //UV repeats: - SMM.EM.RepeatUVType = (GSD.Roads.Splination.RepeatUVTypeEnum)EditorGUILayout.Popup("UV stretch axis: ", (int)SMM.RepeatUVType, RepeatUVTypeDescriptions_Spline, GUILayout.Width(250f)); - EditorGUILayout.EndVertical(); - } - } - else - { - SMM.EM.bIsStretch = false; - } - - - SMM.EM.bTrimStart = EditorGUILayout.Toggle("Trim start:", SMM.bTrimStart); - SMM.EM.bTrimEnd = EditorGUILayout.Toggle("Trim end:", SMM.bTrimEnd); - - //Static option: - SMM.EM.bStatic = EditorGUILayout.Toggle("Static: ", SMM.bStatic); - - //Splination method - // SMM.EM.bMatchRoadIncrements = EditorGUILayout.Toggle("Match road increments: ",SMM.bMatchRoadIncrements); - SMM.EM.bMatchTerrain = EditorGUILayout.Toggle("Match ground: ", SMM.bMatchTerrain); - - //Vector min/max threshold: - EditorGUILayout.BeginHorizontal(); - SMM.EM.MinMaxMod = EditorGUILayout.Slider("Vertex min/max threshold: ", SMM.MinMaxMod, 0.01f, 0.2f); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.MinMaxMod = 0.05f; - } - EditorGUILayout.EndHorizontal(); - - //Vertex matching precision: - EditorGUILayout.BeginHorizontal(); - SMM.EM.VertexMatchingPrecision = EditorGUILayout.Slider("Vertex matching precision: ", SMM.VertexMatchingPrecision, 0f, 0.01f); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.VertexMatchingPrecision = 0.005f; - } - EditorGUILayout.EndHorizontal(); - - //UV repeats: - if (!SMM.bIsStretch) - { - SMM.EM.RepeatUVType = (GSD.Roads.Splination.RepeatUVTypeEnum)EditorGUILayout.Popup("UV repeat axis: ", (int)SMM.RepeatUVType, RepeatUVTypeDescriptions_Spline, GUILayout.Width(250f)); - } - - if (SMM.bMatchRoadDefinition) - { - EditorGUILayout.BeginVertical("TextArea"); - EditorGUILayout.BeginHorizontal(); - SMM.EM.bMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", SMM.bMatchRoadDefinition); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.bMatchRoadDefinition = false; - } - EditorGUILayout.EndHorizontal(); - if (SMM.bMatchRoadDefinition) - { - EditorGUILayout.LabelField(" Only use this option if object length doesn't match the road definition.", EditorStyles.miniLabel); - EditorGUILayout.LabelField(" Matching road definition requires a UV repeat type.", EditorStyles.miniLabel); - EditorGUILayout.LabelField(" If the material fails to scale properly, try flipping the Y rotation.", EditorStyles.miniLabel); - } - //Flip rotation option: - SMM.EM.bFlipRotation = EditorGUILayout.Toggle(" Flip Y rotation: ", SMM.bFlipRotation); - EditorGUILayout.EndVertical(); - } - else - { - EditorGUILayout.BeginHorizontal(); - SMM.EM.bMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", SMM.bMatchRoadDefinition); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.bMatchRoadDefinition = false; - } - EditorGUILayout.EndHorizontal(); - } - EditorGUILayout.EndVertical(); - - //Vertical offset: - EditorGUILayout.LabelField("Vertical options:"); - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - SMM.EM.VerticalRaise = EditorGUILayout.Slider("Vertical raise magnitude:", SMM.VerticalRaise, -512f, 512f); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.VerticalRaise = 0f; - } - EditorGUILayout.EndHorizontal(); - - //Vertical curve: - if (SMM.VerticalCurve == null || SMM.VerticalCurve.keys.Length < 2) { EnforceCurve(ref SMM.VerticalCurve); } - EditorGUILayout.BeginHorizontal(); - SMM.EM.VerticalCurve = EditorGUILayout.CurveField("Curve: ", SMM.VerticalCurve); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - ResetCurve(ref SMM.EM.VerticalCurve); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - //Horizontal offsets: - SMM.EM.HorizontalSep = SMM.HorizontalSep; - EditorGUILayout.LabelField("Horizontal offset options:"); - EditorGUILayout.BeginVertical("box"); - tHorizMatching = HorizMatchingDefaultsEnum.None; - tHorizMatching = (HorizMatchingDefaultsEnum)EditorGUILayout.Popup((int)tHorizMatching, HorizMatchSubTypeDescriptions, GUILayout.Width(100f)); - if (tHorizMatching != HorizMatchingDefaultsEnum.None) - { - if (tHorizMatching == HorizMatchingDefaultsEnum.MatchCenter) - { - SMM.EM.HorizontalSep = 0f; - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadLeft) - { - SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2) * -1; - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderLeft) - { - SMM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1; - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadRight) - { - SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2); - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderRight) - { - SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth; - } - tHorizMatching = HorizMatchingDefaultsEnum.None; - } - EditorGUILayout.BeginHorizontal(); - SMM.EM.HorizontalSep = EditorGUILayout.Slider("Horiz offset magnitude:", SMM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.HorizontalSep = 0f; - } - EditorGUILayout.EndHorizontal(); - - //Horizontal curve: - if (SMM.HorizontalCurve == null || SMM.HorizontalCurve.keys.Length < 2) { EnforceCurve(ref SMM.HorizontalCurve); } - - EditorGUILayout.BeginHorizontal(); - SMM.EM.HorizontalCurve = EditorGUILayout.CurveField("Curve: ", SMM.HorizontalCurve); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - ResetCurve(ref SMM.EM.HorizontalCurve); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - //Vertical cutoff: - EditorGUILayout.LabelField("Vertical cutoff:"); - EditorGUILayout.BeginVertical("box"); - SMM.EM.bVerticalCutoff = EditorGUILayout.Toggle("Height cutoff enabled:", SMM.bVerticalCutoff); - if (SMM.bVerticalCutoff) - { - SMM.EM.bVerticalCutoff_MatchZero = EditorGUILayout.Toggle("Match spline height:", SMM.bVerticalCutoff_MatchZero); - SMM.EM.bVerticalCutoffDownwards = EditorGUILayout.Toggle("Cut direction toggle:", SMM.bVerticalCutoffDownwards); - SMM.EM.VerticalCutoff = EditorGUILayout.Slider("Height cut offset: ", SMM.VerticalCutoff, -50f, 50f); - SMM.EM.bVerticalMeshCutoff_OppositeDir = EditorGUILayout.Toggle("Opposite dir mesh cut:", SMM.bVerticalMeshCutoff_OppositeDir); - SMM.EM.VerticalMeshCutoffOffset = EditorGUILayout.Slider("Mesh cut offset: ", SMM.VerticalMeshCutoffOffset, -5f, 5f); - } - EditorGUILayout.EndVertical(); - - //End type: - EditorGUILayout.LabelField("Extrusion ending options:"); - EditorGUILayout.BeginVertical("box"); - SMM.EM.bStartDown = EditorGUILayout.Toggle("Push start down:", SMM.bStartDown); - SMM.EM.bEndDown = EditorGUILayout.Toggle("Push end down:", SMM.bEndDown); - if (SMM.bStartDown) - { - SMM.EM.bStartTypeDownOverride = EditorGUILayout.Toggle("Override start down value: ", SMM.bStartTypeDownOverride); - if (SMM.bStartTypeDownOverride) - { - SMM.EM.StartTypeDownOverride = EditorGUILayout.Slider("Downward movement: ", SMM.StartTypeDownOverride, -10f, 10f); - } - } - if (SMM.bEndDown) - { - SMM.EM.bEndTypeDownOverride = EditorGUILayout.Toggle("Override end down value: ", SMM.bEndTypeDownOverride); - if (SMM.bEndTypeDownOverride) - { - SMM.EM.EndTypeDownOverride = EditorGUILayout.Slider("Downward movement: ", SMM.EndTypeDownOverride, -10f, 10f); - } - } - EditorGUILayout.EndVertical(); - - //Start and end objects: - EditorGUILayout.LabelField("Start & end objects:"); - EditorGUILayout.BeginVertical("box"); - //End cap custom match start: - SMM.EM.bEndCapCustomMatchStart = EditorGUILayout.Toggle("Match objects to ends:", SMM.bEndCapCustomMatchStart); - - //End objects match ground: - SMM.EM.bEndObjectsMatchGround = EditorGUILayout.Toggle("Force origins to ground:", SMM.bEndObjectsMatchGround); - - //Start cap: - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Start object:"); - tEndObjectAdd = (EndObjectsDefaultsEnum)EditorGUILayout.Popup((int)tEndObjectAdd, EndObjectsDefaultsEnumDesc); - if (tEndObjectAdd != EndObjectsDefaultsEnum.None) - { - SMM.EM.EndCapStart = GetEndObjectQuickAdd(); - tEndObjectAdd = EndObjectsDefaultsEnum.None; - } - EditorGUILayout.EndHorizontal(); - - - SMM.EM.EndCapStart = (GameObject)EditorGUILayout.ObjectField("Prefab:", SMM.EndCapStart, typeof(GameObject), false); - if (SMM.EndCapStart != null) - { - SMM.EM.EndCapCustomOffsetStart = EditorGUILayout.Vector3Field("Position offset:", SMM.EndCapCustomOffsetStart); - SMM.EM.EndCapCustomRotOffsetStart = EditorGUILayout.Vector3Field("Rotation offset:", SMM.EndCapCustomRotOffsetStart); - } - EditorGUILayout.EndVertical(); - - //End cap: - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("End object:"); - tEndObjectAdd = (EndObjectsDefaultsEnum)EditorGUILayout.Popup((int)tEndObjectAdd, EndObjectsDefaultsEnumDesc); - if (tEndObjectAdd != EndObjectsDefaultsEnum.None) - { - SMM.EM.EndCapEnd = GetEndObjectQuickAdd(); - SMM.EM.EndCapCustomRotOffsetEnd = new Vector3(0f, 180f, 0f); - tEndObjectAdd = EndObjectsDefaultsEnum.None; - } - EditorGUILayout.EndHorizontal(); - - - SMM.EM.EndCapEnd = (GameObject)EditorGUILayout.ObjectField("Prefab:", SMM.EndCapEnd, typeof(GameObject), false); - if (SMM.EndCapEnd != null) - { - SMM.EM.EndCapCustomOffsetEnd = EditorGUILayout.Vector3Field("Position offset:", SMM.EndCapCustomOffsetEnd); - SMM.EM.EndCapCustomRotOffsetEnd = EditorGUILayout.Vector3Field("Rotation offset:", SMM.EndCapCustomRotOffsetEnd); - } - EditorGUILayout.EndVertical(); - - EditorGUILayout.EndVertical(); - - //Collision: - EditorGUILayout.LabelField("Collision options:"); - EditorGUILayout.BeginVertical("box"); - SMM.EM.CollisionType = (GSD.Roads.Splination.CollisionTypeEnum)EditorGUILayout.Popup("Collision type: ", (int)SMM.CollisionType, TheCollisionTypeEnumDescSpline, GUILayout.Width(320f)); - //Mesh collison convex option - if (SMM.CollisionType != GSD.Roads.Splination.CollisionTypeEnum.None && SMM.CollisionType != GSD.Roads.Splination.CollisionTypeEnum.BoxCollision) - { - SMM.EM.bCollisionConvex = EditorGUILayout.Toggle(" Convex: ", SMM.bCollisionConvex); - SMM.EM.bCollisionTrigger = EditorGUILayout.Toggle(" Trigger: ", SMM.bCollisionTrigger); - } - - if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle || SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTrapezoid) - { - SMM.EM.bSimpleCollisionAutomatic = EditorGUILayout.Toggle(" Automatic simple collision: ", SMM.bSimpleCollisionAutomatic); - } - //If not automatic simple collisions: - if (!SMM.bSimpleCollisionAutomatic) - { - if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle) - { - SMM.EM.CollisionTriBL = SMM.CollisionTriBL; - SMM.EM.CollisionTriBR = SMM.CollisionTriBR; - SMM.EM.CollisionTriT = SMM.CollisionTriT; - - EditorGUILayout.LabelField("Bottom left:"); - SMM.EM.CollisionTriBL.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriBL.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); - SMM.EM.CollisionTriBL.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriBL.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); - SMM.EM.CollisionTriBL.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriBL.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); - - EditorGUILayout.LabelField("Bottom right:"); - SMM.EM.CollisionTriBR.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriBR.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); - SMM.EM.CollisionTriBR.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriBR.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); - SMM.EM.CollisionTriBR.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriBR.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); - - EditorGUILayout.LabelField("Top:"); - SMM.EM.CollisionTriT.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriT.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); - SMM.EM.CollisionTriT.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriT.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); - SMM.EM.CollisionTriT.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriT.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); - - } - else if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTrapezoid) - { - SMM.EM.CollisionBoxBL = EditorGUILayout.Vector3Field(" Bottom left:", SMM.CollisionBoxBL); - SMM.EM.CollisionBoxBR = EditorGUILayout.Vector3Field(" Bottom right:", SMM.CollisionBoxBR); - SMM.EM.CollisionBoxTL = EditorGUILayout.Vector3Field(" Top left:", SMM.CollisionBoxTL); - SMM.EM.CollisionBoxTR = EditorGUILayout.Vector3Field(" Top right:", SMM.CollisionBoxTR); - } - } - - if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.BoxCollision) - { - SMM.EM.StretchBC_LocOffset = EditorGUILayout.Vector3Field("Box collider center offset:", SMM.StretchBC_LocOffset); - SMM.EM.bBCFlipX = EditorGUILayout.Toggle("Flip center X:", SMM.bBCFlipX); - SMM.EM.bBCFlipZ = EditorGUILayout.Toggle("Flip center Z:", SMM.bBCFlipZ); - - - SMM.EM.bStretchSize = EditorGUILayout.Toggle("Box collider size edit:", SMM.bStretchSize); - if (SMM.bStretchSize) - { - SMM.EM.StretchBC_Size = EditorGUILayout.Vector3Field("Size:", SMM.StretchBC_Size); - } - else - { - EditorGUILayout.LabelField("Size:", SMM.StretchBC_Size.ToString()); - } - } - EditorGUILayout.EndVertical(); - - - EditorGUILayout.LabelField("Rotation options:"); - EditorGUILayout.BeginVertical("box"); - - //Custom rotation: - SMM.EM.CustomRotation = SMM.CustomRotation; - //EOM.CustomRotation = EditorGUILayout.Vector3Field("Custom rotation: ",EOM.CustomRotation); - EditorGUILayout.BeginHorizontal(); - //Flip rotation option: - if (SMM.EM.bFlipRotation != SMM.bFlipRotation) - { - SMM.EM.bFlipRotation = EditorGUILayout.Toggle("Flip Y rotation: ", SMM.EM.bFlipRotation); - } - else - { - SMM.EM.bFlipRotation = EditorGUILayout.Toggle("Flip Y rotation: ", SMM.bFlipRotation); - } - - - // if(GUILayout.Button("Reset custom rotation",EditorStyles.miniButton,GUILayout.Width(160f))){ - // SMM.CustomRotation = new Vector3(0f,0f,0f); - // } - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - SMM.EM.CustomRotation = new Vector3(0f, 0f, 0f); - } - EditorGUILayout.EndHorizontal(); - // SMM.EM.CustomRotation = EditorGUILayout.Vector3Field("",SMM.CustomRotation); - // SMM.EM.CustomRotation.x = EditorGUILayout.Slider("x-axis: ",SMM.CustomRotation.x,-360f,360f); - // SMM.EM.CustomRotation.y = EditorGUILayout.Slider("y-axis: ",SMM.CustomRotation.y,-360f,360f); - // SMM.EM.CustomRotation.z = EditorGUILayout.Slider("z-axis: ",SMM.CustomRotation.z,-360f,360f); - EditorGUILayout.EndVertical(); - EditorGUILayout.EndVertical(); - - - EditorGUILayout.LabelField("Deprecated options:"); - EditorGUILayout.BeginVertical("box"); - SMM.EM.bExactSplination = EditorGUILayout.Toggle("Directional extrusion: ", SMM.bExactSplination); - - EditorGUILayout.EndVertical(); - BigLine(); - BigLine(); - } - } - - public void UpdateSplineObjects() - { - if (!tNode.CanSplinate()) { return; } - if (tNode.SplinatedObjects == null) { tNode.SplinatedObjects = new List(); } - eCount = tNode.SplinatedObjects.Count; - for (int i = 0; i < eCount; i++) - { - SMM = tNode.SplinatedObjects[i]; - if (SMM.EM != null) - { - if (!SMM.EM.IsEqualToSMM(SMM)) - { - SMM.EM.LoadToSMM(SMM); - - SMM.UpdatePositions(); - if (SMM.EM.bIsStretch != SMM.bIsStretch) - { - if (SMM.bIsStretch) - { - SMM.CollisionType = GSD.Roads.Splination.CollisionTypeEnum.BoxCollision; - SMM.bMatchRoadDefinition = false; - SMM.bMatchTerrain = false; - SMM.bCollisionConvex = false; - SMM.bStartDown = false; - SMM.bEndDown = false; - SMM.bVerticalCutoff = false; - SMM.bExactSplination = false; - SMM.bEndTypeDownOverride = false; - } - } - - SMM.Setup(true); - // Debug.Log ("Setup SMM"); - } - } - } - } - - public void UpdateSplineObjects_OnUndo() - { - if (!tNode.CanSplinate()) { return; } - if (tNode.SplinatedObjects == null) { tNode.SplinatedObjects = new List(); } - - //Destroy all children: - for (int i = tNode.transform.childCount - 1; i >= 0; i--) - { - Object.DestroyImmediate(tNode.transform.GetChild(i).gameObject); - } - - //Re-setup the SMM: - eCount = tNode.SplinatedObjects.Count; - for (int i = 0; i < eCount; i++) - { - SMM = tNode.SplinatedObjects[i]; - SMM.UpdatePositions(); - //if(SMM.bIsStretch != SMM.bIsStretch){ - if (SMM.bIsStretch) - { - SMM.CollisionType = GSD.Roads.Splination.CollisionTypeEnum.BoxCollision; - SMM.bMatchRoadDefinition = false; - SMM.bMatchTerrain = false; - SMM.bCollisionConvex = false; - SMM.bStartDown = false; - SMM.bEndDown = false; - SMM.bVerticalCutoff = false; - SMM.bExactSplination = false; - SMM.bEndTypeDownOverride = false; - } - //} - SMM.Setup(true); - } - - UpdateEdgeObjects_OnUndo(); - } - - public void DoEdgeObjects() - { - if (!tNode.CanSplinate()) { return; } - - if (tNode.EdgeObjects == null) - { - tNode.EdgeObjects = new List(); - } - eCount = tNode.EdgeObjects.Count; - - EOM = null; - - for (int i = 0; i < tNode.EdgeObjects.Count; i++) - { - EOM = tNode.EdgeObjects[i]; - if (EOM.EM == null) - { - EOM.EM = new GSD.Roads.EdgeObjects.EdgeObjectMaker.EdgeObjectEditorMaker(); - } - EOM.EM.Setup(EOM); - - currentCount += 1; - EditorGUILayout.BeginVertical("TextArea"); - - - if (EOM.bNeedsUpdate) { EOM.Setup(); } - EOM.bNeedsUpdate = false; - - EditorGUILayout.BeginHorizontal(); - - EOM.bToggle = EditorGUILayout.Foldout(EOM.bToggle, "#" + currentCount.ToString() + ": " + EOM.tName); - - if (GUILayout.Button(btnEdgeText, GSDImageButton, GUILayout.Width(32f))) - { - - } - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - EOM.Setup(); - } - if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) - { - GSDSaveWindow tSave = EditorWindow.GetWindow(); - tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.Edge, tNode, null, EOM); - } - - if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) - { - Undo.RecordObject(tNode, "Copy"); - tNode.CopyEdgeObject(i); - EditorUtility.SetDirty(tNode); - } - if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) - { - Undo.RecordObject(tNode, "Delete"); - tNode.RemoveEdgeObject(i); - EditorUtility.SetDirty(tNode); - } - EditorGUILayout.EndHorizontal(); - - if (!EOM.bToggle) { EditorGUILayout.EndVertical(); continue; } - - GUILayout.Space(8f); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("General options:"); - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginVertical("box"); - //Name: - EOM.EM.tName = EditorGUILayout.TextField("Name: ", EOM.tName); - - //Edge object: - EOM.EM.EdgeObject = (GameObject)EditorGUILayout.ObjectField("Edge object: ", EOM.EdgeObject, typeof(GameObject), false); - if (EOM.EM.EdgeObject != EOM.EdgeObject) - { - EOM.bEdgeSignLabelInit = false; - EOM.bEdgeSignLabel = false; - } - - //Material override: - EOM.EM.bMaterialOverride = EditorGUILayout.Toggle("Material override: ", EOM.bMaterialOverride); - if (!EOM.bMaterialOverride) - { - EOM.EM.EdgeMaterial1 = null; - EOM.EM.EdgeMaterial2 = null; - } - - if (!EOM.bEdgeSignLabelInit && EOM.EM.EdgeObject != null) - { - EOM.bEdgeSignLabel = false; - if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignDiamond") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-diamond"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignSquare-Small") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-Square"; - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignSquare") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-Square"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign988-Small") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-988"; - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign988") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-988"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign861-Small") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-861"; - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign861") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-861"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign617-Small") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-617"; - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign617") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-617"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign396") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-396"; - - } - else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign330") == 0) - { - EOM.bEdgeSignLabel = true; - EOM.EdgeSignLabel = "GSDFedSign-330"; - } - } - - if (EOM.bMaterialOverride) - { - if (EOM.bEdgeSignLabel) - { - EditorGUILayout.TextField("Material search term: ", EOM.EdgeSignLabel); - } - - EOM.EM.EdgeMaterial1 = (Material)EditorGUILayout.ObjectField("Override mat #1: ", EOM.EdgeMaterial1, typeof(Material), false); - EOM.EM.EdgeMaterial2 = (Material)EditorGUILayout.ObjectField("Override mat #2: ", EOM.EdgeMaterial2, typeof(Material), false); - } - - if (EOM.bSingle) - { - EOM.EM.bCombineMesh = false; - } - else - { - EOM.EM.bCombineMesh = EditorGUILayout.Toggle("Combine meshes: ", EOM.bCombineMesh); - - if (EOM.bCombineMesh) - { - EOM.EM.bCombineMeshCollider = EditorGUILayout.Toggle("Combined mesh collider: ", EOM.bCombineMeshCollider); - } - } - - EOM.EM.bSingle = EditorGUILayout.Toggle("Single object only: ", EOM.bSingle); - if (EOM.EM.bSingle != EOM.bSingle) - { - EOM.EM.EndTime = tNode.NextTime; - // EOM.EM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.EM.EndTime,false); - EOM.EM.SinglePosition = tNode.tTime + 0.025f; - if (EOM.EM.bSingle) - { - EOM.EM.bCombineMesh = false; - } - } - - if (EOM.bSingle) - { - EOM.EM.SinglePosition = EditorGUILayout.Slider("Single location: ", EOM.SinglePosition, tNode.tTime, 1f); - - if (tNode.bIsBridgeStart && tNode.bIsBridgeMatched) - { - EOM.EM.SingleOnlyBridgePercent = EditorGUILayout.Slider("Bridge %: ", EOM.SingleOnlyBridgePercent, 0f, 1f); - if (!GSDRootUtil.IsApproximately(EOM.SingleOnlyBridgePercent, EOM.EM.SingleOnlyBridgePercent, 0.001f)) - { - EOM.EM.SingleOnlyBridgePercent = Mathf.Clamp(EOM.EM.SingleOnlyBridgePercent, 0f, 1f); - float tDist = (EOM.EM.SingleOnlyBridgePercent * (tNode.BridgeCounterpartNode.tDist - tNode.tDist) + tNode.tDist); - EOM.EM.SinglePosition = tNode.GSDSpline.TranslateDistBasedToParam(tDist); - } - } - } - - EOM.EM.bStatic = EditorGUILayout.Toggle("Static: ", EOM.bStatic); - EOM.EM.bMatchTerrain = EditorGUILayout.Toggle("Match ground height: ", EOM.bMatchTerrain); - - if (!EOM.bSingle) - { - EOM.EM.MeterSep = EditorGUILayout.Slider("Dist between objects: ", EOM.MeterSep, 1f, 256f); - } - - EOM.EM.bStartMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", EOM.bStartMatchRoadDefinition); - if (EOM.bStartMatchRoadDefinition) - { - EOM.EM.StartMatchRoadDef = EditorGUILayout.Slider("Position fine tuning: ", EOM.StartMatchRoadDef, 0f, 1f); - if (!GSDRootUtil.IsApproximately(EOM.EM.StartMatchRoadDef, EOM.StartMatchRoadDef, 0.001f)) - { - EOM.EM.StartMatchRoadDef = Mathf.Clamp(EOM.EM.StartMatchRoadDef, 0f, 1f); - } - } - - if (!EOM.bSingle) - { - if (EOM.EM.StartTime < tNode.MinSplination) { EOM.EM.StartTime = tNode.MinSplination; } - if (EOM.EM.EndTime > tNode.MaxSplination) { EOM.EM.EndTime = tNode.MaxSplination; } - - EditorGUILayout.BeginHorizontal(); - EOM.EM.StartTime = EditorGUILayout.Slider("Start param: ", EOM.StartTime, tNode.MinSplination, EOM.EndTime); - if (EOM.EM.EndTime < EOM.EM.StartTime) - { - EOM.EM.EndTime = Mathf.Clamp(EOM.StartTime + 0.01f, 0f, 1f); - } - if (GUILayout.Button("match node", EditorStyles.miniButton, GUILayout.Width(80f))) - { - EOM.EM.StartTime = tNode.tTime; - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - EOM.EM.EndTime = EditorGUILayout.Slider("End param: ", EOM.EndTime, EOM.StartTime, tNode.MaxSplination); - if (EOM.EM.StartTime > EOM.EM.EndTime) - { - EOM.EM.StartTime = Mathf.Clamp(EOM.EndTime - 0.01f, 0f, 1f); - } - if (GUILayout.Button("match next", EditorStyles.miniButton, GUILayout.Width(80f))) - { - EOM.EM.EndTime = tNode.NextTime; - } - EditorGUILayout.EndHorizontal(); - } - - EditorGUILayout.EndVertical(); - - //Vertical offset: - EditorGUILayout.LabelField("Vertical options:"); - EditorGUILayout.BeginVertical("box"); - - EditorGUILayout.BeginHorizontal(); - EOM.EM.VerticalRaise = EditorGUILayout.Slider("Vertical raise magnitude:", EOM.VerticalRaise, -512f, 512f); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - EOM.EM.VerticalRaise = 0f; - } - EditorGUILayout.EndHorizontal(); - - if (EOM.VerticalCurve == null || EOM.VerticalCurve.keys.Length < 2) { EnforceCurve(ref EOM.VerticalCurve); } - EditorGUILayout.BeginHorizontal(); - EOM.EM.VerticalCurve = EditorGUILayout.CurveField("Curve: ", EOM.VerticalCurve); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - ResetCurve(ref EOM.EM.VerticalCurve); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - //Horizontal offsets: - EditorGUILayout.LabelField("Horizontal offset options:"); - EditorGUILayout.BeginVertical("box"); - tHorizMatching = HorizMatchingDefaultsEnum.None; - tHorizMatching = (HorizMatchingDefaultsEnum)EditorGUILayout.Popup((int)tHorizMatching, HorizMatchSubTypeDescriptions, GUILayout.Width(100f)); - if (tHorizMatching != HorizMatchingDefaultsEnum.None) - { - if (tHorizMatching == HorizMatchingDefaultsEnum.MatchCenter) - { - EOM.EM.HorizontalSep = 0f; - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadLeft) - { - EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) * -1; - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderLeft) - { - if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) - { - EOM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1; - } - else - { - EOM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() * 0.5f)) * -1; - } - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadRight) - { - EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f); - } - else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderRight) - { - if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) - { - EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) + tNode.GSDSpline.tRoad.opt_ShoulderWidth; - } - else - { - EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f); - } - } - tHorizMatching = HorizMatchingDefaultsEnum.None; - } - if (!GSDRootUtil.IsApproximately(EOM.EM.HorizontalSep, EOM.HorizontalSep)) - { - EOM.EM.HorizontalSep = Mathf.Clamp(EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); - } - - - EditorGUILayout.BeginHorizontal(); - EOM.EM.HorizontalSep = EditorGUILayout.Slider("Horiz offset magnitude:", EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - EOM.EM.HorizontalSep = 0f; - } - if (!GSDRootUtil.IsApproximately(EOM.EM.HorizontalSep, EOM.HorizontalSep)) - { - EOM.EM.HorizontalSep = Mathf.Clamp(EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); - } - EditorGUILayout.EndHorizontal(); - if (EOM.HorizontalCurve == null || EOM.HorizontalCurve.keys.Length < 2) { EnforceCurve(ref EOM.HorizontalCurve); } - EditorGUILayout.BeginHorizontal(); - EOM.EM.HorizontalCurve = EditorGUILayout.CurveField("Curve: ", EOM.HorizontalCurve); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - ResetCurve(ref EOM.EM.HorizontalCurve); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.LabelField("Rotation/scale options:"); - EditorGUILayout.BeginVertical("box"); - if (EOM.HorizontalSep < 0f) - { - EOM.EM.bOncomingRotation = EditorGUILayout.Toggle("Auto rotate oncoming objects: ", EOM.bOncomingRotation); - } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Custom rotation: "); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - EOM.EM.CustomRotation = new Vector3(0f, 0f, 0f); - } - EditorGUILayout.EndHorizontal(); - - EOM.EM.CustomRotation.x = EditorGUILayout.Slider("x-axis: ", EOM.CustomRotation.x, -360f, 360f); - EOM.EM.CustomRotation.y = EditorGUILayout.Slider("y-axis: ", EOM.CustomRotation.y, -360f, 360f); - EOM.EM.CustomRotation.z = EditorGUILayout.Slider("z-axis: ", EOM.CustomRotation.z, -360f, 360f); - EditorGUILayout.EndVertical(); - EditorGUILayout.BeginVertical("box"); /* scale */ - EditorGUILayout.BeginHorizontal(); - float scale = EditorGUILayout.Slider("Custom scale: ", EOM.CustomScale.x, 1f, 10f); - EOM.EM.CustomScale = new Vector3(scale, scale, scale); - if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) - { - EOM.EM.CustomScale = new Vector3(1f, 1f, 1f); - } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndVertical(); /* scale */ - EditorGUILayout.EndVertical(); - } - } - - public void UpdateEdgeObjects() - { - if (!tNode.CanSplinate()) { return; } - eCount = tNode.EdgeObjects.Count; - for (int i = 0; i < tNode.EdgeObjects.Count; i++) - { - EOM = tNode.EdgeObjects[i]; - if (EOM.EM != null) - { - if (!EOM.EM.IsEqual(EOM)) - { - EOM.EM.LoadTo(EOM); - EOM.UpdatePositions(); - EOM.Setup(); - // Debug.Log ("Setup EOM"); - } - } - } - } - - public void UpdateEdgeObjects_OnUndo() - { - if (!tNode.CanSplinate()) { return; } - eCount = tNode.EdgeObjects.Count; - for (int i = 0; i < tNode.EdgeObjects.Count; i++) - { - EOM = tNode.EdgeObjects[i]; - EOM.Setup(); - } - } - - #region "Quick adds" - private void BridgeAdd_TopBase(float tHorizSep = 0f, float tVertRaise = -0.01f, string tMat = "", bool bOverridePrefab = false, string OverridePrefab = "") - { - if (tMat == "") - tMat = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDConcrete2.mat"; - SMM = tNode.AddSplinatedObject(); - string tBridgeTopBaseToAdd = ""; - string tName = ""; - if (tNode.GSDSpline.tRoad.opt_Lanes == 2) - { - if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-19w-5l-1d.fbx"; - tName = "BridgeTop1M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-20w-5l-1d.fbx"; - tName = "BridgeTop2M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-18w-5l-3d.fbx"; - tName = "BridgeTop0M-3M"; - } - else - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-18w-5l-1d.fbx"; - tName = "BridgeTop0M-1M"; - } - } - else if (tNode.GSDSpline.tRoad.opt_Lanes == 4) - { - if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-29w-5l-1d.fbx"; - tName = "BridgeTop1M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-30w-5l-1d.fbx"; - tName = "BridgeTop2M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-28w-5l-3d.fbx"; - tName = "BridgeTop0M-3M"; - } - else - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-28w-5l-1d.fbx"; - tName = "BridgeTop0M-1M"; - } - } - else - { - if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-39w-5l-1d.fbx"; - tName = "BridgeTop1M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-40w-5l-1d.fbx"; - tName = "BridgeTop2M-1M"; - } - else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-38w-5l-3d.fbx"; - tName = "BridgeTop0M-3M"; - } - else - { - tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-38w-5l-1d.fbx"; - tName = "BridgeTop0M-1M"; - } - } - - if (bOverridePrefab) { tBridgeTopBaseToAdd = OverridePrefab; } - - SMM.tName = tName; - SMM.CurrentSplination = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(tBridgeTopBaseToAdd, typeof(GameObject)); - SMM.HorizontalSep = tHorizSep; - SMM.VerticalRaise = tVertRaise; - SMM.bMaterialOverride = true; - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - SMM.Axis = GSD.Roads.Splination.AxisTypeEnum.Z; - - tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; - if (SMM.StartTime < tNode.MinSplination) { SMM.StartTime = tNode.MinSplination; } - if (SMM.EndTime > tNode.MaxSplination) { SMM.EndTime = tNode.MaxSplination; } - } - - private void BridgeAdd_BottomBase(float tHorizSep = 0f, float tVertRaise = -1.01f, string tMat = "", bool bOverridePrefab = false, string OverridePrefab = "") - { - if (tMat == "") - tMat = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDConcrete2.mat"; - SMM = tNode.AddSplinatedObject(); - string tBridgeBottomBaseToAdd = ""; - string tName = ""; - if (tNode.GSDSpline.tRoad.opt_Lanes == 2) - { - if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-18w-5l-3d.fbx"; - tName = "BridgeBase2"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-18w-5l-5d.fbx"; - tName = "BridgeBase3"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-18w-5l-5d.fbx"; - tName = "BridgeBase4"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-18w-5l-5d.fbx"; - tName = "BridgeBase5"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-2L.fbx"; - tName = "BridgeArchBeam80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-2L.fbx"; - tName = "BridgeArchSolid80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-2L.fbx"; - tName = "BridgeArchSolid180"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-18w-5l-5d.fbx"; - tName = "BridgeGrid"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-18w-20l-3d.fbx"; - tName = "BridgeSteelBeams"; - } - } - else if (tNode.GSDSpline.tRoad.opt_Lanes == 4) - { - if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-28w-5l-3d.fbx"; - tName = "BridgeBase2"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-28w-5l-5d.fbx"; - tName = "BridgeBase3"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-28w-5l-5d.fbx"; - tName = "BridgeBase4"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-28w-5l-5d.fbx"; - tName = "BridgeBase5"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-4L.fbx"; - tName = "BridgeArchBeam80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-4L.fbx"; - tName = "BridgeArchSolid80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-4L.fbx"; - tName = "BridgeArchSolid180"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-28w-5l-5d.fbx"; - tName = "BridgeGrid"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-28w-20l-3d.fbx"; - tName = "BridgeSteelBeams"; - } - } - else - { - if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-38w-5l-3d.fbx"; - tName = "BridgeBase2"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-38w-5l-5d.fbx"; - tName = "BridgeBase3"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-38w-5l-5d.fbx"; - tName = "BridgeBase4"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-38w-5l-5d.fbx"; - tName = "BridgeBase5"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-6L.fbx"; - tName = "BridgeArchBeam80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-6L.fbx"; - tName = "BridgeArchSolid80"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-6L.fbx"; - tName = "BridgeArchSolid180"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-38w-5l-5d.fbx"; - tName = "BridgeGrid"; - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) - { - tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-38w-20l-3d.fbx"; - tName = "BridgeBeams"; - } - } - - if (bOverridePrefab) { tBridgeBottomBaseToAdd = OverridePrefab; } - - SMM.CurrentSplination = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(tBridgeBottomBaseToAdd, typeof(GameObject)); - SMM.HorizontalSep = tHorizSep; - SMM.VerticalRaise = tVertRaise; - SMM.bMaterialOverride = true; - SMM.tName = tName; - - if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDSteel7.mat"); - } - else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) - { - SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDSteel7.mat"); - } - - SMM.Axis = GSD.Roads.Splination.AxisTypeEnum.Z; - - tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; - if (SMM.StartTime < tNode.MinSplination) { SMM.StartTime = tNode.MinSplination; } - if (SMM.EndTime > tNode.MaxSplination) { SMM.EndTime = tNode.MaxSplination; } - } - - private void ExtrusionQuickAdd(bool bHorizOverride = false, float tHorizSep = 0f, bool bVertOverride = false, float tVertRaise = 0f) - { - try - { - ExtrusionQuickAdd_Do(); - } - catch (System.Exception e) - { - tSMMQuickAdd = SMMDefaultsEnum.None; - throw e; - } - } - - private void ExtrusionQuickAdd_Do() - { - if (tSMMQuickAdd == SMMDefaultsEnum.KRail) - { - tNode.SplinatedObjectQuickAdd("KRail"); - } - } - - private void ExtrudeHelper(string tPath, string tName, float DefaultHoriz, GSD.Roads.Splination.AxisTypeEnum tAxis = GSD.Roads.Splination.AxisTypeEnum.Z, bool bHorizOverride = false, float tHorizSep = 0f, bool bVertOverride = false, float tVertRaise = 0f, bool bFlipRot = false) - { - SMM = tNode.AddSplinatedObject(); - SMM.CurrentSplination = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(tPath, typeof(GameObject)); - - if (bHorizOverride) - { - SMM.HorizontalSep = tHorizSep; - } - else - { - SMM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1f; - } - - if (bVertOverride) - { - SMM.VerticalRaise = tVertRaise; - } - else - { - if (tNode.bIsBridgeStart) { SMM.VerticalRaise = -0.01f; } - } - - SMM.bFlipRotation = bFlipRot; - SMM.Axis = tAxis; - if (SMM.StartTime < tNode.MinSplination) { SMM.StartTime = tNode.MinSplination; } - if (SMM.EndTime > tNode.MaxSplination) { SMM.EndTime = tNode.MaxSplination; } - SMM.tName = tName; - } - #endregion - - public void OnSceneGUI() - { - Event current = Event.current; - int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - bool bUsed = false; - - if (!bSceneRectSet) - { - try - { - tSceneRect = EditorWindow.GetWindow().position; - } - catch - { - tSceneRect = EditorWindow.GetWindow().position; - } - bSceneRectSet = true; - } - - if (!tNode.bEditorSelected) - { - tNode.bEditorSelected = true; - } - - if (current.type == EventType.ValidateCommand) - { - switch (current.commandName) - { - case "UndoRedoPerformed": - UpdateSplineObjects_OnUndo(); - break; - } - } - - if (controlID != tNode.GetHashCode()) { tNode.bEditorSelected = false; } - - //Drag with left click: - if (Event.current.type == EventType.MouseDrag && Event.current.button == 0) - { - bMouseDragHasProcessed = false; - tNode.bGizmoDrawIntersectionHighlight = true; - } - //Drag with left click release: - if (Event.current.type == EventType.MouseUp && Event.current.button == 0) - { - Object[] xNodeObjects = GameObject.FindObjectsOfType(typeof(GSDSplineN)); - Object[] connectorObjects = GameObject.FindObjectsOfType(typeof(GSDRoadConnector)); - foreach (GSDSplineN xNode in xNodeObjects) - { - if (Vector3.Distance(xNode.transform.position, tNode.transform.position) < 2f) - { - if (xNode == tNode) { continue; } - if (tNode.bSpecialEndNode || xNode.bSpecialEndNode) { continue; } - if (xNode.bIsEndPoint && tNode.bIsEndPoint) - { - //End point connection. - tNode.transform.position = xNode.transform.position; - //Activate special end node for tnode - TriggerRoadConnection(tNode, xNode); - bUsed = true; - break; - } - if (xNode.bIsIntersection) { continue; } - if (xNode.bNeverIntersect) { continue; } - if (tNode.bIsEndPoint && xNode.bIsEndPoint) { continue; } - if (xNode.GSDSpline == tNode.GSDSpline) - { //Don't let intersection be created on consecutive nodes: - if ((tNode.idOnSpline + 1) == xNode.idOnSpline || (tNode.idOnSpline - 1) == xNode.idOnSpline) - { - continue; - } - } - tNode.transform.position = xNode.transform.position; - TriggerIntersection(tNode, xNode); - bUsed = true; - break; - } - else - { - continue; - } - } - foreach (GSDRoadConnector connector in connectorObjects) - { - if (Vector3.Distance(connector.transform.position, tNode.transform.position) < 2f) - { - if (connector.connectedNode != null) continue; - connector.ConnectToNode(tNode); - break; - } - } - - if (!bMouseDragHasProcessed) - { - //Enforce maximum road grade: - if (tNode.IsLegitimate() && tNode.GSDSpline.tRoad.opt_bMaxGradeEnabled) - { - tNode.EnsureGradeValidity(); - } - TriggerRoadUpdate(); - bUsed = true; - } - bMouseDragHasProcessed = true; - tNode.bGizmoDrawIntersectionHighlight = false; - bUsed = true; - } - - //Enforce maximum road grade: - if (bMouseDragHasProcessed) - { - - Vector3 vChangeChecker = tNode.transform.position; - if (VectorDiff(vChangeChecker, tNode.pos)) - { - tNode.pos = vChangeChecker; - if (tNode.IsLegitimate() && tNode.GSDSpline.tRoad.opt_bMaxGradeEnabled) - { - tNode.EnsureGradeValidity(); - } - TriggerRoadUpdate(); - } - bUsed = true; - } - - if (Selection.activeGameObject == tNode.transform.gameObject) - { - if (current.keyCode == KeyCode.F5) - { - TriggerRoadUpdate(); - } - } - - if (bUsed) - { - // switch(current.type){ - // case EventType.layout: - // HandleUtility.AddDefaultControl(controlID); - // break; - // } - } - - if (GUI.changed) - { - EditorUtility.SetDirty(tNode); - } - } - - private bool VectorDiff(Vector3 tVect1, Vector3 tVect2) - { - if (!GSDRootUtil.IsApproximately(tVect1.x, tVect2.x, 0.0001f)) - { - return true; - } - if (!GSDRootUtil.IsApproximately(tVect1.y, tVect2.y, 0.0001f)) - { - return true; - } - if (!GSDRootUtil.IsApproximately(tVect1.z, tVect2.z, 0.0001f)) - { - return true; - } - return false; - } - - private void TriggerRoadConnection(GSDSplineN tNode1, GSDSplineN tNode2) - { - tNode.GSDSpline.ActivateEndNodeConnection(tNode1, tNode2); - } - - private void TriggerIntersection(GSDSplineN tNode1, GSDSplineN tNode2) - { - bCreateIntersection = true; - iNode1 = tNode1; - iNode2 = tNode2; - Selection.activeGameObject = GSD.Roads.GSDIntersections.CreateIntersection(tNode1, tNode2); - } - - private void TriggerRoadUpdate() - { - if (tNode != null) - { - tNode.GSDSpline.tRoad.EditorUpdateMe = true; - } - } - - void Line() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar - GUILayout.Space(4f); - } - - void LineSmall() - { - GUILayout.Space(2f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar - GUILayout.Space(2f); - } - - void BigLine() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(4f)); //Horizontal bar - GUILayout.Space(4f); - } - - void ResetCurve(ref AnimationCurve tCurve) - { - tCurve = null; - tCurve = new AnimationCurve(); - EnforceCurve(ref tCurve); - } - - bool V3Equal(ref Vector3 V1, ref Vector3 V2) - { - if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.001f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.001f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.001f)) - { - return false; - } - return true; - } - - void EnforceCurve(ref AnimationCurve tCurve) - { - if (tCurve == null) - return; - if (tCurve.keys.Length == 0) - { - tCurve.AddKey(0f, 1f); - tCurve.AddKey(1f, 1f); - } - else if (tCurve.keys.Length == 1) - { - tCurve.keys[0].time = 0f; - tCurve.AddKey(1f, 1f); - } - } - - GameObject GetEndObjectQuickAdd() - { - string tPath = ""; - if (tEndObjectAdd == EndObjectsDefaultsEnum.WarningSign1_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDWarningSign_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.WarningSign2_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDWarningSign2_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Atten_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDAtten_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel1_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel1_Rigid) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel_Rigid.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel3_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel3_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel3_Rigid) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel3_Rigid.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel7_Static) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel7_Static.prefab"; - } - else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel7_Rigid) - { - tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel7_Rigid.prefab"; - } - else - { - return null; - } - - return (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(tPath, typeof(GameObject)) as GameObject; - } -} +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using GSD; +#endregion + + +//===================================================== +//== NOTE THAT CUSTOM SERIALIZATION IS USED HERE == +//== SOLELY TO COMPLY WITH UNDO REQUIREMENTS == +//===================================================== + +[CustomEditor(typeof(GSDSplineN))] +public class GSDSplineNEditor : Editor +{ + #region "Vars" + protected GSDSplineN tNode { get { return (GSDSplineN) target; } } + const string tOnlineHelpDesc = "Visit the online manual for the most effective help."; + bool bMouseDragHasProcessed = true; + int eCount = -1; + int currentCount = 0; + public bool bSplinatedObjectHelp = false; + public bool bEdgeObjectHelp = false; + bool bRemoveAll = false; + float HorizRoadMax = 0; + + + #region Button icons: + Texture btnDeleteText = null; + Texture btnCopyText = null; + Texture btnSaveText = null; + Texture btnLoadText = null; + Texture btnExtrudeText = null; + Texture btnEdgeText = null; + Texture btnHelpText = null; + Texture btnRefreshText = null; + Texture btnDefaultText = null; + Texture2D LoadBtnBG = null; + Texture2D GSDTextAreaBG = null; + Texture2D LoadBtnBGGlow = null; + Texture2D ManualBG = null; + #endregion + + + public bool bLoadingEOS = false; + public int LoadingEOSIndex = 0; + public List LoadingEOSNames = null; + public List LoadingEOSPaths = null; + + public bool bLoadingEOM = false; + public int LoadingEOMIndex = 0; + public List LoadingEOMNames = null; + public List LoadingEOMPaths = null; + + //Checkers: + // float ChangeChecker = -1f; + // bool bChangeChecker = false; + // Vector3 vChangeChecker = default(Vector3); + // GameObject tObj = null; + // Material tMat = null; + GSD.Roads.Splination.SplinatedMeshMaker SMM = null; + + + #region "Enums" + public enum EndObjectsDefaultsEnum + { + None, + WarningSign1_Static, + WarningSign2_Static, + Atten_Static, + Barrel1_Static, + Barrel1_Rigid, + Barrel3_Static, + Barrel3_Rigid, + Barrel7_Static, + Barrel7_Rigid + }; + + + EndObjectsDefaultsEnum tEndObjectAdd = EndObjectsDefaultsEnum.None; + + + private static string[] EndObjectsDefaultsEnumDesc = new string[]{ + "Quick add", + "WarningSign1", + "WarningSign2", + "Attenuator", + "1 Sand barrel Static", + "1 Sand barrel Rigid", + "3 Sand barrels Static", + "3 Sand barrels Rigid", + "7 Sand barrels Static", + "7 Sand barrels Rigid" + }; + + + public enum SMMDefaultsEnum + { + None, Custom, + KRail, + WBeamR, + WBeamL, + Railing1, + Railing2, + Railing3, + Railing4, + RailingBase05m, + RailingBase1m + }; + + + SMMDefaultsEnum tSMMQuickAdd = SMMDefaultsEnum.None; + + + public enum BridgeTopBaseDefaultsEnum + { + None, + BaseExact, + Base1MOver, + Base2MOver, + Base3MDeep, + }; + + + BridgeTopBaseDefaultsEnum tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; + + + public enum BridgeBottomBaseDefaultsEnum + { + None, + BridgeBase6, + BridgeBase7, + BridgeBase8, + BridgeBaseGrid, + BridgeSteel, + BridgeBase2, + BridgeBase3, + BridgeBase4, + BridgeBase5, + }; + + + BridgeBottomBaseDefaultsEnum tBridgeBottomBaseQuickAdd = BridgeBottomBaseDefaultsEnum.None; + + + public enum BridgeWizardDefaultsEnum + { + None, + ArchBridge12m, + ArchBridge24m, + ArchBridge48m, + SuspensionBridgeSmall, + SuspensionBridgeLarge, + CausewayBridge1, + CausewayBridge2, + CausewayBridge3, + CausewayBridge4, + ArchBridge1, + ArchBridge2, + ArchBridge3, + GridBridge, + SteelBeamBridge + }; + // BridgeWizardDefaultsEnum tBridgeWizardQuickAdd = BridgeWizardDefaultsEnum.None; + + + public enum HorizMatchingDefaultsEnum + { + None, + MatchCenter, + MatchRoadLeft, + MatchShoulderLeft, + MatchRoadRight, + MatchShoulderRight + }; + + + HorizMatchingDefaultsEnum tHorizMatching = HorizMatchingDefaultsEnum.None; + + + public enum EOMDefaultsEnum { None, Custom, StreetLightSingle, StreetLightDouble }; + #endregion + + + //GSD.Roads.Splination.CollisionTypeEnum tCollisionTypeSpline = GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle; + //GSD.Roads.Splination.RepeatUVTypeEnum tRepeatUVType = GSD.Roads.Splination.RepeatUVTypeEnum.None; + GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = null; + + + private static string[] TheAxisDescriptions_Spline = new string[]{ + "X axis", + "Z axis" + }; + + + private static string[] RepeatUVTypeDescriptions_Spline = new string[]{ + "None", + "X axis", + "Y axis" + }; + + + private static string[] TheCollisionTypeEnumDescSpline = new string[]{ + "None", + "Simple triangle", + "Simple trapezoid", + "Meshfilter collision mesh", + "Straight line box collider" + }; + + + private string[] HorizMatchSubTypeDescriptions; + #endregion + + GUIStyle GSDImageButton = null; + GUIStyle GSDLoadButton = null; + GUIStyle GSDManualButton = null; + GUIStyle GSDUrl = null; + + bool bSceneRectSet = false; + Rect tSceneRect = default(Rect); + + bool bHasInit = false; + + //Buffers: + // bool t_opt_GizmosEnabled = false; + bool t_opt_GizmosEnabled = false; + + // Bridge + bool t_bIsBridgeStart = false; + bool t_bIsBridgeEnd = false; + + bool t_bRoadCut = false; + + + void Init() + { + bHasInit = true; + EditorStyles.label.wordWrap = true; + EditorStyles.miniLabel.wordWrap = true; + + if (btnDeleteText == null) + { + btnDeleteText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/delete.png", typeof(Texture)) as Texture; + } + if (btnCopyText == null) + { + btnCopyText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/copy.png", typeof(Texture)) as Texture; + } + if (btnLoadText == null) + { + btnLoadText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/load.png", typeof(Texture)) as Texture; + } + if (btnSaveText == null) + { + btnSaveText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/save.png", typeof(Texture)) as Texture; + } + if (btnExtrudeText == null) + { + btnExtrudeText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/extrude.png", typeof(Texture)) as Texture; + } + if (btnEdgeText == null) + { + btnEdgeText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/edge.png", typeof(Texture)) as Texture; + } + if (btnHelpText == null) + { + btnHelpText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/help.png", typeof(Texture)) as Texture; + } + if (GSDTextAreaBG == null) + { + GSDTextAreaBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/popupbg.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBG == null) + { + LoadBtnBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/loadbg.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBGGlow == null) + { + LoadBtnBGGlow = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/loadbgglow.png", typeof(Texture2D)) as Texture2D; + } + if (ManualBG == null) + { + ManualBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/manualbg.png", typeof(Texture2D)) as Texture2D; + } + if (btnRefreshText == null) + { + btnRefreshText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh.png", typeof(Texture)) as Texture; + } + if (btnDefaultText == null) + { + btnDefaultText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; + } + + if (GSDImageButton == null) + { + GSDImageButton = new GUIStyle(GUI.skin.button); + GSDImageButton.contentOffset = new Vector2(0f, -2f); + GSDImageButton.border = new RectOffset(0, 0, 0, 0); + GSDImageButton.fixedHeight = 16f; + GSDImageButton.padding = new RectOffset(0, 0, 0, 0); + GSDImageButton.normal.background = null; + } + + if (GSDLoadButton == null) + { + GSDLoadButton = new GUIStyle(GUI.skin.button); + GSDLoadButton.contentOffset = new Vector2(0f, 1f); + GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDLoadButton.normal.background = LoadBtnBG; + GSDLoadButton.active.background = LoadBtnBGGlow; + GSDLoadButton.focused.background = LoadBtnBGGlow; + GSDLoadButton.hover.background = LoadBtnBGGlow; + GSDLoadButton.fixedHeight = 16f; + GSDLoadButton.fixedWidth = 128f; + GSDLoadButton.padding = new RectOffset(0, 35, 0, 0); + } + + if (GSDManualButton == null) + { + GSDManualButton = new GUIStyle(GUI.skin.button); + GSDManualButton.contentOffset = new Vector2(0f, 1f); + GSDManualButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDManualButton.normal.background = ManualBG; + GSDManualButton.fixedHeight = 16f; + GSDManualButton.fixedWidth = 128f; + } + + if (GSDUrl == null) + { + GSDUrl = new GUIStyle(GUI.skin.button); + GSDUrl.normal.textColor = new Color(0.5f, 1f, 0.5f, 1f); + } + + float tRoadWidthHalf = tNode.GSDSpline.tRoad.RoadWidth() * 0.5f; + HorizMatchSubTypeDescriptions = new string[6]; + HorizMatchSubTypeDescriptions[0] = "Select preset"; + HorizMatchSubTypeDescriptions[1] = "Match center: 0 meters"; + HorizMatchSubTypeDescriptions[2] = "Match road left edge: -" + tRoadWidthHalf.ToString("F1") + " meters"; + HorizMatchSubTypeDescriptions[4] = "Match road right edge: " + tRoadWidthHalf.ToString("F1") + " meters"; + + if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) + { + HorizMatchSubTypeDescriptions[3] = "Match shoulder left edge: -" + (tRoadWidthHalf + tNode.GSDSpline.tRoad.opt_ShoulderWidth).ToString("F1") + " meters"; + HorizMatchSubTypeDescriptions[5] = "Match shoulder right edge: " + (tRoadWidthHalf + tNode.GSDSpline.tRoad.opt_ShoulderWidth).ToString("F1") + " meters"; + } + else + { + HorizMatchSubTypeDescriptions[2] = "Match shoulder left edge: -" + tRoadWidthHalf.ToString("F1") + " meters"; + HorizMatchSubTypeDescriptions[4] = "Match shoulder right edge: " + tRoadWidthHalf.ToString("F1") + " meters"; + } + + HorizRoadMax = tNode.GSDSpline.tRoad.RoadWidth() * 20; + } + + + GSDSplineN iNode1 = null; + GSDSplineN iNode2 = null; + bool bCreateIntersection = false; + + + public override void OnInspectorGUI() + { + if (Event.current.type == EventType.ValidateCommand) + { + switch (Event.current.commandName) + { + case "UndoRedoPerformed": + UpdateSplineObjects_OnUndo(); + break; + } + } + + if (Event.current.type != EventType.Layout && bCreateIntersection) + { + bCreateIntersection = false; + Selection.activeGameObject = GSD.Roads.GSDIntersections.CreateIntersection(iNode1, iNode2); + return; + } + + + if (Event.current.type != EventType.Layout && tNode.bQuitGUI) + { + tNode.bQuitGUI = false; + return; + } + + //Graphic null checks: + if (!bHasInit) + { + Init(); + } + + Line(); + + #region Online Manual on Top of SplineN Scripts + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(tNode.EditorDisplayString, EditorStyles.boldLabel); + + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(128f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + #endregion + + + #region Option: Gizmo options, Convoluted due to submission compliance for undo rules: + if (tNode.GSDSpline.tRoad.opt_GizmosEnabled != tNode.opt_GizmosEnabled) + { + tNode.GSDSpline.tRoad.opt_GizmosEnabled = tNode.opt_GizmosEnabled; + tNode.GSDSpline.tRoad.UpdateGizmoOptions(); + tNode.GSDSpline.tRoad.Wireframes_Toggle(); + } + t_opt_GizmosEnabled = EditorGUILayout.Toggle("Gizmos: ", tNode.GSDSpline.tRoad.opt_GizmosEnabled); + #endregion + + + #region Option: Manual road cut: + if (tNode.idOnSpline > 0 && tNode.idOnSpline < (tNode.GSDSpline.GetNodeCount() - 1) && !tNode.bIsIntersection && !tNode.bSpecialEndNode) + { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ + if (tNode.GSDSpline.tRoad.opt_bDynamicCuts) + { + Line(); + t_bRoadCut = EditorGUILayout.Toggle("Cut road at this node: ", tNode.bRoadCut); + } + Line(); + } + #endregion + + + //Option: Bridge options + bool bDidBridge = false; + if (!tNode.bIsEndPoint) + { + //Bridge start: + if (!tNode.bIsBridgeEnd && tNode.CanBridgeStart()) + { + t_bIsBridgeStart = EditorGUILayout.Toggle(" Bridge start", tNode.bIsBridgeStart); + bDidBridge = true; + } + //Bridge end: + if (!tNode.bIsBridgeStart && tNode.CanBridgeEnd()) + { + t_bIsBridgeEnd = EditorGUILayout.Toggle(" Bridge end", tNode.bIsBridgeEnd); + bDidBridge = true; + } + + if (bDidBridge) + { + Line(); + } + } + + + + if ((Selection.objects.Length == 1 && Selection.objects[0] is GSDSplineN) || (tNode.SpecialNodeCounterpart == null && !tNode.bSpecialRoadConnPrimary)) + { + //Do extrusion and edge objects overview: + DoExtAndEdgeOverview(); + } + else + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Road objects")) + { + Selection.objects = new Object[1] { tNode.SpecialNodeCounterpart }; + } + EditorGUILayout.EndHorizontal(); + } + + if (tNode.bSpecialRoadConnPrimary) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Road connection:", EditorStyles.boldLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginVertical(); + if (GUILayout.Button("Update road connection")) + { + GSDSplineN tNode1 = tNode.OriginalConnectionNodes[0]; + GSDSplineN tNode2 = tNode.OriginalConnectionNodes[1]; + tNode.SpecialNodeCounterpart.BreakConnection(); + tNode.GSDSpline.tRoad.UpdateRoad(); + tNode1.GSDSpline.ActivateEndNodeConnection(tNode1, tNode2); + } + if (GUILayout.Button("Break road connection")) + { + tNode.SpecialNodeCounterpart.BreakConnection(); + } + if (GUILayout.Button("Access objects on other node")) + { + Selection.objects = new Object[] { tNode.SpecialNodeCounterpart }; + } + EditorGUILayout.EndVertical(); + if (tNode.SpecialNodeCounterpart != null) + { + EditorGUILayout.LabelField(tNode.SpecialNodeCounterpart.GSDSpline.tRoad.transform.name + " to " + tNode.SpecialNodeCounterpart.SpecialNodeCounterpart.GSDSpline.tRoad.transform.name); + } + EditorGUILayout.LabelField("To break this road connection, click the \"Break road connection\" button."); + Line(); + } + + //Statistics: + DoStats(); + EditorGUILayout.EndVertical(); + + if (GUI.changed) + { + //Set snapshot for undo: + + Undo.RecordObject(tNode, "Modify node"); + + //Option: Gizmo options, Convoluted due to submission compliance for undo rules: + if (t_opt_GizmosEnabled != tNode.GSDSpline.tRoad.opt_GizmosEnabled) + { + tNode.GSDSpline.tRoad.opt_GizmosEnabled = t_opt_GizmosEnabled; + tNode.GSDSpline.tRoad.UpdateGizmoOptions(); + tNode.GSDSpline.tRoad.Wireframes_Toggle(); + SceneView.RepaintAll(); + } + + //Option: Manual cut: + if (tNode.idOnSpline > 0 && tNode.idOnSpline < (tNode.GSDSpline.GetNodeCount() - 1) && !tNode.bIsIntersection && !tNode.bSpecialEndNode) + { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ + if (tNode.GSDSpline.tRoad.opt_bDynamicCuts) + { + if (t_bRoadCut != tNode.bRoadCut) + { + tNode.bRoadCut = t_bRoadCut; + } + } + } + + //Option: Bridge options + //Bridge start: + if (!tNode.bIsEndPoint) + { + if (!tNode.bIsBridgeEnd && tNode.CanBridgeStart()) + { + if (t_bIsBridgeStart != tNode.bIsBridgeStart) + { + tNode.bIsBridgeStart = t_bIsBridgeStart; + tNode.BridgeToggleStart(); + } + } + } + //Bridge end: + if (!tNode.bIsEndPoint) + { + if (!tNode.bIsBridgeStart && tNode.CanBridgeEnd()) + { + if (t_bIsBridgeEnd != tNode.bIsBridgeEnd) + { + tNode.bIsBridgeEnd = t_bIsBridgeEnd; + tNode.BridgeToggleEnd(); + } + } + } + + UpdateSplineObjects(); + UpdateEdgeObjects(); + + EditorUtility.SetDirty(target); + } + } + + + void OnSelectionChanged() + { + Repaint(); + } + + + //GUIStyle SectionBG; + + + void DoExtAndEdgeOverview() + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Extrusion & edge objects", EditorStyles.boldLabel); + EditorGUILayout.LabelField(""); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + if (bEdgeObjectHelp) + { + bEdgeObjectHelp = EditorGUILayout.Foldout(bEdgeObjectHelp, "Hide quick help"); + } + else + { + bEdgeObjectHelp = EditorGUILayout.Foldout(bEdgeObjectHelp, "Show quick help"); + } + EditorGUILayout.LabelField(""); + + if (GUILayout.Button("Save group", EditorStyles.miniButton, GUILayout.Width(108f)) || GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) + { + GSDSaveWindow tSave = EditorWindow.GetWindow(); + if (tNode.bIsBridge) + { + tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.BridgeWizard, tNode); + } + else + { + tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.BridgeWizard, tNode); + } + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(""); + if (GUILayout.Button("Open Wizard", GSDLoadButton, GUILayout.Width(128f))) + {// || GUILayout.Button(btnLoadText,GSDImageButton,GUILayout.Width(16f))){ + GSDWizard tWiz = EditorWindow.GetWindow(); + if (tSceneRect.x < 0) + { + tSceneRect.x = 0f; + } + if (tSceneRect.y < 0) + { + tSceneRect.y = 0f; + } + tWiz.xRect = tSceneRect; + if (tNode.bIsBridgeStart) + { + tWiz.Initialize(GSDWizard.WindowTypeEnum.BridgeComplete, tNode); + } + else + { + tWiz.Initialize(GSDWizard.WindowTypeEnum.Extrusion, tNode); + } + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + + if (bEdgeObjectHelp) + { + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnExtrudeText, GSDImageButton, GUILayout.Width(32f))) + { } + EditorGUILayout.LabelField("= Extrusion objects", EditorStyles.miniLabel); + EditorGUILayout.LabelField(""); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.LabelField("Railings, bridge pieces, center dividers and other connected objects.", EditorStyles.miniLabel); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnEdgeText, GSDImageButton, GUILayout.Width(32f))) + { } + EditorGUILayout.LabelField("= Edge objects", EditorStyles.miniLabel); + EditorGUILayout.LabelField(""); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.LabelField("Signs, street lights, bridge pillars and other unconnected road objects.", EditorStyles.miniLabel); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) + { } + EditorGUILayout.LabelField("= Saves object config to library for use on other nodes.", EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) + { } + EditorGUILayout.LabelField("= Duplicates object onto current node.", EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { } + EditorGUILayout.LabelField("= Deletes object.", EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { } + EditorGUILayout.LabelField("= Refreshes object.", EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { } + EditorGUILayout.LabelField("= Resets setting(s) to default.", EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + Line(); + } + currentCount = 0; + + GUILayout.Space(2f); + + + //Splinated objects: + DoSplineObjects(); + + //Edge Objects: + DoEdgeObjects(); + + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(""); + if (GUILayout.Button("Add custom extrusion object", EditorStyles.miniButton)) + { + tNode.AddSplinatedObject(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(""); + if (GUILayout.Button("Add custom edge object", EditorStyles.miniButton)) + { + tNode.AddEdgeObject(); + } + EditorGUILayout.EndHorizontal(); + + if (tNode.SplinatedObjects.Count > 20 || tNode.EdgeObjects.Count > 20) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(""); + bRemoveAll = EditorGUILayout.Toggle(bRemoveAll, GUILayout.Width(20f)); + if (GUILayout.Button("Remove all", EditorStyles.miniButton, GUILayout.Width(100f))) + { + if (bRemoveAll) + { + tNode.RemoveAllSplinatedObjects(); + tNode.RemoveAllEdgeObjects(); + bRemoveAll = false; + } + } + + EditorGUILayout.EndHorizontal(); + } + Line(); + } + + + void DoStats() + { + EditorGUILayout.LabelField("Statistics:"); + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField("Grade to next node: " + tNode.GradeToNext); + EditorGUILayout.LabelField("Grade to prev node: " + tNode.GradeToPrev); + EditorGUILayout.LabelField("Distance from start: " + tNode.tDist.ToString("F3") + " meters"); + EditorGUILayout.LabelField("% of spline: " + ((tNode.tDist / tNode.GSDSpline.distance) * 100f).ToString("F2") + "%"); + EditorGUILayout.LabelField("Parameter: " + tNode.tTime); + EditorGUILayout.LabelField("Tangent: " + tNode.tangent); + EditorGUILayout.LabelField("POS: " + tNode.pos); + EditorGUILayout.LabelField("ID on spline: " + tNode.idOnSpline); + EditorGUILayout.LabelField("Is intersection node: " + tNode.bIsIntersection); + EditorGUILayout.LabelField("Is end node: " + tNode.bIsEndPoint); + EditorGUILayout.LabelField("Is bridge start: " + tNode.bIsBridgeStart); + EditorGUILayout.LabelField("Is bridge end: " + tNode.bIsBridgeEnd); + EditorGUILayout.LabelField("Road: " + tNode.GSDSpline.tRoad.transform.name); + EditorGUILayout.LabelField("System: " + tNode.GSDSpline.tRoad.GSDRS.transform.name); + EditorGUILayout.SelectableLabel("UID: " + tNode.UID); + } + + + public void DoSplineObjects() + { + if (!tNode.CanSplinate()) + { + return; + } + if (tNode.SplinatedObjects == null) + { + tNode.SplinatedObjects = new List(); + } + eCount = tNode.SplinatedObjects.Count; + + SMM = null; + eCount = tNode.SplinatedObjects.Count; + if (eCount == 0) + { + + } + + for (int index = 0; index < tNode.SplinatedObjects.Count; index++) + { + currentCount += 1; + SMM = tNode.SplinatedObjects[index]; + if (SMM.EM == null) + { + SMM.EM = new GSD.Roads.Splination.SplinatedMeshMaker.SplinatedMeshEditorMaker(); + } + SMM.EM.Setup(SMM); + + //GSD.Roads.Splination.AxisTypeEnum tAxisTypeSpline = GSD.Roads.Splination.AxisTypeEnum.Z; + + EditorGUILayout.BeginVertical("TextArea"); + + if (SMM.bNeedsUpdate) + { + SMM.Setup(true); + } + + + EditorGUILayout.BeginHorizontal(); + + SMM.bToggle = EditorGUILayout.Foldout(SMM.bToggle, "#" + currentCount.ToString() + ": " + SMM.tName); + + if (GUILayout.Button(btnExtrudeText, GSDImageButton, GUILayout.Width(32f))) + { + + } + + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.Setup(); + } + if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) + { + GSDSaveWindow tSave = EditorWindow.GetWindow(); + tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.Extrusion, tNode, SMM); + } + if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) + { + Undo.RecordObject(tNode, "Copy"); + tNode.CopySplinatedObject(ref SMM); + EditorUtility.SetDirty(tNode); + } + if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + Undo.RecordObject(tNode, "Delete"); + tNode.RemoveSplinatedObject(index); + EditorUtility.SetDirty(tNode); + } + EditorGUILayout.EndHorizontal(); + if (!SMM.bToggle) + { + EditorGUILayout.EndVertical(); + continue; + } + + GUILayout.Space(8f); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("General options:"); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginVertical("box"); + + //Name: + SMM.EM.tName = EditorGUILayout.TextField("Name:", SMM.tName); + + //Game object (prefab): + SMM.EM.CurrentSplination = (GameObject) EditorGUILayout.ObjectField("Prefab:", SMM.CurrentSplination, typeof(GameObject), false); + + //Game object (prefab start cap): + SMM.EM.CurrentSplinationCap1 = (GameObject) EditorGUILayout.ObjectField("Prefab start cap:", SMM.CurrentSplinationCap1, typeof(GameObject), false); + //Prefab start cap height offset: + if (SMM.CurrentSplinationCap1 != null) + { + SMM.EM.CapHeightOffset1 = EditorGUILayout.FloatField(" Height offset:", SMM.CapHeightOffset1); + } + + //Game object (prefab end cap): + SMM.EM.CurrentSplinationCap2 = (GameObject) EditorGUILayout.ObjectField("Prefab end cap:", SMM.CurrentSplinationCap2, typeof(GameObject), false); + //Prefab end cap height offset: + if (SMM.CurrentSplinationCap2 != null) + { + SMM.EM.CapHeightOffset2 = EditorGUILayout.FloatField(" Height offset:", SMM.CapHeightOffset2); + } + + //Material overrides: + SMM.EM.bMaterialOverride = EditorGUILayout.Toggle("Material override: ", SMM.bMaterialOverride); + if (SMM.bMaterialOverride) + { + SMM.EM.SplinatedMaterial1 = (Material) EditorGUILayout.ObjectField("Override mat #1: ", SMM.SplinatedMaterial1, typeof(Material), false); + SMM.EM.SplinatedMaterial2 = (Material) EditorGUILayout.ObjectField("Override mat #2: ", SMM.SplinatedMaterial2, typeof(Material), false); + } + + //Axis: + SMM.EM.Axis = (GSD.Roads.Splination.AxisTypeEnum) EditorGUILayout.Popup("Extrusion axis: ", (int) SMM.Axis, TheAxisDescriptions_Spline, GUILayout.Width(250f)); + + //Start time: + if (SMM.StartTime < tNode.MinSplination) + { + SMM.StartTime = tNode.MinSplination; + } + if (SMM.EndTime > tNode.MaxSplination) + { + SMM.EndTime = tNode.MaxSplination; + } + EditorGUILayout.BeginHorizontal(); + + SMM.EM.StartTime = EditorGUILayout.Slider("Start param: ", SMM.StartTime, tNode.MinSplination, tNode.MaxSplination - 0.01f); + if (GUILayout.Button("match node", EditorStyles.miniButton, GUILayout.Width(80f))) + { + SMM.EM.StartTime = tNode.tTime; + } + if (SMM.EM.StartTime >= SMM.EM.EndTime) + { + SMM.EM.EndTime = (SMM.EM.StartTime + 0.01f); + } + EditorGUILayout.EndHorizontal(); + + + //End time: + EditorGUILayout.BeginHorizontal(); + SMM.EM.EndTime = EditorGUILayout.Slider("End param: ", SMM.EndTime, SMM.StartTime, tNode.MaxSplination); + if (GUILayout.Button("match next", EditorStyles.miniButton, GUILayout.Width(80f))) + { + SMM.EM.EndTime = tNode.NextTime; + } + if (SMM.EM.StartTime >= SMM.EM.EndTime) + { + SMM.EM.EndTime = (SMM.EM.StartTime + 0.01f); + } + EditorGUILayout.EndHorizontal(); + + + //Straight line options: + if (tNode.IsStraight()) + { + if (!SMM.bIsStretch) + { + SMM.EM.bIsStretch = EditorGUILayout.Toggle("Straight line stretch:", SMM.bIsStretch); + } + else + { + EditorGUILayout.BeginVertical("box"); + SMM.EM.bIsStretch = EditorGUILayout.Toggle("Straight line stretch:", SMM.bIsStretch); + + //Stretch_UVThreshold: + SMM.EM.Stretch_UVThreshold = EditorGUILayout.Slider("UV stretch threshold:", SMM.Stretch_UVThreshold, 0.01f, 0.5f); + + //UV repeats: + SMM.EM.RepeatUVType = (GSD.Roads.Splination.RepeatUVTypeEnum) EditorGUILayout.Popup("UV stretch axis: ", (int) SMM.RepeatUVType, RepeatUVTypeDescriptions_Spline, GUILayout.Width(250f)); + EditorGUILayout.EndVertical(); + } + } + else + { + SMM.EM.bIsStretch = false; + } + + + + SMM.EM.bTrimStart = EditorGUILayout.Toggle("Trim start:", SMM.bTrimStart); + SMM.EM.bTrimEnd = EditorGUILayout.Toggle("Trim end:", SMM.bTrimEnd); + + + + //Static option: + SMM.EM.bStatic = EditorGUILayout.Toggle("Static: ", SMM.bStatic); + + + //Splination method + // SMM.EM.bMatchRoadIncrements = EditorGUILayout.Toggle("Match road increments: ",SMM.bMatchRoadIncrements); + SMM.EM.bMatchTerrain = EditorGUILayout.Toggle("Match ground: ", SMM.bMatchTerrain); + + //Vector min/max threshold: + EditorGUILayout.BeginHorizontal(); + SMM.EM.MinMaxMod = EditorGUILayout.Slider("Vertex min/max threshold: ", SMM.MinMaxMod, 0.01f, 0.2f); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.MinMaxMod = 0.05f; + } + EditorGUILayout.EndHorizontal(); + + //Vertex matching precision: + EditorGUILayout.BeginHorizontal(); + SMM.EM.VertexMatchingPrecision = EditorGUILayout.Slider("Vertex matching precision: ", SMM.VertexMatchingPrecision, 0f, 0.01f); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.VertexMatchingPrecision = 0.005f; + } + EditorGUILayout.EndHorizontal(); + + //UV repeats: + if (!SMM.bIsStretch) + { + SMM.EM.RepeatUVType = (GSD.Roads.Splination.RepeatUVTypeEnum) EditorGUILayout.Popup("UV repeat axis: ", (int) SMM.RepeatUVType, RepeatUVTypeDescriptions_Spline, GUILayout.Width(250f)); + } + + if (SMM.bMatchRoadDefinition) + { + EditorGUILayout.BeginVertical("TextArea"); + EditorGUILayout.BeginHorizontal(); + SMM.EM.bMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", SMM.bMatchRoadDefinition); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.bMatchRoadDefinition = false; + } + EditorGUILayout.EndHorizontal(); + if (SMM.bMatchRoadDefinition) + { + EditorGUILayout.LabelField(" Only use this option if object length doesn't match the road definition.", EditorStyles.miniLabel); + EditorGUILayout.LabelField(" Matching road definition requires a UV repeat type.", EditorStyles.miniLabel); + EditorGUILayout.LabelField(" If the material fails to scale properly, try flipping the Y rotation.", EditorStyles.miniLabel); + } + //Flip rotation option: + SMM.EM.bFlipRotation = EditorGUILayout.Toggle(" Flip Y rotation: ", SMM.bFlipRotation); + EditorGUILayout.EndVertical(); + } + else + { + EditorGUILayout.BeginHorizontal(); + SMM.EM.bMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", SMM.bMatchRoadDefinition); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.bMatchRoadDefinition = false; + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + + + #region Vertical offset: + EditorGUILayout.LabelField("Vertical options:"); + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + SMM.EM.VerticalRaise = EditorGUILayout.Slider("Vertical raise magnitude:", SMM.VerticalRaise, -512f, 512f); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.VerticalRaise = 0f; + } + EditorGUILayout.EndHorizontal(); + #endregion + + + #region Vertical curve: + if (SMM.VerticalCurve == null || SMM.VerticalCurve.keys.Length < 2) + { EnforceCurve(ref SMM.VerticalCurve); } + EditorGUILayout.BeginHorizontal(); + SMM.EM.VerticalCurve = EditorGUILayout.CurveField("Curve: ", SMM.VerticalCurve); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + ResetCurve(ref SMM.EM.VerticalCurve); + } + EditorGUILayout.EndHorizontal(); + #endregion + EditorGUILayout.EndVertical(); + + + #region Horizontal offsets: + SMM.EM.HorizontalSep = SMM.HorizontalSep; + EditorGUILayout.LabelField("Horizontal offset options:"); + EditorGUILayout.BeginVertical("box"); + tHorizMatching = HorizMatchingDefaultsEnum.None; + tHorizMatching = (HorizMatchingDefaultsEnum) EditorGUILayout.Popup((int) tHorizMatching, HorizMatchSubTypeDescriptions, GUILayout.Width(100f)); + if (tHorizMatching != HorizMatchingDefaultsEnum.None) + { + if (tHorizMatching == HorizMatchingDefaultsEnum.MatchCenter) + { + SMM.EM.HorizontalSep = 0f; + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadLeft) + { + SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2) * -1; + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderLeft) + { + SMM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1; + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadRight) + { + SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2); + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderRight) + { + SMM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth; + } + tHorizMatching = HorizMatchingDefaultsEnum.None; + } + EditorGUILayout.BeginHorizontal(); + SMM.EM.HorizontalSep = EditorGUILayout.Slider("Horiz offset magnitude:", SMM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.HorizontalSep = 0f; + } + EditorGUILayout.EndHorizontal(); + #endregion + + + //Horizontal curve: + if (SMM.HorizontalCurve == null || SMM.HorizontalCurve.keys.Length < 2) + { + EnforceCurve(ref SMM.HorizontalCurve); + } + + EditorGUILayout.BeginHorizontal(); + SMM.EM.HorizontalCurve = EditorGUILayout.CurveField("Curve: ", SMM.HorizontalCurve); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + ResetCurve(ref SMM.EM.HorizontalCurve); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + //Vertical cutoff: + EditorGUILayout.LabelField("Vertical cutoff:"); + EditorGUILayout.BeginVertical("box"); + SMM.EM.bVerticalCutoff = EditorGUILayout.Toggle("Height cutoff enabled:", SMM.bVerticalCutoff); + if (SMM.bVerticalCutoff) + { + SMM.EM.bVerticalCutoff_MatchZero = EditorGUILayout.Toggle("Match spline height:", SMM.bVerticalCutoff_MatchZero); + SMM.EM.bVerticalCutoffDownwards = EditorGUILayout.Toggle("Cut direction toggle:", SMM.bVerticalCutoffDownwards); + SMM.EM.VerticalCutoff = EditorGUILayout.Slider("Height cut offset: ", SMM.VerticalCutoff, -50f, 50f); + SMM.EM.bVerticalMeshCutoff_OppositeDir = EditorGUILayout.Toggle("Opposite dir mesh cut:", SMM.bVerticalMeshCutoff_OppositeDir); + SMM.EM.VerticalMeshCutoffOffset = EditorGUILayout.Slider("Mesh cut offset: ", SMM.VerticalMeshCutoffOffset, -5f, 5f); + } + EditorGUILayout.EndVertical(); + + //End type: + EditorGUILayout.LabelField("Extrusion ending options:"); + EditorGUILayout.BeginVertical("box"); + SMM.EM.bStartDown = EditorGUILayout.Toggle("Push start down:", SMM.bStartDown); + SMM.EM.bEndDown = EditorGUILayout.Toggle("Push end down:", SMM.bEndDown); + if (SMM.bStartDown) + { + SMM.EM.bStartTypeDownOverride = EditorGUILayout.Toggle("Override start down value: ", SMM.bStartTypeDownOverride); + if (SMM.bStartTypeDownOverride) + { + SMM.EM.StartTypeDownOverride = EditorGUILayout.Slider("Downward movement: ", SMM.StartTypeDownOverride, -10f, 10f); + } + } + if (SMM.bEndDown) + { + SMM.EM.bEndTypeDownOverride = EditorGUILayout.Toggle("Override end down value: ", SMM.bEndTypeDownOverride); + if (SMM.bEndTypeDownOverride) + { + SMM.EM.EndTypeDownOverride = EditorGUILayout.Slider("Downward movement: ", SMM.EndTypeDownOverride, -10f, 10f); + } + } + EditorGUILayout.EndVertical(); + + //Start and end objects: + EditorGUILayout.LabelField("Start & end objects:"); + EditorGUILayout.BeginVertical("box"); + //End cap custom match start: + SMM.EM.bEndCapCustomMatchStart = EditorGUILayout.Toggle("Match objects to ends:", SMM.bEndCapCustomMatchStart); + + //End objects match ground: + SMM.EM.bEndObjectsMatchGround = EditorGUILayout.Toggle("Force origins to ground:", SMM.bEndObjectsMatchGround); + + //Start cap: + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Start object:"); + tEndObjectAdd = (EndObjectsDefaultsEnum) EditorGUILayout.Popup((int) tEndObjectAdd, EndObjectsDefaultsEnumDesc); + if (tEndObjectAdd != EndObjectsDefaultsEnum.None) + { + SMM.EM.EndCapStart = GetEndObjectQuickAdd(); + tEndObjectAdd = EndObjectsDefaultsEnum.None; + } + EditorGUILayout.EndHorizontal(); + + + SMM.EM.EndCapStart = (GameObject) EditorGUILayout.ObjectField("Prefab:", SMM.EndCapStart, typeof(GameObject), false); + if (SMM.EndCapStart != null) + { + SMM.EM.EndCapCustomOffsetStart = EditorGUILayout.Vector3Field("Position offset:", SMM.EndCapCustomOffsetStart); + SMM.EM.EndCapCustomRotOffsetStart = EditorGUILayout.Vector3Field("Rotation offset:", SMM.EndCapCustomRotOffsetStart); + } + EditorGUILayout.EndVertical(); + + //End cap: + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("End object:"); + tEndObjectAdd = (EndObjectsDefaultsEnum) EditorGUILayout.Popup((int) tEndObjectAdd, EndObjectsDefaultsEnumDesc); + if (tEndObjectAdd != EndObjectsDefaultsEnum.None) + { + SMM.EM.EndCapEnd = GetEndObjectQuickAdd(); + SMM.EM.EndCapCustomRotOffsetEnd = new Vector3(0f, 180f, 0f); + tEndObjectAdd = EndObjectsDefaultsEnum.None; + } + EditorGUILayout.EndHorizontal(); + + + SMM.EM.EndCapEnd = (GameObject) EditorGUILayout.ObjectField("Prefab:", SMM.EndCapEnd, typeof(GameObject), false); + if (SMM.EndCapEnd != null) + { + SMM.EM.EndCapCustomOffsetEnd = EditorGUILayout.Vector3Field("Position offset:", SMM.EndCapCustomOffsetEnd); + SMM.EM.EndCapCustomRotOffsetEnd = EditorGUILayout.Vector3Field("Rotation offset:", SMM.EndCapCustomRotOffsetEnd); + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.EndVertical(); + + //Collision: + EditorGUILayout.LabelField("Collision options:"); + EditorGUILayout.BeginVertical("box"); + SMM.EM.CollisionType = (GSD.Roads.Splination.CollisionTypeEnum) EditorGUILayout.Popup("Collision type: ", (int) SMM.CollisionType, TheCollisionTypeEnumDescSpline, GUILayout.Width(320f)); + //Mesh collison convex option + if (SMM.CollisionType != GSD.Roads.Splination.CollisionTypeEnum.None && SMM.CollisionType != GSD.Roads.Splination.CollisionTypeEnum.BoxCollision) + { + SMM.EM.bCollisionConvex = EditorGUILayout.Toggle(" Convex: ", SMM.bCollisionConvex); + SMM.EM.bCollisionTrigger = EditorGUILayout.Toggle(" Trigger: ", SMM.bCollisionTrigger); + } + + if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle || SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTrapezoid) + { + SMM.EM.bSimpleCollisionAutomatic = EditorGUILayout.Toggle(" Automatic simple collision: ", SMM.bSimpleCollisionAutomatic); + } + //If not automatic simple collisions: + if (!SMM.bSimpleCollisionAutomatic) + { + if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTriangle) + { + SMM.EM.CollisionTriBL = SMM.CollisionTriBL; + SMM.EM.CollisionTriBR = SMM.CollisionTriBR; + SMM.EM.CollisionTriT = SMM.CollisionTriT; + + EditorGUILayout.LabelField("Bottom left:"); + SMM.EM.CollisionTriBL.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriBL.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); + SMM.EM.CollisionTriBL.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriBL.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); + SMM.EM.CollisionTriBL.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriBL.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); + + EditorGUILayout.LabelField("Bottom right:"); + SMM.EM.CollisionTriBR.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriBR.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); + SMM.EM.CollisionTriBR.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriBR.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); + SMM.EM.CollisionTriBR.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriBR.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); + + EditorGUILayout.LabelField("Top:"); + SMM.EM.CollisionTriT.x = EditorGUILayout.Slider(" x-axis: ", SMM.CollisionTriT.x, SMM.mMinX - 5f, SMM.mMaxX + 5f); + SMM.EM.CollisionTriT.y = EditorGUILayout.Slider(" y-axis: ", SMM.CollisionTriT.y, SMM.mMinY - 5f, SMM.mMaxY + 5f); + SMM.EM.CollisionTriT.z = EditorGUILayout.Slider(" z-axis: ", SMM.CollisionTriT.z, SMM.mMinZ - 5f, SMM.mMaxZ + 5f); + + } + else if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.SimpleMeshTrapezoid) + { + SMM.EM.CollisionBoxBL = EditorGUILayout.Vector3Field(" Bottom left:", SMM.CollisionBoxBL); + SMM.EM.CollisionBoxBR = EditorGUILayout.Vector3Field(" Bottom right:", SMM.CollisionBoxBR); + SMM.EM.CollisionBoxTL = EditorGUILayout.Vector3Field(" Top left:", SMM.CollisionBoxTL); + SMM.EM.CollisionBoxTR = EditorGUILayout.Vector3Field(" Top right:", SMM.CollisionBoxTR); + } + } + + if (SMM.CollisionType == GSD.Roads.Splination.CollisionTypeEnum.BoxCollision) + { + SMM.EM.StretchBC_LocOffset = EditorGUILayout.Vector3Field("Box collider center offset:", SMM.StretchBC_LocOffset); + SMM.EM.bBCFlipX = EditorGUILayout.Toggle("Flip center X:", SMM.bBCFlipX); + SMM.EM.bBCFlipZ = EditorGUILayout.Toggle("Flip center Z:", SMM.bBCFlipZ); + + + SMM.EM.bStretchSize = EditorGUILayout.Toggle("Box collider size edit:", SMM.bStretchSize); + if (SMM.bStretchSize) + { + SMM.EM.StretchBC_Size = EditorGUILayout.Vector3Field("Size:", SMM.StretchBC_Size); + } + else + { + EditorGUILayout.LabelField("Size:", SMM.StretchBC_Size.ToString()); + } + } + EditorGUILayout.EndVertical(); + + + EditorGUILayout.LabelField("Rotation options:"); + EditorGUILayout.BeginVertical("box"); + + //Custom rotation: + SMM.EM.CustomRotation = SMM.CustomRotation; + //EOM.CustomRotation = EditorGUILayout.Vector3Field("Custom rotation: ",EOM.CustomRotation); + EditorGUILayout.BeginHorizontal(); + //Flip rotation option: + if (SMM.EM.bFlipRotation != SMM.bFlipRotation) + { + SMM.EM.bFlipRotation = EditorGUILayout.Toggle("Flip Y rotation: ", SMM.EM.bFlipRotation); + } + else + { + SMM.EM.bFlipRotation = EditorGUILayout.Toggle("Flip Y rotation: ", SMM.bFlipRotation); + } + + + // if(GUILayout.Button("Reset custom rotation",EditorStyles.miniButton,GUILayout.Width(160f))){ + // SMM.CustomRotation = new Vector3(0f,0f,0f); + // } + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + SMM.EM.CustomRotation = new Vector3(0f, 0f, 0f); + } + EditorGUILayout.EndHorizontal(); + // SMM.EM.CustomRotation = EditorGUILayout.Vector3Field("",SMM.CustomRotation); + // SMM.EM.CustomRotation.x = EditorGUILayout.Slider("x-axis: ",SMM.CustomRotation.x,-360f,360f); + // SMM.EM.CustomRotation.y = EditorGUILayout.Slider("y-axis: ",SMM.CustomRotation.y,-360f,360f); + // SMM.EM.CustomRotation.z = EditorGUILayout.Slider("z-axis: ",SMM.CustomRotation.z,-360f,360f); + EditorGUILayout.EndVertical(); + EditorGUILayout.EndVertical(); + + + EditorGUILayout.LabelField("Deprecated options:"); + EditorGUILayout.BeginVertical("box"); + SMM.EM.bExactSplination = EditorGUILayout.Toggle("Directional extrusion: ", SMM.bExactSplination); + + EditorGUILayout.EndVertical(); + BigLine(); + BigLine(); + } + } + + + public void UpdateSplineObjects() + { + if (!tNode.CanSplinate()) + { + return; + } + if (tNode.SplinatedObjects == null) + { + tNode.SplinatedObjects = new List(); + } + eCount = tNode.SplinatedObjects.Count; + for (int index = 0; index < eCount; index++) + { + SMM = tNode.SplinatedObjects[index]; + if (SMM.EM != null) + { + if (!SMM.EM.IsEqualToSMM(SMM)) + { + SMM.EM.LoadToSMM(SMM); + + SMM.UpdatePositions(); + if (SMM.EM.bIsStretch != SMM.bIsStretch) + { + if (SMM.bIsStretch) + { + SMM.CollisionType = GSD.Roads.Splination.CollisionTypeEnum.BoxCollision; + SMM.bMatchRoadDefinition = false; + SMM.bMatchTerrain = false; + SMM.bCollisionConvex = false; + SMM.bStartDown = false; + SMM.bEndDown = false; + SMM.bVerticalCutoff = false; + SMM.bExactSplination = false; + SMM.bEndTypeDownOverride = false; + } + } + + SMM.Setup(true); + // Debug.Log ("Setup SMM"); + } + } + } + } + + + public void UpdateSplineObjects_OnUndo() + { + if (!tNode.CanSplinate()) + { + return; + } + if (tNode.SplinatedObjects == null) + { + tNode.SplinatedObjects = new List(); + } + + //Destroy all children: + for (int index = tNode.transform.childCount - 1; index >= 0; index--) + { + Object.DestroyImmediate(tNode.transform.GetChild(index).gameObject); + } + + //Re-setup the SMM: + eCount = tNode.SplinatedObjects.Count; + for (int index = 0; index < eCount; index++) + { + SMM = tNode.SplinatedObjects[index]; + SMM.UpdatePositions(); + //if(SMM.bIsStretch != SMM.bIsStretch){ + if (SMM.bIsStretch) + { + SMM.CollisionType = GSD.Roads.Splination.CollisionTypeEnum.BoxCollision; + SMM.bMatchRoadDefinition = false; + SMM.bMatchTerrain = false; + SMM.bCollisionConvex = false; + SMM.bStartDown = false; + SMM.bEndDown = false; + SMM.bVerticalCutoff = false; + SMM.bExactSplination = false; + SMM.bEndTypeDownOverride = false; + } + //} + SMM.Setup(true); + } + + UpdateEdgeObjects_OnUndo(); + } + + + public void DoEdgeObjects() + { + if (!tNode.CanSplinate()) + { + return; + } + + if (tNode.EdgeObjects == null) + { + tNode.EdgeObjects = new List(); + } + eCount = tNode.EdgeObjects.Count; + + EOM = null; + + for (int index = 0; index < tNode.EdgeObjects.Count; index++) + { + EOM = tNode.EdgeObjects[index]; + if (EOM.EM == null) + { + EOM.EM = new GSD.Roads.EdgeObjects.EdgeObjectMaker.EdgeObjectEditorMaker(); + } + EOM.EM.Setup(EOM); + + currentCount += 1; + EditorGUILayout.BeginVertical("TextArea"); + + + if (EOM.bNeedsUpdate) + { + EOM.Setup(); + } + EOM.bNeedsUpdate = false; + + EditorGUILayout.BeginHorizontal(); + + EOM.bToggle = EditorGUILayout.Foldout(EOM.bToggle, "#" + currentCount.ToString() + ": " + EOM.tName); + + if (GUILayout.Button(btnEdgeText, GSDImageButton, GUILayout.Width(32f))) + { + + } + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + EOM.Setup(); + } + if (GUILayout.Button(btnSaveText, GSDImageButton, GUILayout.Width(16f))) + { + GSDSaveWindow tSave = EditorWindow.GetWindow(); + tSave.Initialize(ref tSceneRect, GSDSaveWindow.WindowTypeEnum.Edge, tNode, null, EOM); + } + + if (GUILayout.Button(btnCopyText, GSDImageButton, GUILayout.Width(16f))) + { + Undo.RecordObject(tNode, "Copy"); + tNode.CopyEdgeObject(index); + EditorUtility.SetDirty(tNode); + } + if (GUILayout.Button(btnDeleteText, GSDImageButton, GUILayout.Width(16f))) + { + Undo.RecordObject(tNode, "Delete"); + tNode.RemoveEdgeObject(index); + EditorUtility.SetDirty(tNode); + } + EditorGUILayout.EndHorizontal(); + + if (!EOM.bToggle) + { + EditorGUILayout.EndVertical(); + continue; + } + + GUILayout.Space(8f); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("General options:"); + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginVertical("box"); + //Name: + EOM.EM.tName = EditorGUILayout.TextField("Name: ", EOM.tName); + + //Edge object: + EOM.EM.EdgeObject = (GameObject) EditorGUILayout.ObjectField("Edge object: ", EOM.EdgeObject, typeof(GameObject), false); + if (EOM.EM.EdgeObject != EOM.EdgeObject) + { + EOM.bEdgeSignLabelInit = false; + EOM.bEdgeSignLabel = false; + } + + + #region Material override: + EOM.EM.bMaterialOverride = EditorGUILayout.Toggle("Material override: ", EOM.bMaterialOverride); + if (!EOM.bMaterialOverride) + { + EOM.EM.EdgeMaterial1 = null; + EOM.EM.EdgeMaterial2 = null; + } + + if (!EOM.bEdgeSignLabelInit && EOM.EM.EdgeObject != null) + { + EOM.bEdgeSignLabel = false; + if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignDiamond") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-diamond"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignSquare-Small") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-Square"; + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSignSquare") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-Square"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign988-Small") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-988"; + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign988") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-988"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign861-Small") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-861"; + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign861") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-861"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign617-Small") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-617"; + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign617") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-617"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign396") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-396"; + + } + else if (string.CompareOrdinal(EOM.EM.EdgeObject.name, "GSDSign330") == 0) + { + EOM.bEdgeSignLabel = true; + EOM.EdgeSignLabel = "GSDFedSign-330"; + } + } + + if (EOM.bMaterialOverride) + { + if (EOM.bEdgeSignLabel) + { + EditorGUILayout.TextField("Material search term: ", EOM.EdgeSignLabel); + } + + EOM.EM.EdgeMaterial1 = (Material) EditorGUILayout.ObjectField("Override mat #1: ", EOM.EdgeMaterial1, typeof(Material), false); + EOM.EM.EdgeMaterial2 = (Material) EditorGUILayout.ObjectField("Override mat #2: ", EOM.EdgeMaterial2, typeof(Material), false); + } + #endregion + + + #region Combine Mesh / MeshCollider + if (EOM.bSingle) + { + EOM.EM.bCombineMesh = false; + } + else + { + EOM.EM.bCombineMesh = EditorGUILayout.Toggle("Combine meshes: ", EOM.bCombineMesh); + + if (EOM.bCombineMesh) + { + EOM.EM.bCombineMeshCollider = EditorGUILayout.Toggle("Combined mesh collider: ", EOM.bCombineMeshCollider); + } + } + #endregion + + + #region SingleObject + EOM.EM.bSingle = EditorGUILayout.Toggle("Single object only: ", EOM.bSingle); + if (EOM.EM.bSingle != EOM.bSingle) + { + EOM.EM.EndTime = tNode.NextTime; + // EOM.EM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.EM.EndTime,false); + EOM.EM.SinglePosition = tNode.tTime + 0.025f; + if (EOM.EM.bSingle) + { + EOM.EM.bCombineMesh = false; + } + } + + if (EOM.bSingle) + { + EOM.EM.SinglePosition = EditorGUILayout.Slider("Single location: ", EOM.SinglePosition, tNode.tTime, 1f); + + if (tNode.bIsBridgeStart && tNode.bIsBridgeMatched) + { + EOM.EM.SingleOnlyBridgePercent = EditorGUILayout.Slider("Bridge %: ", EOM.SingleOnlyBridgePercent, 0f, 1f); + if (!GSDRootUtil.IsApproximately(EOM.SingleOnlyBridgePercent, EOM.EM.SingleOnlyBridgePercent, 0.001f)) + { + EOM.EM.SingleOnlyBridgePercent = Mathf.Clamp(EOM.EM.SingleOnlyBridgePercent, 0f, 1f); + float tDist = (EOM.EM.SingleOnlyBridgePercent * (tNode.BridgeCounterpartNode.tDist - tNode.tDist) + tNode.tDist); + EOM.EM.SinglePosition = tNode.GSDSpline.TranslateDistBasedToParam(tDist); + } + } + } + #endregion + + + EOM.EM.bStatic = EditorGUILayout.Toggle("Static: ", EOM.bStatic); + + + EOM.EM.bMatchTerrain = EditorGUILayout.Toggle("Match ground height: ", EOM.bMatchTerrain); + + if (!EOM.bSingle) + { + EOM.EM.MeterSep = EditorGUILayout.Slider("Dist between objects: ", EOM.MeterSep, 1f, 256f); + } + + + #region Match Road + EOM.EM.bStartMatchRoadDefinition = EditorGUILayout.Toggle("Match road definition: ", EOM.bStartMatchRoadDefinition); + if (EOM.bStartMatchRoadDefinition) + { + EOM.EM.StartMatchRoadDef = EditorGUILayout.Slider("Position fine tuning: ", EOM.StartMatchRoadDef, 0f, 1f); + if (!GSDRootUtil.IsApproximately(EOM.EM.StartMatchRoadDef, EOM.StartMatchRoadDef, 0.001f)) + { + EOM.EM.StartMatchRoadDef = Mathf.Clamp(EOM.EM.StartMatchRoadDef, 0f, 1f); + } + } + #endregion + + + if (!EOM.bSingle) + { + if (EOM.EM.StartTime < tNode.MinSplination) + { + EOM.EM.StartTime = tNode.MinSplination; + } + if (EOM.EM.EndTime > tNode.MaxSplination) + { + EOM.EM.EndTime = tNode.MaxSplination; + } + + + #region Start param + EditorGUILayout.BeginHorizontal(); + EOM.EM.StartTime = EditorGUILayout.Slider("Start param: ", EOM.StartTime, tNode.MinSplination, EOM.EndTime); // EndTime = 1f?? + + if (EOM.EM.EndTime < EOM.EM.StartTime) + { + EOM.EM.EndTime = Mathf.Clamp(EOM.StartTime + 0.01f, 0f, 1f); + } + + + if (GUILayout.Button("match node", EditorStyles.miniButton, GUILayout.Width(80f))) + { + EOM.EM.StartTime = tNode.tTime; + } + EditorGUILayout.EndHorizontal(); + #endregion + + + #region End param + EditorGUILayout.BeginHorizontal(); + EOM.EM.EndTime = EditorGUILayout.Slider("End param: ", EOM.EndTime, EOM.StartTime, tNode.MaxSplination); + //Mathf.Clamp(EditorGUILayout.Slider( "End param: ", EOM.EndTime, 0f/*EOM.StartTime*/, 1f/*tNode.MaxSplination*/ ), 0f, 1f); + // FH EXPERIMENTAL fix for EdgeObjects??? + + /* + if(EOM.EndTime != 1f) // Does not fix the problem, anyway a really dirty and shitty bugfix... + { + EOM.EndTime = 1f; + } + */ + + if (EOM.EM.StartTime > EOM.EM.EndTime) + { + EOM.EM.StartTime = Mathf.Clamp(EOM.EndTime - 0.01f, 0f, 1f); + } + + + + + if (GUILayout.Button("match next", EditorStyles.miniButton, GUILayout.Width(80f))) + { + EOM.EM.EndTime = tNode.NextTime; + } + EditorGUILayout.EndHorizontal(); + #endregion + } + + + EditorGUILayout.EndVertical(); + + + #region Vertical offset: + EditorGUILayout.LabelField("Vertical options:"); + EditorGUILayout.BeginVertical("box"); + + EditorGUILayout.BeginHorizontal(); + EOM.EM.VerticalRaise = EditorGUILayout.Slider("Vertical raise magnitude:", EOM.VerticalRaise, -512f, 512f); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + EOM.EM.VerticalRaise = 0f; + } + EditorGUILayout.EndHorizontal(); + + if (EOM.VerticalCurve == null || EOM.VerticalCurve.keys.Length < 2) + { + EnforceCurve(ref EOM.VerticalCurve); + } + EditorGUILayout.BeginHorizontal(); + EOM.EM.VerticalCurve = EditorGUILayout.CurveField("Curve: ", EOM.VerticalCurve); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + ResetCurve(ref EOM.EM.VerticalCurve); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + #endregion + + + #region Horizontal offsets: + EditorGUILayout.LabelField("Horizontal offset options:"); + EditorGUILayout.BeginVertical("box"); + tHorizMatching = HorizMatchingDefaultsEnum.None; + tHorizMatching = (HorizMatchingDefaultsEnum) EditorGUILayout.Popup((int) tHorizMatching, HorizMatchSubTypeDescriptions, GUILayout.Width(100f)); + if (tHorizMatching != HorizMatchingDefaultsEnum.None) + { + if (tHorizMatching == HorizMatchingDefaultsEnum.MatchCenter) + { + EOM.EM.HorizontalSep = 0f; + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadLeft) + { + EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) * -1; + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderLeft) + { + if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) + { + EOM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1; + } + else + { + EOM.EM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() * 0.5f)) * -1; + } + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchRoadRight) + { + EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f); + } + else if (tHorizMatching == HorizMatchingDefaultsEnum.MatchShoulderRight) + { + if (tNode.GSDSpline.tRoad.opt_bShouldersEnabled) + { + EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f) + tNode.GSDSpline.tRoad.opt_ShoulderWidth; + } + else + { + EOM.EM.HorizontalSep = (tNode.GSDSpline.tRoad.RoadWidth() * 0.5f); + } + } + tHorizMatching = HorizMatchingDefaultsEnum.None; + } + if (!GSDRootUtil.IsApproximately(EOM.EM.HorizontalSep, EOM.HorizontalSep)) + { + EOM.EM.HorizontalSep = Mathf.Clamp(EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); + } + + + EditorGUILayout.BeginHorizontal(); + EOM.EM.HorizontalSep = EditorGUILayout.Slider("Horiz offset magnitude:", EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + EOM.EM.HorizontalSep = 0f; + } + if (!GSDRootUtil.IsApproximately(EOM.EM.HorizontalSep, EOM.HorizontalSep)) + { + EOM.EM.HorizontalSep = Mathf.Clamp(EOM.EM.HorizontalSep, (-1f * HorizRoadMax), HorizRoadMax); + } + EditorGUILayout.EndHorizontal(); + if (EOM.HorizontalCurve == null || EOM.HorizontalCurve.keys.Length < 2) + { EnforceCurve(ref EOM.HorizontalCurve); } + EditorGUILayout.BeginHorizontal(); + EOM.EM.HorizontalCurve = EditorGUILayout.CurveField("Curve: ", EOM.HorizontalCurve); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + ResetCurve(ref EOM.EM.HorizontalCurve); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + #endregion + + + #region Rotation/scale options + EditorGUILayout.LabelField("Rotation/scale options:"); + EditorGUILayout.BeginVertical("box"); + if (EOM.HorizontalSep < 0f) + { + EOM.EM.bOncomingRotation = EditorGUILayout.Toggle("Auto rotate oncoming objects: ", EOM.bOncomingRotation); + } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Custom rotation: "); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + EOM.EM.CustomRotation = new Vector3(0f, 0f, 0f); + } + EditorGUILayout.EndHorizontal(); + + EOM.EM.CustomRotation.x = EditorGUILayout.Slider("x-axis: ", EOM.CustomRotation.x, -360f, 360f); + EOM.EM.CustomRotation.y = EditorGUILayout.Slider("y-axis: ", EOM.CustomRotation.y, -360f, 360f); + EOM.EM.CustomRotation.z = EditorGUILayout.Slider("z-axis: ", EOM.CustomRotation.z, -360f, 360f); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical("box"); /* scale */ + EditorGUILayout.BeginHorizontal(); + float scale = EditorGUILayout.Slider("Custom scale: ", EOM.CustomScale.x, 1f, 10f); + EOM.EM.CustomScale = new Vector3(scale, scale, scale); + if (GUILayout.Button(btnDefaultText, GSDImageButton, GUILayout.Width(16f))) + { + EOM.EM.CustomScale = new Vector3(1f, 1f, 1f); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); /* scale */ + EditorGUILayout.EndVertical(); + #endregion + } + } + + + public void UpdateEdgeObjects() + { + if (!tNode.CanSplinate()) + { + return; + } + eCount = tNode.EdgeObjects.Count; + for (int index = 0; index < tNode.EdgeObjects.Count; index++) + { + EOM = tNode.EdgeObjects[index]; + if (EOM.EM != null) + { + if (!EOM.EM.IsEqual(EOM)) + { + EOM.EM.LoadTo(EOM); + EOM.UpdatePositions(); + EOM.Setup(); + // Debug.Log ("Setup EOM"); + } + } + } + } + + + public void UpdateEdgeObjects_OnUndo() + { + if (!tNode.CanSplinate()) + { + return; + } + eCount = tNode.EdgeObjects.Count; + for (int index = 0; index < tNode.EdgeObjects.Count; index++) + { + EOM = tNode.EdgeObjects[index]; + EOM.Setup(); + } + } + + + #region "Quick adds" + private void BridgeAdd_TopBase(float tHorizSep = 0f, float tVertRaise = -0.01f, string tMat = "", bool bOverridePrefab = false, string OverridePrefab = "") + { + if (tMat == "") + { + tMat = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDConcrete2.mat"; + } + SMM = tNode.AddSplinatedObject(); + string tBridgeTopBaseToAdd = ""; + string tName = ""; + if (tNode.GSDSpline.tRoad.opt_Lanes == 2) + { + if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-19w-5l-1d.fbx"; + tName = "BridgeTop1M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-20w-5l-1d.fbx"; + tName = "BridgeTop2M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-18w-5l-3d.fbx"; + tName = "BridgeTop0M-3M"; + } + else + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-18w-5l-1d.fbx"; + tName = "BridgeTop0M-1M"; + } + } + else if (tNode.GSDSpline.tRoad.opt_Lanes == 4) + { + if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-29w-5l-1d.fbx"; + tName = "BridgeTop1M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-30w-5l-1d.fbx"; + tName = "BridgeTop2M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-28w-5l-3d.fbx"; + tName = "BridgeTop0M-3M"; + } + else + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-28w-5l-1d.fbx"; + tName = "BridgeTop0M-1M"; + } + } + else + { + if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base1MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-39w-5l-1d.fbx"; + tName = "BridgeTop1M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base2MOver) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-40w-5l-1d.fbx"; + tName = "BridgeTop2M-1M"; + } + else if (tBridgeTopBaseQuickAdd == BridgeTopBaseDefaultsEnum.Base3MDeep) + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-38w-5l-3d.fbx"; + tName = "BridgeTop0M-3M"; + } + else + { + tBridgeTopBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase-38w-5l-1d.fbx"; + tName = "BridgeTop0M-1M"; + } + } + + if (bOverridePrefab) + { + tBridgeTopBaseToAdd = OverridePrefab; + } + + SMM.tName = tName; + SMM.CurrentSplination = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(tBridgeTopBaseToAdd, typeof(GameObject)); + SMM.HorizontalSep = tHorizSep; + SMM.VerticalRaise = tVertRaise; + SMM.bMaterialOverride = true; + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + SMM.Axis = GSD.Roads.Splination.AxisTypeEnum.Z; + + tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; + if (SMM.StartTime < tNode.MinSplination) + { + SMM.StartTime = tNode.MinSplination; + } + if (SMM.EndTime > tNode.MaxSplination) + { + SMM.EndTime = tNode.MaxSplination; + } + } + + + private void BridgeAdd_BottomBase(float tHorizSep = 0f, float tVertRaise = -1.01f, string tMat = "", bool bOverridePrefab = false, string OverridePrefab = "") + { + if (tMat == "") + { + tMat = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDConcrete2.mat"; + } + SMM = tNode.AddSplinatedObject(); + string tBridgeBottomBaseToAdd = ""; + string tName = ""; + if (tNode.GSDSpline.tRoad.opt_Lanes == 2) + { + if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-18w-5l-3d.fbx"; + tName = "BridgeBase2"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-18w-5l-5d.fbx"; + tName = "BridgeBase3"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-18w-5l-5d.fbx"; + tName = "BridgeBase4"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-18w-5l-5d.fbx"; + tName = "BridgeBase5"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-2L.fbx"; + tName = "BridgeArchBeam80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-2L.fbx"; + tName = "BridgeArchSolid80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-2L.fbx"; + tName = "BridgeArchSolid180"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-18w-5l-5d.fbx"; + tName = "BridgeGrid"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-18w-20l-3d.fbx"; + tName = "BridgeSteelBeams"; + } + } + else if (tNode.GSDSpline.tRoad.opt_Lanes == 4) + { + if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-28w-5l-3d.fbx"; + tName = "BridgeBase2"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-28w-5l-5d.fbx"; + tName = "BridgeBase3"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-28w-5l-5d.fbx"; + tName = "BridgeBase4"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-28w-5l-5d.fbx"; + tName = "BridgeBase5"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-4L.fbx"; + tName = "BridgeArchBeam80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-4L.fbx"; + tName = "BridgeArchSolid80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-4L.fbx"; + tName = "BridgeArchSolid180"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-28w-5l-5d.fbx"; + tName = "BridgeGrid"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-28w-20l-3d.fbx"; + tName = "BridgeSteelBeams"; + } + } + else + { + if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase2-38w-5l-3d.fbx"; + tName = "BridgeBase2"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase3-38w-5l-5d.fbx"; + tName = "BridgeBase3"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase4-38w-5l-5d.fbx"; + tName = "BridgeBase4"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase5-38w-5l-5d.fbx"; + tName = "BridgeBase5"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase6-6L.fbx"; + tName = "BridgeArchBeam80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase7-6L.fbx"; + tName = "BridgeArchSolid80"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBase8-6L.fbx"; + tName = "BridgeArchSolid180"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseGrid-38w-5l-5d.fbx"; + tName = "BridgeGrid"; + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) + { + tBridgeBottomBaseToAdd = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Bridges/BridgeBaseSteelBeam-38w-20l-3d.fbx"; + tName = "BridgeBeams"; + } + } + + if (bOverridePrefab) + { + tBridgeBottomBaseToAdd = OverridePrefab; + } + + SMM.CurrentSplination = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(tBridgeBottomBaseToAdd, typeof(GameObject)); + SMM.HorizontalSep = tHorizSep; + SMM.VerticalRaise = tVertRaise; + SMM.bMaterialOverride = true; + SMM.tName = tName; + + if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase2) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase3) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase4) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase5) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase6) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase7) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBase8) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(tMat); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeBaseGrid) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDSteel7.mat"); + } + else if (tBridgeBottomBaseQuickAdd == BridgeBottomBaseDefaultsEnum.BridgeSteel) + { + SMM.SplinatedMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDSteel7.mat"); + } + + SMM.Axis = GSD.Roads.Splination.AxisTypeEnum.Z; + + tBridgeTopBaseQuickAdd = BridgeTopBaseDefaultsEnum.None; + if (SMM.StartTime < tNode.MinSplination) + { + SMM.StartTime = tNode.MinSplination; + } + if (SMM.EndTime > tNode.MaxSplination) + { + SMM.EndTime = tNode.MaxSplination; + } + } + + + private void ExtrusionQuickAdd(bool bHorizOverride = false, float tHorizSep = 0f, bool bVertOverride = false, float tVertRaise = 0f) + { + try + { + ExtrusionQuickAdd_Do(); + } + catch (System.Exception exception) + { + tSMMQuickAdd = SMMDefaultsEnum.None; + throw exception; + } + } + + + private void ExtrusionQuickAdd_Do() + { + if (tSMMQuickAdd == SMMDefaultsEnum.KRail) + { + tNode.SplinatedObjectQuickAdd("KRail"); + } + } + + + private void ExtrudeHelper(string tPath, string tName, float DefaultHoriz, GSD.Roads.Splination.AxisTypeEnum tAxis = GSD.Roads.Splination.AxisTypeEnum.Z, bool bHorizOverride = false, float tHorizSep = 0f, bool bVertOverride = false, float tVertRaise = 0f, bool bFlipRot = false) + { + SMM = tNode.AddSplinatedObject(); + SMM.CurrentSplination = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(tPath, typeof(GameObject)); + + if (bHorizOverride) + { + SMM.HorizontalSep = tHorizSep; + } + else + { + SMM.HorizontalSep = ((tNode.GSDSpline.tRoad.RoadWidth() / 2) + tNode.GSDSpline.tRoad.opt_ShoulderWidth) * -1f; + } + + if (bVertOverride) + { + SMM.VerticalRaise = tVertRaise; + } + else + { + if (tNode.bIsBridgeStart) + { + SMM.VerticalRaise = -0.01f; + } + } + + SMM.bFlipRotation = bFlipRot; + SMM.Axis = tAxis; + if (SMM.StartTime < tNode.MinSplination) + { + SMM.StartTime = tNode.MinSplination; + } + if (SMM.EndTime > tNode.MaxSplination) + { + SMM.EndTime = tNode.MaxSplination; + } + SMM.tName = tName; + } + #endregion + + + public void OnSceneGUI() + { + Event current = Event.current; + int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); + bool bUsed = false; + + if (!bSceneRectSet) + { + try + { + tSceneRect = EditorWindow.GetWindow().position; + } + catch + { + tSceneRect = EditorWindow.GetWindow().position; + } + bSceneRectSet = true; + } + + if (!tNode.bEditorSelected) + { + tNode.bEditorSelected = true; + } + + if (current.type == EventType.ValidateCommand) + { + switch (current.commandName) + { + case "UndoRedoPerformed": + UpdateSplineObjects_OnUndo(); + break; + } + } + + if (controlID != tNode.GetHashCode()) + { + tNode.bEditorSelected = false; + } + + //Drag with left click: + if (Event.current.type == EventType.MouseDrag && Event.current.button == 0) + { + bMouseDragHasProcessed = false; + tNode.bGizmoDrawIntersectionHighlight = true; + } + //Drag with left click release: + if (Event.current.type == EventType.MouseUp && Event.current.button == 0) + { + Object[] xNodeObjects = GameObject.FindObjectsOfType(typeof(GSDSplineN)); + Object[] connectorObjects = GameObject.FindObjectsOfType(typeof(GSDRoadConnector)); + foreach (GSDSplineN xNode in xNodeObjects) + { + if (Vector3.Distance(xNode.transform.position, tNode.transform.position) < 2f) + { + if (xNode == tNode) + { + continue; + } + if (tNode.bSpecialEndNode || xNode.bSpecialEndNode) + { + continue; + } + if (xNode.bIsEndPoint && tNode.bIsEndPoint) + { + //End point connection. + tNode.transform.position = xNode.transform.position; + //Activate special end node for tnode + TriggerRoadConnection(tNode, xNode); + bUsed = true; + break; + } + if (xNode.bIsIntersection) + { + continue; + } + if (xNode.bNeverIntersect) + { + continue; + } + if (tNode.bIsEndPoint && xNode.bIsEndPoint) + { + continue; + } + if (xNode.GSDSpline == tNode.GSDSpline) + { //Don't let intersection be created on consecutive nodes: + if ((tNode.idOnSpline + 1) == xNode.idOnSpline || (tNode.idOnSpline - 1) == xNode.idOnSpline) + { + continue; + } + } + tNode.transform.position = xNode.transform.position; + TriggerIntersection(tNode, xNode); + bUsed = true; + break; + } + else + { + continue; + } + } + foreach (GSDRoadConnector connector in connectorObjects) + { + if (Vector3.Distance(connector.transform.position, tNode.transform.position) < 2f) + { + if (connector.connectedNode != null) + { + continue; + } + connector.ConnectToNode(tNode); + break; + } + } + + if (!bMouseDragHasProcessed) + { + //Enforce maximum road grade: + if (tNode.IsLegitimate() && tNode.GSDSpline.tRoad.opt_bMaxGradeEnabled) + { + tNode.EnsureGradeValidity(); + } + TriggerRoadUpdate(); + bUsed = true; + } + bMouseDragHasProcessed = true; + tNode.bGizmoDrawIntersectionHighlight = false; + bUsed = true; + } + + //Enforce maximum road grade: + if (bMouseDragHasProcessed) + { + + Vector3 vChangeChecker = tNode.transform.position; + if (VectorDiff(vChangeChecker, tNode.pos)) + { + tNode.pos = vChangeChecker; + if (tNode.IsLegitimate() && tNode.GSDSpline.tRoad.opt_bMaxGradeEnabled) + { + tNode.EnsureGradeValidity(); + } + TriggerRoadUpdate(); + } + bUsed = true; + } + + if (Selection.activeGameObject == tNode.transform.gameObject) + { + if (current.keyCode == KeyCode.F5) + { + TriggerRoadUpdate(); + } + } + + if (bUsed) + { + // switch(current.type){ + // case EventType.layout: + // HandleUtility.AddDefaultControl(controlID); + // break; + // } + } + + if (GUI.changed) + { + EditorUtility.SetDirty(tNode); + } + } + + + private bool VectorDiff(Vector3 tVect1, Vector3 tVect2) + { + if (!GSDRootUtil.IsApproximately(tVect1.x, tVect2.x, 0.0001f)) + { + return true; + } + if (!GSDRootUtil.IsApproximately(tVect1.y, tVect2.y, 0.0001f)) + { + return true; + } + if (!GSDRootUtil.IsApproximately(tVect1.z, tVect2.z, 0.0001f)) + { + return true; + } + return false; + } + + + #region Triggers Interesctions; Connections; Update + private void TriggerRoadConnection(GSDSplineN tNode1, GSDSplineN tNode2) + { + tNode.GSDSpline.ActivateEndNodeConnection(tNode1, tNode2); + } + + + private void TriggerIntersection(GSDSplineN tNode1, GSDSplineN tNode2) + { + bCreateIntersection = true; + iNode1 = tNode1; + iNode2 = tNode2; + Selection.activeGameObject = GSD.Roads.GSDIntersections.CreateIntersection(tNode1, tNode2); + } + + + private void TriggerRoadUpdate() + { + if (tNode != null) + { + tNode.GSDSpline.tRoad.EditorUpdateMe = true; + } + } + #endregion + + + #region Optimizable // LineGUILayout + void Line() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar + GUILayout.Space(4f); + } + + + void LineSmall() + { + GUILayout.Space(2f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1f)); //Horizontal bar + GUILayout.Space(2f); + } + + + void BigLine() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(4f)); //Horizontal bar + GUILayout.Space(4f); + } + #endregion + + + void ResetCurve(ref AnimationCurve tCurve) + { + tCurve = null; + tCurve = new AnimationCurve(); + EnforceCurve(ref tCurve); + } + + + bool V3Equal(ref Vector3 V1, ref Vector3 V2) + { + if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.001f)) + { + return false; + } + return true; + } + + + void EnforceCurve(ref AnimationCurve tCurve) + { + if (tCurve == null) + { + return; + } + if (tCurve.keys.Length == 0) + { + tCurve.AddKey(0f, 1f); + tCurve.AddKey(1f, 1f); + } + else if (tCurve.keys.Length == 1) + { + tCurve.keys[0].time = 0f; + tCurve.AddKey(1f, 1f); + } + } + + + GameObject GetEndObjectQuickAdd() + { + string tPath = ""; + if (tEndObjectAdd == EndObjectsDefaultsEnum.WarningSign1_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDWarningSign_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.WarningSign2_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDWarningSign2_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Atten_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDAtten_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel1_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel1_Rigid) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel_Rigid.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel3_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel3_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel3_Rigid) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel3_Rigid.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel7_Static) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel7_Static.prefab"; + } + else if (tEndObjectAdd == EndObjectsDefaultsEnum.Barrel7_Rigid) + { + tPath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Interactive/GSDRoadBarrel7_Rigid.prefab"; + } + else + { + return null; + } + + return (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(tPath, typeof(GameObject)) as GameObject; + } +} \ No newline at end of file diff --git a/Editor/GSDTerrainEditor.cs b/Editor/GSDTerrainEditor.cs index f4f27317..79a91f16 100755 --- a/Editor/GSDTerrainEditor.cs +++ b/Editor/GSDTerrainEditor.cs @@ -1,291 +1,301 @@ -using UnityEngine; -using UnityEditor; -using GSD; -[CustomEditor(typeof(GSDTerrain))] -public class GSDTerrainEditor : Editor -{ - protected GSDTerrain GSDT { get { return (GSDTerrain)target; } } - - //Serialized properties: - SerializedProperty tSplatImageWidth; - SerializedProperty tSplatImageHeight; - SerializedProperty tSplatBackgroundColor; - SerializedProperty tSplatForegroundColor; - SerializedProperty tSplatWidth; - SerializedProperty tSkipBridges; - SerializedProperty tSkipTunnels; - SerializedProperty tSplatSingleRoad; - SerializedProperty tSplatSingleChoiceIndex; - SerializedProperty tRoadSingleChoiceUID; - - public enum SplatImageResoMatchingEnum - { - None, - Match512x512, - Match1024x1024, - Match2048x2048, - Match4096x4096, - MatchHeightmapResolution, - MatchDetailResolution, - MatchTerrainSize - }; - SplatImageResoMatchingEnum tSplatReso = SplatImageResoMatchingEnum.None; - - private static string[] TheSplatResoOptions = new string[]{ - "Select option to match resolution", - "512 x 512", - "1024 x 1024", - "2048 x 2048", - "4096 x 4096", - "Match heightmap resolution", - "Match detail resolution", - "Match terrain size" - }; - - //Editor only variables: - string[] tRoads = null; - string[] tRoadsString = null; - Texture btnRefreshText = null; - GUIStyle GSDImageButton = null; - Texture2D LoadBtnBG = null; - Texture2D LoadBtnBGGlow = null; - GUIStyle GSDLoadButton = null; - - private void OnEnable() - { - tSplatImageWidth = serializedObject.FindProperty("SplatResoWidth"); - tSplatImageHeight = serializedObject.FindProperty("SplatResoHeight"); - tSplatBackgroundColor = serializedObject.FindProperty("SplatBackground"); - tSplatForegroundColor = serializedObject.FindProperty("SplatForeground"); - tSplatWidth = serializedObject.FindProperty("SplatWidth"); - tSkipBridges = serializedObject.FindProperty("SplatSkipBridges"); - tSkipTunnels = serializedObject.FindProperty("SplatSkipTunnels"); - tSplatSingleRoad = serializedObject.FindProperty("SplatSingleRoad"); - tSplatSingleChoiceIndex = serializedObject.FindProperty("SplatSingleChoiceIndex"); - tRoadSingleChoiceUID = serializedObject.FindProperty("RoadSingleChoiceUID"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - InitNullChecks(); - - Line(); - EditorGUILayout.BeginHorizontal(); - //Main label: - EditorGUILayout.LabelField("Splat map generation:", EditorStyles.boldLabel); - //Online manual button: - if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) - { - Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); - } - EditorGUILayout.EndHorizontal(); - GUILayout.Space(6f); - - //Splat Resolution input: - tSplatImageWidth.intValue = GSDT.SplatResoWidth; - tSplatImageHeight.intValue = GSDT.SplatResoHeight; - EditorGUILayout.BeginHorizontal(); - tSplatReso = (SplatImageResoMatchingEnum)EditorGUILayout.Popup("Match resolutions:", (int)tSplatReso, TheSplatResoOptions); - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tSplatImageWidth.intValue = 1024; - tSplatImageHeight.intValue = 1024; - } - EditorGUILayout.EndHorizontal(); - - if (tSplatReso != SplatImageResoMatchingEnum.None) - { - if (tSplatReso == SplatImageResoMatchingEnum.MatchHeightmapResolution) - { - tSplatImageWidth.intValue = GSDT.tTerrain.terrainData.heightmapResolution; - tSplatImageHeight.intValue = GSDT.tTerrain.terrainData.heightmapResolution; - } - else if (tSplatReso == SplatImageResoMatchingEnum.MatchDetailResolution) - { - tSplatImageWidth.intValue = GSDT.tTerrain.terrainData.detailResolution; - tSplatImageHeight.intValue = GSDT.tTerrain.terrainData.detailResolution; - } - else if (tSplatReso == SplatImageResoMatchingEnum.MatchTerrainSize) - { - tSplatImageWidth.intValue = (int)GSDT.tTerrain.terrainData.size.x; - tSplatImageHeight.intValue = (int)GSDT.tTerrain.terrainData.size.z; - } - else if (tSplatReso == SplatImageResoMatchingEnum.Match512x512) - { - tSplatImageWidth.intValue = 512; - tSplatImageHeight.intValue = 512; - } - else if (tSplatReso == SplatImageResoMatchingEnum.Match1024x1024) - { - tSplatImageWidth.intValue = 1024; - tSplatImageHeight.intValue = 1024; - } - else if (tSplatReso == SplatImageResoMatchingEnum.Match2048x2048) - { - tSplatImageWidth.intValue = 2048; - tSplatImageHeight.intValue = 2048; - } - else if (tSplatReso == SplatImageResoMatchingEnum.Match4096x4096) - { - tSplatImageWidth.intValue = 4096; - tSplatImageHeight.intValue = 4096; - } - tSplatReso = SplatImageResoMatchingEnum.None; - } - - //Splat image width input: - tSplatImageWidth.intValue = EditorGUILayout.IntField("Splat image width:", tSplatImageWidth.intValue); - //Splat image height input: - tSplatImageHeight.intValue = EditorGUILayout.IntField("Splat image height:", tSplatImageHeight.intValue); - - - //Splat background color input: - EditorGUILayout.BeginHorizontal(); - tSplatBackgroundColor.colorValue = EditorGUILayout.ColorField("Splat background:", GSDT.SplatBackground); - //Default button: - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tSplatBackgroundColor.colorValue = new Color(0f, 0f, 0f, 1f); - } - EditorGUILayout.EndHorizontal(); - - //Splat foreground color input: - EditorGUILayout.BeginHorizontal(); - tSplatForegroundColor.colorValue = EditorGUILayout.ColorField("Splat foreground:", GSDT.SplatForeground); - //Default button: - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tSplatForegroundColor.colorValue = new Color(1f, 1f, 1f, 1f); - } - EditorGUILayout.EndHorizontal(); - - //Splat width (meters) input: - EditorGUILayout.BeginHorizontal(); - tSplatWidth.floatValue = EditorGUILayout.Slider("Splat width (meters):", GSDT.SplatWidth, 0.02f, 256f); - //Default button: - if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) - { - tSplatWidth.floatValue = 30f; - } - EditorGUILayout.EndHorizontal(); - - //Skip bridges: - tSkipBridges.boolValue = EditorGUILayout.Toggle("Skip bridges: ", GSDT.SplatSkipBridges); - - //Skip tunnels: - tSkipTunnels.boolValue = EditorGUILayout.Toggle("Skip tunnels: ", GSDT.SplatSkipTunnels); - - //Splat single road bool input: - EditorGUILayout.BeginHorizontal(); - tSplatSingleRoad.boolValue = EditorGUILayout.Toggle("Splat a single road: ", GSDT.SplatSingleRoad); - - //Splat single road , road input: - if (GSDT.SplatSingleRoad) - { - LoadSplatSingleChoice(); - tSplatSingleChoiceIndex.intValue = EditorGUILayout.Popup(GSDT.SplatSingleChoiceIndex, tRoadsString, GUILayout.Width(150f)); - tRoadSingleChoiceUID.stringValue = tRoads[tSplatSingleChoiceIndex.intValue]; - } - - EditorGUILayout.EndHorizontal(); - - //Generate splatmap button: - GUILayout.Space(8f); - if (GUILayout.Button("Generate splatmap for this terrain")) - { - GenerateSplatMap(); - } - GUILayout.Space(10f); - - if (GUI.changed) - { - serializedObject.ApplyModifiedProperties(); - // EditorUtility.SetDirty(target); //Necessary? - } - } - - void InitNullChecks() - { - if (btnRefreshText == null) - { - btnRefreshText = (Texture)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; - } - if (GSDImageButton == null) - { - GSDImageButton = new GUIStyle(GUI.skin.button); - GSDImageButton.contentOffset = new Vector2(0f, 0f); - GSDImageButton.border = new RectOffset(0, 0, 0, 0); - GSDImageButton.fixedHeight = 16f; - GSDImageButton.padding = new RectOffset(0, 0, 0, 0); - GSDImageButton.normal.background = null; - } - if (LoadBtnBG == null) - { - LoadBtnBG = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/FlexBG.png", typeof(Texture2D)) as Texture2D; - } - if (LoadBtnBGGlow == null) - { - LoadBtnBGGlow = (Texture2D)AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/FlexBG.png", typeof(Texture2D)) as Texture2D; - } - if (GSDLoadButton == null) - { - GSDLoadButton = new GUIStyle(GUI.skin.button); - GSDLoadButton.contentOffset = new Vector2(0f, 1f); - GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); - GSDLoadButton.normal.background = LoadBtnBG; - GSDLoadButton.active.background = LoadBtnBGGlow; - GSDLoadButton.focused.background = LoadBtnBGGlow; - GSDLoadButton.hover.background = LoadBtnBGGlow; - GSDLoadButton.fixedHeight = 16f; - GSDLoadButton.padding = new RectOffset(0, 0, 0, 0); - } - } - - private void LoadSplatSingleChoice() - { - tRoads = null; - tRoadsString = null; - Object[] xRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); - int xRoadsCount = xRoads.Length; - tRoads = new string[xRoadsCount]; - tRoadsString = new string[xRoadsCount]; - int xCounter = 0; - foreach (GSDRoad tRoad in xRoads) - { - tRoads[xCounter] = tRoad.UID; - tRoadsString[xCounter] = tRoad.transform.name; - xCounter += 1; - } - } - - private void GenerateSplatMap() - { - byte[] tBytes = null; - if (GSDT.SplatSingleRoad && GSDT.RoadSingleChoiceUID != "") - { - tBytes = GSD.Roads.GSDRoadUtil.MakeSplatMap(GSDT.tTerrain, GSDT.SplatBackground, GSDT.SplatForeground, GSDT.SplatResoWidth, GSDT.SplatResoHeight, GSDT.SplatWidth, GSDT.SplatSkipBridges, GSDT.SplatSkipTunnels, GSDT.RoadSingleChoiceUID); - } - else - { - tBytes = GSD.Roads.GSDRoadUtil.MakeSplatMap(GSDT.tTerrain, GSDT.SplatBackground, GSDT.SplatForeground, GSDT.SplatResoWidth, GSDT.SplatResoHeight, GSDT.SplatWidth, GSDT.SplatSkipBridges, GSDT.SplatSkipTunnels); - } - - if (tBytes != null && tBytes.Length > 3) - { - string tPath = UnityEditor.EditorUtility.SaveFilePanel("Save splat map", Application.dataPath, "Splat", "png"); - if (tPath != null && tPath.Length > 3) - { - System.IO.File.WriteAllBytes(tPath, tBytes); - } - tBytes = null; - } - } - - void Line() - { - GUILayout.Space(4f); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar - GUILayout.Space(4f); - } +#region "Imports" +using UnityEngine; +using UnityEditor; +using GSD; +#endregion + + +[CustomEditor(typeof(GSDTerrain))] +public class GSDTerrainEditor : Editor +{ + protected GSDTerrain GSDT { get { return (GSDTerrain) target; } } + + //Serialized properties: + SerializedProperty tSplatImageWidth; + SerializedProperty tSplatImageHeight; + SerializedProperty tSplatBackgroundColor; + SerializedProperty tSplatForegroundColor; + SerializedProperty tSplatWidth; + SerializedProperty tSkipBridges; + SerializedProperty tSkipTunnels; + SerializedProperty tSplatSingleRoad; + SerializedProperty tSplatSingleChoiceIndex; + SerializedProperty tRoadSingleChoiceUID; + + public enum SplatImageResoMatchingEnum + { + None, + Match512x512, + Match1024x1024, + Match2048x2048, + Match4096x4096, + MatchHeightmapResolution, + MatchDetailResolution, + MatchTerrainSize + }; + SplatImageResoMatchingEnum tSplatReso = SplatImageResoMatchingEnum.None; + + private static string[] TheSplatResoOptions = new string[]{ + "Select option to match resolution", + "512 x 512", + "1024 x 1024", + "2048 x 2048", + "4096 x 4096", + "Match heightmap resolution", + "Match detail resolution", + "Match terrain size" + }; + + //Editor only variables: + string[] tRoads = null; + string[] tRoadsString = null; + Texture btnRefreshText = null; + GUIStyle GSDImageButton = null; + Texture2D LoadBtnBG = null; + Texture2D LoadBtnBGGlow = null; + GUIStyle GSDLoadButton = null; + + + private void OnEnable() + { + tSplatImageWidth = serializedObject.FindProperty("SplatResoWidth"); + tSplatImageHeight = serializedObject.FindProperty("SplatResoHeight"); + tSplatBackgroundColor = serializedObject.FindProperty("SplatBackground"); + tSplatForegroundColor = serializedObject.FindProperty("SplatForeground"); + tSplatWidth = serializedObject.FindProperty("SplatWidth"); + tSkipBridges = serializedObject.FindProperty("SplatSkipBridges"); + tSkipTunnels = serializedObject.FindProperty("SplatSkipTunnels"); + tSplatSingleRoad = serializedObject.FindProperty("SplatSingleRoad"); + tSplatSingleChoiceIndex = serializedObject.FindProperty("SplatSingleChoiceIndex"); + tRoadSingleChoiceUID = serializedObject.FindProperty("RoadSingleChoiceUID"); + } + + + public override void OnInspectorGUI() + { + serializedObject.Update(); + InitNullChecks(); + + Line(); + EditorGUILayout.BeginHorizontal(); + //Main label: + EditorGUILayout.LabelField("Splat map generation:", EditorStyles.boldLabel); + //Online manual button: + if (GUILayout.Button("Online manual", EditorStyles.miniButton, GUILayout.Width(120f))) + { + Application.OpenURL("http://microgsd.com/Support/RoadArchitectManual.aspx"); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(6f); + + //Splat Resolution input: + tSplatImageWidth.intValue = GSDT.SplatResoWidth; + tSplatImageHeight.intValue = GSDT.SplatResoHeight; + EditorGUILayout.BeginHorizontal(); + tSplatReso = (SplatImageResoMatchingEnum) EditorGUILayout.Popup("Match resolutions:", (int) tSplatReso, TheSplatResoOptions); + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tSplatImageWidth.intValue = 1024; + tSplatImageHeight.intValue = 1024; + } + EditorGUILayout.EndHorizontal(); + + if (tSplatReso != SplatImageResoMatchingEnum.None) + { + if (tSplatReso == SplatImageResoMatchingEnum.MatchHeightmapResolution) + { + tSplatImageWidth.intValue = GSDT.tTerrain.terrainData.heightmapResolution; + tSplatImageHeight.intValue = GSDT.tTerrain.terrainData.heightmapResolution; + } + else if (tSplatReso == SplatImageResoMatchingEnum.MatchDetailResolution) + { + tSplatImageWidth.intValue = GSDT.tTerrain.terrainData.detailResolution; + tSplatImageHeight.intValue = GSDT.tTerrain.terrainData.detailResolution; + } + else if (tSplatReso == SplatImageResoMatchingEnum.MatchTerrainSize) + { + tSplatImageWidth.intValue = (int) GSDT.tTerrain.terrainData.size.x; + tSplatImageHeight.intValue = (int) GSDT.tTerrain.terrainData.size.z; + } + else if (tSplatReso == SplatImageResoMatchingEnum.Match512x512) + { + tSplatImageWidth.intValue = 512; + tSplatImageHeight.intValue = 512; + } + else if (tSplatReso == SplatImageResoMatchingEnum.Match1024x1024) + { + tSplatImageWidth.intValue = 1024; + tSplatImageHeight.intValue = 1024; + } + else if (tSplatReso == SplatImageResoMatchingEnum.Match2048x2048) + { + tSplatImageWidth.intValue = 2048; + tSplatImageHeight.intValue = 2048; + } + else if (tSplatReso == SplatImageResoMatchingEnum.Match4096x4096) + { + tSplatImageWidth.intValue = 4096; + tSplatImageHeight.intValue = 4096; + } + tSplatReso = SplatImageResoMatchingEnum.None; + } + + //Splat image width input: + tSplatImageWidth.intValue = EditorGUILayout.IntField("Splat image width:", tSplatImageWidth.intValue); + //Splat image height input: + tSplatImageHeight.intValue = EditorGUILayout.IntField("Splat image height:", tSplatImageHeight.intValue); + + + //Splat background color input: + EditorGUILayout.BeginHorizontal(); + tSplatBackgroundColor.colorValue = EditorGUILayout.ColorField("Splat background:", GSDT.SplatBackground); + //Default button: + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tSplatBackgroundColor.colorValue = new Color(0f, 0f, 0f, 1f); + } + EditorGUILayout.EndHorizontal(); + + //Splat foreground color input: + EditorGUILayout.BeginHorizontal(); + tSplatForegroundColor.colorValue = EditorGUILayout.ColorField("Splat foreground:", GSDT.SplatForeground); + //Default button: + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tSplatForegroundColor.colorValue = new Color(1f, 1f, 1f, 1f); + } + EditorGUILayout.EndHorizontal(); + + //Splat width (meters) input: + EditorGUILayout.BeginHorizontal(); + tSplatWidth.floatValue = EditorGUILayout.Slider("Splat width (meters):", GSDT.SplatWidth, 0.02f, 256f); + //Default button: + if (GUILayout.Button(btnRefreshText, GSDImageButton, GUILayout.Width(16f))) + { + tSplatWidth.floatValue = 30f; + } + EditorGUILayout.EndHorizontal(); + + //Skip bridges: + tSkipBridges.boolValue = EditorGUILayout.Toggle("Skip bridges: ", GSDT.SplatSkipBridges); + + //Skip tunnels: + tSkipTunnels.boolValue = EditorGUILayout.Toggle("Skip tunnels: ", GSDT.SplatSkipTunnels); + + //Splat single road bool input: + EditorGUILayout.BeginHorizontal(); + tSplatSingleRoad.boolValue = EditorGUILayout.Toggle("Splat a single road: ", GSDT.SplatSingleRoad); + + //Splat single road , road input: + if (GSDT.SplatSingleRoad) + { + LoadSplatSingleChoice(); + tSplatSingleChoiceIndex.intValue = EditorGUILayout.Popup(GSDT.SplatSingleChoiceIndex, tRoadsString, GUILayout.Width(150f)); + tRoadSingleChoiceUID.stringValue = tRoads[tSplatSingleChoiceIndex.intValue]; + } + + EditorGUILayout.EndHorizontal(); + + //Generate splatmap button: + GUILayout.Space(8f); + if (GUILayout.Button("Generate splatmap for this terrain")) + { + GenerateSplatMap(); + } + GUILayout.Space(10f); + + if (GUI.changed) + { + serializedObject.ApplyModifiedProperties(); + // EditorUtility.SetDirty(target); //Necessary? + } + } + + + void InitNullChecks() + { + if (btnRefreshText == null) + { + btnRefreshText = (Texture) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/refresh2.png", typeof(Texture)) as Texture; + } + if (GSDImageButton == null) + { + GSDImageButton = new GUIStyle(GUI.skin.button); + GSDImageButton.contentOffset = new Vector2(0f, 0f); + GSDImageButton.border = new RectOffset(0, 0, 0, 0); + GSDImageButton.fixedHeight = 16f; + GSDImageButton.padding = new RectOffset(0, 0, 0, 0); + GSDImageButton.normal.background = null; + } + if (LoadBtnBG == null) + { + LoadBtnBG = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/FlexBG.png", typeof(Texture2D)) as Texture2D; + } + if (LoadBtnBGGlow == null) + { + LoadBtnBGGlow = (Texture2D) AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Icons/FlexBG.png", typeof(Texture2D)) as Texture2D; + } + if (GSDLoadButton == null) + { + GSDLoadButton = new GUIStyle(GUI.skin.button); + GSDLoadButton.contentOffset = new Vector2(0f, 1f); + GSDLoadButton.normal.textColor = new Color(1f, 1f, 1f, 1f); + GSDLoadButton.normal.background = LoadBtnBG; + GSDLoadButton.active.background = LoadBtnBGGlow; + GSDLoadButton.focused.background = LoadBtnBGGlow; + GSDLoadButton.hover.background = LoadBtnBGGlow; + GSDLoadButton.fixedHeight = 16f; + GSDLoadButton.padding = new RectOffset(0, 0, 0, 0); + } + } + + + private void LoadSplatSingleChoice() + { + tRoads = null; + tRoadsString = null; + Object[] xRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); + int xRoadsCount = xRoads.Length; + tRoads = new string[xRoadsCount]; + tRoadsString = new string[xRoadsCount]; + int xCounter = 0; + foreach (GSDRoad tRoad in xRoads) + { + tRoads[xCounter] = tRoad.UID; + tRoadsString[xCounter] = tRoad.transform.name; + xCounter += 1; + } + } + + + private void GenerateSplatMap() + { + byte[] tBytes = null; + if (GSDT.SplatSingleRoad && GSDT.RoadSingleChoiceUID != "") + { + tBytes = GSD.Roads.GSDRoadUtil.MakeSplatMap(GSDT.tTerrain, GSDT.SplatBackground, GSDT.SplatForeground, GSDT.SplatResoWidth, GSDT.SplatResoHeight, GSDT.SplatWidth, GSDT.SplatSkipBridges, GSDT.SplatSkipTunnels, GSDT.RoadSingleChoiceUID); + } + else + { + tBytes = GSD.Roads.GSDRoadUtil.MakeSplatMap(GSDT.tTerrain, GSDT.SplatBackground, GSDT.SplatForeground, GSDT.SplatResoWidth, GSDT.SplatResoHeight, GSDT.SplatWidth, GSDT.SplatSkipBridges, GSDT.SplatSkipTunnels); + } + + if (tBytes != null && tBytes.Length > 3) + { + string tPath = UnityEditor.EditorUtility.SaveFilePanel("Save splat map", Application.dataPath, "Splat", "png"); + if (tPath != null && tPath.Length > 3) + { + System.IO.File.WriteAllBytes(tPath, tBytes); + } + tBytes = null; + } + } + + + void Line() + { + GUILayout.Space(4f); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); //Horizontal bar + GUILayout.Space(4f); + } } \ No newline at end of file diff --git a/Editor/GSDWizard.cs b/Editor/GSDWizard.cs index 0f60d5c9..b2699e86 100755 --- a/Editor/GSDWizard.cs +++ b/Editor/GSDWizard.cs @@ -1,956 +1,1013 @@ -#region "Imports" -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using GSD.Roads.Splination; -using GSD.Roads.EdgeObjects; -using GSD; -using System.IO; -using GSD.Roads; -#endregion -public class GSDWizard : EditorWindow -{ - public enum WindowTypeEnum - { - Extrusion, - Edge, - BridgeComplete, - Groups - }; - public enum WindowTypeEnumShort - { - Extrusion, - Edge, - Groups - }; - private static string[] WindowTypeDescBridge = new string[]{ - "Extrusion items", - "Edge objects", - "Complete bridges", - "Other groups" - }; - private static string[] WindowTypeDesc = new string[]{ - "Extrusion items", - "Edge objects", - "Other groups" - }; - WindowTypeEnum tWindowType = WindowTypeEnum.Extrusion; - WindowTypeEnum xWindowType = WindowTypeEnum.Extrusion; - WindowTypeEnumShort StWindowType = WindowTypeEnumShort.Extrusion; - WindowTypeEnumShort SxWindowType = WindowTypeEnumShort.Extrusion; - static string xPath = ""; - - GUIStyle ThumbStyle; - Vector2 scrollPos = new Vector2(0f, 25f); - GSDSplineN tNode = null; - List oList = null; - bool bNoGUI = false; - - void OnGUI() - { - DoGUI(); - } - - private void DoGUI() - { - if (bNoGUI) { return; } - if (oList == null) { Close(); return; } - - GUILayout.Space(4f); - EditorGUILayout.BeginHorizontal(); - - if (tNode.bIsBridgeStart) - { - xWindowType = (WindowTypeEnum)EditorGUILayout.Popup("Category: ", (int)tWindowType, WindowTypeDescBridge, GUILayout.Width(312f)); - } - else - { - - if (xWindowType == WindowTypeEnum.Edge) - { - SxWindowType = WindowTypeEnumShort.Edge; - } - else if (xWindowType == WindowTypeEnum.Extrusion) - { - SxWindowType = WindowTypeEnumShort.Extrusion; - } - else - { - SxWindowType = WindowTypeEnumShort.Groups; - } - - SxWindowType = (WindowTypeEnumShort)EditorGUILayout.Popup("Category: ", (int)StWindowType, WindowTypeDesc, GUILayout.Width(312f)); - - if (SxWindowType == WindowTypeEnumShort.Extrusion) - { - xWindowType = WindowTypeEnum.Extrusion; - } - else if (SxWindowType == WindowTypeEnumShort.Edge) - { - xWindowType = WindowTypeEnum.Edge; - } - else - { - xWindowType = WindowTypeEnum.Groups; - } - StWindowType = SxWindowType; - } - - if (xWindowType != tWindowType) - { - Initialize(xWindowType, tNode); - EditorGUILayout.EndHorizontal(); - return; - } - - - - EditorGUILayout.LabelField(""); - EditorGUILayout.LabelField("Single-click items to load", EditorStyles.boldLabel, GUILayout.Width(200f)); - - - - EditorGUILayout.EndHorizontal(); - if (oList.Count == 0) { return; } - int oCount = oList.Count; - - int WidthSpacing = 160; - int HeightSpacing = 200; - int HeightOffset = 30; - int ScrollHeightOffset = 25; - - int xCount = 0; - int yCount = 0; - int yMod = Mathf.FloorToInt((float)position.width / 142f) - 1; - - int yMax = 0; - if (yMod == 0) - { - yMax = 1; - } - else - { - yMax = Mathf.CeilToInt((float)oCount / (float)yMod); - } - - bool bScrolling = false; - if ((((yMax) * HeightSpacing) + 25) > position.height) - { - scrollPos = GUI.BeginScrollView(new Rect(0, 25, position.width - 10, position.height - 30), scrollPos, new Rect(0, 0, (yMod * WidthSpacing) + 25, (((yMax) * HeightSpacing) + 50))); - bScrolling = true; - HeightOffset = ScrollHeightOffset; - } - - EditorGUILayout.BeginHorizontal(); - - bool bClicked = false; - for (int i = 0; i < oCount; i++) - { - if (i > 0) - { - if (yMod == 0) - { - EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); yCount += 1; xCount = 0; - } - else - { - if (i % yMod == 0) { EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); yCount += 1; xCount = 0; } - } - } - - if (xCount == 0) - { - bClicked = DoItem((xCount * WidthSpacing) + 5, (yCount * HeightSpacing) + HeightOffset, i); - } - else - { - bClicked = DoItem(xCount * WidthSpacing, (yCount * HeightSpacing) + HeightOffset, i); - } - - if (bClicked) - { - if (tWindowType == WindowTypeEnum.Extrusion) - { - GSD.Roads.Splination.SplinatedMeshMaker SMM = tNode.AddSplinatedObject(); - SMM.SetDefaultTimes(tNode.bIsEndPoint, tNode.tTime, tNode.NextTime, tNode.idOnSpline, tNode.GSDSpline.distance); - SMM.LoadFromLibrary(oList[i].FileName, oList[i].bIsDefault); - SMM.bIsGSD = oList[i].bIsDefault; - SMM.Setup(true); - } - else if (tWindowType == WindowTypeEnum.Edge) - { - GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = tNode.AddEdgeObject(); - EOM.SetDefaultTimes(tNode.bIsEndPoint, tNode.tTime, tNode.NextTime, tNode.idOnSpline, tNode.GSDSpline.distance); - EOM.LoadFromLibrary(oList[i].FileName, oList[i].bIsDefault); - EOM.bIsGSD = oList[i].bIsDefault; - EOM.Setup(); - } - else if (tWindowType == WindowTypeEnum.Groups) - { - tNode.LoadWizardObjectsFromLibrary(oList[i].FileName, oList[i].bIsDefault, oList[i].bIsBridge); - } - else if (tWindowType == WindowTypeEnum.BridgeComplete) - { - tNode.LoadWizardObjectsFromLibrary(oList[i].FileName, oList[i].bIsDefault, oList[i].bIsBridge); - } - tNode.bQuitGUI = true; - oList.Clear(); oList = null; - EditorGUILayout.EndHorizontal(); - if (bScrolling) - { - GUI.EndScrollView(); - } - bNoGUI = true; - Close(); - return; - } - xCount += 1; - - } - EditorGUILayout.EndHorizontal(); - - if (bScrolling) - { - GUI.EndScrollView(); - } - } - - bool DoItem(int x1, int y1, int i) - { - if (oList[i].Thumb != null) - { - if (GUI.Button(new Rect(x1, y1, 132f, 132f), oList[i].Thumb)) - { - return true; - } - } - else - { - if (GUI.Button(new Rect(x1, y1, 132f, 132f), "No image")) - { - return true; - } - } - - GUI.Label(new Rect(x1, y1 + 132f, 148f, 20f), oList[i].DisplayName, EditorStyles.boldLabel); - GUI.Label(new Rect(x1, y1 + 148f, 148f, 52f), oList[i].Desc, EditorStyles.miniLabel); - - return false; - } - - #region "Init" - public Rect xRect; - public void Initialize(WindowTypeEnum _tWindowType, GSDSplineN _tNode) - { - if (xRect.width < 1f && xRect.height < 1f) - { - xRect.x = 275f; - xRect.y = 200f; - xRect.width = 860f; - xRect.height = 500f; - } - - position = xRect; - tWindowType = _tWindowType; - tNode = _tNode; - InitWindow(); - Show(); - } - - private void InitWindow() - { - if (oList != null) { oList.Clear(); oList = null; } - oList = new List(); - if (tWindowType == WindowTypeEnum.Extrusion) - { - titleContent.text = "Extrusion"; - InitObjs(); - } - else if (tWindowType == WindowTypeEnum.Edge) - { - titleContent.text = "Edge objects"; - InitObjs(); - } - else if (tWindowType == WindowTypeEnum.BridgeComplete) - { - titleContent.text = "Bridges"; - InitGroups(true); - } - else if (tWindowType == WindowTypeEnum.Groups) - { - titleContent.text = "Groups"; - InitGroups(false); - } - - ThumbStyle = new GUIStyle(GUI.skin.button); - ThumbStyle.contentOffset = new Vector2(0f, 0f); - ThumbStyle.border = new RectOffset(0, 0, 0, 0); - ThumbStyle.fixedHeight = 128f; - ThumbStyle.fixedWidth = 128f; - ThumbStyle.padding = new RectOffset(0, 0, 0, 0); - ThumbStyle.normal.background = null; - ThumbStyle.hover.background = null; - ThumbStyle.active.background = null; - - EditorStyles.label.wordWrap = true; - EditorStyles.miniLabel.wordWrap = true; - GUI.skin.label.wordWrap = true; - } - - #region "Init complete bridges" - private void InitGroups(bool bIsBridge) - { - string[] tNames = null; - string[] tPaths = null; - //Load user custom ones first: - GetGroupListing(out tNames, out tPaths, tNode.GSDSpline.tRoad.opt_Lanes, false); - LoadGroupObjs(ref tNames, ref tPaths, bIsBridge); - //Load GSD ones last: - GetGroupListing(out tNames, out tPaths, tNode.GSDSpline.tRoad.opt_Lanes, true); - LoadGroupObjs(ref tNames, ref tPaths, bIsBridge); - } - - private void LoadGroupObjs(ref string[] tNames, ref string[] tPaths, bool bIsBridge) - { - int tCount = tNames.Length; - string tPath = ""; - // string tStringPath = ""; - // string tDesc = ""; - // string tDisplayName = ""; - // string ThumbString = ""; - for (int i = 0; i < tCount; i++) - { - GSDRoadUtil.WizardObject tO = GSDRoadUtil.WizardObject.LoadFromLibrary(tPaths[i]); - if (tO == null) { continue; } - if (tO.bIsBridge != bIsBridge) { continue; } - try - { - tO.Thumb = (Texture2D)AssetDatabase.LoadAssetAtPath(tO.ThumbString, typeof(Texture2D)) as Texture2D; - } - catch - { - tO.Thumb = null; - } - tO.FileName = tNames[i]; - tO.FullPath = tPath; - - if (tO.bIsDefault && bIsBridge) - { - if (tO.DisplayName.Contains("SuspL") || tO.DisplayName.Contains("Large Suspension")) - { - tO.DisplayName = "Large Suspension"; - tO.Desc = "Designed after the Golden Gate bridge. For lengths over 850m. Best results over 1300m."; - tO.sortID = 11; - } - else if (tO.DisplayName.Contains("SuspS") || tO.DisplayName.Contains("Small Suspension")) - { - tO.DisplayName = "Small Suspension"; - tO.Desc = "Similar style as the large with smaller pillars. For lengths under 725m."; - tO.sortID = 10; - } - else if (tO.DisplayName.Contains("SemiArch1")) - { - tO.DisplayName = "SemiArch 80 Degree"; - tO.Desc = "80 Degree arch. For lengths under 300m and small heights."; - tO.sortID = 40; - } - else if (tO.DisplayName.Contains("SemiArch2")) - { - tO.DisplayName = "SemiArch 80 Girder"; - tO.Desc = "80 Degree arch with girder style. For lengths under 300m and small heights."; - tO.sortID = 41; - } - else if (tO.DisplayName.Contains("SemiArch3")) - { - tO.DisplayName = "SemiArch 180 Degree"; - tO.Desc = "180 Degree arch. For lengths under 300m and small heights."; - tO.sortID = 42; - } - else if (tO.DisplayName.Contains("Arch12m")) - { - tO.DisplayName = "Arch 12m Beams"; - tO.Desc = "Full deck arch bridge with 12m beams. Good for any length."; - tO.sortID = 0; - } - else if (tO.DisplayName.Contains("Arch24m")) - { - tO.DisplayName = "Arch 24m Beams"; - tO.Desc = "Full deck arch bridge with 24m beams. Good for any length and non-small width roads."; - tO.sortID = 1; - } - else if (tO.DisplayName.Contains("Arch48m")) - { - tO.DisplayName = "Arch 48m Beams"; - tO.Desc = "Full deck arch bridge with 48m beams. Good for any length and large width roads."; - tO.sortID = 3; - } - else if (tO.DisplayName.Contains("Grid")) - { - tO.DisplayName = "Grid Steel"; - tO.Desc = "Grid based steel bridge. Good for any length depending on triangle counts."; - tO.sortID = 30; - } - else if (tO.DisplayName.Contains("Steel")) - { - tO.DisplayName = "Steel Beam"; - tO.Desc = "Standard steel beam bridge. Good for any length depending on triangle counts."; - tO.sortID = 4; - } - else if (tO.DisplayName.Contains("Causeway1")) - { - tO.DisplayName = "Causeway Federal"; - tO.Desc = "Standard federal highway bridge style. Good for any length depending on triangle counts."; - tO.sortID = 5; - } - else if (tO.DisplayName.Contains("Causeway2")) - { - tO.DisplayName = "Causeway Overpass"; - tO.Desc = "Overpass style. Good for any length depending on triangle counts."; - tO.sortID = 8; - } - else if (tO.DisplayName.Contains("Causeway3")) - { - tO.DisplayName = "Causeway Classic"; - tO.Desc = "Classic causeway style. Good for any length depending on triangle counts."; - tO.sortID = 7; - } - else if (tO.DisplayName.Contains("Causeway4")) - { - tO.DisplayName = "Causeway Highway"; - tO.Desc = "State highway style. Good for any length depending on triangle counts."; - tO.sortID = 6; - } - } - - if (tO.bIsDefault && !bIsBridge) - { - if (tO.DisplayName.Contains("GSDTunnel")) - { - tO.DisplayName = "Tunnel"; - tO.Desc = "Designed after the Eisenhower tunnel."; - } - else if (tO.DisplayName.Contains("GSDGroup-WBeamLeftTurn")) - { - tO.DisplayName = "Left turn wbeams"; - tO.Desc = "Contains wbeam and signs on right side of road for left turn."; - } - else if (tO.DisplayName.Contains("GSDGroup-KRailLights")) - { - tO.DisplayName = "K-rail with lights"; - tO.Desc = "Center divider k-rail with double sided lights. Best used on mostly straight highway type roads."; - } - else if (tO.DisplayName.Contains("GSDGroup-Rumblestrips")) - { - tO.DisplayName = "Rumblestrips x2"; - tO.Desc = "Rumble strips on both sides of the road."; - } - else if (tO.DisplayName.Contains("GSDGroup-Fancy1")) - { - tO.DisplayName = "Fancy railing x2"; - tO.Desc = "Luxurious railing with lighting on both sides of the road."; - } - } - - oList.Add(tO); - } - oListSort(); - } - - public static void GetGroupListing(out string[] tNames, out string[] tPaths, int Lanes, bool bIsDefault = false) - { - - xPath = GSDRootUtil.Dir_GetLibrary(); - Debug.Log(xPath); - - string LaneText = "-2L"; - if (Lanes == 4) - { - LaneText = "-4L"; - } - else if (Lanes == 6) - { - LaneText = "-6L"; - } - - tNames = null; - tPaths = null; - DirectoryInfo info; - if (bIsDefault) - { - info = new DirectoryInfo(xPath + "B/W/"); - } - else - { - info = new DirectoryInfo(xPath + "B/"); - } - - FileInfo[] fileInfo = info.GetFiles(); - int tCount = 0; - foreach (FileInfo tInfo in fileInfo) - { - if (tInfo.Extension.ToLower().Contains("gsd")) - { - if (!bIsDefault) - { - tCount += 1; - } - else - { - if (tInfo.Name.Contains(LaneText)) - { - tCount += 1; - } - } - } - } - - tNames = new string[tCount]; - tPaths = new string[tCount]; - tCount = 0; - foreach (FileInfo tInfo in fileInfo) - { - if (tInfo.Extension.ToLower().Contains("gsd")) - { - if (!bIsDefault) - { - tNames[tCount] = tInfo.Name.Replace(".gsd", ""); - tPaths[tCount] = tInfo.FullName; - tCount += 1; - } - else - { - if (tInfo.Name.Contains(LaneText)) - { - tNames[tCount] = tInfo.Name.Replace(".gsd", ""); - tPaths[tCount] = tInfo.FullName; - tCount += 1; - } - } - } - } - } - #endregion - - #region "Init objs" - private void InitObjs() - { - string[] tNames = null; - string[] tPaths = null; - //Load user custom ones first: - if (tWindowType == WindowTypeEnum.Extrusion) - { - SplinatedMeshMaker.GetLibraryFiles(out tNames, out tPaths, false); - } - else - { - EdgeObjectMaker.GetLibraryFiles(out tNames, out tPaths, false); - } - LoadObjs(ref tNames, ref tPaths, false); - //Load GSD ones last: - if (tWindowType == WindowTypeEnum.Extrusion) - { - SplinatedMeshMaker.GetLibraryFiles(out tNames, out tPaths, true); - } - else - { - EdgeObjectMaker.GetLibraryFiles(out tNames, out tPaths, true); - } - LoadObjs(ref tNames, ref tPaths, true); - } - - private void LoadObjs(ref string[] tNames, ref string[] tPaths, bool bIsDefault = false) - { - int tCount = tNames.Length; - string tPath = ""; - string tStringPath = ""; - string tDesc = ""; - string tDisplayName = ""; - string ThumbString = ""; - bool bIsBridge = false; - for (int i = 0; i < tCount; i++) - { - bIsBridge = false; - tPath = tPaths[i]; - - if (tWindowType == WindowTypeEnum.Extrusion) - { - SplinatedMeshMaker.SplinatedMeshLibraryMaker SLM = (SplinatedMeshMaker.SplinatedMeshLibraryMaker)GSDRootUtil.LoadXML(ref tPath); - if (SLM == null) { continue; } - tStringPath = SLM.CurrentSplinationString; - tDesc = SLM.Desc; - tDisplayName = SLM.DisplayName; - ThumbString = SLM.ThumbString; - bIsBridge = SLM.bIsBridge; - } - else if (tWindowType == WindowTypeEnum.Edge) - { - EdgeObjectMaker.EdgeObjectLibraryMaker ELM = (EdgeObjectMaker.EdgeObjectLibraryMaker)GSDRootUtil.LoadXML(ref tPath); - if (ELM == null) { continue; } - tStringPath = ELM.EdgeObjectString; - tDesc = ELM.Desc; - tDisplayName = ELM.DisplayName; - ThumbString = ELM.ThumbString; - bIsBridge = ELM.bIsBridge; - } - - //Don't continue if bridge pieces and this is not a bridge piece: - if (tWindowType == WindowTypeEnum.Extrusion && bIsBridge) { continue; } - - GSDRoadUtil.WizardObject tO = new GSDRoadUtil.WizardObject(); - try - { - tO.Thumb = (Texture2D)AssetDatabase.LoadAssetAtPath(ThumbString, typeof(Texture2D)) as Texture2D; - } - catch - { - tO.Thumb = null; - } - if (tO.Thumb == null) - { - try - { - GameObject xObj = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(tStringPath, typeof(GameObject)) as GameObject; - tO.Thumb = AssetPreview.GetAssetPreview(xObj); - } - catch - { - tO.Thumb = null; - } - } - tO.DisplayName = tDisplayName; - tO.FileName = tNames[i]; - tO.FullPath = tPath; - tO.Desc = tDesc; - tO.bIsDefault = bIsDefault; - - if (bIsDefault && tWindowType == WindowTypeEnum.Edge) - { - if (tO.DisplayName.Contains("GSDAtten")) - { - tO.DisplayName = "Attenuator"; - tO.Desc = "Standard double WBeam with impact absorption."; - } - else if (tO.DisplayName.Contains("GSDGreenBlinder")) - { - tO.DisplayName = "KRail Blinder"; - tO.Desc = "Best results when placed on KRail for KRail blinders."; - tO.sortID = 5; - } - else if (tO.DisplayName.Contains("GSDRoadBarrelStatic")) - { - tO.DisplayName = "Sand Barrel Static"; - tO.Desc = "One static sand barrel. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadBarrelRigid")) - { - tO.DisplayName = "Sand Barrel Rigid"; - tO.Desc = "One rigid sand barrel. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadBarrel3Static")) - { - tO.DisplayName = "Sand Barrels Static 3"; - tO.Desc = "Three static sand barrels in a line. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadBarrel3Rigid")) - { - tO.DisplayName = "Sand Barrels Rigid 3"; - tO.Desc = "Three rigid sand barrels in a line. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadBarrel7Static")) - { - tO.DisplayName = "Sand Barrels Static 7"; - tO.Desc = "Seven static sand barrels in standard formation. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadBarrel7Rigid")) - { - tO.DisplayName = "Sand Barrel Rigid 7"; - tO.Desc = "Seven rigid sand barrels in standard formation. Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDRoadConBarrelStatic")) - { - tO.DisplayName = "Con Barrels Static"; - tO.Desc = "Static road construction barrels."; - tO.sortID = 3; - } - else if (tO.DisplayName.Contains("GSDRoadConBarrelRigid")) - { - tO.DisplayName = "Con Barrels Rigid"; - tO.Desc = "Rigid road construction barrels."; - tO.sortID = 3; - } - else if (tO.DisplayName.Contains("GSDTrafficConeStatic")) - { - tO.DisplayName = "Traffic cones Static"; - tO.Desc = "Static traffic cones."; - tO.sortID = 4; - } - else if (tO.DisplayName.Contains("GSDTrafficConeRigid")) - { - tO.DisplayName = "Traffic cones Rigid"; - tO.Desc = "Rigid traffic cones."; - tO.sortID = 4; - } - else if (tO.DisplayName.Contains("GSDRoadReflector")) - { - tO.DisplayName = "Road reflectors"; - tO.Desc = "Placed one center line of road for center line reflection."; - tO.sortID = 4; - } - else if (tO.DisplayName.Contains("GSDStopSign")) - { - tO.DisplayName = "Stop sign"; - tO.Desc = "Standard specification non-interstate stop sign."; - } - else if (tO.DisplayName.Contains("GSDStreetLightSingle")) - { - tO.DisplayName = "Streetlight Singlesided"; - tO.Desc = "Best used on side of roads."; - } - else if (tO.DisplayName.Contains("GSDStreetLightDouble")) - { - tO.DisplayName = "Streetlight Doublesided"; - tO.Desc = "Best results when embedded in KRail in centerline of road."; - } - else if (tO.DisplayName.Contains("GSDWarningSign1")) - { - tO.DisplayName = "Warning Sign #1"; - tO.Desc = "Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDWarningSign2")) - { - tO.DisplayName = "Warning Sign #2"; - tO.Desc = "Best results when placed in front of railings or bridges."; - } - else if (tO.DisplayName.Contains("GSDSignRightTurnOnly")) - { - tO.DisplayName = "Right turn only"; - tO.Desc = "Best results when placed near intersection right turn lane."; - tO.sortID = 4; - } - - else if (tO.DisplayName.Contains("GSDSign330")) - { - tO.DisplayName = "Signs 330"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-330\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign396")) - { - tO.DisplayName = "Signs 396"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-396\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign617-Small")) - { - tO.DisplayName = "Signs 617 small"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-617\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign617")) - { - tO.DisplayName = "Signs 617"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-617\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign861-Small")) - { - tO.DisplayName = "Signs 861 small"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-861\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign861")) - { - tO.DisplayName = "Sign type 861"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-861\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign988-Small")) - { - tO.DisplayName = "Signs 988 small"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-988\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSign988")) - { - tO.DisplayName = "Signs 988"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-988\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSignDiamond")) - { - tO.DisplayName = "Signs diamond"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-diamond\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSignSquare-Small")) - { - tO.DisplayName = "Signs square small"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-Square\" as the search term."; - tO.sortID = 21; - } - else if (tO.DisplayName.Contains("GSDSignSquare")) - { - tO.DisplayName = "Signs square"; - tO.Desc = "Interchangeable materials, use \"GSDFedSign-Square\" as the search term."; - tO.sortID = 21; - } - } - - if (bIsDefault && tWindowType == WindowTypeEnum.Extrusion) - { - if (tO.DisplayName.Contains("GSDKRail")) - { - tO.DisplayName = "KRail"; - tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with down ends."; - } - else if (tO.DisplayName.Contains("GSDKRailCurvedR")) - { - tO.DisplayName = "KRail Curved Right"; - tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with curved ends for right shoulder."; - } - else if (tO.DisplayName.Contains("GSDKRailCurvedL")) - { - tO.DisplayName = "KRail Curved Left"; - tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with curved ends for left shoulder."; - } - else if (tO.DisplayName.Contains("GSDWBeam1R")) - { - tO.DisplayName = "WBeam Wood Right"; - tO.Desc = "Federal spec wooden pole WBeam railing. Best used as outer shoulder railing. Right shoulder."; - } - else if (tO.DisplayName.Contains("GSDWBeam1L")) - { - tO.DisplayName = "WBeam Wood Left"; - tO.Desc = "Federal spec wooden pole WBeam railing. Best used as outer shoulder railing. Left shoulder."; - } - else if (tO.DisplayName.Contains("GSDWBeam2R")) - { - tO.DisplayName = "WBeam Metal Right"; - tO.Desc = "Federal spec metal pole WBeam railing. Best used as outer shoulder railing. Right shoulder."; - } - else if (tO.DisplayName.Contains("GSDWBeam2L")) - { - tO.DisplayName = "WBeam Metal Left"; - tO.Desc = "Federal spec metal pole WBeam railing. Best used as outer shoulder railing. Left shoulder."; - } - else if (tO.DisplayName.Contains("GSDRailing1")) - { - tO.DisplayName = "Railing #1"; - tO.Desc = "Standard double square pole railing."; - } - else if (tO.DisplayName.Contains("GSDRailing2")) - { - tO.DisplayName = "Railing #2"; - tO.Desc = "Standard concrete big block railing."; - } - else if (tO.DisplayName.Contains("GSDRailing3")) - { - tO.DisplayName = "Railing #3"; - tO.Desc = "Standard four-strand metal railing."; - } - else if (tO.DisplayName.Contains("GSDRailing5")) - { - tO.DisplayName = "Railing #5"; - tO.Desc = "Basic concrete railing with pylons."; - } - else if (tO.DisplayName.Contains("GSDRailing6")) - { - tO.DisplayName = "Railing #6"; - tO.Desc = "Standard two-strand metal pole railing."; - } - else if (tO.DisplayName.Contains("GSDRailing7")) - { - tO.DisplayName = "Railing #7"; - tO.Desc = "Rock-decorated concrete railing with pylons and double strand rusted look metal railing."; - } - else if (tO.DisplayName.Contains("GSDRailing8")) - { - tO.DisplayName = "Railing #8"; - tO.Desc = "Rock-decorated concrete railing with standard single pole metal railing."; - } - else if (tO.DisplayName.Contains("GSDRailing9")) - { - tO.DisplayName = "Railing #9"; - tO.Desc = "Very low poly railing used for mobile."; - } - else if (tO.DisplayName.Contains("GSDSidewalk")) - { - tO.DisplayName = "Sidewalk"; - tO.Desc = "Sidewalk."; - } - else if (tO.DisplayName.Contains("GSDRumbleStrip")) - { - tO.DisplayName = "Rumblestrip"; - tO.Desc = "State spec rumblestrip. For best results place several cm from road edge into shoulder."; - } - else if (tO.DisplayName.Contains("GSDRailing4R")) - { - tO.DisplayName = "Railing #4 Right"; - tO.Desc = "Three bar angled pole railing. Right side of road."; - } - else if (tO.DisplayName.Contains("GSDRailing4L")) - { - tO.DisplayName = "Railing #4 Left"; - tO.Desc = "Three bar angled pole railing. Left side of road."; - } - else if (tO.DisplayName.Contains("GSDRailing4-LightR")) - { - tO.DisplayName = "Railing #4 Light Right"; - tO.Desc = "Three bar angled pole railing. Right side of road. Light version with fewer triangle count."; - } - else if (tO.DisplayName.Contains("GSDRailing4-LightL")) - { - tO.DisplayName = "Railing #4 Light Left"; - tO.Desc = "Three bar angled pole railing. Left side of road. Light version with fewer triangle count."; - } - else if (tO.DisplayName.Contains("GSDRailingBase1")) - { - tO.DisplayName = "Railing base #1"; - tO.Desc = "Use as a base on other railings to create more detail."; - } - else if (tO.DisplayName.Contains("GSDRailingBase2")) - { - tO.DisplayName = "Railing base #2"; - tO.Desc = "Use as a base on other railings to create more detail."; - } - else if (tO.DisplayName.Contains("GSDCableBarrier-Light")) - { - tO.DisplayName = "Cable barrier 10m"; - tO.Desc = "Cable barrier 10m light triangle version. Best used as center divider or as railing barriers."; - tO.sortID = 20; - } - else if (tO.DisplayName.Contains("GSDCableBarrier")) - { - tO.DisplayName = "Cable barrier 5m"; - tO.Desc = "Cable barrier 5m. Best used as center divider or as railing barriers."; - tO.sortID = 20; - } - } - - oList.Add(tO); - } - oListSort(); - } - - void oListSort() - { - oList.Sort((GSDRoadUtil.WizardObject t1, GSDRoadUtil.WizardObject t2) => - { - if (t1.bIsDefault != t2.bIsDefault) - { - return t1.bIsDefault.CompareTo(t2.bIsDefault); - } - else if (t1.sortID != t2.sortID) - { - return t1.sortID.CompareTo(t2.sortID); - } - else - { - return t1.DisplayName.CompareTo(t2.DisplayName); - } - }); - } - #endregion - #endregion +#region "Imports" +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using GSD.Roads.Splination; +using GSD.Roads.EdgeObjects; +using GSD; +using System.IO; +using GSD.Roads; +#endregion + + +public class GSDWizard : EditorWindow +{ + public enum WindowTypeEnum + { + Extrusion, + Edge, + BridgeComplete, + Groups + }; + + + public enum WindowTypeEnumShort + { + Extrusion, + Edge, + Groups + }; + + + private static string[] WindowTypeDescBridge = new string[]{ + "Extrusion items", + "Edge objects", + "Complete bridges", + "Other groups" + }; + + + private static string[] WindowTypeDesc = new string[]{ + "Extrusion items", + "Edge objects", + "Other groups" + }; + + + WindowTypeEnum tWindowType = WindowTypeEnum.Extrusion; + WindowTypeEnum xWindowType = WindowTypeEnum.Extrusion; + WindowTypeEnumShort StWindowType = WindowTypeEnumShort.Extrusion; + WindowTypeEnumShort SxWindowType = WindowTypeEnumShort.Extrusion; + static string xPath = ""; + + GUIStyle ThumbStyle; + Vector2 scrollPos = new Vector2(0f, 25f); + GSDSplineN tNode = null; + List oList = null; + bool bNoGUI = false; + + + void OnGUI() + { + DoGUI(); + } + + + private void DoGUI() + { + if (bNoGUI) + { + return; + } + if (oList == null) + { + Close(); + return; + } + + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(); + + if (tNode.bIsBridgeStart) + { + xWindowType = (WindowTypeEnum) EditorGUILayout.Popup("Category: ", (int) tWindowType, WindowTypeDescBridge, GUILayout.Width(312f)); + } + else + { + + if (xWindowType == WindowTypeEnum.Edge) + { + SxWindowType = WindowTypeEnumShort.Edge; + } + else if (xWindowType == WindowTypeEnum.Extrusion) + { + SxWindowType = WindowTypeEnumShort.Extrusion; + } + else + { + SxWindowType = WindowTypeEnumShort.Groups; + } + + SxWindowType = (WindowTypeEnumShort) EditorGUILayout.Popup("Category: ", (int) StWindowType, WindowTypeDesc, GUILayout.Width(312f)); + + if (SxWindowType == WindowTypeEnumShort.Extrusion) + { + xWindowType = WindowTypeEnum.Extrusion; + } + else if (SxWindowType == WindowTypeEnumShort.Edge) + { + xWindowType = WindowTypeEnum.Edge; + } + else + { + xWindowType = WindowTypeEnum.Groups; + } + StWindowType = SxWindowType; + } + + if (xWindowType != tWindowType) + { + Initialize(xWindowType, tNode); + EditorGUILayout.EndHorizontal(); + return; + } + + + + EditorGUILayout.LabelField(""); + EditorGUILayout.LabelField("Single-click items to load", EditorStyles.boldLabel, GUILayout.Width(200f)); + + + + EditorGUILayout.EndHorizontal(); + if (oList.Count == 0) + { + return; + } + int oCount = oList.Count; + + int WidthSpacing = 160; + int HeightSpacing = 200; + int HeightOffset = 30; + int ScrollHeightOffset = 25; + + int xCount = 0; + int yCount = 0; + int yMod = Mathf.FloorToInt((float) position.width / 142f) - 1; + + int yMax = 0; + if (yMod == 0) + { + yMax = 1; + } + else + { + yMax = Mathf.CeilToInt((float) oCount / (float) yMod); + } + + bool bScrolling = false; + if ((((yMax) * HeightSpacing) + 25) > position.height) + { + scrollPos = GUI.BeginScrollView(new Rect(0, 25, position.width - 10, position.height - 30), scrollPos, new Rect(0, 0, (yMod * WidthSpacing) + 25, (((yMax) * HeightSpacing) + 50))); + bScrolling = true; + HeightOffset = ScrollHeightOffset; + } + + EditorGUILayout.BeginHorizontal(); + + bool bClicked = false; + for (int i = 0; i < oCount; i++) + { + if (i > 0) + { + if (yMod == 0) + { + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + yCount += 1; + xCount = 0; + } + else + { + if (i % yMod == 0) + { EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); yCount += 1; xCount = 0; } + } + } + + if (xCount == 0) + { + bClicked = DoItem((xCount * WidthSpacing) + 5, (yCount * HeightSpacing) + HeightOffset, i); + } + else + { + bClicked = DoItem(xCount * WidthSpacing, (yCount * HeightSpacing) + HeightOffset, i); + } + + if (bClicked) + { + if (tWindowType == WindowTypeEnum.Extrusion) + { + GSD.Roads.Splination.SplinatedMeshMaker SMM = tNode.AddSplinatedObject(); + SMM.SetDefaultTimes(tNode.bIsEndPoint, tNode.tTime, tNode.NextTime, tNode.idOnSpline, tNode.GSDSpline.distance); + SMM.LoadFromLibrary(oList[i].FileName, oList[i].bIsDefault); + SMM.bIsGSD = oList[i].bIsDefault; + SMM.Setup(true); + } + else if (tWindowType == WindowTypeEnum.Edge) + { + GSD.Roads.EdgeObjects.EdgeObjectMaker EOM = tNode.AddEdgeObject(); + EOM.SetDefaultTimes(tNode.bIsEndPoint, tNode.tTime, tNode.NextTime, tNode.idOnSpline, tNode.GSDSpline.distance); + EOM.LoadFromLibrary(oList[i].FileName, oList[i].bIsDefault); + EOM.bIsGSD = oList[i].bIsDefault; + EOM.Setup(); + } + else if (tWindowType == WindowTypeEnum.Groups) + { + tNode.LoadWizardObjectsFromLibrary(oList[i].FileName, oList[i].bIsDefault, oList[i].bIsBridge); + } + else if (tWindowType == WindowTypeEnum.BridgeComplete) + { + tNode.LoadWizardObjectsFromLibrary(oList[i].FileName, oList[i].bIsDefault, oList[i].bIsBridge); + } + tNode.bQuitGUI = true; + oList.Clear(); + oList = null; + EditorGUILayout.EndHorizontal(); + if (bScrolling) + { + GUI.EndScrollView(); + } + bNoGUI = true; + Close(); + return; + } + xCount += 1; + + } + EditorGUILayout.EndHorizontal(); + + if (bScrolling) + { + GUI.EndScrollView(); + } + } + + + bool DoItem(int x1, int y1, int i) + { + if (oList[i].Thumb != null) + { + if (GUI.Button(new Rect(x1, y1, 132f, 132f), oList[i].Thumb)) + { + return true; + } + } + else + { + if (GUI.Button(new Rect(x1, y1, 132f, 132f), "No image")) + { + return true; + } + } + + GUI.Label(new Rect(x1, y1 + 132f, 148f, 20f), oList[i].DisplayName, EditorStyles.boldLabel); + GUI.Label(new Rect(x1, y1 + 148f, 148f, 52f), oList[i].Desc, EditorStyles.miniLabel); + + return false; + } + + + #region "Init" + public Rect xRect; + + + public void Initialize(WindowTypeEnum _tWindowType, GSDSplineN _tNode) + { + if (xRect.width < 1f && xRect.height < 1f) + { + xRect.x = 275f; + xRect.y = 200f; + xRect.width = 860f; + xRect.height = 500f; + } + + position = xRect; + tWindowType = _tWindowType; + tNode = _tNode; + InitWindow(); + Show(); + } + + + private void InitWindow() + { + if (oList != null) + { + oList.Clear(); + oList = null; + } + oList = new List(); + if (tWindowType == WindowTypeEnum.Extrusion) + { + titleContent.text = "Extrusion"; + InitObjs(); + } + else if (tWindowType == WindowTypeEnum.Edge) + { + titleContent.text = "Edge objects"; + InitObjs(); + } + else if (tWindowType == WindowTypeEnum.BridgeComplete) + { + titleContent.text = "Bridges"; + InitGroups(true); + } + else if (tWindowType == WindowTypeEnum.Groups) + { + titleContent.text = "Groups"; + InitGroups(false); + } + + ThumbStyle = new GUIStyle(GUI.skin.button); + ThumbStyle.contentOffset = new Vector2(0f, 0f); + ThumbStyle.border = new RectOffset(0, 0, 0, 0); + ThumbStyle.fixedHeight = 128f; + ThumbStyle.fixedWidth = 128f; + ThumbStyle.padding = new RectOffset(0, 0, 0, 0); + ThumbStyle.normal.background = null; + ThumbStyle.hover.background = null; + ThumbStyle.active.background = null; + + EditorStyles.label.wordWrap = true; + EditorStyles.miniLabel.wordWrap = true; + GUI.skin.label.wordWrap = true; + } + + + #region "Init complete bridges" + private void InitGroups(bool bIsBridge) + { + string[] tNames = null; + string[] tPaths = null; + //Load user custom ones first: + GetGroupListing(out tNames, out tPaths, tNode.GSDSpline.tRoad.opt_Lanes, false); + LoadGroupObjs(ref tNames, ref tPaths, bIsBridge); + //Load GSD ones last: + GetGroupListing(out tNames, out tPaths, tNode.GSDSpline.tRoad.opt_Lanes, true); + LoadGroupObjs(ref tNames, ref tPaths, bIsBridge); + } + + + private void LoadGroupObjs(ref string[] tNames, ref string[] tPaths, bool bIsBridge) + { + int tCount = tNames.Length; + string tPath = ""; + // string tStringPath = ""; + // string tDesc = ""; + // string tDisplayName = ""; + // string ThumbString = ""; + for (int index = 0; index < tCount; index++) + { + GSDRoadUtil.WizardObject tO = GSDRoadUtil.WizardObject.LoadFromLibrary(tPaths[index]); + if (tO == null) + { + continue; + } + if (tO.bIsBridge != bIsBridge) + { + continue; + } + try + { + tO.Thumb = (Texture2D) AssetDatabase.LoadAssetAtPath(tO.ThumbString, typeof(Texture2D)) as Texture2D; + } + catch + { + tO.Thumb = null; + } + tO.FileName = tNames[index]; + tO.FullPath = tPath; + + if (tO.bIsDefault && bIsBridge) + { + if (tO.DisplayName.Contains("SuspL") || tO.DisplayName.Contains("Large Suspension")) + { + tO.DisplayName = "Large Suspension"; + tO.Desc = "Designed after the Golden Gate bridge. For lengths over 850m. Best results over 1300m."; + tO.sortID = 11; + } + else if (tO.DisplayName.Contains("SuspS") || tO.DisplayName.Contains("Small Suspension")) + { + tO.DisplayName = "Small Suspension"; + tO.Desc = "Similar style as the large with smaller pillars. For lengths under 725m."; + tO.sortID = 10; + } + else if (tO.DisplayName.Contains("SemiArch1")) + { + tO.DisplayName = "SemiArch 80 Degree"; + tO.Desc = "80 Degree arch. For lengths under 300m and small heights."; + tO.sortID = 40; + } + else if (tO.DisplayName.Contains("SemiArch2")) + { + tO.DisplayName = "SemiArch 80 Girder"; + tO.Desc = "80 Degree arch with girder style. For lengths under 300m and small heights."; + tO.sortID = 41; + } + else if (tO.DisplayName.Contains("SemiArch3")) + { + tO.DisplayName = "SemiArch 180 Degree"; + tO.Desc = "180 Degree arch. For lengths under 300m and small heights."; + tO.sortID = 42; + } + else if (tO.DisplayName.Contains("Arch12m")) + { + tO.DisplayName = "Arch 12m Beams"; + tO.Desc = "Full deck arch bridge with 12m beams. Good for any length."; + tO.sortID = 0; + } + else if (tO.DisplayName.Contains("Arch24m")) + { + tO.DisplayName = "Arch 24m Beams"; + tO.Desc = "Full deck arch bridge with 24m beams. Good for any length and non-small width roads."; + tO.sortID = 1; + } + else if (tO.DisplayName.Contains("Arch48m")) + { + tO.DisplayName = "Arch 48m Beams"; + tO.Desc = "Full deck arch bridge with 48m beams. Good for any length and large width roads."; + tO.sortID = 3; + } + else if (tO.DisplayName.Contains("Grid")) + { + tO.DisplayName = "Grid Steel"; + tO.Desc = "Grid based steel bridge. Good for any length depending on triangle counts."; + tO.sortID = 30; + } + else if (tO.DisplayName.Contains("Steel")) + { + tO.DisplayName = "Steel Beam"; + tO.Desc = "Standard steel beam bridge. Good for any length depending on triangle counts."; + tO.sortID = 4; + } + else if (tO.DisplayName.Contains("Causeway1")) + { + tO.DisplayName = "Causeway Federal"; + tO.Desc = "Standard federal highway bridge style. Good for any length depending on triangle counts."; + tO.sortID = 5; + } + else if (tO.DisplayName.Contains("Causeway2")) + { + tO.DisplayName = "Causeway Overpass"; + tO.Desc = "Overpass style. Good for any length depending on triangle counts."; + tO.sortID = 8; + } + else if (tO.DisplayName.Contains("Causeway3")) + { + tO.DisplayName = "Causeway Classic"; + tO.Desc = "Classic causeway style. Good for any length depending on triangle counts."; + tO.sortID = 7; + } + else if (tO.DisplayName.Contains("Causeway4")) + { + tO.DisplayName = "Causeway Highway"; + tO.Desc = "State highway style. Good for any length depending on triangle counts."; + tO.sortID = 6; + } + } + + if (tO.bIsDefault && !bIsBridge) + { + if (tO.DisplayName.Contains("GSDTunnel")) + { + tO.DisplayName = "Tunnel"; + tO.Desc = "Designed after the Eisenhower tunnel."; + } + else if (tO.DisplayName.Contains("GSDGroup-WBeamLeftTurn")) + { + tO.DisplayName = "Left turn wbeams"; + tO.Desc = "Contains wbeam and signs on right side of road for left turn."; + } + else if (tO.DisplayName.Contains("GSDGroup-KRailLights")) + { + tO.DisplayName = "K-rail with lights"; + tO.Desc = "Center divider k-rail with double sided lights. Best used on mostly straight highway type roads."; + } + else if (tO.DisplayName.Contains("GSDGroup-Rumblestrips")) + { + tO.DisplayName = "Rumblestrips x2"; + tO.Desc = "Rumble strips on both sides of the road."; + } + else if (tO.DisplayName.Contains("GSDGroup-Fancy1")) + { + tO.DisplayName = "Fancy railing x2"; + tO.Desc = "Luxurious railing with lighting on both sides of the road."; + } + } + + oList.Add(tO); + } + oListSort(); + } + + + public static void GetGroupListing(out string[] tNames, out string[] tPaths, int Lanes, bool bIsDefault = false) + { + + xPath = GSDRootUtil.Dir_GetLibrary(); + Debug.Log(xPath); + + string LaneText = "-2L"; + if (Lanes == 4) + { + LaneText = "-4L"; + } + else if (Lanes == 6) + { + LaneText = "-6L"; + } + + tNames = null; + tPaths = null; + DirectoryInfo info; + if (bIsDefault) + { + info = new DirectoryInfo(xPath + "B/W/"); + } + else + { + info = new DirectoryInfo(xPath + "B/"); + } + + FileInfo[] fileInfo = info.GetFiles(); + int tCount = 0; + foreach (FileInfo tInfo in fileInfo) + { + if (tInfo.Extension.ToLower().Contains("gsd")) + { + if (!bIsDefault) + { + tCount += 1; + } + else + { + if (tInfo.Name.Contains(LaneText)) + { + tCount += 1; + } + } + } + } + + tNames = new string[tCount]; + tPaths = new string[tCount]; + tCount = 0; + foreach (FileInfo tInfo in fileInfo) + { + if (tInfo.Extension.ToLower().Contains("gsd")) + { + if (!bIsDefault) + { + tNames[tCount] = tInfo.Name.Replace(".gsd", ""); + tPaths[tCount] = tInfo.FullName; + tCount += 1; + } + else + { + if (tInfo.Name.Contains(LaneText)) + { + tNames[tCount] = tInfo.Name.Replace(".gsd", ""); + tPaths[tCount] = tInfo.FullName; + tCount += 1; + } + } + } + } + } + #endregion + + + #region "Init objs" + private void InitObjs() + { + string[] tNames = null; + string[] tPaths = null; + //Load user custom ones first: + if (tWindowType == WindowTypeEnum.Extrusion) + { + SplinatedMeshMaker.GetLibraryFiles(out tNames, out tPaths, false); + } + else + { + EdgeObjectMaker.GetLibraryFiles(out tNames, out tPaths, false); + } + LoadObjs(ref tNames, ref tPaths, false); + //Load GSD ones last: + if (tWindowType == WindowTypeEnum.Extrusion) + { + SplinatedMeshMaker.GetLibraryFiles(out tNames, out tPaths, true); + } + else + { + EdgeObjectMaker.GetLibraryFiles(out tNames, out tPaths, true); + } + LoadObjs(ref tNames, ref tPaths, true); + } + + + private void LoadObjs(ref string[] tNames, ref string[] tPaths, bool bIsDefault = false) + { + int tCount = tNames.Length; + string tPath = ""; + string tStringPath = ""; + string tDesc = ""; + string tDisplayName = ""; + string ThumbString = ""; + bool bIsBridge = false; + for (int i = 0; i < tCount; i++) + { + bIsBridge = false; + tPath = tPaths[i]; + + if (tWindowType == WindowTypeEnum.Extrusion) + { + SplinatedMeshMaker.SplinatedMeshLibraryMaker SLM = (SplinatedMeshMaker.SplinatedMeshLibraryMaker) GSDRootUtil.LoadXML(ref tPath); + if (SLM == null) + { + continue; + } + tStringPath = SLM.CurrentSplinationString; + tDesc = SLM.Desc; + tDisplayName = SLM.DisplayName; + ThumbString = SLM.ThumbString; + bIsBridge = SLM.bIsBridge; + } + else if (tWindowType == WindowTypeEnum.Edge) + { + EdgeObjectMaker.EdgeObjectLibraryMaker ELM = (EdgeObjectMaker.EdgeObjectLibraryMaker) GSDRootUtil.LoadXML(ref tPath); + if (ELM == null) + { + continue; + } + tStringPath = ELM.EdgeObjectString; + tDesc = ELM.Desc; + tDisplayName = ELM.DisplayName; + ThumbString = ELM.ThumbString; + bIsBridge = ELM.bIsBridge; + } + + //Don't continue if bridge pieces and this is not a bridge piece: + if (tWindowType == WindowTypeEnum.Extrusion && bIsBridge) + { + continue; + } + + GSDRoadUtil.WizardObject tO = new GSDRoadUtil.WizardObject(); + try + { + tO.Thumb = (Texture2D) AssetDatabase.LoadAssetAtPath(ThumbString, typeof(Texture2D)) as Texture2D; + } + catch + { + tO.Thumb = null; + } + if (tO.Thumb == null) + { + try + { + GameObject xObj = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(tStringPath, typeof(GameObject)) as GameObject; + tO.Thumb = AssetPreview.GetAssetPreview(xObj); + } + catch + { + tO.Thumb = null; + } + } + tO.DisplayName = tDisplayName; + tO.FileName = tNames[i]; + tO.FullPath = tPath; + tO.Desc = tDesc; + tO.bIsDefault = bIsDefault; + + if (bIsDefault && tWindowType == WindowTypeEnum.Edge) + { + if (tO.DisplayName.Contains("GSDAtten")) + { + tO.DisplayName = "Attenuator"; + tO.Desc = "Standard double WBeam with impact absorption."; + } + else if (tO.DisplayName.Contains("GSDGreenBlinder")) + { + tO.DisplayName = "KRail Blinder"; + tO.Desc = "Best results when placed on KRail for KRail blinders."; + tO.sortID = 5; + } + else if (tO.DisplayName.Contains("GSDRoadBarrelStatic")) + { + tO.DisplayName = "Sand Barrel Static"; + tO.Desc = "One static sand barrel. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadBarrelRigid")) + { + tO.DisplayName = "Sand Barrel Rigid"; + tO.Desc = "One rigid sand barrel. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadBarrel3Static")) + { + tO.DisplayName = "Sand Barrels Static 3"; + tO.Desc = "Three static sand barrels in a line. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadBarrel3Rigid")) + { + tO.DisplayName = "Sand Barrels Rigid 3"; + tO.Desc = "Three rigid sand barrels in a line. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadBarrel7Static")) + { + tO.DisplayName = "Sand Barrels Static 7"; + tO.Desc = "Seven static sand barrels in standard formation. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadBarrel7Rigid")) + { + tO.DisplayName = "Sand Barrel Rigid 7"; + tO.Desc = "Seven rigid sand barrels in standard formation. Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDRoadConBarrelStatic")) + { + tO.DisplayName = "Con Barrels Static"; + tO.Desc = "Static road construction barrels."; + tO.sortID = 3; + } + else if (tO.DisplayName.Contains("GSDRoadConBarrelRigid")) + { + tO.DisplayName = "Con Barrels Rigid"; + tO.Desc = "Rigid road construction barrels."; + tO.sortID = 3; + } + else if (tO.DisplayName.Contains("GSDTrafficConeStatic")) + { + tO.DisplayName = "Traffic cones Static"; + tO.Desc = "Static traffic cones."; + tO.sortID = 4; + } + else if (tO.DisplayName.Contains("GSDTrafficConeRigid")) + { + tO.DisplayName = "Traffic cones Rigid"; + tO.Desc = "Rigid traffic cones."; + tO.sortID = 4; + } + else if (tO.DisplayName.Contains("GSDRoadReflector")) + { + tO.DisplayName = "Road reflectors"; + tO.Desc = "Placed one center line of road for center line reflection."; + tO.sortID = 4; + } + else if (tO.DisplayName.Contains("GSDStopSign")) + { + tO.DisplayName = "Stop sign"; + tO.Desc = "Standard specification non-interstate stop sign."; + } + else if (tO.DisplayName.Contains("GSDStreetLightSingle")) + { + tO.DisplayName = "Streetlight Singlesided"; + tO.Desc = "Best used on side of roads."; + } + else if (tO.DisplayName.Contains("GSDStreetLightDouble")) + { + tO.DisplayName = "Streetlight Doublesided"; + tO.Desc = "Best results when embedded in KRail in centerline of road."; + } + else if (tO.DisplayName.Contains("GSDWarningSign1")) + { + tO.DisplayName = "Warning Sign #1"; + tO.Desc = "Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDWarningSign2")) + { + tO.DisplayName = "Warning Sign #2"; + tO.Desc = "Best results when placed in front of railings or bridges."; + } + else if (tO.DisplayName.Contains("GSDSignRightTurnOnly")) + { + tO.DisplayName = "Right turn only"; + tO.Desc = "Best results when placed near intersection right turn lane."; + tO.sortID = 4; + } + + else if (tO.DisplayName.Contains("GSDSign330")) + { + tO.DisplayName = "Signs 330"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-330\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign396")) + { + tO.DisplayName = "Signs 396"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-396\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign617-Small")) + { + tO.DisplayName = "Signs 617 small"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-617\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign617")) + { + tO.DisplayName = "Signs 617"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-617\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign861-Small")) + { + tO.DisplayName = "Signs 861 small"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-861\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign861")) + { + tO.DisplayName = "Sign type 861"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-861\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign988-Small")) + { + tO.DisplayName = "Signs 988 small"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-988\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSign988")) + { + tO.DisplayName = "Signs 988"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-988\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSignDiamond")) + { + tO.DisplayName = "Signs diamond"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-diamond\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSignSquare-Small")) + { + tO.DisplayName = "Signs square small"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-Square\" as the search term."; + tO.sortID = 21; + } + else if (tO.DisplayName.Contains("GSDSignSquare")) + { + tO.DisplayName = "Signs square"; + tO.Desc = "Interchangeable materials, use \"GSDFedSign-Square\" as the search term."; + tO.sortID = 21; + } + } + + if (bIsDefault && tWindowType == WindowTypeEnum.Extrusion) + { + if (tO.DisplayName.Contains("GSDKRail")) + { + tO.DisplayName = "KRail"; + tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with down ends."; + } + else if (tO.DisplayName.Contains("GSDKRailCurvedR")) + { + tO.DisplayName = "KRail Curved Right"; + tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with curved ends for right shoulder."; + } + else if (tO.DisplayName.Contains("GSDKRailCurvedL")) + { + tO.DisplayName = "KRail Curved Left"; + tO.Desc = "Federal spec cement KRailing (also known as Jersey Barriers). Variant with curved ends for left shoulder."; + } + else if (tO.DisplayName.Contains("GSDWBeam1R")) + { + tO.DisplayName = "WBeam Wood Right"; + tO.Desc = "Federal spec wooden pole WBeam railing. Best used as outer shoulder railing. Right shoulder."; + } + else if (tO.DisplayName.Contains("GSDWBeam1L")) + { + tO.DisplayName = "WBeam Wood Left"; + tO.Desc = "Federal spec wooden pole WBeam railing. Best used as outer shoulder railing. Left shoulder."; + } + else if (tO.DisplayName.Contains("GSDWBeam2R")) + { + tO.DisplayName = "WBeam Metal Right"; + tO.Desc = "Federal spec metal pole WBeam railing. Best used as outer shoulder railing. Right shoulder."; + } + else if (tO.DisplayName.Contains("GSDWBeam2L")) + { + tO.DisplayName = "WBeam Metal Left"; + tO.Desc = "Federal spec metal pole WBeam railing. Best used as outer shoulder railing. Left shoulder."; + } + else if (tO.DisplayName.Contains("GSDRailing1")) + { + tO.DisplayName = "Railing #1"; + tO.Desc = "Standard double square pole railing."; + } + else if (tO.DisplayName.Contains("GSDRailing2")) + { + tO.DisplayName = "Railing #2"; + tO.Desc = "Standard concrete big block railing."; + } + else if (tO.DisplayName.Contains("GSDRailing3")) + { + tO.DisplayName = "Railing #3"; + tO.Desc = "Standard four-strand metal railing."; + } + else if (tO.DisplayName.Contains("GSDRailing5")) + { + tO.DisplayName = "Railing #5"; + tO.Desc = "Basic concrete railing with pylons."; + } + else if (tO.DisplayName.Contains("GSDRailing6")) + { + tO.DisplayName = "Railing #6"; + tO.Desc = "Standard two-strand metal pole railing."; + } + else if (tO.DisplayName.Contains("GSDRailing7")) + { + tO.DisplayName = "Railing #7"; + tO.Desc = "Rock-decorated concrete railing with pylons and double strand rusted look metal railing."; + } + else if (tO.DisplayName.Contains("GSDRailing8")) + { + tO.DisplayName = "Railing #8"; + tO.Desc = "Rock-decorated concrete railing with standard single pole metal railing."; + } + else if (tO.DisplayName.Contains("GSDRailing9")) + { + tO.DisplayName = "Railing #9"; + tO.Desc = "Very low poly railing used for mobile."; + } + else if (tO.DisplayName.Contains("GSDSidewalk")) + { + tO.DisplayName = "Sidewalk"; + tO.Desc = "Sidewalk."; + } + else if (tO.DisplayName.Contains("GSDRumbleStrip")) + { + tO.DisplayName = "Rumblestrip"; + tO.Desc = "State spec rumblestrip. For best results place several cm from road edge into shoulder."; + } + else if (tO.DisplayName.Contains("GSDRailing4R")) + { + tO.DisplayName = "Railing #4 Right"; + tO.Desc = "Three bar angled pole railing. Right side of road."; + } + else if (tO.DisplayName.Contains("GSDRailing4L")) + { + tO.DisplayName = "Railing #4 Left"; + tO.Desc = "Three bar angled pole railing. Left side of road."; + } + else if (tO.DisplayName.Contains("GSDRailing4-LightR")) + { + tO.DisplayName = "Railing #4 Light Right"; + tO.Desc = "Three bar angled pole railing. Right side of road. Light version with fewer triangle count."; + } + else if (tO.DisplayName.Contains("GSDRailing4-LightL")) + { + tO.DisplayName = "Railing #4 Light Left"; + tO.Desc = "Three bar angled pole railing. Left side of road. Light version with fewer triangle count."; + } + else if (tO.DisplayName.Contains("GSDRailingBase1")) + { + tO.DisplayName = "Railing base #1"; + tO.Desc = "Use as a base on other railings to create more detail."; + } + else if (tO.DisplayName.Contains("GSDRailingBase2")) + { + tO.DisplayName = "Railing base #2"; + tO.Desc = "Use as a base on other railings to create more detail."; + } + else if (tO.DisplayName.Contains("GSDCableBarrier-Light")) + { + tO.DisplayName = "Cable barrier 10m"; + tO.Desc = "Cable barrier 10m light triangle version. Best used as center divider or as railing barriers."; + tO.sortID = 20; + } + else if (tO.DisplayName.Contains("GSDCableBarrier")) + { + tO.DisplayName = "Cable barrier 5m"; + tO.Desc = "Cable barrier 5m. Best used as center divider or as railing barriers."; + tO.sortID = 20; + } + } + + oList.Add(tO); + } + oListSort(); + } + + + void oListSort() + { + oList.Sort((GSDRoadUtil.WizardObject t1, GSDRoadUtil.WizardObject t2) => + { + if (t1.bIsDefault != t2.bIsDefault) + { + return t1.bIsDefault.CompareTo(t2.bIsDefault); + } + else if (t1.sortID != t2.sortID) + { + return t1.sortID.CompareTo(t2.sortID); + } + else + { + return t1.DisplayName.CompareTo(t2.DisplayName); + } + }); + } + #endregion + #endregion } \ No newline at end of file diff --git a/Editor/Library.meta b/Editor/Library.meta index c1c7c731..ed243992 100755 --- a/Editor/Library.meta +++ b/Editor/Library.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 0c2a5b8a5881fbf4891420e63e1769ad -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 58e33fe3598ca124a80db310156eda99 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/GSDOffRoadObject.cs b/GSDOffRoadObject.cs index 76815fdf..5a43713b 100644 --- a/GSDOffRoadObject.cs +++ b/GSDOffRoadObject.cs @@ -1,20 +1,17 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class GSDOffRoadObject : MonoBehaviour -{ - public static readonly Color Color_NodeOffRoadColor = new Color(1f, 0f, 0.5f, 0.75f); - public static readonly Color Color_NodeOffRoadSelectedColor = new Color(1f, 0f, 0.8f, 1f); - // Start is called before the first frame update - void Start() - { - - } - - // Update is called once per frame - void Update() - { - - } -} +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + + +public class GSDOffRoadObject : MonoBehaviour +{ + public static readonly Color Color_NodeOffRoadColor = new Color(1f, 0f, 0.5f, 0.75f); + public static readonly Color Color_NodeOffRoadSelectedColor = new Color(1f, 0f, 0.8f, 1f); + + + // Update is called once per frame + void Update() + { + + } +} \ No newline at end of file diff --git a/GSDRigidBody.cs b/GSDRigidBody.cs index 4766f02e..da54bbbd 100755 --- a/GSDRigidBody.cs +++ b/GSDRigidBody.cs @@ -1,53 +1,77 @@ -using UnityEngine; - -public class GSDRigidBody : MonoBehaviour -{ - public float MinCollVelocity = 2f; - // bool bIsForcedSleeping = false; - Rigidbody RB; - // bool bIgnoreRB = false; - - void Awake() - { - RB = transform.GetComponent(); - if (RB != null) - { - DestroyImmediate(RB); - } - } - - // void OnCollisionEnter(Collision collision) { - // if(bIgnoreRB || !bIsForcedSleeping){ return; } - // Debug.Log (collision.relativeVelocity.magnitude); - // if(RB != null){ - // if(collision.relativeVelocity.magnitude <= MinCollVelocity){ - // RB.Sleep(); - // }else{ - // //RB.isKinematic = false; - // bIsForcedSleeping = false; - // //RB.AddForce(collision.relativeVelocity*collision.relativeVelocity.magnitude*(RB.mass*0.3f)); - // } - // } - // } - // - // void OnCollisionExit(Collision collisionInfo) { - // if(bIgnoreRB || !bIsForcedSleeping){ return; } - // if(bIsForcedSleeping && RB != null){ - // RB.Sleep(); - // } - // } - // - // float TimerMax = 0.1f; - // float TimerNow = 0f; - // void Update(){ - // if(bIsForcedSleeping){ - // TimerNow += Time.deltaTime; - // if(TimerNow > TimerMax){ - // if(RB != null && !RB.IsSleeping()){ - // RB.Sleep(); - // } - // TimerNow = 0f; - // } - // } - // } +using UnityEngine; + + +public class GSDRigidBody : MonoBehaviour +{ + public float MinCollVelocity = 2f; + // bool bIsForcedSleeping = false; + Rigidbody rigidBody; // Formerly RB // FH 29.01.19 + // bool bIgnoreRB = false; + + + void Awake() + { + rigidBody = transform.GetComponent(); + if (rigidBody != null) + { + DestroyImmediate(rigidBody); + } + } + + + /* + void OnCollisionEnter(Collision collision) + { + if ( bIgnoreRB || !bIsForcedSleeping ) + { + return; + } + Debug.Log( collision.relativeVelocity.magnitude ); + if ( rigidbody != null ) + { + if ( collision.relativeVelocity.magnitude <= MinCollVelocity ) + { + rigidbody.Sleep(); + } + else + { + //RB.isKinematic = false; + bIsForcedSleeping = false; + //RB.AddForce(collision.relativeVelocity*collision.relativeVelocity.magnitude*(RB.mass*0.3f)); + } + } + } + + + void OnCollisionExit(Collision collisionInfo) + { + if ( bIgnoreRB || !bIsForcedSleeping ) + { return; } + if ( bIsForcedSleeping && rigidbody != null ) + { + rigidbody.Sleep(); + } + } + + + float TimerMax = 0.1f; + float TimerNow = 0f; + + + void Update() + { + if ( bIsForcedSleeping ) + { + TimerNow += Time.deltaTime; + if ( TimerNow > TimerMax ) + { + if ( rigidbody != null && !rigidbody.IsSleeping() ) + { + rigidbody.Sleep(); + } + TimerNow = 0f; + } + } + } + */ } \ No newline at end of file diff --git a/GSDRoad.cs b/GSDRoad.cs index dad832fc..446884a4 100755 --- a/GSDRoad.cs +++ b/GSDRoad.cs @@ -1,1808 +1,1938 @@ -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using GSD.Roads; -using GSD; -#if UNITY_EDITOR -using UnityEditor; -#endif -[ExecuteInEditMode] -public class GSDRoad : MonoBehaviour -{ - - - public GameObject MainMeshes; - public GameObject MeshRoad; - public GameObject MeshShoR; - public GameObject MeshShoL; - public GameObject MeshiLanes; - public GameObject MeshiLanes0; - public GameObject MeshiLanes1; - public GameObject MeshiLanes2; - public GameObject MeshiLanes3; - public GameObject MeshiMainPlates; - public GameObject MeshiMarkerPlates; - [System.NonSerialized] - public string EditorTitleString = ""; - - public GSDSplineC GSDSpline; - - public int MostRecentNodeCount = -1; - // private bool bMostRecentCheck = false; - public GameObject GSDSplineObj; - public GSDRoadSystem GSDRS; - public GSDSplineC[] PiggyBacks = null; - public bool bEditorProgressBar = false; - public string UID; //Unique ID -#if UNITY_EDITOR - [SerializeField] - public List TerrainHistory; - public string TerrainHistoryByteSize = ""; -#endif - [System.NonSerialized] - public bool bUpdateSpline = false; - - //Road editor options: - public float opt_LaneWidth = 5f; //Done. - public bool opt_bShouldersEnabled = true; //Disabled for now. Comprimises integrity of roads. - public float opt_ShoulderWidth = 3f; //Done. - public int opt_Lanes = 2; //Done. - public float opt_RoadDefinition = 5f; //Done. - public bool opt_RoadCornerDefinition = false; //Disable for now. No point. - public bool opt_bRoadCuts = true; - public bool opt_bShoulderCuts = true; - public bool opt_bDynamicCuts = false; - public bool opt_bMaxGradeEnabled = true; - public float opt_MaxGrade = 0.08f; - public bool opt_UseDefaultMaterials = true; - public bool opt_AutoUpdateInEditor = true; - - public float opt_TerrainSubtract_Match = 0.1f; - public bool opt_bGSDRoadRaise = false; - - public float opt_MatchHeightsDistance = 50f; - public float opt_ClearDetailsDistance = 30f; - public float opt_ClearDetailsDistanceHeight = 5f; - public float opt_ClearTreesDistance = 30f; - public float opt_ClearTreesDistanceHeight = 50f; - - public bool opt_HeightModEnabled = true; - public bool opt_DetailModEnabled = true; - public bool opt_TreeModEnabled = true; - - public bool opt_SaveTerrainHistoryOnDisk = true; - public float opt_MagnitudeThreshold = 300f; - public bool opt_GizmosEnabled = true; - public bool opt_bMultithreading = true; - public bool opt_bSaveMeshes = false; - public bool opt_bUseMeshColliders = true; - public bool opt_bIsStatic = false; - public bool opt_bIsLightmapped = false; - - public enum RoadMaterialDropdownEnum - { - Asphalt, - Dirt, - Brick, - Cobblestone - }; - public RoadMaterialDropdownEnum opt_tRoadMaterialDropdown = RoadMaterialDropdownEnum.Asphalt; - public RoadMaterialDropdownEnum tRoadMaterialDropdownOLD = RoadMaterialDropdownEnum.Asphalt; - - - public Material RoadMaterial1; - public Material RoadMaterial2; - public Material RoadMaterial3; - public Material RoadMaterial4; - public Material RoadMaterialMarker1; - public Material RoadMaterialMarker2; - public Material RoadMaterialMarker3; - public Material RoadMaterialMarker4; - public Material ShoulderMaterial1; - public Material ShoulderMaterial2; - public Material ShoulderMaterial3; - public Material ShoulderMaterial4; - public Material ShoulderMaterialMarker1; - public Material ShoulderMaterialMarker2; - public Material ShoulderMaterialMarker3; - public Material ShoulderMaterialMarker4; - - public PhysicMaterial RoadPhysicMaterial; - public PhysicMaterial ShoulderPhysicMaterial; -#if UNITY_EDITOR - #region "Road Construction" - [System.NonSerialized] - public GSD.Threaded.TerrainCalcs TerrainCalcsJob; - [System.NonSerialized] - public GSD.Threaded.RoadCalcs1 RoadCalcsJob1; - [System.NonSerialized] - public GSD.Threaded.RoadCalcs2 RoadCalcsJob2; - [System.NonSerialized] - public RoadConstructorBufferMaker RCS; - - public string tName = ""; - public bool bProfiling = false; - public bool bSkipStore = true; - [System.NonSerialized] - public float EditorConstructionStartTime = 0f; - - void CleanRunTime() - { - //Make sure unused items are not using memory space in runtime: - TerrainHistory = null; - RCS = null; - } - - public bool bEditorError = false; - public System.Exception tError = null; - void OnEnable() - { - if (!Application.isEditor) { return; } - // if(Application.isEditor && !UnityEditor.EditorApplication.isPlaying){ - Editor_bIsConstructing = false; - UnityEditor.EditorApplication.update += delegate { EditorUpdate(); }; -#if UNITY_2018_1_OR_NEWER - UnityEditor.EditorApplication.hierarchyChanged += delegate { hWindowChanged(); }; -#else - UnityEditor.EditorApplication.hierarchyWindowChanged += delegate { hWindowChanged(); }; -#endif - // } - if (GSDSpline == null || GSDSpline.mNodes == null) - { - MostRecentNodeCount = 0; - } - else - { - MostRecentNodeCount = GSDSpline.GetNodeCount(); - } - tRoadMaterialDropdownOLD = opt_tRoadMaterialDropdown; - CheckMats(); - } - - public void Awake() - { - if (GSDSpline == null || GSDSpline.mNodes == null) - { - MostRecentNodeCount = 0; - } - else - { - MostRecentNodeCount = GSDSpline.GetNodeCount(); - } - } - - int EditorTimer = 0; - int EditorTimerMax = 0; - int EditorTimerSpline = 0; - const int EditorTimerSplineMax = 2; - [System.NonSerialized] - public int EditorProgress = 0; - const int GizmoNodeTimerMax = 2; - public bool EditorUpdateMe = false; - public bool bTriggerGC = false; - bool bTriggerGC_Happening; - float TriggerGC_End = 0f; - private void EditorUpdate() - { - if (!Application.isEditor) - { - UnityEditor.EditorApplication.update -= delegate { EditorUpdate(); }; - } - - if (this == null) - { - UnityEditor.EditorApplication.update -= delegate { EditorUpdate(); }; - Editor_bIsConstructing = false; - EditorUtility.ClearProgressBar(); - return; - } - - //Custom garbage collection demands for editor: - if (bTriggerGC) - { - bTriggerGC = false; - TriggerGC_End = Time.realtimeSinceStartup + 1f; - bTriggerGC_Happening = true; - } - if (bTriggerGC_Happening) - { - if (Time.realtimeSinceStartup > TriggerGC_End) - { - bTriggerGC_Happening = false; - GSDRootUtil.ForceCollection(); - TriggerGC_End = 200000f; - } - } - - if (Editor_bIsConstructing) - { // && !Application.isPlaying && !UnityEditor.EditorApplication.isPlaying){ - if (GSDRS != null) - { - if (GSDRS.opt_bMultithreading) - { - EditorTimer += 1; - if (EditorTimer > EditorTimerMax) - { - if ((Time.realtimeSinceStartup - EditorConstructionStartTime) > 180f) - { - Editor_bIsConstructing = false; - EditorUtility.ClearProgressBar(); - Debug.Log("Update shouldn't take longer than 180 seconds. Aborting update."); - } - - EditorTimer = 0; - if (bEditorError) - { - Editor_bIsConstructing = false; - EditorUtility.ClearProgressBar(); - bEditorError = false; - if (tError != null) - { - Debug.LogError(tError.StackTrace); - throw tError; - } - } - - if (TerrainCalcsJob != null && TerrainCalcsJob.Update()) - { - ConstructRoad2(); - } - else if (RoadCalcsJob1 != null && RoadCalcsJob1.Update()) - { - ConstructRoad3(); - } - else if (RoadCalcsJob2 != null && RoadCalcsJob2.Update()) - { - ConstructRoad4(); - } - } - } - } - } - else - { - if (EditorUpdateMe && !Editor_bIsConstructing) - { - EditorUpdateMe = false; - GSDSpline.Setup_Trigger(); - } - } - - if (Editor_bIsConstructing) - { - RoadUpdateProgressBar(); - } - else if (bEditorProgressBar) - { - RoadUpdateProgressBar(); - } - - if (!Application.isPlaying && bUpdateSpline && !UnityEditor.EditorApplication.isPlaying) - { - EditorTimerSpline += 1; - if (EditorTimerSpline > EditorTimerSplineMax) - { - EditorTimerSpline = 0; - bUpdateSpline = false; - GSDSpline.Setup_Trigger(); - MostRecentNodeCount = GSDSpline.mNodes.Count; - } - } - - if (bEditorCameraMoving && EditorCameraNextMove < EditorApplication.timeSinceStartup) - { - EditorCameraNextMove = (float)EditorApplication.timeSinceStartup + EditorCameraTimeUpdateInterval; - DoEditorCameraLoop(); - } - } - - [System.NonSerialized] - public bool bEditorCameraMoving = false; - [System.NonSerialized] - public float EditorCameraPos = 0f; - // float EditorCameraPos_Full = 0f; - const float EditorCameraTimeUpdateInterval = 0.015f; - float EditorCameraNextMove = 0f; - bool bEditorCameraSetup = false; - float EditorCameraStartPos = 0f; - float EditorCameraEndPos = 1f; - float EditorCameraIncrementDistance = 0f; - float EditorCameraIncrementDistance_Full = 0f; - public float EditorCameraMetersPerSecond = 60f; - public bool bEditorCameraRotate = false; - Vector3 EditorCameraV1 = default(Vector3); - Vector3 EditorCameraV2 = default(Vector3); - [System.NonSerialized] - public Vector3 EditorCameraOffset = new Vector3(0f, 5f, 0f); - [System.NonSerialized] - public Camera EditorPlayCamera = null; - Vector3 EditorCameraBadVec = default(Vector3); - - public void DoEditorCameraLoop() - { - if (!bEditorCameraSetup) - { - bEditorCameraSetup = true; - if (GSDSpline.bSpecialEndControlNode) - { //If control node, start after the control node: - EditorCameraEndPos = GSDSpline.mNodes[GSDSpline.GetNodeCount() - 2].tTime; - } - if (GSDSpline.bSpecialStartControlNode) - { //If ends in control node, end construction before the control node: - EditorCameraStartPos = GSDSpline.mNodes[1].tTime; - } - // EditorCameraPos_Full = 0f; - ChangeEditorCameraMetersPerSec(); - } - - if (!Selection.Contains(this.transform.gameObject)) - { - QuitEditorCamera(); - return; - } - - // EditorCameraPos_Full+=EditorCameraIncrementDistance_Full; - // if(EditorCameraPos_Full > GSDSpline.distance){ EditorCameraPos = EditorCameraStartPos; bEditorCameraMoving = false; bEditorCameraSetup = false; EditorCameraPos_Full = 0f; return; } - // EditorCameraPos = GSDSpline.TranslateDistBasedToParam(EditorCameraPos_Full); - - EditorCameraPos += EditorCameraIncrementDistance; - if (EditorCameraPos > EditorCameraEndPos) - { - QuitEditorCamera(); - return; - } - if (EditorCameraPos < EditorCameraStartPos) - { - EditorCameraPos = EditorCameraStartPos; - } - - GSDSpline.GetSplineValue_Both(EditorCameraPos, out EditorCameraV1, out EditorCameraV2); - - if (EditorApplication.isPlaying) - { - if (EditorPlayCamera != null) - { - EditorPlayCamera.transform.position = EditorCameraV1; - if (bEditorCameraRotate) - { - EditorPlayCamera.transform.position += EditorCameraOffset; - if (EditorCameraV2 != EditorCameraBadVec) - { - EditorPlayCamera.transform.rotation = Quaternion.LookRotation(EditorCameraV2); - } - } - } - } - else - { - SceneView.lastActiveSceneView.pivot = EditorCameraV1; - if (bEditorCameraRotate) - { - SceneView.lastActiveSceneView.pivot += EditorCameraOffset; - if (EditorCameraV2 != EditorCameraBadVec) - { - SceneView.lastActiveSceneView.rotation = Quaternion.LookRotation(EditorCameraV2); - } - } - SceneView.lastActiveSceneView.Repaint(); - } - } - public void EditorCameraSetSingle() - { - if (EditorPlayCamera == null) - { - Camera[] EditorCams = (Camera[])GameObject.FindObjectsOfType(typeof(Camera)); - if (EditorCams != null && EditorCams.Length == 1) - { - EditorPlayCamera = EditorCams[0]; - } - } - } - public void QuitEditorCamera() - { - EditorCameraPos = EditorCameraStartPos; - bEditorCameraMoving = false; - bEditorCameraSetup = false; - // EditorCameraPos_Full = 0f; - } - public void ChangeEditorCameraMetersPerSec() - { - EditorCameraIncrementDistance_Full = (EditorCameraMetersPerSecond / 60); - EditorCameraIncrementDistance = (EditorCameraIncrementDistance_Full / GSDSpline.distance); - } - - private void hWindowChanged() - { - if (!Application.isEditor) - { -#if UNITY_2018_1_OR_NEWER - UnityEditor.EditorApplication.hierarchyChanged -= delegate { hWindowChanged(); }; -#else - UnityEditor.EditorApplication.hierarchyWindowChanged -= delegate { hWindowChanged(); }; -#endif - } - if (Application.isPlaying || !Application.isEditor) { return; } - if (Application.isEditor && UnityEditor.EditorApplication.isPlaying) { return; } - if (Application.isEditor && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) { return; } - - int tCount = 0; - if (GSDSpline != null && GSDSpline.mNodes != null) - { - tCount = GSDSpline.GetNodeCountNonNull(); - } - if (tCount != MostRecentNodeCount) - { - bUpdateSpline = true; - } - } - - void RoadUpdateProgressBar() - { - if (Editor_bIsConstructing) - { - EditorUtility.DisplayProgressBar( - "GSD Road Update", - EditorTitleString, - ((float)EditorProgress / 100f)); - } - else if (bEditorProgressBar) - { - bEditorProgressBar = false; - EditorUtility.ClearProgressBar(); - } - } - - public void UpdateRoad(RoadUpdateTypeEnum tUpdateType = RoadUpdateTypeEnum.Full) - { - if (!GSDRS.opt_bAllowRoadUpdates) - { - GSDSpline.Setup(); - Editor_bIsConstructing = false; - return; - } - - if (Editor_bIsConstructing) - { - return; - } - - SetupUniqueIdentifier(); - - - - if (bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("UpdateRoadPrelim"); } - opt_RoadDefinition = Mathf.Clamp(opt_RoadDefinition, 1f, 50f); - opt_LaneWidth = Mathf.Clamp(opt_LaneWidth, 0.2f, 500f); - EditorConstructionStartTime = Time.realtimeSinceStartup; - EditorTitleString = "Updating " + transform.name + "..."; - System.GC.Collect(); - - if (opt_SaveTerrainHistoryOnDisk) - { - ConstructRoad_LoadTerrainHistory(); - } - - CheckMats(); - - EditorUtility.ClearProgressBar(); - - bProfiling = true; - if (GSDRS.opt_bMultithreading) { bProfiling = false; } - - //Set all terrains to height 0: - GSD.Roads.GSDTerraforming.CheckAllTerrainsHeight0(); - - EditorProgress = 20; - bEditorProgressBar = true; - if (Editor_bIsConstructing) - { - if (TerrainCalcsJob != null) { TerrainCalcsJob.Abort(); TerrainCalcsJob = null; } - if (RoadCalcsJob1 != null) { RoadCalcsJob1.Abort(); RoadCalcsJob1 = null; } - if (RoadCalcsJob2 != null) { RoadCalcsJob2.Abort(); RoadCalcsJob2 = null; } - Editor_bIsConstructing = false; - } - - // if(Application.isPlaying || !Application.isEditor){ return; } - // if(Application.isEditor && UnityEditor.EditorApplication.isPlaying){ return; } - // if(Application.isEditor && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode){ return; } - - //In here for intersection patching purposes: - int mCount = GSDSpline.GetNodeCount(); - GSDSplineN tNode = null; - GSDSplineN tNode1 = null; - GSDSplineN tNode2 = null; - if (GSDSpline.CheckInvalidNodeCount()) - { - GSDSpline.Setup(); - mCount = GSDSpline.GetNodeCount(); - } - if (mCount > 1) - { - for (int i = 0; i < mCount; i++) - { - // try{ - tNode = GSDSpline.mNodes[i]; - // }catch{ - // Editor_bIsConstructing = false; - // EditorUpdateMe = true; - // return; - // } - - //If node is intersection with an invalid GSDRI, mark it at non-intersection. Just-in-case. - if (tNode.bIsIntersection && tNode.GSDRI == null) - { - tNode.bIsIntersection = false; - tNode.id_intersection_othernode = -1; - tNode.Intersection_OtherNode = null; - } - //If node is intersection, re-setup: - if (tNode.bIsIntersection && tNode.GSDRI != null) - { - tNode1 = tNode.GSDRI.Node1; - tNode2 = tNode.GSDRI.Node2; - tNode.GSDRI.Setup(tNode1, tNode2); - tNode.GSDRI.DeleteRelevantChildren(tNode, tNode.GSDSpline.tRoad.transform.name); - //If primary node on intersection, do more re-setup: - if (tNode.GSDRI.Node1 == tNode) - { - tNode.GSDRI.Lanes = opt_Lanes; - tNode.GSDRI.name = tNode.GSDRI.transform.name; - } - //Setup construction objects: - tNode.GSDRI.Node1.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); - tNode.GSDRI.Node2.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); - } - - //Store materials and physical materials for road and or shoulder cuts on each node, if necessary: - tNode.StoreCuts(); - } - } - name = transform.name; - - - - GSDSpline.RoadWidth = RoadWidth(); - // if(bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("SplineSetup"); } - GSDSpline.Setup(); - // if(bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } - mCount = GSDSpline.GetNodeCount(); - - if (GSDSpline == null || GSDSpline.mNodes == null) - { - MostRecentNodeCount = 0; - } - else - { - MostRecentNodeCount = GSDSpline.GetNodeCount(); - } - - if (opt_UseDefaultMaterials) - { - SetDefaultMats(); - } - - if (opt_UseDefaultMaterials) - { - if (DetectInvalidDefaultMatsForUndo()) - { - SetAllCutsToCurrentMaterials(); - } - } - - //Hiding in hierarchy: - for (int i = 0; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode != null) - { - if (tNode.bIsIntersection || tNode.bSpecialEndNode) - { - tNode.ToggleHideFlags(true); - } - else - { - tNode.ToggleHideFlags(false); - } - } - } - - int cCount = transform.childCount; - GameObject tMainMeshes = null; - List tObjs = new List(); - for (int i = 0; i < cCount; i++) - { - if (transform.GetChild(i).transform.name.ToLower().Contains("mainmeshes")) - { - tMainMeshes = transform.GetChild(i).transform.gameObject; - tObjs.Add(tMainMeshes); - } - } - for (int i = (tObjs.Count - 1); i >= 0; i--) - { - tMainMeshes = tObjs[i]; - Object.DestroyImmediate(tMainMeshes); - } - - if (mCount < 2) - { - //Delete old objs and return: - if (MainMeshes != null) { Object.DestroyImmediate(MainMeshes); } - if (MeshRoad != null) { Object.DestroyImmediate(MeshRoad); } - if (MeshShoR != null) { Object.DestroyImmediate(MeshShoR); } - if (MeshShoL != null) { Object.DestroyImmediate(MeshShoL); } - if (MeshiLanes != null) { Object.DestroyImmediate(MeshiLanes); } - if (MeshiLanes0 != null) { Object.DestroyImmediate(MeshiLanes0); } - if (MeshiLanes1 != null) { Object.DestroyImmediate(MeshiLanes1); } - if (MeshiLanes2 != null) { Object.DestroyImmediate(MeshiLanes2); } - if (MeshiLanes3 != null) { Object.DestroyImmediate(MeshiLanes3); } - if (MeshiMainPlates != null) { Object.DestroyImmediate(MeshiMainPlates); } - if (MeshiMarkerPlates != null) { Object.DestroyImmediate(MeshiMarkerPlates); } - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - return; - } - - GSDSpline.HeightHistory = new List>(); - if (GSDRS == null) { GSDRS = transform.parent.GetComponent(); } //Compatibility update. - - if (GSDRS.opt_bMultithreading) - { - Editor_bIsConstructing = true; - } - else - { - Editor_bIsConstructing = false; - } - Editor_bConstructionID = 0; - - - - //Check if road takes place on only 1 terrain: - Terrain tTerrain = GSD.Roads.GSDRoadUtil.GetTerrain(GSDSpline.mNodes[0].pos); - bool bSameTerrain = true; - for (int i = 1; i < mCount; i++) - { - if (tTerrain != GSD.Roads.GSDRoadUtil.GetTerrain(GSDSpline.mNodes[0].pos)) - { - bSameTerrain = false; - break; - } - } - - RCS = new RoadConstructorBufferMaker(this, tUpdateType); - - if (bSameTerrain) - { - RCS.tTerrain = tTerrain; - } - else - { - RCS.tTerrain = null; - } - tTerrain = null; - - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - if (GSDRS.opt_bMultithreading) - { - if (RCS.bTerrainOn || TerrainHistory == null) - { - GSDTerraforming.ProcessRoad_Terrain_Hook1(GSDSpline, this); - } - else - { - ConstructRoad2(); - } - } - else - { - UpdateRoad_NoMultiThreading(); - } - } - - #region "Terrain history" - public void ConstructRoad_StoreTerrainHistory(bool bDiskOnly = false) - { - if (!bDiskOnly) - { - GSDRoad tRoad = this; - GSDRoadUtil.ConstructRoad_StoreTerrainHistory(ref tRoad); - } - - if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null && TerrainHistory.Count > 0) - { - if (bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("TerrainHistory_Save"); } - GSDGeneralEditor.TerrainHistory_Save(TerrainHistory, this); - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - TerrainHistory.Clear(); - TerrainHistory = null; - } - else - { - if (TerrainHistory != null && TerrainHistory.Count > 0) - { - int tSize = 0; - for (int i = 0; i < TerrainHistory.Count; i++) - { - tSize += TerrainHistory[i].GetSize(); - } - TerrainHistoryByteSize = (tSize * 0.001f).ToString("n0") + " kb"; - } - else - { - TerrainHistoryByteSize = "0 bytes"; - } - } - } - public void ConstructRoad_ResetTerrainHistory() - { - GSDRoad tRoad = this; - if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null) - { - GSDGeneralEditor.TerrainHistory_Delete(this); - } - else - { - GSDRoadUtil.ConstructRoad_ResetTerrainHistory(ref tRoad); - } - } - public void ConstructRoad_LoadTerrainHistory(bool bForce = false) - { - if (opt_SaveTerrainHistoryOnDisk || bForce) - { - if (TerrainHistory != null) - { - TerrainHistory.Clear(); - TerrainHistory = null; - } - TerrainHistory = GSDGeneralEditor.TerrainHistory_Load(this); - } - if (bForce) - { - GSDGeneralEditor.TerrainHistory_Delete(this); - } - } - #endregion - - #region "Construction process" - #region "No multithread" - private void UpdateRoad_NoMultiThreading() - { - if (opt_HeightModEnabled || opt_DetailModEnabled || opt_TreeModEnabled) - { - if (bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Terrain"); } - if (RCS.bTerrainOn || TerrainHistory == null) - { - GSDTerraforming.ProcessRoad_Terrain_Hook1(GSDSpline, this, false); - GSDTerraforming.ProcessRoad_Terrain_Hook2(GSDSpline, ref EditorTTDList); - ConstructRoad_StoreTerrainHistory();//Store history. - int EditorTTDListCount = EditorTTDList.Count; - for (int i = 0; i < EditorTTDListCount; i++) - { - EditorTTDList[i] = null; - } - EditorTTDList = null; - System.GC.Collect(); - } - if (bProfiling) - { - UnityEngine.Profiling.Profiler.EndSample(); - } - } - - EditorProgress = 50; - GSDRoad tRoad = this; - if (bProfiling) - { - UnityEngine.Profiling.Profiler.BeginSample("RoadCon_RoadPrelim"); - } - - EditorProgress = 80; - GSD.Threaded.GSDRoadCreationT.RoadJob_Prelim(ref tRoad); - if (bProfiling) - { - UnityEngine.Profiling.Profiler.EndSample(); - UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Road1"); - } - EditorProgress = 90; - GSD.Threaded.RoadCalcs1_static.RunMe(ref RCS); - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - if (bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("MeshSetup1"); } - EditorProgress = 92; - RCS.MeshSetup1(); - if (bProfiling) - { - UnityEngine.Profiling.Profiler.EndSample(); - UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Road2"); - } - EditorProgress = 94; - GSD.Threaded.RoadCalcs2_static.RunMe(ref RCS); - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - if (bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("MeshSetup2"); } - EditorProgress = 96; - RCS.MeshSetup2(); - if (bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - Construction_Cleanup(); - } - #endregion - - private void ConstructRoad2() - { - EditorProgress = 40; - if (RCS.bTerrainOn) - { - //Store history: - GSDTerraforming.ProcessRoad_Terrain_Hook2(GSDSpline, ref EditorTTDList); - ConstructRoad_StoreTerrainHistory(); - int EditorTTDListCount = EditorTTDList.Count; - for (int i = 0; i < EditorTTDListCount; i++) - { - EditorTTDList[i] = null; - } - EditorTTDList = null; - System.GC.Collect(); - } - EditorProgress = 60; - - if (TerrainCalcsJob != null) { TerrainCalcsJob.Abort(); TerrainCalcsJob = null; } - GSDRoad tRoad = this; - EditorProgress = 72; - RoadCalcsJob1 = new GSD.Threaded.RoadCalcs1(); - RoadCalcsJob1.Setup(ref RCS, ref tRoad); - RoadCalcsJob1.Start(); - } - - private void ConstructRoad3() - { - EditorProgress = 84; - RCS.MeshSetup1(); - EditorProgress = 96; - if (RoadCalcsJob1 != null) { RoadCalcsJob1.Abort(); RoadCalcsJob1 = null; } - RoadCalcsJob2 = new GSD.Threaded.RoadCalcs2(); - RoadCalcsJob2.Setup(ref RCS); - RoadCalcsJob2.Start(); - EditorProgress = 98; - } - - private void ConstructRoad4() - { - RCS.MeshSetup2(); - Construction_Cleanup(); - } - #endregion - - private void Construction_Cleanup() - { - FixZ(); - - if (TerrainCalcsJob != null) { TerrainCalcsJob.Abort(); TerrainCalcsJob = null; } - if (RoadCalcsJob1 != null) { RoadCalcsJob1.Abort(); RoadCalcsJob1 = null; } - if (RoadCalcsJob2 != null) { RoadCalcsJob2.Abort(); RoadCalcsJob2 = null; } - Editor_bIsConstructing = false; - int mCount = GSDSpline.GetNodeCount(); - GSDSplineN tNode; - for (int i = 0; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.bIsIntersection) - { - if (tNode.iConstruction != null) - { - tNode.iConstruction.Nullify(); - tNode.iConstruction = null; - } - } - tNode.SetupSplinationLimits(); - tNode.SetupEdgeObjects(false); - tNode.SetupSplinatedMeshes(false); - } - if (GSDSpline.HeightHistory != null) { GSDSpline.HeightHistory.Clear(); GSDSpline.HeightHistory = null; } - if (RCS != null) - { - RCS.Nullify(); - RCS = null; - } - - if (GSDRS.opt_bSaveMeshes) - { - UnityEditor.AssetDatabase.SaveAssets(); - } - bEditorProgressBar = false; - EditorUtility.ClearProgressBar(); - //Make sure terrain history out of memory if necessary (redudant but keep): - if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null) - { - TerrainHistory.Clear(); - TerrainHistory = null; - } - - //Collect: - bTriggerGC = true; - - if (tRoadMaterialDropdownOLD != opt_tRoadMaterialDropdown) - { - tRoadMaterialDropdownOLD = opt_tRoadMaterialDropdown; - SetAllCutsToCurrentMaterials(); - } - - if (PiggyBacks != null && PiggyBacks.Length > 0) - { - for (int i = 0; i < PiggyBacks.Length; i++) - { - if (PiggyBacks[i] == null) - { - PiggyBacks = null; - break; - } - } - - if (PiggyBacks != null) - { - GSDSplineC tPiggy = PiggyBacks[0]; - GSDSplineC[] NewPiggys = null; - - PiggyBacks[0] = null; - if (PiggyBacks.Length > 1) - { - NewPiggys = new GSDSplineC[PiggyBacks.Length - 1]; - for (int i = 1; i < PiggyBacks.Length; i++) - { - NewPiggys[i - 1] = PiggyBacks[i]; - } - } - - if (NewPiggys != null) - { - tPiggy.tRoad.PiggyBacks = NewPiggys; - } - NewPiggys = null; - tPiggy.Setup_Trigger(); - } - } - } - - public List EditorTTDList; - public void EditorTerrainCalcs(ref List tList) - { - EditorTTDList = tList; - } - #endregion - - #region "Gizmos" - public bool Editor_bIsConstructing = false; - public int Editor_bConstructionID = 0; - public bool Editor_bSelected = false; - public bool Editor_MouseTerrainHit = false; - public Vector3 Editor_MousePos = new Vector3(0f, 0f, 0f); - public readonly Color Color_NodeDefaultColor = new Color(0f, 1f, 1f, 0.75f); - public readonly Color Color_NodeConnColor = new Color(0f, 1f, 0f, 0.75f); - public readonly Color Color_NodeInter = new Color(0f, 1f, 0f, 0.75f); - - void OnDrawGizmosSelected() - { - if (Editor_MouseTerrainHit) - { - Gizmos.color = Color.red; - Gizmos.DrawCube(Editor_MousePos, new Vector3(10f, 4f, 10f)); - } - } - #endregion -#endif - public float RoadWidth() - { - return (opt_LaneWidth * (float)opt_Lanes); - } -#if UNITY_EDITOR - public float EditorCameraTimer = 0f; - float EditorTestTimer = 0f; - bool bEditorTestTimer = true; - void Update() - { - if (Application.isEditor && bEditorCameraMoving) - { - EditorCameraTimer += Time.deltaTime; - if (EditorCameraTimer > EditorCameraTimeUpdateInterval) - { - EditorCameraTimer = 0f; - DoEditorCameraLoop(); - } - } - - if (bEditorTestTimer) - { - if (transform.name == "Road1") - { - EditorTestTimer += Time.deltaTime; - if (EditorTestTimer > 2f) - { - // UpdateRoad(RoadUpdateTypeEnum.Full); - // akjsdfkajlgffdghfsdghsdf(); - bEditorTestTimer = false; - } - } - else - { - bEditorTestTimer = false; - } - } - } - - - - - static void akjsdfkajlgffdghfsdghsdf() - { - int LoopMax = 1000; - DoShort(LoopMax); - DoInt(LoopMax); - DoLong(LoopMax); - } - - - static void DoShort(int LoopMax) - { - ushort[] tSubject = new ushort[25000]; - // int tInt = 0; - for (int i = 0; i < LoopMax; i++) - { - for (int j = 0; j < 25000; j++) - { - tSubject[j] = (ushort)(j + 1); - // int xTemp = (int)tSubject[j]; - } - } - } - - static void DoInt(int LoopMax) - { - int[] tSubject = new int[25000]; - // int tInt = 0; - for (int i = 0; i < LoopMax; i++) - { - for (int j = 0; j < 25000; j++) - { - tSubject[j] = j + 1; - // int xTemp = tSubject[j]; - } - } - } - - static void DoLong(int LoopMax) - { - long[] tSubject = new long[25000]; - // int tInt = 0; - for (int i = 0; i < LoopMax; i++) - { - for (int j = 0; j < 25000; j++) - { - tSubject[j] = (long)(j + 1); - // int xTemp = (int)tSubject[j]; - } - } - } - - #region "Default materials retrieval" - public bool DetectInvalidDefaultMatsForUndo() - { - string tNameLower = ""; - int tCounter = 0; - if (!MeshRoad) { return false; } - - MeshRenderer[] MRs = MeshRoad.GetComponentsInChildren(); - Material tMat2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); - Material tMat4 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); - Material tMat6 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); - foreach (MeshRenderer MR in MRs) - { - tNameLower = MR.transform.name.ToLower(); - if (tNameLower.Contains("marker")) - { - if (opt_Lanes == 2) - { - if (MR.sharedMaterials[0] == tMat4) - { - tCounter += 1; - } - else if (MR.sharedMaterials[0] == tMat6) - { - tCounter += 1; - } - } - else if (opt_Lanes == 4) - { - if (MR.sharedMaterials[0] == tMat2) - { - tCounter += 1; - } - else if (MR.sharedMaterials[0] == tMat6) - { - tCounter += 1; - } - } - else if (opt_Lanes == 6) - { - if (MR.sharedMaterials[0] == tMat2) - { - tCounter += 1; - } - else if (MR.sharedMaterials[0] == tMat4) - { - tCounter += 1; - } - } - } - if (tCounter > 1) - { - return true; - } - } - return false; - } - - public void SetAllCutsToCurrentMaterials() - { - string tNameLower = ""; - if (!MeshRoad) { return; } - - MeshRenderer[] MRs = MeshRoad.GetComponentsInChildren(); - Material[] tMats_World = GetMaterials_RoadWorld(); - Material[] tMats_Marker = GetMaterials_RoadMarker(); - foreach (MeshRenderer MR in MRs) - { - tNameLower = MR.transform.name.ToLower(); - if (tNameLower.Contains("marker")) - { - if (tMats_Marker != null) - { - MR.sharedMaterials = tMats_Marker; - } - } - else if (tNameLower.Contains("cut")) - { - if (tMats_World != null) - { - MR.sharedMaterials = tMats_World; - } - } - } - - if (opt_bShouldersEnabled && MeshShoL != null) - { - MRs = MeshShoL.GetComponentsInChildren(); - tMats_World = GetMaterials_ShoulderWorld(); - tMats_Marker = GetMaterials_ShoulderMarker(); - foreach (MeshRenderer MR in MRs) - { - tNameLower = MR.transform.name.ToLower(); - if (tNameLower.Contains("marker")) - { - if (tMats_Marker != null) - { - MR.sharedMaterials = tMats_Marker; - } - } - else if (tNameLower.Contains("cut")) - { - if (tMats_World != null) - { - MR.sharedMaterials = tMats_World; - } - } - } - } - - if (opt_bShouldersEnabled && MeshShoR != null) - { - MRs = MeshShoR.GetComponentsInChildren(); - foreach (MeshRenderer MR in MRs) - { - tNameLower = MR.transform.name.ToLower(); - if (tNameLower.Contains("marker")) - { - if (tMats_Marker != null) - { - MR.sharedMaterials = tMats_Marker; - } - } - else if (tNameLower.Contains("cut")) - { - if (tMats_World != null) - { - MR.sharedMaterials = tMats_World; - } - } - } - } - } - - public Material[] GetMaterials_RoadWorld() - { - int mCounter = 0; - if (RoadMaterial1 != null) - { - mCounter += 1; - if (RoadMaterial2 != null) - { - mCounter += 1; - if (RoadMaterial3 != null) - { - mCounter += 1; - if (RoadMaterial4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (RoadMaterial1 != null) - { - tMats[0] = RoadMaterial1; - if (RoadMaterial2 != null) - { - tMats[1] = RoadMaterial2; - if (RoadMaterial3 != null) - { - tMats[2] = RoadMaterial3; - if (RoadMaterial4 != null) - { - tMats[3] = RoadMaterial4; - } - } - } - } - return tMats; - } - else - { - return null; - } - } - - public Material[] GetMaterials_RoadMarker() - { - int mCounter = 0; - if (RoadMaterialMarker1 != null) - { - mCounter += 1; - if (RoadMaterialMarker2 != null) - { - mCounter += 1; - if (RoadMaterialMarker3 != null) - { - mCounter += 1; - if (RoadMaterialMarker4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (RoadMaterialMarker1 != null) - { - tMats[0] = RoadMaterialMarker1; - if (RoadMaterialMarker2 != null) - { - tMats[1] = RoadMaterialMarker2; - if (RoadMaterialMarker3 != null) - { - tMats[2] = RoadMaterialMarker3; - if (RoadMaterialMarker4 != null) - { - tMats[3] = RoadMaterialMarker4; - } - } - } - } - return tMats; - } - else - { - return null; - } - } - - public Material[] GetMaterials_ShoulderWorld() - { - if (!opt_bShouldersEnabled) - { - return null; - } - - int mCounter = 0; - if (ShoulderMaterial1 != null) - { - mCounter += 1; - if (ShoulderMaterial2 != null) - { - mCounter += 1; - if (ShoulderMaterial3 != null) - { - mCounter += 1; - if (ShoulderMaterial4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (ShoulderMaterial1 != null) - { - tMats[0] = ShoulderMaterial1; - if (ShoulderMaterial2 != null) - { - tMats[1] = ShoulderMaterial2; - if (ShoulderMaterial3 != null) - { - tMats[2] = ShoulderMaterial3; - if (ShoulderMaterial4 != null) - { - tMats[3] = ShoulderMaterial4; - } - } - } - } - return tMats; - } - else - { - return null; - } - } - - public Material[] GetMaterials_ShoulderMarker() - { - if (!opt_bShouldersEnabled) - { - return null; - } - - int mCounter = 0; - if (ShoulderMaterialMarker1 != null) - { - mCounter += 1; - if (ShoulderMaterialMarker2 != null) - { - mCounter += 1; - if (ShoulderMaterialMarker3 != null) - { - mCounter += 1; - if (ShoulderMaterialMarker4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (ShoulderMaterialMarker1 != null) - { - tMats[0] = ShoulderMaterialMarker1; - if (ShoulderMaterialMarker2 != null) - { - tMats[1] = ShoulderMaterialMarker2; - if (ShoulderMaterialMarker3 != null) - { - tMats[2] = ShoulderMaterialMarker3; - if (ShoulderMaterialMarker4 != null) - { - tMats[3] = ShoulderMaterialMarker4; - } - } - } - } - return tMats; - } - else - { - return null; - } - } - #endregion - - #region "Materials" - void CheckMats() - { - if (!opt_UseDefaultMaterials) - { - return; - } - - if (!RoadMaterial1) - { - RoadMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); - RoadMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - } - if (!RoadMaterialMarker1) - { - if (opt_Lanes == 2) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); - } - else if (opt_Lanes == 4) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); - } - else if (opt_Lanes == 6) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); - } - else - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); - } - - if (opt_Lanes == 2) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); - } - else if (opt_Lanes == 4) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-4L.mat"); - } - else if (opt_Lanes == 6) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-6L.mat"); - } - else - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); - } - } - if (opt_bShouldersEnabled && !ShoulderMaterial1) - { - ShoulderMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDShoulder1.mat"); - ShoulderMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - } - - if (opt_bShouldersEnabled && !RoadPhysicMaterial) - { - RoadPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDPavement.physicMaterial"); - } - if (opt_bShouldersEnabled && !ShoulderPhysicMaterial) - { - ShoulderPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDDirt.physicMaterial"); - } - } - - public void SetDefaultMats() - { - if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Asphalt) - { - RoadMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); - RoadMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - - if (opt_Lanes == 2) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); - } - else if (opt_Lanes == 4) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); - } - else if (opt_Lanes == 6) - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); - } - else - { - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); - } - - if (opt_Lanes == 2) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); - } - else if (opt_Lanes == 4) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-4L.mat"); - } - else if (opt_Lanes == 6) - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-6L.mat"); - } - else - { - RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); - } - - ShoulderMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDShoulder1.mat"); - ShoulderMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - - RoadPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDPavement.physicMaterial"); - ShoulderPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDDirt.physicMaterial"); - } - else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Dirt) - { - RoadMaterial1 = null; - RoadMaterial2 = null; - RoadMaterial3 = null; - RoadMaterial4 = null; - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDDirtRoad.mat"); - RoadMaterialMarker2 = null; - RoadMaterialMarker3 = null; - RoadMaterialMarker4 = null; - } - else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Brick) - { - RoadMaterial1 = null; - RoadMaterial2 = null; - RoadMaterial3 = null; - RoadMaterial4 = null; - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDBrickRoad.mat"); - RoadMaterialMarker2 = null; - RoadMaterialMarker3 = null; - RoadMaterialMarker4 = null; - } - else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Cobblestone) - { - RoadMaterial1 = null; - RoadMaterial2 = null; - RoadMaterial3 = null; - RoadMaterial4 = null; - RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDCobblestoneRoad.mat"); - RoadMaterialMarker2 = null; - RoadMaterialMarker3 = null; - RoadMaterialMarker4 = null; - } - if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Brick - || opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Cobblestone - || opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Dirt) - { - if (opt_Lanes > 2) - { - RoadMaterialMarker1 = new Material(RoadMaterialMarker1); - RoadMaterialMarker1.mainTextureScale *= new Vector2(opt_Lanes / 2, 1f); - } - } - - int mCount = GSDSpline.GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - if (GSDSpline.mNodes[i] && GSDSpline.mNodes[i].bIsIntersection && GSDSpline.mNodes[i].GSDRI != null && GSDSpline.mNodes[i].GSDRI.bUseDefaultMaterials) - { - GSDSpline.mNodes[i].GSDRI.ResetMaterials_All(); - } - } - } - #endregion - - public void Wireframes_Toggle() - { - MeshRenderer[] tMRs = transform.GetComponentsInChildren(); - Wireframes_Toggle_Help(ref tMRs); - - if (GSDSpline != null) - { - tMRs = GSDSpline.transform.GetComponentsInChildren(); - Wireframes_Toggle_Help(ref tMRs); - } - } - void Wireframes_Toggle_Help(ref MeshRenderer[] tMRs) - { - int tCount = tMRs.Length; - for (int i = 0; i < tCount; i++) - { - //EditorUtility.SetSelectedWireframeHidden(tMRs[i], !opt_GizmosEnabled); - EditorUtility.SetSelectedRenderState(tMRs[i], opt_GizmosEnabled ? EditorSelectedRenderState.Wireframe : EditorSelectedRenderState.Hidden); - } - } - -#endif - - void Start() - { -#if UNITY_EDITOR - if (Application.isPlaying) - { - CleanRunTime(); - } -#else - this.enabled = false; -#endif - } - -#if UNITY_EDITOR - //For compliance on submission rules: - public void UpdateGizmoOptions() - { - if (GSDSpline == null) { return; } - GSDSplineN tNode = null; - - int mCount = GSDSpline.GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode != null) - { - tNode.opt_GizmosEnabled = opt_GizmosEnabled; - } - } - } - - public void SetupUniqueIdentifier() - { - if (UID == null || UID.Length < 4) - { - UID = System.Guid.NewGuid().ToString(); - } - } - - public void DuplicateRoad() - { - GameObject tRoadObj = GSDRS.AddRoad(); - UnityEditor.Undo.RegisterCreatedObjectUndo(tRoadObj, "Duplicate"); - - GSDRoad xRoad = tRoadObj.GetComponent(); - if (xRoad == null) { return; } - - //Road editor options: - xRoad.opt_LaneWidth = opt_LaneWidth; //Done. - xRoad.opt_bShouldersEnabled = opt_bShouldersEnabled; //Disabled for now. Comprimises integrity of roads. - xRoad.opt_ShoulderWidth = opt_ShoulderWidth; //Done. - xRoad.opt_Lanes = opt_Lanes; //Done. - xRoad.opt_RoadDefinition = opt_RoadDefinition; //Done. - xRoad.opt_RoadCornerDefinition = opt_RoadCornerDefinition; //Disable for now. No point. - xRoad.opt_bRoadCuts = opt_bRoadCuts; - xRoad.opt_bShoulderCuts = opt_bShoulderCuts; - xRoad.opt_bDynamicCuts = opt_bDynamicCuts; - xRoad.opt_bMaxGradeEnabled = opt_bMaxGradeEnabled; - xRoad.opt_MaxGrade = opt_MaxGrade; - xRoad.opt_UseDefaultMaterials = opt_UseDefaultMaterials; - xRoad.opt_AutoUpdateInEditor = opt_AutoUpdateInEditor; - - xRoad.opt_TerrainSubtract_Match = opt_TerrainSubtract_Match; - xRoad.opt_bGSDRoadRaise = opt_bGSDRoadRaise; - - xRoad.opt_MatchHeightsDistance = opt_MatchHeightsDistance; - xRoad.opt_ClearDetailsDistance = opt_ClearDetailsDistance; - xRoad.opt_ClearDetailsDistanceHeight = opt_ClearDetailsDistanceHeight; - xRoad.opt_ClearTreesDistance = opt_ClearTreesDistance; - xRoad.opt_ClearTreesDistanceHeight = opt_ClearTreesDistanceHeight; - - xRoad.opt_HeightModEnabled = opt_HeightModEnabled; - xRoad.opt_DetailModEnabled = opt_DetailModEnabled; - xRoad.opt_TreeModEnabled = opt_TreeModEnabled; - - xRoad.opt_SaveTerrainHistoryOnDisk = opt_SaveTerrainHistoryOnDisk; - xRoad.opt_MagnitudeThreshold = opt_MagnitudeThreshold; - xRoad.opt_GizmosEnabled = opt_GizmosEnabled; - xRoad.opt_bMultithreading = opt_bMultithreading; - xRoad.opt_bSaveMeshes = opt_bSaveMeshes; - xRoad.opt_bUseMeshColliders = opt_bUseMeshColliders; - - xRoad.opt_tRoadMaterialDropdown = opt_tRoadMaterialDropdown; - xRoad.tRoadMaterialDropdownOLD = tRoadMaterialDropdownOLD; - - xRoad.RoadMaterial1 = RoadMaterial1; - xRoad.RoadMaterial2 = RoadMaterial2; - xRoad.RoadMaterial3 = RoadMaterial3; - xRoad.RoadMaterial4 = RoadMaterial4; - xRoad.RoadMaterialMarker1 = RoadMaterialMarker1; - xRoad.RoadMaterialMarker2 = RoadMaterialMarker2; - xRoad.RoadMaterialMarker3 = RoadMaterialMarker3; - xRoad.RoadMaterialMarker4 = RoadMaterialMarker4; - xRoad.ShoulderMaterial1 = ShoulderMaterial1; - xRoad.ShoulderMaterial2 = ShoulderMaterial2; - xRoad.ShoulderMaterial3 = ShoulderMaterial3; - xRoad.ShoulderMaterial4 = ShoulderMaterial4; - xRoad.ShoulderMaterialMarker1 = ShoulderMaterialMarker1; - xRoad.ShoulderMaterialMarker2 = ShoulderMaterialMarker2; - xRoad.ShoulderMaterialMarker3 = ShoulderMaterialMarker3; - xRoad.ShoulderMaterialMarker4 = ShoulderMaterialMarker4; - - xRoad.RoadPhysicMaterial = RoadPhysicMaterial; - xRoad.ShoulderPhysicMaterial = ShoulderPhysicMaterial; - - xRoad.GSDSpline.Setup_Trigger(); - - Selection.activeGameObject = xRoad.transform.gameObject; - } - - private void FixZ() - { - FixZ_Mobile(); - } - - private void FixZ_Mobile() - { - //This road: - Object[] tMarkerObjs = transform.GetComponentsInChildren(); - Vector3 tVect = default(Vector3); - foreach (MeshRenderer MR in tMarkerObjs) - { - if (MR.transform.name.Contains("Marker")) - { - tVect = new Vector3(0f, 0.02f, 0f); - MR.transform.localPosition = tVect; - } - else if (MR.transform.name.Contains("SCut") || MR.transform.name.Contains("RoadCut") - || MR.transform.name.Contains("ShoulderR") - || MR.transform.name.Contains("ShoulderL")) - { - tVect = MR.transform.position; - tVect.y += 0.01f; - MR.transform.position = tVect; - } - else if (MR.transform.name.Contains("RoadMesh")) - { - tVect = MR.transform.position; - tVect.y += 0.02f; - MR.transform.position = tVect; - } - else if (MR.transform.name.Contains("Pavement")) - { - tVect = MR.transform.position; - tVect.y -= 0.01f; - MR.transform.position = tVect; - } - } - - //Intersections (all): - tMarkerObjs = GSDRS.GetComponentsInChildren(); - foreach (MeshRenderer MR in tMarkerObjs) - { - if (MR.transform.name.Contains("CenterMarkers")) - { - tVect = new Vector3(0f, 0.02f, 0f); - MR.transform.localPosition = tVect; - } - else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Lane")) - { - tVect = new Vector3(0f, 0.02f, 0f); - MR.transform.localPosition = tVect; - } - else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Stretch")) - { - tVect = new Vector3(0f, 0.03f, 0f); - MR.transform.localPosition = tVect; - } - else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Tiled")) - { - tVect = new Vector3(0f, 0.01f, 0f); - MR.transform.localPosition = tVect; - } - } - } - - private void FixZ_Win() - { - //This road: - Object[] tMarkerObjs = transform.GetComponentsInChildren(); - Vector3 tVect = default(Vector3); - foreach (MeshRenderer MR in tMarkerObjs) - { - if (MR.transform.name.Contains("Marker")) - { - tVect = new Vector3(0f, 0.01f, 0f); - MR.transform.localPosition = tVect; - } - } - - //Intersections (all): - tMarkerObjs = Object.FindObjectsOfType(); - foreach (MeshRenderer MR in tMarkerObjs) - { - if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Lane")) - { - tVect = new Vector3(0f, 0.01f, 0f); - MR.transform.localPosition = tVect; - } - else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Stretch")) - { - tVect = new Vector3(0f, 0.01f, 0f); - MR.transform.localPosition = tVect; - } - } - } -#endif -} +#region Imports +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using GSD.Roads; +using GSD; +#if UNITY_EDITOR +using UnityEditor; +#endif +#endregion + + +[ExecuteInEditMode] +public class GSDRoad : MonoBehaviour +{ + + public GameObject MainMeshes; + public GameObject MeshRoad; + public GameObject MeshShoR; + public GameObject MeshShoL; + public GameObject MeshiLanes; + public GameObject MeshiLanes0; + public GameObject MeshiLanes1; + public GameObject MeshiLanes2; + public GameObject MeshiLanes3; + public GameObject MeshiMainPlates; + public GameObject MeshiMarkerPlates; + + [System.NonSerialized] + public string EditorTitleString = ""; + + public GSDSplineC GSDSpline; + + public int MostRecentNodeCount = -1; + // private bool bMostRecentCheck = false; + public GameObject GSDSplineObj; + public GSDRoadSystem GSDRS; + public GSDSplineC[] PiggyBacks = null; + public bool bEditorProgressBar = false; + public string UID; //Unique ID +#if UNITY_EDITOR + [SerializeField] + public List TerrainHistory; + public string TerrainHistoryByteSize = ""; +#endif + [System.NonSerialized] + public bool bUpdateSpline = false; + + //Road editor options: + public float opt_LaneWidth = 5f; //Done. + public bool opt_bShouldersEnabled = true; //Disabled for now. Comprimises integrity of roads. + public float opt_ShoulderWidth = 3f; //Done. + public int opt_Lanes = 2; //Done. + public float opt_RoadDefinition = 5f; //Done. + public bool opt_RoadCornerDefinition = false; //Disable for now. No point. + public bool opt_bRoadCuts = true; + public bool opt_bShoulderCuts = true; + public bool opt_bDynamicCuts = false; + public bool opt_bMaxGradeEnabled = true; + public float opt_MaxGrade = 0.08f; + public bool opt_UseDefaultMaterials = true; + public bool opt_AutoUpdateInEditor = true; + + public float opt_TerrainSubtract_Match = 0.1f; + public bool opt_bGSDRoadRaise = false; + + public float opt_MatchHeightsDistance = 50f; + public float opt_ClearDetailsDistance = 30f; + public float opt_ClearDetailsDistanceHeight = 5f; + public float opt_ClearTreesDistance = 30f; + public float opt_ClearTreesDistanceHeight = 50f; + + public bool opt_HeightModEnabled = true; + public bool opt_DetailModEnabled = true; + public bool opt_TreeModEnabled = true; + + public bool opt_SaveTerrainHistoryOnDisk = true; + public float opt_MagnitudeThreshold = 300f; + public bool opt_GizmosEnabled = true; + public bool opt_bMultithreading = true; + public bool opt_bSaveMeshes = false; + public bool opt_bUseMeshColliders = true; + public bool opt_bIsStatic = false; + public bool opt_bIsLightmapped = false; + + public enum RoadMaterialDropdownEnum + { + Asphalt, + Dirt, + Brick, + Cobblestone + }; + + public RoadMaterialDropdownEnum opt_tRoadMaterialDropdown = RoadMaterialDropdownEnum.Asphalt; + public RoadMaterialDropdownEnum tRoadMaterialDropdownOLD = RoadMaterialDropdownEnum.Asphalt; + + + public Material RoadMaterial1; + public Material RoadMaterial2; + public Material RoadMaterial3; + public Material RoadMaterial4; + public Material RoadMaterialMarker1; + public Material RoadMaterialMarker2; + public Material RoadMaterialMarker3; + public Material RoadMaterialMarker4; + public Material ShoulderMaterial1; + public Material ShoulderMaterial2; + public Material ShoulderMaterial3; + public Material ShoulderMaterial4; + public Material ShoulderMaterialMarker1; + public Material ShoulderMaterialMarker2; + public Material ShoulderMaterialMarker3; + public Material ShoulderMaterialMarker4; + + public PhysicMaterial RoadPhysicMaterial; + public PhysicMaterial ShoulderPhysicMaterial; +#if UNITY_EDITOR + #region "Road Construction" + [System.NonSerialized] + public GSD.Threaded.TerrainCalcs TerrainCalcsJob; + [System.NonSerialized] + public GSD.Threaded.RoadCalcs1 RoadCalcsJob1; + [System.NonSerialized] + public GSD.Threaded.RoadCalcs2 RoadCalcsJob2; + [System.NonSerialized] + public RoadConstructorBufferMaker RCS; + + public string tName = ""; + public bool bProfiling = false; + public bool bSkipStore = true; + [System.NonSerialized] + public float EditorConstructionStartTime = 0f; + + + void CleanRunTime() + { + //Make sure unused items are not using memory space in runtime: + TerrainHistory = null; + RCS = null; + } + + + public bool bEditorError = false; + public System.Exception tError = null; + + + void OnEnable() + { + if (!Application.isEditor) + { + return; + } + // if(Application.isEditor && !UnityEditor.EditorApplication.isPlaying){ + Editor_bIsConstructing = false; + UnityEditor.EditorApplication.update += delegate + { EditorUpdate(); }; +#if UNITY_2018_1_OR_NEWER + UnityEditor.EditorApplication.hierarchyChanged += delegate + { hWindowChanged(); }; +#else + UnityEditor.EditorApplication.hierarchyWindowChanged += delegate { hWindowChanged(); }; +#endif + // } + if (GSDSpline == null || GSDSpline.mNodes == null) + { + MostRecentNodeCount = 0; + } + else + { + MostRecentNodeCount = GSDSpline.GetNodeCount(); + } + tRoadMaterialDropdownOLD = opt_tRoadMaterialDropdown; + CheckMats(); + } + + + public void Awake() + { + if (GSDSpline == null || GSDSpline.mNodes == null) + { + MostRecentNodeCount = 0; + } + else + { + MostRecentNodeCount = GSDSpline.GetNodeCount(); + } + } + + + int EditorTimer = 0; + int EditorTimerMax = 0; + int EditorTimerSpline = 0; + const int EditorTimerSplineMax = 2; + [System.NonSerialized] + public int EditorProgress = 0; + const int GizmoNodeTimerMax = 2; + public bool EditorUpdateMe = false; + public bool bTriggerGC = false; + bool bTriggerGC_Happening; + float TriggerGC_End = 0f; + + + private void EditorUpdate() + { + if (!Application.isEditor) + { + UnityEditor.EditorApplication.update -= delegate + { EditorUpdate(); }; + } + + if (this == null) + { + UnityEditor.EditorApplication.update -= delegate + { EditorUpdate(); }; + Editor_bIsConstructing = false; + EditorUtility.ClearProgressBar(); + return; + } + + //Custom garbage collection demands for editor: + if (bTriggerGC) + { + bTriggerGC = false; + TriggerGC_End = Time.realtimeSinceStartup + 1f; + bTriggerGC_Happening = true; + } + if (bTriggerGC_Happening) + { + if (Time.realtimeSinceStartup > TriggerGC_End) + { + bTriggerGC_Happening = false; + GSDRootUtil.ForceCollection(); + TriggerGC_End = 200000f; + } + } + + if (Editor_bIsConstructing) + { // && !Application.isPlaying && !UnityEditor.EditorApplication.isPlaying){ + if (GSDRS != null) + { + if (GSDRS.opt_bMultithreading) + { + EditorTimer += 1; + if (EditorTimer > EditorTimerMax) + { + if ((Time.realtimeSinceStartup - EditorConstructionStartTime) > 180f) + { + Editor_bIsConstructing = false; + EditorUtility.ClearProgressBar(); + Debug.Log("Update shouldn't take longer than 180 seconds. Aborting update."); + } + + EditorTimer = 0; + if (bEditorError) + { + Editor_bIsConstructing = false; + EditorUtility.ClearProgressBar(); + bEditorError = false; + if (tError != null) + { + Debug.LogError(tError.StackTrace); + throw tError; + } + } + + if (TerrainCalcsJob != null && TerrainCalcsJob.Update()) + { + ConstructRoad2(); + } + else if (RoadCalcsJob1 != null && RoadCalcsJob1.Update()) + { + ConstructRoad3(); + } + else if (RoadCalcsJob2 != null && RoadCalcsJob2.Update()) + { + ConstructRoad4(); + } + } + } + } + } + else + { + if (EditorUpdateMe && !Editor_bIsConstructing) + { + EditorUpdateMe = false; + GSDSpline.Setup_Trigger(); + } + } + + if (Editor_bIsConstructing) + { + RoadUpdateProgressBar(); + } + else if (bEditorProgressBar) + { + RoadUpdateProgressBar(); + } + + if (!Application.isPlaying && bUpdateSpline && !UnityEditor.EditorApplication.isPlaying) + { + EditorTimerSpline += 1; + if (EditorTimerSpline > EditorTimerSplineMax) + { + EditorTimerSpline = 0; + bUpdateSpline = false; + GSDSpline.Setup_Trigger(); + MostRecentNodeCount = GSDSpline.mNodes.Count; + } + } + + if (bEditorCameraMoving && EditorCameraNextMove < EditorApplication.timeSinceStartup) + { + EditorCameraNextMove = (float) EditorApplication.timeSinceStartup + EditorCameraTimeUpdateInterval; + DoEditorCameraLoop(); + } + } + + + [System.NonSerialized] + public bool bEditorCameraMoving = false; + [System.NonSerialized] + public float EditorCameraPos = 0f; + // float EditorCameraPos_Full = 0f; + const float EditorCameraTimeUpdateInterval = 0.015f; + float EditorCameraNextMove = 0f; + bool bEditorCameraSetup = false; + float EditorCameraStartPos = 0f; + float EditorCameraEndPos = 1f; + float EditorCameraIncrementDistance = 0f; + float EditorCameraIncrementDistance_Full = 0f; + public float EditorCameraMetersPerSecond = 60f; + public bool bEditorCameraRotate = false; + Vector3 EditorCameraV1 = default(Vector3); + Vector3 EditorCameraV2 = default(Vector3); + [System.NonSerialized] + public Vector3 EditorCameraOffset = new Vector3(0f, 5f, 0f); + [System.NonSerialized] + public Camera EditorPlayCamera = null; + Vector3 EditorCameraBadVec = default(Vector3); + + + public void DoEditorCameraLoop() + { + if (!bEditorCameraSetup) + { + bEditorCameraSetup = true; + if (GSDSpline.bSpecialEndControlNode) + { //If control node, start after the control node: + EditorCameraEndPos = GSDSpline.mNodes[GSDSpline.GetNodeCount() - 2].tTime; + } + if (GSDSpline.bSpecialStartControlNode) + { //If ends in control node, end construction before the control node: + EditorCameraStartPos = GSDSpline.mNodes[1].tTime; + } + // EditorCameraPos_Full = 0f; + ChangeEditorCameraMetersPerSec(); + } + + if (!Selection.Contains(this.transform.gameObject)) + { + QuitEditorCamera(); + return; + } + + // EditorCameraPos_Full+=EditorCameraIncrementDistance_Full; + // if(EditorCameraPos_Full > GSDSpline.distance){ EditorCameraPos = EditorCameraStartPos; bEditorCameraMoving = false; bEditorCameraSetup = false; EditorCameraPos_Full = 0f; return; } + // EditorCameraPos = GSDSpline.TranslateDistBasedToParam(EditorCameraPos_Full); + + EditorCameraPos += EditorCameraIncrementDistance; + if (EditorCameraPos > EditorCameraEndPos) + { + QuitEditorCamera(); + return; + } + if (EditorCameraPos < EditorCameraStartPos) + { + EditorCameraPos = EditorCameraStartPos; + } + + GSDSpline.GetSplineValue_Both(EditorCameraPos, out EditorCameraV1, out EditorCameraV2); + + if (EditorApplication.isPlaying) + { + if (EditorPlayCamera != null) + { + EditorPlayCamera.transform.position = EditorCameraV1; + if (bEditorCameraRotate) + { + EditorPlayCamera.transform.position += EditorCameraOffset; + if (EditorCameraV2 != EditorCameraBadVec) + { + EditorPlayCamera.transform.rotation = Quaternion.LookRotation(EditorCameraV2); + } + } + } + } + else + { + SceneView.lastActiveSceneView.pivot = EditorCameraV1; + if (bEditorCameraRotate) + { + SceneView.lastActiveSceneView.pivot += EditorCameraOffset; + if (EditorCameraV2 != EditorCameraBadVec) + { + SceneView.lastActiveSceneView.rotation = Quaternion.LookRotation(EditorCameraV2); + } + } + SceneView.lastActiveSceneView.Repaint(); + } + } + + + public void EditorCameraSetSingle() + { + if (EditorPlayCamera == null) + { + Camera[] EditorCams = (Camera[]) GameObject.FindObjectsOfType(typeof(Camera)); + if (EditorCams != null && EditorCams.Length == 1) + { + EditorPlayCamera = EditorCams[0]; + } + } + } + + + public void QuitEditorCamera() + { + EditorCameraPos = EditorCameraStartPos; + bEditorCameraMoving = false; + bEditorCameraSetup = false; + // EditorCameraPos_Full = 0f; + } + + + public void ChangeEditorCameraMetersPerSec() + { + EditorCameraIncrementDistance_Full = (EditorCameraMetersPerSecond / 60); + EditorCameraIncrementDistance = (EditorCameraIncrementDistance_Full / GSDSpline.distance); + } + + + private void hWindowChanged() + { + if (!Application.isEditor) + { +#if UNITY_2018_1_OR_NEWER + UnityEditor.EditorApplication.hierarchyChanged -= delegate + { hWindowChanged(); }; +#else + UnityEditor.EditorApplication.hierarchyWindowChanged -= delegate { hWindowChanged(); }; +#endif + } + if (Application.isPlaying || !Application.isEditor) + { + return; + } + if (Application.isEditor && UnityEditor.EditorApplication.isPlaying) + { + return; + } + if (Application.isEditor && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) + { + return; + } + + int tCount = 0; + if (GSDSpline != null && GSDSpline.mNodes != null) + { + tCount = GSDSpline.GetNodeCountNonNull(); + } + if (tCount != MostRecentNodeCount) + { + bUpdateSpline = true; + } + } + + + void RoadUpdateProgressBar() + { + if (Editor_bIsConstructing) + { + EditorUtility.DisplayProgressBar( + "GSD Road Update", + EditorTitleString, + ((float) EditorProgress / 100f)); + } + else if (bEditorProgressBar) + { + bEditorProgressBar = false; + EditorUtility.ClearProgressBar(); + } + } + + + public void UpdateRoad(RoadUpdateTypeEnum tUpdateType = RoadUpdateTypeEnum.Full) + { + if (!GSDRS.opt_bAllowRoadUpdates) + { + GSDSpline.Setup(); + Editor_bIsConstructing = false; + return; + } + + if (Editor_bIsConstructing) + { + return; + } + + SetupUniqueIdentifier(); + + + + if (bProfiling) + { UnityEngine.Profiling.Profiler.BeginSample("UpdateRoadPrelim"); } + opt_RoadDefinition = Mathf.Clamp(opt_RoadDefinition, 1f, 50f); + opt_LaneWidth = Mathf.Clamp(opt_LaneWidth, 0.2f, 500f); + EditorConstructionStartTime = Time.realtimeSinceStartup; + EditorTitleString = "Updating " + transform.name + "..."; + System.GC.Collect(); + + if (opt_SaveTerrainHistoryOnDisk) + { + ConstructRoad_LoadTerrainHistory(); + } + + CheckMats(); + + EditorUtility.ClearProgressBar(); + + bProfiling = true; + if (GSDRS.opt_bMultithreading) + { bProfiling = false; } + + //Set all terrains to height 0: + GSD.Roads.GSDTerraforming.CheckAllTerrainsHeight0(); + + EditorProgress = 20; + bEditorProgressBar = true; + if (Editor_bIsConstructing) + { + if (TerrainCalcsJob != null) + { TerrainCalcsJob.Abort(); TerrainCalcsJob = null; } + if (RoadCalcsJob1 != null) + { RoadCalcsJob1.Abort(); RoadCalcsJob1 = null; } + if (RoadCalcsJob2 != null) + { RoadCalcsJob2.Abort(); RoadCalcsJob2 = null; } + Editor_bIsConstructing = false; + } + + // if(Application.isPlaying || !Application.isEditor){ return; } + // if(Application.isEditor && UnityEditor.EditorApplication.isPlaying){ return; } + // if(Application.isEditor && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode){ return; } + + //In here for intersection patching purposes: + int mCount = GSDSpline.GetNodeCount(); + GSDSplineN tNode = null; + GSDSplineN tNode1 = null; + GSDSplineN tNode2 = null; + if (GSDSpline.CheckInvalidNodeCount()) + { + GSDSpline.Setup(); + mCount = GSDSpline.GetNodeCount(); + } + if (mCount > 1) + { + for (int i = 0; i < mCount; i++) + { + // try{ + tNode = GSDSpline.mNodes[i]; + // }catch{ + // Editor_bIsConstructing = false; + // EditorUpdateMe = true; + // return; + // } + + //If node is intersection with an invalid GSDRI, mark it at non-intersection. Just-in-case. + if (tNode.bIsIntersection && tNode.GSDRI == null) + { + tNode.bIsIntersection = false; + tNode.id_intersection_othernode = -1; + tNode.Intersection_OtherNode = null; + } + //If node is intersection, re-setup: + if (tNode.bIsIntersection && tNode.GSDRI != null) + { + tNode1 = tNode.GSDRI.Node1; + tNode2 = tNode.GSDRI.Node2; + tNode.GSDRI.Setup(tNode1, tNode2); + tNode.GSDRI.DeleteRelevantChildren(tNode, tNode.GSDSpline.tRoad.transform.name); + //If primary node on intersection, do more re-setup: + if (tNode.GSDRI.Node1 == tNode) + { + tNode.GSDRI.Lanes = opt_Lanes; + tNode.GSDRI.name = tNode.GSDRI.transform.name; + } + //Setup construction objects: + tNode.GSDRI.Node1.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); + tNode.GSDRI.Node2.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); + } + + //Store materials and physical materials for road and or shoulder cuts on each node, if necessary: + tNode.StoreCuts(); + } + } + name = transform.name; + + + + GSDSpline.RoadWidth = RoadWidth(); + // if(bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("SplineSetup"); } + GSDSpline.Setup(); + // if(bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } + mCount = GSDSpline.GetNodeCount(); + + if (GSDSpline == null || GSDSpline.mNodes == null) + { + MostRecentNodeCount = 0; + } + else + { + MostRecentNodeCount = GSDSpline.GetNodeCount(); + } + + if (opt_UseDefaultMaterials) + { + SetDefaultMats(); + } + + if (opt_UseDefaultMaterials) + { + if (DetectInvalidDefaultMatsForUndo()) + { + SetAllCutsToCurrentMaterials(); + } + } + + //Hiding in hierarchy: + for (int i = 0; i < mCount; i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode != null) + { + if (tNode.bIsIntersection || tNode.bSpecialEndNode) + { + tNode.ToggleHideFlags(true); + } + else + { + tNode.ToggleHideFlags(false); + } + } + } + + int cCount = transform.childCount; + GameObject tMainMeshes = null; + List tObjs = new List(); + for (int i = 0; i < cCount; i++) + { + if (transform.GetChild(i).transform.name.ToLower().Contains("mainmeshes")) + { + tMainMeshes = transform.GetChild(i).transform.gameObject; + tObjs.Add(tMainMeshes); + } + } + for (int i = (tObjs.Count - 1); i >= 0; i--) + { + tMainMeshes = tObjs[i]; + Object.DestroyImmediate(tMainMeshes); + } + + if (mCount < 2) + { + //Delete old objs and return: + if (MainMeshes != null) + { Object.DestroyImmediate(MainMeshes); } + if (MeshRoad != null) + { Object.DestroyImmediate(MeshRoad); } + if (MeshShoR != null) + { Object.DestroyImmediate(MeshShoR); } + if (MeshShoL != null) + { Object.DestroyImmediate(MeshShoL); } + if (MeshiLanes != null) + { Object.DestroyImmediate(MeshiLanes); } + if (MeshiLanes0 != null) + { Object.DestroyImmediate(MeshiLanes0); } + if (MeshiLanes1 != null) + { Object.DestroyImmediate(MeshiLanes1); } + if (MeshiLanes2 != null) + { Object.DestroyImmediate(MeshiLanes2); } + if (MeshiLanes3 != null) + { Object.DestroyImmediate(MeshiLanes3); } + if (MeshiMainPlates != null) + { Object.DestroyImmediate(MeshiMainPlates); } + if (MeshiMarkerPlates != null) + { Object.DestroyImmediate(MeshiMarkerPlates); } + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + return; + } + + GSDSpline.HeightHistory = new List>(); + if (GSDRS == null) + { GSDRS = transform.parent.GetComponent(); } //Compatibility update. + + if (GSDRS.opt_bMultithreading) + { + Editor_bIsConstructing = true; + } + else + { + Editor_bIsConstructing = false; + } + Editor_bConstructionID = 0; + + + + //Check if road takes place on only 1 terrain: + Terrain tTerrain = GSD.Roads.GSDRoadUtil.GetTerrain(GSDSpline.mNodes[0].pos); + bool bSameTerrain = true; + for (int i = 1; i < mCount; i++) + { + if (tTerrain != GSD.Roads.GSDRoadUtil.GetTerrain(GSDSpline.mNodes[0].pos)) + { + bSameTerrain = false; + break; + } + } + + RCS = new RoadConstructorBufferMaker(this, tUpdateType); + + if (bSameTerrain) + { + RCS.tTerrain = tTerrain; + } + else + { + RCS.tTerrain = null; + } + tTerrain = null; + + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + + if (GSDRS.opt_bMultithreading) + { + if (RCS.bTerrainOn || TerrainHistory == null) + { + GSDTerraforming.ProcessRoad_Terrain_Hook1(GSDSpline, this); + } + else + { + ConstructRoad2(); + } + } + else + { + UpdateRoad_NoMultiThreading(); + } + } + + + #region "Terrain history" + public void ConstructRoad_StoreTerrainHistory(bool bDiskOnly = false) + { + if (!bDiskOnly) + { + GSDRoad tRoad = this; + GSDRoadUtil.ConstructRoad_StoreTerrainHistory(ref tRoad); + } + + if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null && TerrainHistory.Count > 0) + { + if (bProfiling) + { UnityEngine.Profiling.Profiler.BeginSample("TerrainHistory_Save"); } + GSDGeneralEditor.TerrainHistory_Save(TerrainHistory, this); + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + TerrainHistory.Clear(); + TerrainHistory = null; + } + else + { + if (TerrainHistory != null && TerrainHistory.Count > 0) + { + int tSize = 0; + for (int i = 0; i < TerrainHistory.Count; i++) + { + tSize += TerrainHistory[i].GetSize(); + } + TerrainHistoryByteSize = (tSize * 0.001f).ToString("n0") + " kb"; + } + else + { + TerrainHistoryByteSize = "0 bytes"; + } + } + } + public void ConstructRoad_ResetTerrainHistory() + { + GSDRoad tRoad = this; + if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null) + { + GSDGeneralEditor.TerrainHistory_Delete(this); + } + else + { + GSDRoadUtil.ConstructRoad_ResetTerrainHistory(ref tRoad); + } + } + public void ConstructRoad_LoadTerrainHistory(bool bForce = false) + { + if (opt_SaveTerrainHistoryOnDisk || bForce) + { + if (TerrainHistory != null) + { + TerrainHistory.Clear(); + TerrainHistory = null; + } + TerrainHistory = GSDGeneralEditor.TerrainHistory_Load(this); + } + if (bForce) + { + GSDGeneralEditor.TerrainHistory_Delete(this); + } + } + #endregion + + + #region "Construction process" + #region "No multithread" + private void UpdateRoad_NoMultiThreading() + { + if (opt_HeightModEnabled || opt_DetailModEnabled || opt_TreeModEnabled) + { + if (bProfiling) + { UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Terrain"); } + if (RCS.bTerrainOn || TerrainHistory == null) + { + GSDTerraforming.ProcessRoad_Terrain_Hook1(GSDSpline, this, false); + GSDTerraforming.ProcessRoad_Terrain_Hook2(GSDSpline, ref EditorTTDList); + ConstructRoad_StoreTerrainHistory();//Store history. + int EditorTTDListCount = EditorTTDList.Count; + for (int i = 0; i < EditorTTDListCount; i++) + { + EditorTTDList[i] = null; + } + EditorTTDList = null; + System.GC.Collect(); + } + if (bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + } + + EditorProgress = 50; + GSDRoad tRoad = this; + if (bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("RoadCon_RoadPrelim"); + } + + EditorProgress = 80; + GSD.Threaded.GSDRoadCreationT.RoadJob_Prelim(ref tRoad); + if (bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Road1"); + } + EditorProgress = 90; + GSD.Threaded.RoadCalcs1_static.RunMe(ref RCS); + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + if (bProfiling) + { UnityEngine.Profiling.Profiler.BeginSample("MeshSetup1"); } + EditorProgress = 92; + RCS.MeshSetup1(); + if (bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + UnityEngine.Profiling.Profiler.BeginSample("RoadCon_Road2"); + } + EditorProgress = 94; + GSD.Threaded.RoadCalcs2_static.RunMe(ref RCS); + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + if (bProfiling) + { UnityEngine.Profiling.Profiler.BeginSample("MeshSetup2"); } + EditorProgress = 96; + RCS.MeshSetup2(); + if (bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + Construction_Cleanup(); + } + #endregion + + private void ConstructRoad2() + { + EditorProgress = 40; + if (RCS.bTerrainOn) + { + //Store history: + GSDTerraforming.ProcessRoad_Terrain_Hook2(GSDSpline, ref EditorTTDList); + ConstructRoad_StoreTerrainHistory(); + int EditorTTDListCount = EditorTTDList.Count; + for (int i = 0; i < EditorTTDListCount; i++) + { + EditorTTDList[i] = null; + } + EditorTTDList = null; + System.GC.Collect(); + } + EditorProgress = 60; + + if (TerrainCalcsJob != null) + { TerrainCalcsJob.Abort(); TerrainCalcsJob = null; } + GSDRoad tRoad = this; + EditorProgress = 72; + RoadCalcsJob1 = new GSD.Threaded.RoadCalcs1(); + RoadCalcsJob1.Setup(ref RCS, ref tRoad); + RoadCalcsJob1.Start(); + } + + private void ConstructRoad3() + { + EditorProgress = 84; + RCS.MeshSetup1(); + EditorProgress = 96; + if (RoadCalcsJob1 != null) + { RoadCalcsJob1.Abort(); RoadCalcsJob1 = null; } + RoadCalcsJob2 = new GSD.Threaded.RoadCalcs2(); + RoadCalcsJob2.Setup(ref RCS); + RoadCalcsJob2.Start(); + EditorProgress = 98; + } + + private void ConstructRoad4() + { + RCS.MeshSetup2(); + Construction_Cleanup(); + } + #endregion + + + private void Construction_Cleanup() + { + FixZ(); + + if (TerrainCalcsJob != null) + { + TerrainCalcsJob.Abort(); + TerrainCalcsJob = null; + } + if (RoadCalcsJob1 != null) + { + RoadCalcsJob1.Abort(); + RoadCalcsJob1 = null; + } + if (RoadCalcsJob2 != null) + { + RoadCalcsJob2.Abort(); + RoadCalcsJob2 = null; + } + Editor_bIsConstructing = false; + int mCount = GSDSpline.GetNodeCount(); + GSDSplineN tNode; + for (int i = 0; i < mCount; i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode.bIsIntersection) + { + if (tNode.iConstruction != null) + { + tNode.iConstruction.Nullify(); + tNode.iConstruction = null; + } + } + tNode.SetupSplinationLimits(); + tNode.SetupEdgeObjects(false); + tNode.SetupSplinatedMeshes(false); + } + if (GSDSpline.HeightHistory != null) + { + GSDSpline.HeightHistory.Clear(); + GSDSpline.HeightHistory = null; + } + if (RCS != null) + { + RCS.Nullify(); + RCS = null; + } + + if (GSDRS.opt_bSaveMeshes) + { + UnityEditor.AssetDatabase.SaveAssets(); + } + bEditorProgressBar = false; + EditorUtility.ClearProgressBar(); + //Make sure terrain history out of memory if necessary (redudant but keep): + if (opt_SaveTerrainHistoryOnDisk && TerrainHistory != null) + { + TerrainHistory.Clear(); + TerrainHistory = null; + } + + //Collect: + bTriggerGC = true; + + if (tRoadMaterialDropdownOLD != opt_tRoadMaterialDropdown) + { + tRoadMaterialDropdownOLD = opt_tRoadMaterialDropdown; + SetAllCutsToCurrentMaterials(); + } + + if (PiggyBacks != null && PiggyBacks.Length > 0) + { + for (int i = 0; i < PiggyBacks.Length; i++) + { + if (PiggyBacks[i] == null) + { + PiggyBacks = null; + break; + } + } + + if (PiggyBacks != null) + { + GSDSplineC tPiggy = PiggyBacks[0]; + GSDSplineC[] NewPiggys = null; + + PiggyBacks[0] = null; + if (PiggyBacks.Length > 1) + { + NewPiggys = new GSDSplineC[PiggyBacks.Length - 1]; + for (int i = 1; i < PiggyBacks.Length; i++) + { + NewPiggys[i - 1] = PiggyBacks[i]; + } + } + + if (NewPiggys != null) + { + tPiggy.tRoad.PiggyBacks = NewPiggys; + } + NewPiggys = null; + tPiggy.Setup_Trigger(); + } + } + } + + + public List EditorTTDList; + + + public void EditorTerrainCalcs(ref List tList) + { + EditorTTDList = tList; + } + #endregion + + + #region "Gizmos" + public bool Editor_bIsConstructing = false; + public int Editor_bConstructionID = 0; + public bool Editor_bSelected = false; + public bool Editor_MouseTerrainHit = false; + public Vector3 Editor_MousePos = new Vector3(0f, 0f, 0f); + public readonly Color Color_NodeDefaultColor = new Color(0f, 1f, 1f, 0.75f); + public readonly Color Color_NodeConnColor = new Color(0f, 1f, 0f, 0.75f); + public readonly Color Color_NodeInter = new Color(0f, 1f, 0f, 0.75f); + + + void OnDrawGizmosSelected() + { + if (Editor_MouseTerrainHit) + { + Gizmos.color = Color.red; + Gizmos.DrawCube(Editor_MousePos, new Vector3(10f, 4f, 10f)); + } + } + #endregion +#endif + + + public float RoadWidth() + { + return (opt_LaneWidth * (float) opt_Lanes); + } + + +#if UNITY_EDITOR + public float EditorCameraTimer = 0f; + float EditorTestTimer = 0f; + bool bEditorTestTimer = true; + + + void Update() + { + if (Application.isEditor && bEditorCameraMoving) + { + EditorCameraTimer += Time.deltaTime; + if (EditorCameraTimer > EditorCameraTimeUpdateInterval) + { + EditorCameraTimer = 0f; + DoEditorCameraLoop(); + } + } + + if (bEditorTestTimer) + { + if (transform.name == "Road1") + { + EditorTestTimer += Time.deltaTime; + if (EditorTestTimer > 2f) + { + // UpdateRoad(RoadUpdateTypeEnum.Full); + // akjsdfkajlgffdghfsdghsdf(); + bEditorTestTimer = false; + } + } + else + { + bEditorTestTimer = false; + } + } + } + + + + // TODO: Needs a proper Name, who did this anyway? // FH 29.01.19 + static void akjsdfkajlgffdghfsdghsdf() + { + int LoopMax = 1000; + DoShort(LoopMax); + DoInt(LoopMax); + DoLong(LoopMax); + } + + + static void DoShort(int LoopMax) + { + ushort[] tSubject = new ushort[25000]; + // int tInt = 0; + for (int i = 0; i < LoopMax; i++) + { + for (int j = 0; j < 25000; j++) + { + tSubject[j] = (ushort) (j + 1); + // int xTemp = (int)tSubject[j]; + } + } + } + + + static void DoInt(int LoopMax) + { + int[] tSubject = new int[25000]; + // int tInt = 0; + for (int i = 0; i < LoopMax; i++) + { + for (int j = 0; j < 25000; j++) + { + tSubject[j] = j + 1; + // int xTemp = tSubject[j]; + } + } + } + + + static void DoLong(int LoopMax) + { + long[] tSubject = new long[25000]; + // int tInt = 0; + for (int i = 0; i < LoopMax; i++) + { + for (int j = 0; j < 25000; j++) + { + tSubject[j] = (long) (j + 1); + // int xTemp = (int)tSubject[j]; + } + } + } + + + #region "Default materials retrieval" + public bool DetectInvalidDefaultMatsForUndo() + { + string tNameLower = ""; + int tCounter = 0; + if (!MeshRoad) + { return false; } + + MeshRenderer[] MRs = MeshRoad.GetComponentsInChildren(); + Material tMat2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); + Material tMat4 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); + Material tMat6 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); + foreach (MeshRenderer MR in MRs) + { + tNameLower = MR.transform.name.ToLower(); + if (tNameLower.Contains("marker")) + { + if (opt_Lanes == 2) + { + if (MR.sharedMaterials[0] == tMat4) + { + tCounter += 1; + } + else if (MR.sharedMaterials[0] == tMat6) + { + tCounter += 1; + } + } + else if (opt_Lanes == 4) + { + if (MR.sharedMaterials[0] == tMat2) + { + tCounter += 1; + } + else if (MR.sharedMaterials[0] == tMat6) + { + tCounter += 1; + } + } + else if (opt_Lanes == 6) + { + if (MR.sharedMaterials[0] == tMat2) + { + tCounter += 1; + } + else if (MR.sharedMaterials[0] == tMat4) + { + tCounter += 1; + } + } + } + if (tCounter > 1) + { + return true; + } + } + return false; + } + + + public void SetAllCutsToCurrentMaterials() + { + string tNameLower = ""; + if (!MeshRoad) + { return; } + + MeshRenderer[] MRs = MeshRoad.GetComponentsInChildren(); + Material[] tMats_World = GetMaterials_RoadWorld(); + Material[] tMats_Marker = GetMaterials_RoadMarker(); + foreach (MeshRenderer MR in MRs) + { + tNameLower = MR.transform.name.ToLower(); + if (tNameLower.Contains("marker")) + { + if (tMats_Marker != null) + { + MR.sharedMaterials = tMats_Marker; + } + } + else if (tNameLower.Contains("cut")) + { + if (tMats_World != null) + { + MR.sharedMaterials = tMats_World; + } + } + } + + if (opt_bShouldersEnabled && MeshShoL != null) + { + MRs = MeshShoL.GetComponentsInChildren(); + tMats_World = GetMaterials_ShoulderWorld(); + tMats_Marker = GetMaterials_ShoulderMarker(); + foreach (MeshRenderer MR in MRs) + { + tNameLower = MR.transform.name.ToLower(); + if (tNameLower.Contains("marker")) + { + if (tMats_Marker != null) + { + MR.sharedMaterials = tMats_Marker; + } + } + else if (tNameLower.Contains("cut")) + { + if (tMats_World != null) + { + MR.sharedMaterials = tMats_World; + } + } + } + } + + if (opt_bShouldersEnabled && MeshShoR != null) + { + MRs = MeshShoR.GetComponentsInChildren(); + foreach (MeshRenderer MR in MRs) + { + tNameLower = MR.transform.name.ToLower(); + if (tNameLower.Contains("marker")) + { + if (tMats_Marker != null) + { + MR.sharedMaterials = tMats_Marker; + } + } + else if (tNameLower.Contains("cut")) + { + if (tMats_World != null) + { + MR.sharedMaterials = tMats_World; + } + } + } + } + } + + + public Material[] GetMaterials_RoadWorld() + { + int mCounter = 0; + if (RoadMaterial1 != null) + { + mCounter += 1; + if (RoadMaterial2 != null) + { + mCounter += 1; + if (RoadMaterial3 != null) + { + mCounter += 1; + if (RoadMaterial4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (RoadMaterial1 != null) + { + tMats[0] = RoadMaterial1; + if (RoadMaterial2 != null) + { + tMats[1] = RoadMaterial2; + if (RoadMaterial3 != null) + { + tMats[2] = RoadMaterial3; + if (RoadMaterial4 != null) + { + tMats[3] = RoadMaterial4; + } + } + } + } + return tMats; + } + else + { + return null; + } + } + + + public Material[] GetMaterials_RoadMarker() + { + int mCounter = 0; + if (RoadMaterialMarker1 != null) + { + mCounter += 1; + if (RoadMaterialMarker2 != null) + { + mCounter += 1; + if (RoadMaterialMarker3 != null) + { + mCounter += 1; + if (RoadMaterialMarker4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (RoadMaterialMarker1 != null) + { + tMats[0] = RoadMaterialMarker1; + if (RoadMaterialMarker2 != null) + { + tMats[1] = RoadMaterialMarker2; + if (RoadMaterialMarker3 != null) + { + tMats[2] = RoadMaterialMarker3; + if (RoadMaterialMarker4 != null) + { + tMats[3] = RoadMaterialMarker4; + } + } + } + } + return tMats; + } + else + { + return null; + } + } + + + public Material[] GetMaterials_ShoulderWorld() + { + if (!opt_bShouldersEnabled) + { + return null; + } + + int mCounter = 0; + if (ShoulderMaterial1 != null) + { + mCounter += 1; + if (ShoulderMaterial2 != null) + { + mCounter += 1; + if (ShoulderMaterial3 != null) + { + mCounter += 1; + if (ShoulderMaterial4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (ShoulderMaterial1 != null) + { + tMats[0] = ShoulderMaterial1; + if (ShoulderMaterial2 != null) + { + tMats[1] = ShoulderMaterial2; + if (ShoulderMaterial3 != null) + { + tMats[2] = ShoulderMaterial3; + if (ShoulderMaterial4 != null) + { + tMats[3] = ShoulderMaterial4; + } + } + } + } + return tMats; + } + else + { + return null; + } + } + + + public Material[] GetMaterials_ShoulderMarker() + { + if (!opt_bShouldersEnabled) + { + return null; + } + + int mCounter = 0; + if (ShoulderMaterialMarker1 != null) + { + mCounter += 1; + if (ShoulderMaterialMarker2 != null) + { + mCounter += 1; + if (ShoulderMaterialMarker3 != null) + { + mCounter += 1; + if (ShoulderMaterialMarker4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (ShoulderMaterialMarker1 != null) + { + tMats[0] = ShoulderMaterialMarker1; + if (ShoulderMaterialMarker2 != null) + { + tMats[1] = ShoulderMaterialMarker2; + if (ShoulderMaterialMarker3 != null) + { + tMats[2] = ShoulderMaterialMarker3; + if (ShoulderMaterialMarker4 != null) + { + tMats[3] = ShoulderMaterialMarker4; + } + } + } + } + return tMats; + } + else + { + return null; + } + } + #endregion + + + #region "Materials" + void CheckMats() + { + if (!opt_UseDefaultMaterials) + { + return; + } + + if (!RoadMaterial1) + { + RoadMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); + RoadMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + } + if (!RoadMaterialMarker1) + { + if (opt_Lanes == 2) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); + } + else if (opt_Lanes == 4) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); + } + else if (opt_Lanes == 6) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); + } + else + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); + } + + if (opt_Lanes == 2) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); + } + else if (opt_Lanes == 4) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-4L.mat"); + } + else if (opt_Lanes == 6) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-6L.mat"); + } + else + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); + } + } + if (opt_bShouldersEnabled && !ShoulderMaterial1) + { + ShoulderMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDShoulder1.mat"); + ShoulderMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + } + + if (opt_bShouldersEnabled && !RoadPhysicMaterial) + { + RoadPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDPavement.physicMaterial"); + } + if (opt_bShouldersEnabled && !ShoulderPhysicMaterial) + { + ShoulderPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDDirt.physicMaterial"); + } + } + + + public void SetDefaultMats() + { + if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Asphalt) + { + RoadMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); + RoadMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + + if (opt_Lanes == 2) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); + } + else if (opt_Lanes == 4) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-4L.mat"); + } + else if (opt_Lanes == 6) + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble-6L.mat"); + } + else + { + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDWhiteYellowDouble.mat"); + } + + if (opt_Lanes == 2) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); + } + else if (opt_Lanes == 4) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-4L.mat"); + } + else if (opt_Lanes == 6) + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks-6L.mat"); + } + else + { + RoadMaterialMarker2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDTireMarks.mat"); + } + + ShoulderMaterial1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDShoulder1.mat"); + ShoulderMaterial2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + + RoadPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDPavement.physicMaterial"); + ShoulderPhysicMaterial = GSD.Roads.GSDRoadUtilityEditor.GivePhysicsMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Physics/GSDDirt.physicMaterial"); + } + else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Dirt) + { + RoadMaterial1 = null; + RoadMaterial2 = null; + RoadMaterial3 = null; + RoadMaterial4 = null; + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDDirtRoad.mat"); + RoadMaterialMarker2 = null; + RoadMaterialMarker3 = null; + RoadMaterialMarker4 = null; + } + else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Brick) + { + RoadMaterial1 = null; + RoadMaterial2 = null; + RoadMaterial3 = null; + RoadMaterial4 = null; + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDBrickRoad.mat"); + RoadMaterialMarker2 = null; + RoadMaterialMarker3 = null; + RoadMaterialMarker4 = null; + } + else if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Cobblestone) + { + RoadMaterial1 = null; + RoadMaterial2 = null; + RoadMaterial3 = null; + RoadMaterial4 = null; + RoadMaterialMarker1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDCobblestoneRoad.mat"); + RoadMaterialMarker2 = null; + RoadMaterialMarker3 = null; + RoadMaterialMarker4 = null; + } + if (opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Brick + || opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Cobblestone + || opt_tRoadMaterialDropdown == RoadMaterialDropdownEnum.Dirt) + { + if (opt_Lanes > 2) + { + RoadMaterialMarker1 = new Material(RoadMaterialMarker1); + RoadMaterialMarker1.mainTextureScale *= new Vector2(opt_Lanes / 2, 1f); + } + } + + int mCount = GSDSpline.GetNodeCount(); + for (int i = 0; i < mCount; i++) + { + if (GSDSpline.mNodes[i] && GSDSpline.mNodes[i].bIsIntersection && GSDSpline.mNodes[i].GSDRI != null && GSDSpline.mNodes[i].GSDRI.bUseDefaultMaterials) + { + GSDSpline.mNodes[i].GSDRI.ResetMaterials_All(); + } + } + } + #endregion + + + public void Wireframes_Toggle() + { + MeshRenderer[] tMRs = transform.GetComponentsInChildren(); + Wireframes_Toggle_Help(ref tMRs); + + if (GSDSpline != null) + { + tMRs = GSDSpline.transform.GetComponentsInChildren(); + Wireframes_Toggle_Help(ref tMRs); + } + } + + + void Wireframes_Toggle_Help(ref MeshRenderer[] tMRs) + { + int tCount = tMRs.Length; + for (int i = 0; i < tCount; i++) + { + //EditorUtility.SetSelectedWireframeHidden(tMRs[i], !opt_GizmosEnabled); + EditorUtility.SetSelectedRenderState(tMRs[i], opt_GizmosEnabled ? EditorSelectedRenderState.Wireframe : EditorSelectedRenderState.Hidden); + } + } + +#endif + + + void Start() + { +#if UNITY_EDITOR + if (Application.isPlaying) + { + CleanRunTime(); + } +#else + this.enabled = false; +#endif + } + + +#if UNITY_EDITOR + //For compliance on submission rules: + public void UpdateGizmoOptions() + { + if (GSDSpline == null) + { + return; + } + GSDSplineN tNode = null; + + int mCount = GSDSpline.GetNodeCount(); + for (int i = 0; i < mCount; i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode != null) + { + tNode.opt_GizmosEnabled = opt_GizmosEnabled; + } + } + } + + + public void SetupUniqueIdentifier() + { + if (UID == null || UID.Length < 4) + { + UID = System.Guid.NewGuid().ToString(); + } + } + + + public void DuplicateRoad() + { + GameObject tRoadObj = GSDRS.AddRoad(); + UnityEditor.Undo.RegisterCreatedObjectUndo(tRoadObj, "Duplicate"); + + GSDRoad xRoad = tRoadObj.GetComponent(); + if (xRoad == null) + { + return; + } + + //Road editor options: + xRoad.opt_LaneWidth = opt_LaneWidth; //Done. + xRoad.opt_bShouldersEnabled = opt_bShouldersEnabled; //Disabled for now. Comprimises integrity of roads. + xRoad.opt_ShoulderWidth = opt_ShoulderWidth; //Done. + xRoad.opt_Lanes = opt_Lanes; //Done. + xRoad.opt_RoadDefinition = opt_RoadDefinition; //Done. + xRoad.opt_RoadCornerDefinition = opt_RoadCornerDefinition; //Disable for now. No point. + xRoad.opt_bRoadCuts = opt_bRoadCuts; + xRoad.opt_bShoulderCuts = opt_bShoulderCuts; + xRoad.opt_bDynamicCuts = opt_bDynamicCuts; + xRoad.opt_bMaxGradeEnabled = opt_bMaxGradeEnabled; + xRoad.opt_MaxGrade = opt_MaxGrade; + xRoad.opt_UseDefaultMaterials = opt_UseDefaultMaterials; + xRoad.opt_AutoUpdateInEditor = opt_AutoUpdateInEditor; + + xRoad.opt_TerrainSubtract_Match = opt_TerrainSubtract_Match; + xRoad.opt_bGSDRoadRaise = opt_bGSDRoadRaise; + + xRoad.opt_MatchHeightsDistance = opt_MatchHeightsDistance; + xRoad.opt_ClearDetailsDistance = opt_ClearDetailsDistance; + xRoad.opt_ClearDetailsDistanceHeight = opt_ClearDetailsDistanceHeight; + xRoad.opt_ClearTreesDistance = opt_ClearTreesDistance; + xRoad.opt_ClearTreesDistanceHeight = opt_ClearTreesDistanceHeight; + + xRoad.opt_HeightModEnabled = opt_HeightModEnabled; + xRoad.opt_DetailModEnabled = opt_DetailModEnabled; + xRoad.opt_TreeModEnabled = opt_TreeModEnabled; + + xRoad.opt_SaveTerrainHistoryOnDisk = opt_SaveTerrainHistoryOnDisk; + xRoad.opt_MagnitudeThreshold = opt_MagnitudeThreshold; + xRoad.opt_GizmosEnabled = opt_GizmosEnabled; + xRoad.opt_bMultithreading = opt_bMultithreading; + xRoad.opt_bSaveMeshes = opt_bSaveMeshes; + xRoad.opt_bUseMeshColliders = opt_bUseMeshColliders; + + xRoad.opt_tRoadMaterialDropdown = opt_tRoadMaterialDropdown; + xRoad.tRoadMaterialDropdownOLD = tRoadMaterialDropdownOLD; + + xRoad.RoadMaterial1 = RoadMaterial1; + xRoad.RoadMaterial2 = RoadMaterial2; + xRoad.RoadMaterial3 = RoadMaterial3; + xRoad.RoadMaterial4 = RoadMaterial4; + xRoad.RoadMaterialMarker1 = RoadMaterialMarker1; + xRoad.RoadMaterialMarker2 = RoadMaterialMarker2; + xRoad.RoadMaterialMarker3 = RoadMaterialMarker3; + xRoad.RoadMaterialMarker4 = RoadMaterialMarker4; + xRoad.ShoulderMaterial1 = ShoulderMaterial1; + xRoad.ShoulderMaterial2 = ShoulderMaterial2; + xRoad.ShoulderMaterial3 = ShoulderMaterial3; + xRoad.ShoulderMaterial4 = ShoulderMaterial4; + xRoad.ShoulderMaterialMarker1 = ShoulderMaterialMarker1; + xRoad.ShoulderMaterialMarker2 = ShoulderMaterialMarker2; + xRoad.ShoulderMaterialMarker3 = ShoulderMaterialMarker3; + xRoad.ShoulderMaterialMarker4 = ShoulderMaterialMarker4; + + xRoad.RoadPhysicMaterial = RoadPhysicMaterial; + xRoad.ShoulderPhysicMaterial = ShoulderPhysicMaterial; + + xRoad.GSDSpline.Setup_Trigger(); + + Selection.activeGameObject = xRoad.transform.gameObject; + } + + + private void FixZ() + { + FixZ_Mobile(); + } + + + private void FixZ_Mobile() + { + //This road: + Object[] tMarkerObjs = transform.GetComponentsInChildren(); + Vector3 tVect = default(Vector3); + foreach (MeshRenderer MR in tMarkerObjs) + { + if (MR.transform.name.Contains("Marker")) + { + tVect = new Vector3(0f, 0.02f, 0f); + MR.transform.localPosition = tVect; + } + else if (MR.transform.name.Contains("SCut") || MR.transform.name.Contains("RoadCut") + || MR.transform.name.Contains("ShoulderR") + || MR.transform.name.Contains("ShoulderL")) + { + tVect = MR.transform.position; + tVect.y += 0.01f; + MR.transform.position = tVect; + } + else if (MR.transform.name.Contains("RoadMesh")) + { + tVect = MR.transform.position; + tVect.y += 0.02f; + MR.transform.position = tVect; + } + else if (MR.transform.name.Contains("Pavement")) + { + tVect = MR.transform.position; + tVect.y -= 0.01f; + MR.transform.position = tVect; + } + } + + + //Intersections (all): + tMarkerObjs = GSDRS.GetComponentsInChildren(); + foreach (MeshRenderer MR in tMarkerObjs) + { + if (MR.transform.name.Contains("CenterMarkers")) + { + tVect = new Vector3(0f, 0.02f, 0f); + MR.transform.localPosition = tVect; + } + else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Lane")) + { + tVect = new Vector3(0f, 0.02f, 0f); + MR.transform.localPosition = tVect; + } + else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Stretch")) + { + tVect = new Vector3(0f, 0.03f, 0f); + MR.transform.localPosition = tVect; + } + else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Tiled")) + { + tVect = new Vector3(0f, 0.01f, 0f); + MR.transform.localPosition = tVect; + } + } + } + + + private void FixZ_Win() + { + //This road: + Object[] tMarkerObjs = transform.GetComponentsInChildren(); + Vector3 tVect = default(Vector3); + foreach (MeshRenderer MR in tMarkerObjs) + { + if (MR.transform.name.Contains("Marker")) + { + tVect = new Vector3(0f, 0.01f, 0f); + MR.transform.localPosition = tVect; + } + } + + + //Intersections (all): + tMarkerObjs = Object.FindObjectsOfType(); + foreach (MeshRenderer MR in tMarkerObjs) + { + if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Lane")) + { + tVect = new Vector3(0f, 0.01f, 0f); + MR.transform.localPosition = tVect; + } + else if (MR.transform.name.Contains("-Inter") && MR.transform.name.Contains("-Stretch")) + { + tVect = new Vector3(0f, 0.01f, 0f); + MR.transform.localPosition = tVect; + } + } + } +#endif +} \ No newline at end of file diff --git a/GSDRoadAutomation.cs b/GSDRoadAutomation.cs index b46f34fe..d474dccd 100755 --- a/GSDRoadAutomation.cs +++ b/GSDRoadAutomation.cs @@ -1,351 +1,384 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -using System.Collections; -using System.IO; -using System.Text; -using System.Runtime.Serialization.Formatters.Binary; -using System.Runtime.Serialization; -#endif -namespace GSD.Roads -{ -#if UNITY_EDITOR - // Proper automation flow: - // 1. Make sure opt_bAllowRoadUpdates in the scene's GSDRoadSystem is set to FALSE. - // 2. Create your roads programmatically via CreateRoad_Programmatically (pass it the road, and then the points in a list) - // a. Optionally you can do it via CreateNode_Programmatically and InsertNode_Programmatically - // 3. Call CreateIntersections_ProgrammaticallyForRoad for each road to create intersections automatically at intersection points. - // 4. Set opt_bAllowRoadUpdates in the scene's GSDRoadSystem is set to TRUE. - // 5. Call GSDRoadSystem.UpdateAllRoads(); - // 6. Call GSDRoadSystem.UpdateAllRoads(); after step #5 completes. - // - // See "GSDUnitTests.cs" for an example on automation (ignore unit test #3). - - - public static class GSDRoadAutomation - { - /// - /// Use this to create nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. - /// - /// The road system to create nodes on. - /// The location of the newly created node. - /// - public static GSDRoad CreateRoad_Programmatically(GSDRoadSystem GSDRS, ref List tLocs) - { - GameObject tRoadObj = GSDRS.AddRoad(false); - GSDRoad tRoad = tRoadObj.GetComponent(); - - int hCount = tLocs.Count; - for (int i = 0; i < hCount; i++) - { - CreateNode_Programmatically(tRoad, tLocs[i]); - } - - return tRoad; - } - - - /// - /// Use this to create nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. - /// - /// The road system to create nodes on. - /// The location of the newly created node. - /// - public static GSDSplineN CreateNode_Programmatically(GSDRoad tRoad, Vector3 NodeLocation) - { - int SplineChildCount = tRoad.GSDSpline.transform.childCount; - GameObject tNodeObj = new GameObject("Node" + (SplineChildCount + 1).ToString()); - GSDSplineN tNode = tNodeObj.AddComponent(); //Add the node component. - - //Set node location: - if (NodeLocation.y < 0.03f) { NodeLocation.y = 0.03f; } //Make sure it doesn't try to create a node below 0 height. - tNodeObj.transform.position = NodeLocation; - - //Set the node's parent: - tNodeObj.transform.parent = tRoad.GSDSplineObj.transform; - - //Set the idOnSpline: - tNode.idOnSpline = (SplineChildCount + 1); - tNode.GSDSpline = tRoad.GSDSpline; - - //Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates - tRoad.UpdateRoad(); - - return tNode; - } - - /// - /// Use this to insert nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. - /// - /// The road system to insert nodes in. - /// The location of the newly inserted node. - /// - public static GSDSplineN InsertNode_Programmatically(GSDRoad RS, Vector3 NodeLocation) - { - GameObject tNodeObj; - Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); - tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); - - //Set node location: - if (NodeLocation.y < 0.03f) { NodeLocation.y = 0.03f; } //Make sure it doesn't try to create a node below 0 height. - tNodeObj.transform.position = NodeLocation; - - //Set the node's parent: - tNodeObj.transform.parent = RS.GSDSplineObj.transform; - - int cCount = RS.GSDSpline.mNodes.Count; - - //Get the closet param on spline: - float tParam = RS.GSDSpline.GetClosestParam(NodeLocation, false, true); - - bool bEndInsert = false; - bool bZeroInsert = false; - int iStart = 0; - if (GSDRootUtil.IsApproximately(tParam, 0f, 0.0001f)) - { - bZeroInsert = true; - iStart = 0; - } - else if (GSDRootUtil.IsApproximately(tParam, 1f, 0.0001f)) - { - //Inserted at end, switch to create node instead: - Object.DestroyImmediate(tNodeObj); - return CreateNode_Programmatically(RS, NodeLocation); - } - - //Figure out where to insert the node: - for (int i = 0; i < cCount; i++) - { - GSDSplineN xNode = RS.GSDSpline.mNodes[i]; - if (!bZeroInsert && !bEndInsert) - { - if (tParam > xNode.tTime) - { - iStart = xNode.idOnSpline + 1; - } - } - } - for (int i = iStart; i < cCount; i++) - { - RS.GSDSpline.mNodes[i].idOnSpline += 1; - } - - GSDSplineN tNode = tNodeObj.AddComponent(); - tNode.GSDSpline = RS.GSDSpline; - tNode.idOnSpline = iStart; - tNode.pos = NodeLocation; - RS.GSDSpline.mNodes.Insert(iStart, tNode); - - //Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates - RS.UpdateRoad(); - - return tNode; - } - - - /// - /// Creates intersections where this road intersects with other roads. - /// - /// The primary road to create intersections for. - /// Stop signs, traffic lights #1 (US) or traffic lights #2 (Euro). Defaults to none. - /// Intersection type: No turn lane, left turn lane or both turn lanes. Defaults to no turn lane. - public static void CreateIntersections_ProgrammaticallyForRoad(GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType = GSDRoadIntersection.iStopTypeEnum.None, GSDRoadIntersection.RoadTypeEnum rType = GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - /* - General logic: - 20m increments to gather collection of which roads intersect - 2m increments to find actual intersection point - each 2m, primary road checks all intersecting array for an intersection. - find intersection point - if any intersections already within 75m or 100m, dont create intersection here - check if nodes within 50m, if more than one just grab closest, and move it to intersecting point - if no node within 50m, add - create intersection with above two nodes - */ - - Object[] GSDRoadObjs = Object.FindObjectsOfType(); - - //20m increments to gather collection of which roads intersect - List xRoads = new List(); - foreach (GSDRoad xRoad in GSDRoadObjs) - { - if (tRoad != xRoad) - { - float EarlyDistanceCheckMeters = 10f; - float EarlyDistanceCheckThreshold = 50f; - bool EarlyDistanceFound = false; - float tRoadMod = EarlyDistanceCheckMeters / tRoad.GSDSpline.distance; - float xRoadMod = EarlyDistanceCheckMeters / xRoad.GSDSpline.distance; - Vector3 tVect1 = default(Vector3); - Vector3 tVect2 = default(Vector3); - for (float i = 0f; i < 1.0000001f; i += tRoadMod) - { - tVect1 = tRoad.GSDSpline.GetSplineValue(i); - for (float x = 0f; x < 1.000001f; x += xRoadMod) - { - tVect2 = xRoad.GSDSpline.GetSplineValue(x); - if (Vector3.Distance(tVect1, tVect2) < EarlyDistanceCheckThreshold) - { - if (!xRoads.Contains(xRoad)) - { - xRoads.Add(xRoad); - } - EarlyDistanceFound = true; - break; - } - } - if (EarlyDistanceFound) { break; } - } - } - } - - //See if any end point nodes are on top of each other already since T might not intersect all the time.: - List> tKVP = new List>(); - foreach (GSDRoad xRoad in xRoads) - { - foreach (GSDSplineN IntersectionNode1 in tRoad.GSDSpline.mNodes) - { - if (IntersectionNode1.bIsIntersection || !IntersectionNode1.IsLegitimate()) { continue; } - foreach (GSDSplineN IntersectionNode2 in xRoad.GSDSpline.mNodes) - { - if (IntersectionNode2.bIsIntersection || !IntersectionNode2.IsLegitimate()) { continue; } - if (IntersectionNode1.transform.position == IntersectionNode2.transform.position) - { - //Only do T intersections and let the next algorithm handle the +, since T might not intersect all the time. - if (IntersectionNode1.bIsEndPoint || IntersectionNode2.bIsEndPoint) - { - tKVP.Add(new KeyValuePair(IntersectionNode1, IntersectionNode2)); - } - } - } - } - } - foreach (KeyValuePair KVP in tKVP) - { - //Now create the fucking intersection: - GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(KVP.Key, KVP.Value); - GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent(); - GSDRI_JustCreated.iStopType = iStopType; - GSDRI_JustCreated.rType = rType; - } - - //Main algorithm: 2m increments to find actual intersection point: - foreach (GSDRoad xRoad in xRoads) - { - if (tRoad != xRoad) - { - //Debug.Log("Checking road: " + xRoad.transform.name); - float DistanceCheckMeters = 2f; - bool EarlyDistanceFound = false; - float tRoadMod = DistanceCheckMeters / tRoad.GSDSpline.distance; - float xRoadMod = DistanceCheckMeters / xRoad.GSDSpline.distance; - Vector3 tVect = default(Vector3); - Vector2 iVect1 = default(Vector2); - Vector2 iVect2 = default(Vector2); - Vector2 xVect1 = default(Vector2); - Vector2 xVect2 = default(Vector2); - Vector2 IntersectPoint2D = default(Vector2); - float i2 = 0f; - for (float i = 0f; i < 1.0000001f; i += tRoadMod) - { - i2 = (i + tRoadMod); - if (i2 > 1f) { i2 = 1f; } - tVect = tRoad.GSDSpline.GetSplineValue(i); - iVect1 = new Vector2(tVect.x, tVect.z); - tVect = tRoad.GSDSpline.GetSplineValue(i2); - iVect2 = new Vector2(tVect.x, tVect.z); - - float x2 = 0f; - for (float x = 0f; x < 1.000001f; x += xRoadMod) - { - x2 = (x + xRoadMod); - if (x2 > 1f) { x2 = 1f; } - tVect = xRoad.GSDSpline.GetSplineValue(x); - xVect1 = new Vector2(tVect.x, tVect.z); - tVect = xRoad.GSDSpline.GetSplineValue(x2); - xVect2 = new Vector2(tVect.x, tVect.z); - - //Now see if these two lines intersect: - if (GSD.GSDRootUtil.Intersects2D(ref iVect1, ref iVect2, ref xVect1, ref xVect2, out IntersectPoint2D)) - { - //Get height of intersection on primary road: - float tHeight = 0f; - float hParam = tRoad.GSDSpline.GetClosestParam(new Vector3(IntersectPoint2D.x, 0f, IntersectPoint2D.y)); - Vector3 hVect = tRoad.GSDSpline.GetSplineValue(hParam); - tHeight = hVect.y; - - //if any intersections already within 75m or 100m, dont create intersection here - Object[] AllInterectionObjects = Object.FindObjectsOfType(); - foreach (GSDRoadIntersection GSDRI in AllInterectionObjects) - { - if (Vector2.Distance(new Vector2(GSDRI.transform.position.x, GSDRI.transform.position.z), IntersectPoint2D) < 100f) - { - goto NoIntersectionCreation; - } - } - - GSDSplineN IntersectionNode1 = null; - GSDSplineN IntersectionNode2 = null; - Vector3 IntersectionPoint3D = new Vector3(IntersectPoint2D.x, tHeight, IntersectPoint2D.y); - //Debug.Log("Instersect found road: " + xRoad.transform.name + " at point: " + IntersectionPoint3D.ToString()); - - //Check primary road if any nodes are nearby and usable for intersection - foreach (GSDSplineN tNode in tRoad.GSDSpline.mNodes) - { - if (tNode.IsLegitimate()) - { - if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) - { - IntersectionNode1 = tNode; - IntersectionNode1.transform.position = IntersectionPoint3D; - IntersectionNode1.pos = IntersectionPoint3D; - break; - } - } - } - - //Check secondary road if any nodes are nearby and usable for intersection - foreach (GSDSplineN tNode in xRoad.GSDSpline.mNodes) - { - if (tNode.IsLegitimate()) - { - if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) - { - IntersectionNode2 = tNode; - IntersectionNode2.transform.position = IntersectionPoint3D; - IntersectionNode2.pos = IntersectionPoint3D; - break; - } - } - } - - //Check if any of the nodes are null. If so, need to insert node. And maybe update it. - if (IntersectionNode1 == null) - { - IntersectionNode1 = InsertNode_Programmatically(tRoad, IntersectionPoint3D); - } - if (IntersectionNode2 == null) - { - IntersectionNode2 = InsertNode_Programmatically(xRoad, IntersectionPoint3D); - } - - //Now create the fucking intersection: - GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(IntersectionNode1, IntersectionNode2); - GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent(); - GSDRI_JustCreated.iStopType = iStopType; - GSDRI_JustCreated.rType = rType; - } - - NoIntersectionCreation: - //Gibberish to get rid of warnings: - int xxx = 1; - if (xxx == 1) { xxx = 2; } - } - if (EarlyDistanceFound) { break; } - } - } - } - } - } -#endif -} +#region Imports +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +using System.Collections; +using System.IO; +using System.Text; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; +#endif +#endregion + + +namespace GSD.Roads +{ +#if UNITY_EDITOR + /* Proper automation flow: + * 1. Make sure opt_bAllowRoadUpdates in the scene's GSDRoadSystem is set to FALSE. + * 2. Create your roads programmatically via CreateRoad_Programmatically (pass it the road, and then the points in a list) + * a. Optionally you can do it via CreateNode_Programmatically and InsertNode_Programmatically + * 3. Call CreateIntersections_ProgrammaticallyForRoad for each road to create intersections automatically at intersection points. + * 4. Set opt_bAllowRoadUpdates in the scene's GSDRoadSystem is set to TRUE. + * 5. Call GSDRoadSystem.UpdateAllRoads(); + * 6. Call GSDRoadSystem.UpdateAllRoads(); after step #5 completes. + * + * See "GSDUnitTests.cs" for an example on automation (ignore unit test #3). + */ + + + public static class GSDRoadAutomation + { + /// + /// Use this to create nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. + /// + /// The road system to create nodes on. + /// The location of the newly created node. + /// + public static GSDRoad CreateRoad_Programmatically(GSDRoadSystem GSDRS, ref List tLocs) + { + GameObject tRoadObj = GSDRS.AddRoad(false); + GSDRoad tRoad = tRoadObj.GetComponent(); + + int hCount = tLocs.Count; + for (int index = 0; index < hCount; index++) + { + CreateNode_Programmatically(tRoad, tLocs[index]); + } + + return tRoad; + } + + + /// + /// Use this to create nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. + /// + /// The road system to create nodes on. + /// The location of the newly created node. + /// + public static GSDSplineN CreateNode_Programmatically(GSDRoad tRoad, Vector3 NodeLocation) + { + int SplineChildCount = tRoad.GSDSpline.transform.childCount; + GameObject tNodeObj = new GameObject("Node" + (SplineChildCount + 1).ToString()); + GSDSplineN tNode = tNodeObj.AddComponent(); //Add the node component. + + //Set node location: + if (NodeLocation.y < 0.03f) + { + NodeLocation.y = 0.03f; + } //Make sure it doesn't try to create a node below 0 height. + tNodeObj.transform.position = NodeLocation; + + //Set the node's parent: + tNodeObj.transform.parent = tRoad.GSDSplineObj.transform; + + //Set the idOnSpline: + tNode.idOnSpline = (SplineChildCount + 1); + tNode.GSDSpline = tRoad.GSDSpline; + + //Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates + tRoad.UpdateRoad(); + + return tNode; + } + + + /// + /// Use this to insert nodes via coding while in editor mode. Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates. + /// + /// The road system to insert nodes in. + /// The location of the newly inserted node. + /// + public static GSDSplineN InsertNode_Programmatically(GSDRoad RS, Vector3 NodeLocation) + { + GameObject tNodeObj; + Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); + tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); + + //Set node location: + if (NodeLocation.y < 0.03f) + { + NodeLocation.y = 0.03f; //Make sure it doesn't try to create a node below 0 height. + } + tNodeObj.transform.position = NodeLocation; + + //Set the node's parent: + tNodeObj.transform.parent = RS.GSDSplineObj.transform; + + int cCount = RS.GSDSpline.mNodes.Count; + + //Get the closet param on spline: + float tParam = RS.GSDSpline.GetClosestParam(NodeLocation, false, true); + + bool bEndInsert = false; + bool bZeroInsert = false; + int iStart = 0; + if (GSDRootUtil.IsApproximately(tParam, 0f, 0.0001f)) + { + bZeroInsert = true; + iStart = 0; + } + else if (GSDRootUtil.IsApproximately(tParam, 1f, 0.0001f)) + { + //Inserted at end, switch to create node instead: + Object.DestroyImmediate(tNodeObj); + return CreateNode_Programmatically(RS, NodeLocation); + } + + //Figure out where to insert the node: + for (int index = 0; index < cCount; index++) + { + GSDSplineN xNode = RS.GSDSpline.mNodes[index]; + if (!bZeroInsert && !bEndInsert) + { + if (tParam > xNode.tTime) + { + iStart = xNode.idOnSpline + 1; + } + } + } + for (int index = iStart; index < cCount; index++) + { + RS.GSDSpline.mNodes[index].idOnSpline += 1; + } + + GSDSplineN tNode = tNodeObj.AddComponent(); + tNode.GSDSpline = RS.GSDSpline; + tNode.idOnSpline = iStart; + tNode.pos = NodeLocation; + RS.GSDSpline.mNodes.Insert(iStart, tNode); + + //Make sure opt_bAllowRoadUpdates is set to false in RS.GSDRS.opt_bAllowRoadUpdates + RS.UpdateRoad(); + + return tNode; + } + + + /// + /// Creates intersections where this road intersects with other roads. + /// + /// The primary road to create intersections for. + /// Stop signs, traffic lights #1 (US) or traffic lights #2 (Euro). Defaults to none. + /// Intersection type: No turn lane, left turn lane or both turn lanes. Defaults to no turn lane. + public static void CreateIntersections_ProgrammaticallyForRoad(GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType = GSDRoadIntersection.iStopTypeEnum.None, GSDRoadIntersection.RoadTypeEnum rType = GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + /* + General logic: + 20m increments to gather collection of which roads intersect + 2m increments to find actual intersection point + each 2m, primary road checks all intersecting array for an intersection. + find intersection point + if any intersections already within 75m or 100m, dont create intersection here + check if nodes within 50m, if more than one just grab closest, and move it to intersecting point + if no node within 50m, add + create intersection with above two nodes + */ + + Object[] GSDRoadObjs = Object.FindObjectsOfType(); + + //20m increments to gather collection of which roads intersect + List xRoads = new List(); + foreach (GSDRoad xRoad in GSDRoadObjs) + { + if (tRoad != xRoad) + { + float EarlyDistanceCheckMeters = 10f; + float EarlyDistanceCheckThreshold = 50f; + bool EarlyDistanceFound = false; + float tRoadMod = EarlyDistanceCheckMeters / tRoad.GSDSpline.distance; + float xRoadMod = EarlyDistanceCheckMeters / xRoad.GSDSpline.distance; + Vector3 tVect1 = default(Vector3); + Vector3 tVect2 = default(Vector3); + for (float index = 0f; index < 1.0000001f; index += tRoadMod) + { + tVect1 = tRoad.GSDSpline.GetSplineValue(index); + for (float x = 0f; x < 1.000001f; x += xRoadMod) + { + tVect2 = xRoad.GSDSpline.GetSplineValue(x); + if (Vector3.Distance(tVect1, tVect2) < EarlyDistanceCheckThreshold) + { + if (!xRoads.Contains(xRoad)) + { + xRoads.Add(xRoad); + } + EarlyDistanceFound = true; + break; + } + } + if (EarlyDistanceFound) + { + break; + } + } + } + } + + //See if any end point nodes are on top of each other already since T might not intersect all the time.: + List> tKVP = new List>(); + foreach (GSDRoad xRoad in xRoads) + { + foreach (GSDSplineN IntersectionNode1 in tRoad.GSDSpline.mNodes) + { + if (IntersectionNode1.bIsIntersection || !IntersectionNode1.IsLegitimate()) + { + continue; + } + foreach (GSDSplineN IntersectionNode2 in xRoad.GSDSpline.mNodes) + { + if (IntersectionNode2.bIsIntersection || !IntersectionNode2.IsLegitimate()) + { + continue; + } + if (IntersectionNode1.transform.position == IntersectionNode2.transform.position) + { + //Only do T intersections and let the next algorithm handle the +, since T might not intersect all the time. + if (IntersectionNode1.bIsEndPoint || IntersectionNode2.bIsEndPoint) + { + tKVP.Add(new KeyValuePair(IntersectionNode1, IntersectionNode2)); + } + } + } + } + } + foreach (KeyValuePair KVP in tKVP) + { + //Now create the fucking intersection: + GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(KVP.Key, KVP.Value); + GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent(); + GSDRI_JustCreated.iStopType = iStopType; + GSDRI_JustCreated.rType = rType; + } + + //Main algorithm: 2m increments to find actual intersection point: + foreach (GSDRoad xRoad in xRoads) + { + if (tRoad != xRoad) + { + //Debug.Log("Checking road: " + xRoad.transform.name); + float DistanceCheckMeters = 2f; + bool EarlyDistanceFound = false; + float tRoadMod = DistanceCheckMeters / tRoad.GSDSpline.distance; + float xRoadMod = DistanceCheckMeters / xRoad.GSDSpline.distance; + Vector3 tVect = default(Vector3); + Vector2 iVect1 = default(Vector2); + Vector2 iVect2 = default(Vector2); + Vector2 xVect1 = default(Vector2); + Vector2 xVect2 = default(Vector2); + Vector2 IntersectPoint2D = default(Vector2); + float i2 = 0f; + for (float index = 0f; index < 1.0000001f; index += tRoadMod) + { + i2 = (index + tRoadMod); + if (i2 > 1f) + { + i2 = 1f; + } + tVect = tRoad.GSDSpline.GetSplineValue(index); + iVect1 = new Vector2(tVect.x, tVect.z); + tVect = tRoad.GSDSpline.GetSplineValue(i2); + iVect2 = new Vector2(tVect.x, tVect.z); + + float x2 = 0f; + for (float x = 0f; x < 1.000001f; x += xRoadMod) + { + x2 = (x + xRoadMod); + if (x2 > 1f) + { + x2 = 1f; + } + tVect = xRoad.GSDSpline.GetSplineValue(x); + xVect1 = new Vector2(tVect.x, tVect.z); + tVect = xRoad.GSDSpline.GetSplineValue(x2); + xVect2 = new Vector2(tVect.x, tVect.z); + + //Now see if these two lines intersect: + if (GSD.GSDRootUtil.Intersects2D(ref iVect1, ref iVect2, ref xVect1, ref xVect2, out IntersectPoint2D)) + { + //Get height of intersection on primary road: + float tHeight = 0f; + float hParam = tRoad.GSDSpline.GetClosestParam(new Vector3(IntersectPoint2D.x, 0f, IntersectPoint2D.y)); + Vector3 hVect = tRoad.GSDSpline.GetSplineValue(hParam); + tHeight = hVect.y; + + //if any intersections already within 75m or 100m, dont create intersection here + Object[] AllInterectionObjects = Object.FindObjectsOfType(); + foreach (GSDRoadIntersection GSDRI in AllInterectionObjects) + { + if (Vector2.Distance(new Vector2(GSDRI.transform.position.x, GSDRI.transform.position.z), IntersectPoint2D) < 100f) + { + goto NoIntersectionCreation; + } + } + + GSDSplineN IntersectionNode1 = null; + GSDSplineN IntersectionNode2 = null; + Vector3 IntersectionPoint3D = new Vector3(IntersectPoint2D.x, tHeight, IntersectPoint2D.y); + //Debug.Log("Instersect found road: " + xRoad.transform.name + " at point: " + IntersectionPoint3D.ToString()); + + //Check primary road if any nodes are nearby and usable for intersection + foreach (GSDSplineN tNode in tRoad.GSDSpline.mNodes) + { + if (tNode.IsLegitimate()) + { + if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) + { + IntersectionNode1 = tNode; + IntersectionNode1.transform.position = IntersectionPoint3D; + IntersectionNode1.pos = IntersectionPoint3D; + break; + } + } + } + + //Check secondary road if any nodes are nearby and usable for intersection + foreach (GSDSplineN tNode in xRoad.GSDSpline.mNodes) + { + if (tNode.IsLegitimate()) + { + if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) + { + IntersectionNode2 = tNode; + IntersectionNode2.transform.position = IntersectionPoint3D; + IntersectionNode2.pos = IntersectionPoint3D; + break; + } + } + } + + //Check if any of the nodes are null. If so, need to insert node. And maybe update it. + if (IntersectionNode1 == null) + { + IntersectionNode1 = InsertNode_Programmatically(tRoad, IntersectionPoint3D); + } + if (IntersectionNode2 == null) + { + IntersectionNode2 = InsertNode_Programmatically(xRoad, IntersectionPoint3D); + } + + //Now create the fucking intersection: + GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(IntersectionNode1, IntersectionNode2); + GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent(); + GSDRI_JustCreated.iStopType = iStopType; + GSDRI_JustCreated.rType = rType; + } + + NoIntersectionCreation: + //Gibberish to get rid of warnings: + int xxx = 1; + if (xxx == 1) + { + xxx = 2; + } + } + if (EarlyDistanceFound) + { + break; + } + } + } + } + } + } +#endif +} \ No newline at end of file diff --git a/GSDRoadConnector.cs b/GSDRoadConnector.cs index cd6ef715..74ae4e41 100644 --- a/GSDRoadConnector.cs +++ b/GSDRoadConnector.cs @@ -1,73 +1,85 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif -[ExecuteInEditMode] -public class GSDRoadConnector : MonoBehaviour -{ - public GSDSplineN connectedNode; - [HideInInspector] - public GSDOffRoadObject obj { get { return transform.parent.GetComponent(); } } - -#if UNITY_EDITOR - void OnDrawGizmos() - { - Gizmos.color = GSDOffRoadObject.Color_NodeOffRoadColor; - Gizmos.DrawCube(transform.position + new Vector3(0f, 6f, 0f), new Vector3(2f, 11f, 2f)); - } - void OnDrawGizmosSelected() - { - Gizmos.color = GSDOffRoadObject.Color_NodeOffRoadSelectedColor; - Gizmos.DrawCube(transform.position + new Vector3(0f, 6.25f, 0f), new Vector3(3.5f, 12.5f, 3.5f)); - } - - public void ConnectToNode(GSDSplineN node) - { - Debug.Log("Would connect to " + node); - connectedNode = node; - connectedNode.transform.position = transform.position; - connectedNode.GSDSpline.tRoad.UpdateRoad(); - } - - // Update is called once per frame - void Update() - { - if (connectedNode != null) - { - if (obj == null) - { - Debug.LogError("Parent should have GSDOffRoadObject component attached"); - } - if (connectedNode.transform.position != transform.position) - { - connectedNode.transform.position = transform.position; - connectedNode.GSDSpline.tRoad.UpdateRoad(); - } - } - } -#endif -} - -#if UNITY_EDITOR -[CustomEditor(typeof(GSDRoadConnector))] -public class GSDRoadConnectorEditor : Editor -{ - public GSDRoadConnector tConnector { get { return (GSDRoadConnector)target; } } - public override void OnInspectorGUI() - { - if (tConnector.connectedNode != null) - { - EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Off-road connection:", EditorStyles.boldLabel); - EditorGUILayout.LabelField(tConnector.connectedNode.GSDSpline.tRoad.name + " to " + tConnector.obj.name); - if (GUILayout.Button("Break connection")) - { - tConnector.connectedNode = null; - } - EditorGUILayout.EndVertical(); - } - } -} +#region Imports +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif +#endregion + + +[ExecuteInEditMode] +public class GSDRoadConnector : MonoBehaviour +{ + public GSDSplineN connectedNode; + [HideInInspector] + public GSDOffRoadObject obj { get { return transform.parent.GetComponent(); } } + + +#if UNITY_EDITOR + void OnDrawGizmos() + { + Gizmos.color = GSDOffRoadObject.Color_NodeOffRoadColor; + Gizmos.DrawCube(transform.position + new Vector3(0f, 6f, 0f), new Vector3(2f, 11f, 2f)); + } + + + void OnDrawGizmosSelected() + { + Gizmos.color = GSDOffRoadObject.Color_NodeOffRoadSelectedColor; + Gizmos.DrawCube(transform.position + new Vector3(0f, 6.25f, 0f), new Vector3(3.5f, 12.5f, 3.5f)); + } + + + public void ConnectToNode(GSDSplineN node) + { + Debug.Log("Would connect to " + node); + connectedNode = node; + connectedNode.transform.position = transform.position; + connectedNode.GSDSpline.tRoad.UpdateRoad(); + } + + + // Update is called once per frame + void Update() + { + if (connectedNode != null) + { + if (obj == null) + { + Debug.LogError("Parent should have GSDOffRoadObject component attached"); + } + if (connectedNode.transform.position != transform.position) + { + connectedNode.transform.position = transform.position; + connectedNode.GSDSpline.tRoad.UpdateRoad(); + } + } + } +#endif +} + + +#if UNITY_EDITOR +[CustomEditor(typeof(GSDRoadConnector))] +public class GSDRoadConnectorEditor : Editor +{ + public GSDRoadConnector tConnector { get { return (GSDRoadConnector) target; } } + + + public override void OnInspectorGUI() + { + if (tConnector.connectedNode != null) + { + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Off-road connection:", EditorStyles.boldLabel); + EditorGUILayout.LabelField(tConnector.connectedNode.GSDSpline.tRoad.name + " to " + tConnector.obj.name); + if (GUILayout.Button("Break connection")) + { + tConnector.connectedNode = null; + } + EditorGUILayout.EndVertical(); + } + } +} #endif \ No newline at end of file diff --git a/GSDRoadEdgeObjects.cs b/GSDRoadEdgeObjects.cs index 22b09fbc..f5297890 100755 --- a/GSDRoadEdgeObjects.cs +++ b/GSDRoadEdgeObjects.cs @@ -7,6 +7,8 @@ using System.IO; #endif #endregion + + namespace GSD.Roads.EdgeObjects { #if UNITY_EDITOR @@ -27,11 +29,13 @@ public class EdgeObjectMaker public string EdgeMaterial2String = null; public bool bMatchTerrain = true; + //Temp editor buffers: public bool bEdgeSignLabelInit = false; public bool bEdgeSignLabel = false; public string EdgeSignLabel = ""; + public bool bCombineMesh = false; public bool bCombineMeshCollider = false; public GameObject MasterObj = null; @@ -43,7 +47,8 @@ public class EdgeObjectMaker public bool bToggle = false; public bool bIsBridge = false; - //Horizontal offsets: + + #region Horizontal offsets: public float HorizontalSep = 5f; public AnimationCurve HorizontalCurve; public float HorizCurve_tempchecker1 = 0f; @@ -54,7 +59,10 @@ public class EdgeObjectMaker public float HorizCurve_tempchecker6 = 0f; public float HorizCurve_tempchecker7 = 0f; public float HorizCurve_tempchecker8 = 0f; - //Vertical offsets: + #endregion + + + #region Vertical offsets: public float VerticalRaise = 0f; public AnimationCurve VerticalCurve; public float VerticalCurve_tempchecker1 = 0f; @@ -65,24 +73,39 @@ public class EdgeObjectMaker public float VerticalCurve_tempchecker6 = 0f; public float VerticalCurve_tempchecker7 = 0f; public float VerticalCurve_tempchecker8 = 0f; + #endregion + + // Custom Rotation public Vector3 CustomRotation = default(Vector3); public bool bOncomingRotation = true; + + + // EdgeObject is static public bool bStatic = true; + + // The CustomScale of the EdgeObject public Vector3 CustomScale = new Vector3(1f, 1f, 1f); + + // Start and EndTime public float StartTime = 0f; public float EndTime = 1f; + + public float SingleOnlyBridgePercent = 0f; public Vector3 StartPos = default(Vector3); public Vector3 EndPos = default(Vector3); public bool bSingle = false; + + // Should it be only on a single position public float SinglePosition; public bool bStartMatchRoadDefinition = false; public float StartMatchRoadDef = 0f; + // EdgeObjectName public string tName = "EdgeObject"; public string ThumbString = ""; public string Desc = ""; @@ -90,13 +113,14 @@ public class EdgeObjectMaker public EdgeObjectEditorMaker EM; + public EdgeObjectMaker Copy() { EdgeObjectMaker EOM = new EdgeObjectMaker(); EOM.EdgeObjectString = EdgeObjectString; #if UNITY_EDITOR - EOM.EdgeObject = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeObjectString, typeof(GameObject)); + EOM.EdgeObject = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeObjectString, typeof(GameObject)); #endif EOM.bIsGSD = bIsGSD; @@ -136,9 +160,9 @@ public EdgeObjectMaker Copy() EOM.VerticalCurve = new AnimationCurve(); if (VerticalCurve != null && VerticalCurve.keys.Length > 0) { - for (int i = 0; i < VerticalCurve.keys.Length; i++) + for (int index = 0; index < VerticalCurve.keys.Length; index++) { - EOM.VerticalCurve.AddKey(VerticalCurve.keys[i]); + EOM.VerticalCurve.AddKey(VerticalCurve.keys[index]); } } @@ -161,12 +185,15 @@ public EdgeObjectMaker Copy() return EOM; } + public void UpdatePositions() { StartPos = tNode.GSDSpline.GetSplineValue(StartTime); - EndPos = tNode.GSDSpline.GetSplineValue(EndTime); + EndPos = tNode.GSDSpline.GetSplineValue(EndTime); // FH EXPERIMENTAL fix for NodeEdgeObjectPlacement? + // This does not affect the 1f = -0.0001f bug } + #region "Library" public void SetupUniqueIdentifier() { @@ -176,6 +203,7 @@ public void SetupUniqueIdentifier() } } + public void SaveToLibrary(string fName = "", bool bIsDefault = false) { EdgeObjectLibraryMaker ELM = new EdgeObjectLibraryMaker(); @@ -197,6 +225,7 @@ public void SaveToLibrary(string fName = "", bool bIsDefault = false) GSDRootUtil.CreateXML(ref tPath, ELM); } + public void LoadFromLibrary(string xName, bool bIsQuickAdd = false) { GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); @@ -206,17 +235,18 @@ public void LoadFromLibrary(string xName, bool bIsQuickAdd = false) { tPath = xPath + "Q/EOM" + xName + ".gsd"; } - EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker)GSDRootUtil.LoadXML(ref tPath); + EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker) GSDRootUtil.LoadXML(ref tPath); ELM.LoadTo(this); bNeedsUpdate = true; } + public void LoadFromLibraryWizard(string xName) { GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); string xPath = GSDRootUtil.Dir_GetLibrary(); string tPath = xPath + "W/" + xName + ".gsd"; - EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker)GSDRootUtil.LoadXML(ref tPath); + EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker) GSDRootUtil.LoadXML(ref tPath); ELM.LoadTo(this); bNeedsUpdate = true; } @@ -229,16 +259,18 @@ public string ConvertToString() return GSDRootUtil.GetString(ELM); } + public void LoadFromLibraryBulk(ref EdgeObjectLibraryMaker ELM) { ELM.LoadTo(this); } + public static EdgeObjectLibraryMaker ELMFromData(string tData) { try { - EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker)GSDRootUtil.LoadData(ref tData); + EdgeObjectLibraryMaker ELM = (EdgeObjectLibraryMaker) GSDRootUtil.LoadData(ref tData); return ELM; } catch @@ -247,6 +279,7 @@ public static EdgeObjectLibraryMaker ELMFromData(string tData) } } + public static void GetLibraryFiles(out string[] tNames, out string[] tPaths, bool bIsDefault = false) { #if UNITY_WEBPLAYER @@ -295,10 +328,14 @@ public static void GetLibraryFiles(out string[] tNames, out string[] tPaths, boo #endif } + private void SaveMesh(Mesh tMesh, bool bIsCollider) { #if UNITY_EDITOR - if (!tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) { return; } + if (!tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) + { + return; + } //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; @@ -325,6 +362,7 @@ private void SaveMesh(Mesh tMesh, bool bIsCollider) #endif } + #region "Library object" [System.Serializable] public class EdgeObjectLibraryMaker @@ -370,6 +408,7 @@ public class EdgeObjectLibraryMaker public string Desc = ""; public string DisplayName = ""; + public void Setup(EdgeObjectMaker EOM) { EdgeObjectString = EOM.EdgeObjectString; @@ -405,21 +444,22 @@ public void Setup(EdgeObjectMaker EOM) DisplayName = EOM.DisplayName; } + public void LoadTo(EdgeObjectMaker EOM) { EOM.EdgeObjectString = EdgeObjectString; #if UNITY_EDITOR - EOM.EdgeObject = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeObjectString, typeof(GameObject)); + EOM.EdgeObject = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeObjectString, typeof(GameObject)); #endif EOM.bMaterialOverride = bMaterialOverride; #if UNITY_EDITOR if (EdgeMaterial1String.Length > 0) { - EOM.EdgeMaterial1 = (Material)UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeMaterial1String, typeof(Material)); + EOM.EdgeMaterial1 = (Material) UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeMaterial1String, typeof(Material)); } if (EdgeMaterial2String.Length > 0) { - EOM.EdgeMaterial2 = (Material)UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeMaterial2String, typeof(Material)); + EOM.EdgeMaterial2 = (Material) UnityEditor.AssetDatabase.LoadAssetAtPath(EdgeMaterial2String, typeof(Material)); } #endif @@ -459,16 +499,32 @@ public void LoadTo(EdgeObjectMaker EOM) public class EdgeObjectEditorMaker { public GameObject EdgeObject = null; + + // Should we combine the Mesh? public bool bCombineMesh = false; + + // Should it also combine the Colliders public bool bCombineMeshCollider = false; + + // Seems to be a List with all Locations for the EdgeObjects public List EdgeObjectLocations; + // Seems to be a List with all Rotations for the EdgeObjects public List EdgeObjectRotations; public GSD.Roads.SignPlacementSubTypeEnum SubType = GSD.Roads.SignPlacementSubTypeEnum.Right; + + // Sounds like Speration public float MeterSep = 5f; + + // A Toggle for? for What? public bool bToggle = false; + + // Is it Bridge? I think? public bool bIsBridge = false; + + // ?? public bool bIsGSD = false; + // Materials of EdgeObject public bool bMaterialOverride = false; public Material EdgeMaterial1; public Material EdgeMaterial2; @@ -487,8 +543,10 @@ public class EdgeObjectEditorMaker public Vector3 CustomScale = new Vector3(1f, 1f, 1f); + // Start and EndTime public float StartTime = 0f; public float EndTime = 1f; + public float SingleOnlyBridgePercent = 0f; public bool bSingle = false; public float SinglePosition; @@ -510,27 +568,40 @@ public void Setup(EdgeObjectMaker EOM) EdgeMaterial1 = EOM.EdgeMaterial1; EdgeMaterial2 = EOM.EdgeMaterial2; + // Horizontal HorizontalSep = EOM.HorizontalSep; HorizontalCurve = EOM.HorizontalCurve; + + // Vertical VerticalRaise = EOM.VerticalRaise; VerticalCurve = EOM.VerticalCurve; + bMatchTerrain = EOM.bMatchTerrain; + // Rotation CustomRotation = EOM.CustomRotation; bOncomingRotation = EOM.bOncomingRotation; + CustomScale = EOM.CustomScale; bStatic = EOM.bStatic; + + // Is it Single and if yes Position bSingle = EOM.bSingle; SinglePosition = EOM.SinglePosition; + + // Name of EdgeObject?? tName = EOM.tName; + // Start and EndTime of EdgeObject StartTime = EOM.StartTime; EndTime = EOM.EndTime; + SingleOnlyBridgePercent = EOM.SingleOnlyBridgePercent; bStartMatchRoadDefinition = EOM.bStartMatchRoadDefinition; StartMatchRoadDef = EOM.StartMatchRoadDef; } + public void LoadTo(EdgeObjectMaker EOM) { EOM.EdgeObject = EdgeObject; @@ -555,47 +626,130 @@ public void LoadTo(EdgeObjectMaker EOM) EOM.bOncomingRotation = bOncomingRotation; EOM.bStatic = bStatic; EOM.bSingle = bSingle; + + EOM.StartTime = StartTime; EOM.EndTime = EndTime; + + EOM.SinglePosition = SinglePosition; + + EOM.tName = tName; EOM.SingleOnlyBridgePercent = SingleOnlyBridgePercent; EOM.bStartMatchRoadDefinition = bStartMatchRoadDefinition; EOM.StartMatchRoadDef = StartMatchRoadDef; } + public bool IsEqual(EdgeObjectMaker EOM) { - if (EOM.EdgeObject != EdgeObject) { return false; } - if (EOM.bMaterialOverride != bMaterialOverride) { return false; } - if (EOM.EdgeMaterial1 != EdgeMaterial1) { return false; } - if (EOM.EdgeMaterial2 != EdgeMaterial2) { return false; } - - if (EOM.bCombineMesh != bCombineMesh) { return false; } - if (EOM.bCombineMeshCollider != bCombineMeshCollider) { return false; } - if (EOM.SubType != SubType) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.MeterSep, MeterSep, 0.001f)) { return false; } - // if(EOM.bToggle != bToggle){ return false; } - - if (!GSDRootUtil.IsApproximately(EOM.HorizontalSep, HorizontalSep, 0.001f)) { return false; } - if (EOM.HorizontalCurve != HorizontalCurve) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.VerticalRaise, VerticalRaise, 0.001f)) { return false; } - if (EOM.VerticalCurve != VerticalCurve) { return false; } - if (EOM.bMatchTerrain != bMatchTerrain) { return false; } - - if (EOM.CustomRotation != CustomRotation) { return false; } - if (EOM.CustomScale != CustomScale) { return false; } - if (EOM.bOncomingRotation != bOncomingRotation) { return false; } - if (EOM.bStatic != bStatic) { return false; } - if (EOM.bSingle != bSingle) { return false; } - - if (!GSDRootUtil.IsApproximately(EOM.SinglePosition, SinglePosition, 0.001f)) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.StartTime, StartTime, 0.001f)) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.EndTime, EndTime, 0.001f)) { return false; } - if (EOM.tName != tName) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.SingleOnlyBridgePercent, SingleOnlyBridgePercent, 0.001f)) { return false; } - if (EOM.bStartMatchRoadDefinition != bStartMatchRoadDefinition) { return false; } - if (!GSDRootUtil.IsApproximately(EOM.StartMatchRoadDef, StartMatchRoadDef, 0.001f)) { return false; } + if (EOM.EdgeObject != EdgeObject) + { + return false; + } + if (EOM.bMaterialOverride != bMaterialOverride) + { + return false; + } + if (EOM.EdgeMaterial1 != EdgeMaterial1) + { + return false; + } + if (EOM.EdgeMaterial2 != EdgeMaterial2) + { + return false; + } + + if (EOM.bCombineMesh != bCombineMesh) + { + return false; + } + if (EOM.bCombineMeshCollider != bCombineMeshCollider) + { + return false; + } + if (EOM.SubType != SubType) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.MeterSep, MeterSep, 0.001f)) + { + return false; + } + // if(EOM.bToggle != bToggle) + // { return false; } + + if (!GSDRootUtil.IsApproximately(EOM.HorizontalSep, HorizontalSep, 0.001f)) + { + return false; + } + if (EOM.HorizontalCurve != HorizontalCurve) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.VerticalRaise, VerticalRaise, 0.001f)) + { + return false; + } + if (EOM.VerticalCurve != VerticalCurve) + { + return false; + } + if (EOM.bMatchTerrain != bMatchTerrain) + { + return false; + } + + if (EOM.CustomRotation != CustomRotation) + { + return false; + } + if (EOM.CustomScale != CustomScale) + { + return false; + } + if (EOM.bOncomingRotation != bOncomingRotation) + { + return false; + } + if (EOM.bStatic != bStatic) + { + return false; + } + if (EOM.bSingle != bSingle) + { + return false; + } + + if (!GSDRootUtil.IsApproximately(EOM.SinglePosition, SinglePosition, 0.001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.StartTime, StartTime, 0.001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.EndTime, EndTime, 0.001f)) + { + return false; + } + if (EOM.tName != tName) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.SingleOnlyBridgePercent, SingleOnlyBridgePercent, 0.001f)) + { + return false; + } + if (EOM.bStartMatchRoadDefinition != bStartMatchRoadDefinition) + { + return false; + } + if (!GSDRootUtil.IsApproximately(EOM.StartMatchRoadDef, StartMatchRoadDef, 0.001f)) + { + return false; + } return true; } @@ -611,27 +765,32 @@ public void Setup(bool bCollect = true) { Setup_Do(bCollect, ref tErrorObjs); } - catch (System.Exception e) + catch (System.Exception exception) { if (tErrorObjs != null && tErrorObjs.Count > 0) { int tCount = tErrorObjs.Count; - for (int i = 0; i < tCount; i++) + for (int index = 0; index < tCount; index++) { - if (tErrorObjs[i] != null) + if (tErrorObjs[index] != null) { - Object.DestroyImmediate(tErrorObjs[i]); + Object.DestroyImmediate(tErrorObjs[index]); } } - throw e; + throw exception; } } #endif } + + private void Setup_Do(bool bCollect, ref List tErrorObjs) { #if UNITY_EDITOR - if (EdgeObjects == null) { EdgeObjects = new List(); } + if (EdgeObjects == null) + { + EdgeObjects = new List(); + } if (HorizontalCurve == null) { HorizontalCurve = new AnimationCurve(); @@ -648,9 +807,16 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) SetupUniqueIdentifier(); SetupLocations(); + EdgeObjectString = GSDRootUtil.GetPrefabString(EdgeObject); - if (EdgeMaterial1 != null) { EdgeMaterial1String = UnityEditor.AssetDatabase.GetAssetPath(EdgeMaterial1); } - if (EdgeMaterial2 != null) { EdgeMaterial2String = UnityEditor.AssetDatabase.GetAssetPath(EdgeMaterial2); } + if (EdgeMaterial1 != null) + { + EdgeMaterial1String = UnityEditor.AssetDatabase.GetAssetPath(EdgeMaterial1); + } + if (EdgeMaterial2 != null) + { + EdgeMaterial2String = UnityEditor.AssetDatabase.GetAssetPath(EdgeMaterial2); + } EdgeObjects = new List(); Quaternion xRot = default(Quaternion); @@ -658,8 +824,10 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) xRot.eulerAngles = CustomRotation; int lCount = EdgeObjectLocations.Count; // Quaternion OrigRot = Quaternion.identity; + Material[] tMats = null; GameObject tObj = null; + if (EdgeObject != null) { GameObject mObj = new GameObject(EdgeObject.name); @@ -673,13 +841,14 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) { if (EdgeObjectRotations[j] == default(Vector3)) { - tObj = (GameObject)GameObject.Instantiate(EdgeObject); + tObj = GameObject.Instantiate(EdgeObject); // (GameObject) removed; FH Experimental 25.01.19 tErrorObjs.Add(tObj); tObj.transform.position = EdgeObjectLocations[j]; } else { - tObj = (GameObject)GameObject.Instantiate(EdgeObject, EdgeObjectLocations[j], Quaternion.LookRotation(EdgeObjectRotations[j])); + tObj = GameObject.Instantiate(EdgeObject, EdgeObjectLocations[j], Quaternion.LookRotation(EdgeObjectRotations[j])); + // (GameObject) removed, since Instantiate returns a GameObject anyway; FH Experimental 25.01.19 tErrorObjs.Add(tObj); } // OrigRot = tObj.transform.rotation; @@ -782,27 +951,36 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) System.Array.Copy(kUV, hUV[j], OrigMVL); Vector3 tVect = default(Vector3); - for (int i = 0; i < OrigMVL; i++) + for (int index = 0; index < OrigMVL; index++) { - tVect = hVerts[j][i]; - hVerts[j][i] = tTrans.rotation * tVect; - hVerts[j][i] += tTrans.localPosition; + tVect = hVerts[j][index]; + hVerts[j][index] = tTrans.rotation * tVect; + hVerts[j][index] += tTrans.localPosition; } } GameObject xObj = new GameObject(tName); MeshRenderer MR = xObj.GetComponent(); - if (MR == null) { MR = xObj.AddComponent(); } + if (MR == null) + { + MR = xObj.AddComponent(); + } xObj.isStatic = bStatic; xObj.transform.parent = MasterObj.transform; tErrorObjs.Add(xObj); xObj.transform.name = xObj.transform.name + "Combined"; xObj.transform.name = xObj.transform.name.Replace("(Clone)", ""); MeshFilter MF = xObj.GetComponent(); - if (MF == null) { MF = xObj.AddComponent(); } + if (MF == null) + { + MF = xObj.AddComponent(); + } MF.sharedMesh = GSDCombineMeshes(ref hVerts, ref hTris, ref hUV, OrigMVL, OrigTriCount); MeshCollider MC = xObj.GetComponent(); - if (MC == null) { MC = xObj.AddComponent(); } + if (MC == null) + { + MC = xObj.AddComponent(); + } xObj.transform.position = tNode.transform.position; xObj.transform.rotation = Quaternion.identity; @@ -823,7 +1001,10 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) } BoxCollider BC = xObj.GetComponent(); - if (BC != null) { Object.DestroyImmediate(BC); } + if (BC != null) + { + Object.DestroyImmediate(BC); + } int cCount = xObj.transform.childCount; int spamc = 0; while (cCount > 0 && spamc < 10) @@ -835,7 +1016,10 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) if (bCombineMeshCollider) { - if (MC == null) { MC = xObj.AddComponent(); } + if (MC == null) + { + MC = xObj.AddComponent(); + } MC.sharedMesh = MF.sharedMesh; } else @@ -863,8 +1047,16 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) } //Zero these out, as they are not needed anymore: - if (EdgeObjectLocations != null) { EdgeObjectLocations.Clear(); EdgeObjectLocations = null; } - if (EdgeObjectRotations != null) { EdgeObjectRotations.Clear(); EdgeObjectRotations = null; } + if (EdgeObjectLocations != null) + { + EdgeObjectLocations.Clear(); + EdgeObjectLocations = null; + } + if (EdgeObjectRotations != null) + { + EdgeObjectRotations.Clear(); + EdgeObjectRotations = null; + } if (bCollect) { @@ -873,6 +1065,8 @@ private void Setup_Do(bool bCollect, ref List tErrorObjs) #endif } + + // FH_Tag Optimizable private void SetupLocations() { float OrigHeight = 0f; @@ -898,19 +1092,31 @@ private void SetupLocations() // Vector3 lVect = default(Vector3); // float fTimeMax = -1f; int mCount = tNode.GSDSpline.GetNodeCount(); - if (tNode.idOnSpline >= mCount - 1) { return; } + if (tNode.idOnSpline >= mCount - 1) + { + return; + } // fTimeMax = tNode.GSDSpline.mNodes[tNode.idOnSpline+1].tTime; // float tStep = -1f; Vector3 tVect = default(Vector3); Vector3 POS = default(Vector3); + // tStep = MeterSep/tNode.GSDSpline.distance; //Destroy old objects: ClearEOM(); //Make sure old locs and rots are fresh: - if (EdgeObjectLocations != null) { EdgeObjectLocations.Clear(); EdgeObjectLocations = null; } + if (EdgeObjectLocations != null) + { + EdgeObjectLocations.Clear(); + EdgeObjectLocations = null; + } EdgeObjectLocations = new List(); - if (EdgeObjectRotations != null) { EdgeObjectRotations.Clear(); EdgeObjectRotations = null; } + if (EdgeObjectRotations != null) + { + EdgeObjectRotations.Clear(); + EdgeObjectRotations = null; + } EdgeObjectRotations = new List(); bool bIsCenter = GSDRootUtil.IsApproximately(HorizontalSep, 0f, 0.02f); @@ -920,8 +1126,11 @@ private void SetupLocations() Ray tRay = default(Ray); RaycastHit[] tRayHit = null; float[] tRayYs = null; - if (bSingle) + if (bSingle) { + // If the Object is a SingleObject // FH 03.02.19 + + tNode.GSDSpline.GetSplineValue_Both(SinglePosition, out tVect, out POS); OrigHeight = tVect.y; @@ -967,6 +1176,7 @@ private void SetupLocations() } else { + // If this Object is not marked as a single Object // FH 03.02.19 //Get the vector series that this mesh is interpolated on: List tTimes = new List(); @@ -985,15 +1195,22 @@ private void SetupLocations() fHeight = HorizontalCurve.Evaluate((cTime - FakeStartTime) / pDiffTime); CurrentH = fHeight * HorizontalSep; + // FH 06.02.19 + // Hoirzontal1: if (CurrentH < 0f) { - CurrentH *= -1f; - tVect = (tVect + new Vector3(CurrentH * -POS.normalized.z, 0, CurrentH * POS.normalized.x)); + CurrentH *= -1f; // So we get a positiv Number again + tVect = (tVect + new Vector3(CurrentH * (-POS.normalized.x + (POS.normalized.y / 2)), 0, CurrentH * (POS.normalized.z + +(POS.normalized.y / 2)))); + // I implemented the POS.normalized.y value to make sure we get to a value of 1 overall to ensure 50m distance, is this mathematicly correct?? FH 10.02.19 + // Original: tVect = (tVect + new Vector3(CurrentH * -POS.normalized.z, 0, CurrentH * POS.normalized.x)); } else if (CurrentH > 0f) { - tVect = (tVect + new Vector3(CurrentH * POS.normalized.z, 0, CurrentH * -POS.normalized.x)); + tVect = (tVect + new Vector3(CurrentH * (-POS.normalized.x + (POS.normalized.y / 2)), 0, CurrentH * (POS.normalized.z + (POS.normalized.y / 2)))); + // I implemented the POS.normalized.y value to make sure we get to a value of 1 overall to ensure 50m distance, is this mathematicly correct?? FH 10.02.19 + //Original: tVect = (tVect + new Vector3(CurrentH * POS.normalized.z, 0, CurrentH * -POS.normalized.x)); } + // FH 06.02.19 xVect = (POS.normalized * MeterSep) + tVect; @@ -1011,22 +1228,27 @@ private void SetupLocations() float mMin = FakeStartTime; float mMax = EndTime; float tPercent = 0; - for (int i = 0; i < vSeriesCount; i++) + for (int index = 0; index < vSeriesCount; index++) { - tNode.GSDSpline.GetSplineValue_Both(tTimes[i], out tVect, out POS); + tNode.GSDSpline.GetSplineValue_Both(tTimes[index], out tVect, out POS); - tPercent = ((tTimes[i] - mMin) / (mMax - mMin)); + tPercent = ((tTimes[index] - mMin) / (mMax - mMin)); //Horiz: CurrentH = (HorizontalCurve.Evaluate(tPercent) * HorizontalSep); if (CurrentH < 0f) { CurrentH *= -1f; - tVect = (tVect + new Vector3(CurrentH * -POS.normalized.z, 0, CurrentH * POS.normalized.x)); + // FH 03.02.19 // Why has this Code a "wrong" logic, it multiplies z to x and x to z. + // Original Code: tVect = (tVect + new Vector3(CurrentH * -POS.normalized.z, 0, CurrentH * POS.normalized.x)); + tVect = (tVect + new Vector3(CurrentH * (-POS.normalized.z + (POS.normalized.y / 2)), 0, CurrentH * (POS.normalized.x + (POS.normalized.y / 2)))); } else if (CurrentH > 0f) { - tVect = (tVect + new Vector3(CurrentH * POS.normalized.z, 0, CurrentH * -POS.normalized.x)); + // FH 03.02.19 + // Original Code: tVect = (tVect + new Vector3(CurrentH * POS.normalized.z, 0, CurrentH * -POS.normalized.x)); + // Look at the Bug embeddedt/RoadArchitect/issues/4 + tVect = (tVect + new Vector3(CurrentH * (POS.normalized.z + (POS.normalized.y / 2)), 0, CurrentH * (-POS.normalized.x + (POS.normalized.y / 2)))); } //Vertical: @@ -1045,16 +1267,19 @@ private void SetupLocations() } } - tVect.y += (VerticalCurve.Evaluate(tPercent) * VerticalRaise); + tVect.y += (VerticalCurve.Evaluate(tPercent) * VerticalRaise); // Adds the Height to the Node including the VerticalRaise + // Adds the Vector and the POS to the List of the EdgeObjects, so they can be created EdgeObjectLocations.Add(tVect); EdgeObjectRotations.Add(POS); } StartPos = tNode.GSDSpline.GetSplineValue(StartTime); EndPos = tNode.GSDSpline.GetSplineValue(EndTime); } + // FH_Tag Optimizable } + //ref hVerts,ref hTris, ref hNormals, ref hUV, ref hTangents private Mesh GSDCombineMeshes(ref List hVerts, ref List hTris, ref List hUV, int OrigMVL, int OrigTriCount) { @@ -1074,9 +1299,9 @@ private Mesh GSDCombineMeshes(ref List hVerts, ref List hTris, if (j > 0) { - for (int i = 0; i < OrigTriCount; i++) + for (int index = 0; index < OrigTriCount; index++) { - hTris[j][i] += CurrentMVLIndex; + hTris[j][index] += CurrentMVLIndex; } } @@ -1096,6 +1321,7 @@ private Mesh GSDCombineMeshes(ref List hVerts, ref List hTris, return tMesh; } + public void ClearEOM() { if (EdgeObjects != null) @@ -1140,8 +1366,6 @@ public void SetDefaultTimes(bool bIsEndPoint, float tTime, float tTimeNext, int } } - } - #endif } \ No newline at end of file diff --git a/GSDRoadIntersection.cs b/GSDRoadIntersection.cs index 672744c1..9272b38c 100755 --- a/GSDRoadIntersection.cs +++ b/GSDRoadIntersection.cs @@ -1,1211 +1,1304 @@ -#region "Imports" -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -#endregion -public class GSDRoadIntersection : MonoBehaviour -{ - - public GSDSplineN Node1; - public GSDSplineN Node2; - - public string Node1UID; - public string Node2UID; - - public bool bSameSpline = false; - public bool bDrawGizmo = true; - public bool bSelected = false; - public string tName = ""; - - //Markers: - - public bool bUseDefaultMaterials = true; - public Material MarkerCenter1 = null; - public Material MarkerCenter2 = null; - public Material MarkerCenter3 = null; - public Material MarkerExt_Stretch1 = null; - public Material MarkerExt_Stretch2 = null; - public Material MarkerExt_Stretch3 = null; - public Material MarkerExt_Tiled1 = null; - public Material MarkerExt_Tiled2 = null; - public Material MarkerExt_Tiled3 = null; - - public Material Lane0Mat1 = null; - public Material Lane0Mat2 = null; - public Material Lane1Mat1 = null; - public Material Lane1Mat2 = null; - public Material Lane2Mat1 = null; - public Material Lane2Mat2 = null; - public Material Lane3Mat1 = null; - public Material Lane3Mat2 = null; - - public Material Lane1Mat1_Disabled = null; - public Material Lane1Mat2_Disabled = null; - public Material Lane1Mat1_DisabledActive = null; - public Material Lane1Mat2_DisabledActive = null; - public Material Lane2Mat1_Disabled = null; - public Material Lane2Mat2_Disabled = null; - public Material Lane2Mat1_DisabledActive = null; - public Material Lane2Mat2_DisabledActive = null; - public Material Lane2Mat1_DisabledActiveR = null; - public Material Lane2Mat2_DisabledActiveR = null; - public Material Lane3Mat1_Disabled = null; - public Material Lane3Mat2_Disabled = null; - - public int IntersectionWidth = 10; //Width of the largest of road connected - public int Lanes; - public enum IntersectionTypeEnum { ThreeWay, FourWay }; - public IntersectionTypeEnum iType = IntersectionTypeEnum.FourWay; - public bool bNode2B_LeftTurnLane = true; - public bool bNode2B_RightTurnLane = true; - public bool bNode2F_LeftTurnLane = true; - public bool bNode2F_RightTurnLane = true; - - public enum iStopTypeEnum { StopSign_AllWay, TrafficLight1, None, TrafficLight2 }; - public iStopTypeEnum iStopType = iStopTypeEnum.StopSign_AllWay; - public bool bLightsEnabled = true; - public bool bFlipped = false; - public bool bLeftTurnYieldOnGreen = true; - public RoadTypeEnum rType = RoadTypeEnum.NoTurnLane; - public enum RoadTypeEnum { NoTurnLane, TurnLane, BothTurnLanes }; - public enum LightTypeEnum { Timed, Sensors }; - public LightTypeEnum lType = LightTypeEnum.Timed; - - public bool bRegularPoleAlignment = true; - public bool bTrafficPoleStreetLight = true; - public bool bTrafficLightGray = false; - public float StreetLight_Range = 30f; - public float StreetLight_Intensity = 1f; - public Color StreetLight_Color = new Color(1f, 0.7451f, 0.27451f, 1f); - - public float GradeMod = 0.375f; - public float GradeModNegative = 0.75f; - - public int IgnoreSide = -1; - public int IgnoreCorner = -1; - public bool bFirstSpecial_First = false; - public bool bFirstSpecial_Last = false; - public bool bSecondSpecial_First = false; - public bool bSecondSpecial_Last = false; - - public float ScalingSense = 3f; - - public class CornerPositionMaker - { - public Vector3 position; - public Quaternion rotation; - public Vector3 DirectionFromCenter; - } - public CornerPositionMaker[] CornerPoints; - - protected string UID; //Unique ID - public void SetupUniqueIdentifier() - { - if (UID == null || UID.Length < 4) - { - UID = System.Guid.NewGuid().ToString(); - } - } - - public Vector3 CornerRR, CornerRR_Outer, CornerRR_RampOuter; - public Vector3 CornerRL, CornerRL_Outer, CornerRL_RampOuter; - public Vector3 CornerLR, CornerLR_Outer, CornerLR_RampOuter; - public Vector3 CornerLL, CornerLL_Outer, CornerLL_RampOuter; - - public Vector2 CornerRR_2D; - public Vector2 CornerRL_2D; - public Vector2 CornerLR_2D; - public Vector2 CornerLL_2D; - - public Vector3[] fCornerLR_CornerRR; - public Vector3[] fCornerLL_CornerRL; - public Vector3[] fCornerLL_CornerLR; - public Vector3[] fCornerRL_CornerRR; - - public float OddAngle, EvenAngle; - - - public bool CornerRR1 = false; - public bool CornerRR2 = false; - public bool CornerRL1 = false; - public bool CornerRL2 = false; - public bool CornerLR1 = false; - public bool CornerLR2 = false; - public bool CornerLL1 = false; - public bool CornerLL2 = false; - - public float MaxInterDistance = 0f; - public float MaxInterDistanceSQ = 0f; - public float Height = 50000f; - public float SignHeight = -2000f; - - //Traffic lights: - public GSDTrafficLightController LightsRR; - public GSDTrafficLightController LightsRL; - public GSDTrafficLightController LightsLL; - public GSDTrafficLightController LightsLR; - public float opt_FixedTime_RegularLightLength = 10f; - public float opt_FixedTime_LeftTurnLightLength = 5f; - public float opt_FixedTime_AllRedLightLength = 1f; - public float opt_FixedTime_YellowLightLength = 2f; - public bool opt_AutoUpdateIntersections = true; - public List FixedTimeSequenceList; - -#if UNITY_EDITOR - #region "Setup" - public void Setup(GSDSplineN tNode, GSDSplineN xNode) - { - if (tNode.GSDSpline == xNode.GSDSpline) - { - bSameSpline = true; - } - - if (bSameSpline) - { - if (tNode.idOnSpline < xNode.idOnSpline) - { - Node1 = tNode; - Node2 = xNode; - } - else - { - Node1 = xNode; - Node2 = tNode; - } - } - else - { - Node1 = tNode; - Node2 = xNode; - } - - Node1.Intersection_OtherNode = Node2; - Node2.Intersection_OtherNode = Node1; - - Node1.ToggleHideFlags(true); - Node2.ToggleHideFlags(true); - - Node1UID = Node1.UID; - Node2UID = Node2.UID; - Node1.bIsIntersection = true; - Node2.bIsIntersection = true; - Node1.GSDRI = this; - Node2.GSDRI = this; - } - - public void DeleteRelevantChildren(GSDSplineN tNode, string tString) - { - int cCount = transform.childCount; - for (int i = cCount - 1; i >= 0; i--) - { - if (transform.GetChild(i).name.ToLower().Contains(tString.ToLower())) - { - Object.DestroyImmediate(transform.GetChild(i).gameObject); - } - else if (tNode == Node1) - { - if (transform.GetChild(i).name.ToLower().Contains("centermarkers")) - { - Object.DestroyImmediate(transform.GetChild(i).gameObject); - } - } - } - } - #endregion - - #region "Utility" - public void UpdateRoads() - { -#if UNITY_EDITOR - if (!bSameSpline) - { - GSDSplineC[] tPiggys = new GSDSplineC[1]; - tPiggys[0] = Node2.GSDSpline; - Node1.GSDSpline.tRoad.PiggyBacks = tPiggys; - Node1.GSDSpline.Setup_Trigger(); - } - else - { - Node1.GSDSpline.Setup_Trigger(); - } -#endif - } - - GSD.Roads.GSDRoadUtil.Construction2DRect BoundsRect; - public void ConstructBoundsRect() - { - BoundsRect = null; - BoundsRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(CornerRR.x, CornerRR.z), new Vector2(CornerRL.x, CornerRL.z), new Vector2(CornerLR.x, CornerLR.z), new Vector2(CornerLL.x, CornerLL.z)); - } - - public bool Contains(ref Vector3 tVect) - { - Vector2 vVect = new Vector2(tVect.x, tVect.z); - if (BoundsRect == null) { ConstructBoundsRect(); } - return BoundsRect.Contains(ref vVect); - } - - private bool ContainsLineOld(Vector3 tVect1, Vector3 tVect2, int LineDef = 30) - { - int MaxDef = LineDef; - float MaxDefF = (float)MaxDef; - - Vector3[] tVects = new Vector3[MaxDef]; - - tVects[0] = tVect1; - float mMod = 0f; - float fcounter = 1f; - for (int i = 1; i < (MaxDef - 1); i++) - { - mMod = fcounter / MaxDefF; - tVects[i] = ((tVect2 - tVect1) * mMod) + tVect1; - fcounter += 1f; - } - tVects[MaxDef - 1] = tVect2; - - Vector2 xVect = default(Vector2); - for (int i = 0; i < MaxDef; i++) - { - xVect = new Vector2(tVects[i].x, tVects[i].z); - if (BoundsRect.Contains(ref xVect)) - { - return true; - } - } - return false; - } - - public bool ContainsLine(Vector3 tVect1, Vector3 tVect2) - { - Vector2 tVectStart = new Vector2(tVect1.x, tVect1.z); - Vector2 tVectEnd = new Vector2(tVect2.x, tVect2.z); - bool bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerRR_2D, ref CornerRL_2D); - if (bIntersects) { return true; } - bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerRL_2D, ref CornerLL_2D); - if (bIntersects) { return true; } - bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerLL_2D, ref CornerLR_2D); - if (bIntersects) { return true; } - bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerLR_2D, ref CornerRR_2D); - return bIntersects; - } - - // Returns true if the lines intersect, otherwise false. If the lines - // intersect, intersectionPoint holds the intersection point. - private static bool Intersects2D(ref Vector2 Line1S, ref Vector2 Line1E, ref Vector2 Line2S, ref Vector2 Line2E) - { - float firstLineSlopeX, firstLineSlopeY, secondLineSlopeX, secondLineSlopeY; - - firstLineSlopeX = Line1E.x - Line1S.x; - firstLineSlopeY = Line1E.y - Line1S.y; - - secondLineSlopeX = Line2E.x - Line2S.x; - secondLineSlopeY = Line2E.y - Line2S.y; - - float s, t; - s = (-firstLineSlopeY * (Line1S.x - Line2S.x) + firstLineSlopeX * (Line1S.y - Line2S.y)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); - t = (secondLineSlopeX * (Line1S.y - Line2S.y) - secondLineSlopeY * (Line1S.x - Line2S.x)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); - - if (s >= 0 && s <= 1 && t >= 0 && t <= 1) - { - return true; - } - return false; // No collision - } - - #endregion - - #region "Gizmos" - void OnDrawGizmos() - { - if (!bDrawGizmo) { return; } - Gizmos.color = Color.blue; - Gizmos.DrawCube(transform.position + new Vector3(0f, 5f, 0f), new Vector3(2f, 11f, 2f)); - } - #endregion -#endif - - #region "Traffic light controlling" - void Start() - { - LightsRR.Setup(bLeftTurnYieldOnGreen); - LightsRL.Setup(bLeftTurnYieldOnGreen); - LightsLL.Setup(bLeftTurnYieldOnGreen); - LightsLR.Setup(bLeftTurnYieldOnGreen); - if (lType == LightTypeEnum.Timed) - { - CreateFixedSequence(); - FixedTime_Increment(); - } - else - { - //Do your custom stuff - //In GSD Traffic addon, this will include sensor mode. - } - } - - private void CreateFixedSequence() - { - GSDTrafficLightSequence SMaker = null; FixedTimeSequenceList = new List(); - if (rType != RoadTypeEnum.NoTurnLane) { SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_LeftTurnLightLength); FixedTimeSequenceList.Add(SMaker); } - if (rType != RoadTypeEnum.NoTurnLane) { SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); FixedTimeSequenceList.Add(SMaker); } - SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_RegularLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); FixedTimeSequenceList.Add(SMaker); - - if (rType != RoadTypeEnum.NoTurnLane) { SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_LeftTurnLightLength); FixedTimeSequenceList.Add(SMaker); } - if (rType != RoadTypeEnum.NoTurnLane) { SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); FixedTimeSequenceList.Add(SMaker); } - SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_RegularLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); FixedTimeSequenceList.Add(SMaker); - SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); FixedTimeSequenceList.Add(SMaker); - } - - private IEnumerator TrafficLightFixedUpdate(float tTime) - { - yield return new WaitForSeconds(tTime); - FixedTime_Increment(); - } - - int FixedTimeIndex = 0; - private void FixedTime_Increment() - { - GSDTrafficLightSequence SMaker = FixedTimeSequenceList[FixedTimeIndex]; - FixedTimeIndex += 1; - if (FixedTimeIndex > (FixedTimeSequenceList.Count - 1)) { FixedTimeIndex = 0; } - - GSDTrafficLightController Lights1 = null; - GSDTrafficLightController Lights2 = null; - - GSDTrafficLightController Lights_outer1 = null; - GSDTrafficLightController Lights_outer2 = null; - - if (SMaker.bLightMasterPath1) - { - Lights1 = LightsRL; - Lights2 = LightsLR; - - if (bFlipped) - { - Lights_outer1 = LightsRR; - Lights_outer2 = LightsLL; - } - else - { - Lights_outer1 = LightsRR; - Lights_outer2 = LightsLL; - } - } - else - { - if (bFlipped) - { - Lights1 = LightsRR; - Lights2 = LightsLL; - } - else - { - Lights1 = LightsRR; - Lights2 = LightsLL; - } - - Lights_outer1 = LightsRL; - Lights_outer2 = LightsLR; - } - - GSDTrafficLightController.iLightControllerEnum LCE = SMaker.iLightController; - GSDTrafficLightController.iLightSubStatusEnum LCESub = SMaker.iLightSubcontroller; - - if (LCE == GSDTrafficLightController.iLightControllerEnum.Regular) - { - Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Regular, LCESub, bLightsEnabled); - Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Regular, LCESub, bLightsEnabled); - Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - } - else if (LCE == GSDTrafficLightController.iLightControllerEnum.LeftTurn) - { - Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.LeftTurn, LCESub, bLightsEnabled); - Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.LeftTurn, LCESub, bLightsEnabled); - Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.RightTurn, LCESub, bLightsEnabled); - Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.RightTurn, LCESub, bLightsEnabled); - } - else if (LCE == GSDTrafficLightController.iLightControllerEnum.Red) - { - Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); - } - - // Debug.Log ("Starting: " + SMaker.ToString()); - StartCoroutine(TrafficLightFixedUpdate(SMaker.tTime)); - } - #endregion - -#if UNITY_EDITOR - #region "Materials" - public void ResetMaterials_All() - { - ResetMaterials_Center(false); - ResetMaterials_Ext_Stretched(false); - ResetMaterials_Ext_Tiled(false); - ResetMaterials_Lanes(false); - UpdateMaterials(); - } - - public void ResetMaterials_Center(bool bUpdate = true) - { - string tLanes = "-2L"; - Lanes = Node1.GSDSpline.tRoad.opt_Lanes; - if (Lanes == 4) - { - tLanes = "-4L"; - } - else if (Lanes == 6) - { - tLanes = "-6L"; - } - if (iType == IntersectionTypeEnum.ThreeWay) - { - tLanes += "-3"; - if (Node1.idOnSpline < 2 || Node2.idOnSpline < 2) - { - // if(bFirstSpecial_First || bFirstSpecial_Last){ //Reverse if from node 0 - tLanes += "-crev"; //stands for "Center Reversed" - // } - } - } - - if (rType == RoadTypeEnum.BothTurnLanes) - { - MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-Both" + tLanes + ".mat"); - MarkerCenter2 = null; - MarkerCenter3 = null; - } - else if (rType == RoadTypeEnum.TurnLane) - { - MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-Left" + tLanes + ".mat"); - MarkerCenter2 = null; - MarkerCenter3 = null; - } - else if (rType == RoadTypeEnum.NoTurnLane) - { - MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-None" + tLanes + ".mat"); - MarkerCenter2 = null; - MarkerCenter3 = null; - } - if (bUpdate) { UpdateMaterials(); } - } - public void ResetMaterials_Ext_Stretched(bool bUpdate = true) - { - string tLanes = "-2L"; - Lanes = Node1.GSDSpline.tRoad.opt_Lanes; - if (Lanes == 4) - { - tLanes = "-4L"; - } - else if (Lanes == 6) - { - tLanes = "-6L"; - } - - if (rType == RoadTypeEnum.BothTurnLanes) - { - MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-Both" + tLanes + ".mat"); - MarkerExt_Stretch2 = null; - MarkerExt_Stretch3 = null; - } - else if (rType == RoadTypeEnum.TurnLane) - { - MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-Left" + tLanes + ".mat"); - MarkerExt_Stretch2 = null; - MarkerExt_Stretch3 = null; - } - else if (rType == RoadTypeEnum.NoTurnLane) - { - MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-None" + tLanes + ".mat"); - MarkerExt_Stretch2 = null; - MarkerExt_Stretch3 = null; - } - if (bUpdate) { UpdateMaterials(); } - } - - public void ResetMaterials_Ext_Tiled(bool bUpdate = true) - { - if (rType == RoadTypeEnum.BothTurnLanes) - { - MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); - MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - MarkerExt_Tiled3 = null; - } - else if (rType == RoadTypeEnum.TurnLane) - { - MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); - MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - MarkerExt_Tiled3 = null; - } - else if (rType == RoadTypeEnum.NoTurnLane) - { - MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); - MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); - MarkerExt_Tiled3 = null; - } - if (bUpdate) { UpdateMaterials(); } - } - - public void ResetMaterials_Lanes(bool bUpdate = true) - { - string tLanes = ""; - Lanes = Node1.GSDSpline.tRoad.opt_Lanes; - if (Lanes == 4) - { - tLanes = "-4L"; - } - else if (Lanes == 6) - { - tLanes = "-6L"; - } - - if (iType == IntersectionTypeEnum.ThreeWay) - { - Lane1Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - Lane1Mat2_Disabled = null; - if (rType == RoadTypeEnum.BothTurnLanes) - { - Lane1Mat1_DisabledActive = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterRR.mat"); - Lane1Mat2_DisabledActive = null; - Lane2Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledR.mat"); - Lane2Mat2_Disabled = null; - } - else - { - Lane2Mat1_Disabled = null; - Lane2Mat2_Disabled = null; - Lane2Mat1_DisabledActive = null; - Lane2Mat2_DisabledActive = null; - } - Lane2Mat1_DisabledActive = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter" + tLanes + ".mat"); - Lane2Mat2_DisabledActive = null; - if (rType == RoadTypeEnum.BothTurnLanes) - { - Lane2Mat1_DisabledActiveR = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); - Lane2Mat2_DisabledActiveR = null; - Lane3Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledR.mat"); - Lane3Mat2_Disabled = null; - } - else - { - Lane2Mat1_DisabledActiveR = null; - Lane2Mat2_DisabledActiveR = null; - Lane3Mat1_Disabled = null; - Lane3Mat2_Disabled = null; - } - } - else - { - Lane1Mat1_Disabled = null; - Lane1Mat2_Disabled = null; - Lane2Mat1_Disabled = null; - Lane2Mat2_Disabled = null; - Lane2Mat1_DisabledActive = null; - Lane2Mat2_DisabledActive = null; - Lane2Mat1_DisabledActiveR = null; - Lane2Mat2_DisabledActiveR = null; - Lane3Mat1_Disabled = null; - Lane3Mat2_Disabled = null; - } - - if (rType == RoadTypeEnum.BothTurnLanes) - { - Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); - Lane0Mat2 = null; - Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); - Lane1Mat2 = null; - Lane2Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR" + tLanes + ".mat"); - Lane2Mat2 = null; - Lane3Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - Lane3Mat2 = null; - } - else if (rType == RoadTypeEnum.TurnLane) - { - Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); - Lane0Mat2 = null; - Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); - Lane1Mat2 = null; - Lane2Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR" + tLanes + ".mat"); - Lane2Mat2 = null; - Lane3Mat1 = null; - Lane3Mat2 = null; - } - else if (rType == RoadTypeEnum.NoTurnLane) - { - Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); - Lane0Mat2 = null; - Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR" + tLanes + ".mat"); - Lane1Mat2 = null; - Lane2Mat1 = null; - Lane2Mat2 = null; - Lane3Mat1 = null; - Lane3Mat2 = null; - } - - if (bUpdate) { UpdateMaterials(); } - } - - public void UpdateMaterials() - { - UpdateMaterials_Do(); - } - private void UpdateMaterials_Do() - { - int cCount = transform.childCount; - List MR_Ext_Stretch = new List(); - List MR_Ext_Tiled = new List(); - MeshRenderer MR_Center = null; - List MR_Lane0 = new List(); - List MR_Lane1 = new List(); - List MR_Lane2 = new List(); - List MR_Lane3 = new List(); - List MR_LaneD1 = new List(); - List MR_LaneD3 = new List(); - List MR_LaneDA2 = new List(); - List MR_LaneDAR2 = new List(); - List MR_LaneD2 = new List(); - List MR_LaneDA1 = new List(); - - string tTransName = ""; - for (int i = 0; i < cCount; i++) - { - tTransName = transform.GetChild(i).name.ToLower(); - if (tTransName.Contains("-stretchext")) - { - MR_Ext_Stretch.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("-tiledext")) - { - MR_Ext_Tiled.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("centermarkers")) - { - MR_Center = transform.GetChild(i).GetComponent(); continue; - } - if (tTransName.Contains("lane0")) - { - MR_Lane0.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("lane1")) - { - MR_Lane1.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("lane2")) - { - MR_Lane2.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("lane3")) - { - MR_Lane3.Add(transform.GetChild(i).GetComponent()); continue; - } - if (iType == IntersectionTypeEnum.ThreeWay) - { - if (tTransName.Contains("laned1")) - { - MR_LaneD1.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("laned3")) - { - MR_LaneD3.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("laneda2")) - { - MR_LaneDA2.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("lanedar2")) - { - MR_LaneDAR2.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("laned2")) - { - MR_LaneD2.Add(transform.GetChild(i).GetComponent()); continue; - } - if (tTransName.Contains("laneda1")) - { - MR_LaneDA1.Add(transform.GetChild(i).GetComponent()); continue; - } - } - } - - if (MR_Ext_Stretch != null && MR_Ext_Stretch.Count > 0) - { - int MarkerExtStretchCounter = 0; - if (MarkerExt_Stretch1 != null) - { - MarkerExtStretchCounter += 1; - if (MarkerExt_Stretch2 != null) - { - MarkerExtStretchCounter += 1; - if (MarkerExt_Stretch3 != null) - { - MarkerExtStretchCounter += 1; - } - } - } - Material[] MarkerExtStretchMats = new Material[MarkerExtStretchCounter]; - for (int i = 0; i < MarkerExtStretchCounter; i++) - { - if (i == 0) - { - MarkerExtStretchMats[i] = MarkerExt_Stretch1; - } - else if (i == 1) - { - MarkerExtStretchMats[i] = MarkerExt_Stretch2; - } - else if (i == 2) - { - MarkerExtStretchMats[i] = MarkerExt_Stretch3; - } - } - for (int i = 0; i < MR_Ext_Stretch.Count; i++) - { - MR_Ext_Stretch[i].materials = MarkerExtStretchMats; - } - } - - if (MR_Ext_Tiled != null && MR_Ext_Tiled.Count > 0) - { - int MarkerExtTiledCounter = 0; - if (MarkerExt_Tiled1 != null) - { - MarkerExtTiledCounter += 1; - if (MarkerExt_Tiled2 != null) - { - MarkerExtTiledCounter += 1; - if (MarkerExt_Tiled3 != null) - { - MarkerExtTiledCounter += 1; - } - } - } - Material[] MarkerExtTiledMats = new Material[MarkerExtTiledCounter]; - for (int i = 0; i < MarkerExtTiledCounter; i++) - { - if (i == 0) - { - MarkerExtTiledMats[i] = MarkerExt_Tiled1; - } - else if (i == 1) - { - MarkerExtTiledMats[i] = MarkerExt_Tiled2; - } - else if (i == 2) - { - MarkerExtTiledMats[i] = MarkerExt_Tiled3; - } - } - for (int i = 0; i < MR_Ext_Tiled.Count; i++) - { - MR_Ext_Tiled[i].materials = MarkerExtTiledMats; - } - } - - if (MR_Center != null) - { - int CenterCounter = 0; - if (MarkerCenter1 != null) - { - CenterCounter += 1; - if (MarkerCenter2 != null) - { - CenterCounter += 1; - if (MarkerCenter3 != null) - { - CenterCounter += 1; - } - } - } - Material[] CenterMats = new Material[CenterCounter]; - for (int i = 0; i < CenterCounter; i++) - { - if (i == 0) - { - CenterMats[i] = MarkerCenter1; - } - else if (i == 1) - { - CenterMats[i] = MarkerCenter2; - } - else if (i == 2) - { - CenterMats[i] = MarkerCenter3; - } - } - MR_Center.materials = CenterMats; - } - - int LaneCounter = 0; - if (MR_Lane0 != null && MR_Lane0.Count > 0) - { - LaneCounter = 0; - if (Lane0Mat1 != null) - { - LaneCounter += 1; - if (Lane0Mat2 != null) - { - LaneCounter += 1; - } - } - Material[] Lane0Mats = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane0Mats[i] = Lane0Mat1; - } - else if (i == 1) - { - Lane0Mats[i] = Lane0Mat2; - } - } - for (int i = 0; i < MR_Lane0.Count; i++) - { - MR_Lane0[i].materials = Lane0Mats; - } - } - - if (MR_Lane1 != null && MR_Lane1.Count > 0) - { - LaneCounter = 0; - if (Lane1Mat1 != null) - { - LaneCounter += 1; - if (Lane1Mat2 != null) - { - LaneCounter += 1; - } - } - Material[] Lane1Mats = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane1Mats[i] = Lane1Mat1; - } - else if (i == 1) - { - Lane1Mats[i] = Lane1Mat2; - } - } - for (int i = 0; i < MR_Lane1.Count; i++) - { - MR_Lane1[i].materials = Lane1Mats; - } - } - - if (MR_Lane2 != null && MR_Lane2.Count > 0) - { - LaneCounter = 0; - if (Lane2Mat1 != null) - { - LaneCounter += 1; - if (Lane2Mat2 != null) - { - LaneCounter += 1; - } - } - Material[] Lane2Mats = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane2Mats[i] = Lane2Mat1; - } - else if (i == 1) - { - Lane2Mats[i] = Lane2Mat2; - } - } - for (int i = 0; i < MR_Lane2.Count; i++) - { - MR_Lane2[i].materials = Lane2Mats; - } - } - - if (MR_Lane3 != null && MR_Lane3.Count > 0) - { - LaneCounter = 0; - if (Lane3Mat1 != null) - { - LaneCounter += 1; - if (Lane3Mat2 != null) - { - LaneCounter += 1; - } - } - Material[] Lane3Mats = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane3Mats[i] = Lane3Mat1; - } - else if (i == 1) - { - Lane3Mats[i] = Lane3Mat2; - } - } - for (int i = 0; i < MR_Lane3.Count; i++) - { - MR_Lane3[i].materials = Lane3Mats; - } - } - - if (MR_LaneD1 != null && MR_LaneD1.Count > 0) - { - LaneCounter = 0; - if (Lane1Mat1_Disabled != null) - { - LaneCounter += 1; - if (Lane1Mat2_Disabled != null) - { - LaneCounter += 1; - } - } - Material[] Lane1Mats_Disabled = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane1Mats_Disabled[i] = Lane1Mat1_Disabled; - } - else if (i == 1) - { - Lane1Mats_Disabled[i] = Lane1Mat2_Disabled; - } - } - for (int i = 0; i < MR_LaneD1.Count; i++) - { - MR_LaneD1[i].materials = Lane1Mats_Disabled; - } - } - - if (MR_LaneD3 != null && MR_LaneD3.Count > 0) - { - LaneCounter = 0; - if (Lane3Mat1_Disabled != null) - { - LaneCounter += 1; - if (Lane3Mat2_Disabled != null) - { - LaneCounter += 1; - } - } - Material[] Lane3Mats_Disabled = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane3Mats_Disabled[i] = Lane3Mat1_Disabled; - } - else if (i == 1) - { - Lane3Mats_Disabled[i] = Lane3Mat2_Disabled; - } - } - for (int i = 0; i < MR_LaneD3.Count; i++) - { - MR_LaneD3[i].materials = Lane3Mats_Disabled; - } - } - - if (MR_LaneDA2 != null && MR_LaneDA2.Count > 0) - { - LaneCounter = 0; - if (Lane2Mat1_DisabledActive != null) - { - LaneCounter += 1; - if (Lane2Mat2_DisabledActive != null) - { - LaneCounter += 1; - } - } - Material[] Lane2Mats_DisabledActive = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane2Mats_DisabledActive[i] = Lane2Mat1_DisabledActive; - } - else if (i == 1) - { - Lane2Mats_DisabledActive[i] = Lane2Mat2_DisabledActive; - } - } - for (int i = 0; i < MR_LaneDA2.Count; i++) - { - MR_LaneDA2[i].materials = Lane2Mats_DisabledActive; - } - } - - if (MR_LaneDAR2 != null && MR_LaneDAR2.Count > 0) - { - LaneCounter = 0; - if (Lane2Mat1_DisabledActiveR != null) - { - LaneCounter += 1; - if (Lane2Mat2_DisabledActiveR != null) - { - LaneCounter += 1; - } - } - Material[] Lane2Mats_DisabledActiveR = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane2Mats_DisabledActiveR[i] = Lane2Mat1_DisabledActiveR; - } - else if (i == 1) - { - Lane2Mats_DisabledActiveR[i] = Lane2Mat2_DisabledActiveR; - } - } - for (int i = 0; i < MR_LaneDAR2.Count; i++) - { - MR_LaneDAR2[i].materials = Lane2Mats_DisabledActiveR; - } - } - - if (MR_LaneD2 != null && MR_LaneD2.Count > 0) - { - LaneCounter = 0; - if (Lane2Mat1_Disabled != null) - { - LaneCounter += 1; - if (Lane2Mat2_Disabled != null) - { - LaneCounter += 1; - } - } - Material[] Lane2Mats_Disabled = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane2Mats_Disabled[i] = Lane2Mat1_Disabled; - } - else if (i == 1) - { - Lane2Mats_Disabled[i] = Lane2Mat2_Disabled; - } - } - for (int i = 0; i < MR_LaneD2.Count; i++) - { - MR_LaneD2[i].materials = Lane2Mats_Disabled; - } - } - - - if (MR_LaneDA1 != null && MR_LaneDA1.Count > 0) - { - LaneCounter = 0; - if (Lane1Mat1_DisabledActive != null) - { - LaneCounter += 1; - if (Lane1Mat2_DisabledActive != null) - { - LaneCounter += 1; - } - } - Material[] Lane1Mats_DisabledActive = new Material[LaneCounter]; - for (int i = 0; i < LaneCounter; i++) - { - if (i == 0) - { - Lane1Mats_DisabledActive[i] = Lane1Mat1_DisabledActive; - } - else if (i == 1) - { - Lane1Mats_DisabledActive[i] = Lane1Mat2_DisabledActive; - } - } - for (int i = 0; i < MR_LaneDA1.Count; i++) - { - MR_LaneDA1[i].materials = Lane1Mats_DisabledActive; - } - } - } - #endregion - - public void ToggleTrafficLightPoleColor() - { - Material TrafficLightMaterial = null; - if (bTrafficLightGray) - { - TrafficLightMaterial = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB2.mat"); - } - else - { - TrafficLightMaterial = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB1.mat"); - } - int cCount = transform.childCount; - string tName = ""; - MeshRenderer MR = null; - Material[] tMats = new Material[1]; - tMats[0] = TrafficLightMaterial; - for (int i = 0; i < cCount; i++) - { - tName = transform.GetChild(i).name.ToLower(); - if (tName.Contains("trafficlight")) - { - MR = transform.GetChild(i).GetComponent(); - MR.materials = tMats; - } - } - } - - public void TogglePointLights(bool _bLightsEnabled) - { - bLightsEnabled = _bLightsEnabled; - int cCount = transform.childCount; - Light[] fLights = null; - Transform tTrans = null; - for (int i = 0; i < cCount; i++) - { - if (transform.GetChild(i).name.ToLower().Contains("trafficlight")) - { - tTrans = transform.GetChild(i); - int kCount = tTrans.childCount; - for (int k = 0; k < kCount; k++) - { - if (tTrans.GetChild(k).name.ToLower().Contains("streetlight")) - { - fLights = tTrans.GetChild(k).GetComponentsInChildren(); - if (fLights != null) - { - for (int j = 0; j < fLights.Length; j++) - { - fLights[j].enabled = bLightsEnabled; - fLights[j].range = StreetLight_Range; - fLights[j].intensity = StreetLight_Intensity; - fLights[j].color = StreetLight_Color; - } - } - fLights = null; - break; - } - } - } - } - } - - public void ResetStreetLightSettings() - { - StreetLight_Range = 30f; - StreetLight_Intensity = 1f; - StreetLight_Color = new Color(1f, 0.7451f, 0.27451f, 1f); - TogglePointLights(bLightsEnabled); - } - -#endif +#region "Imports" +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +#endregion + + +public class GSDRoadIntersection : MonoBehaviour +{ + + public GSDSplineN Node1; + public GSDSplineN Node2; + + public string Node1UID; + public string Node2UID; + + public bool bSameSpline = false; + public bool bDrawGizmo = true; + public bool bSelected = false; + public string tName = ""; + + //Markers: + public bool bUseDefaultMaterials = true; + public Material MarkerCenter1 = null; + public Material MarkerCenter2 = null; + public Material MarkerCenter3 = null; + public Material MarkerExt_Stretch1 = null; + public Material MarkerExt_Stretch2 = null; + public Material MarkerExt_Stretch3 = null; + public Material MarkerExt_Tiled1 = null; + public Material MarkerExt_Tiled2 = null; + public Material MarkerExt_Tiled3 = null; + + public Material Lane0Mat1 = null; + public Material Lane0Mat2 = null; + public Material Lane1Mat1 = null; + public Material Lane1Mat2 = null; + public Material Lane2Mat1 = null; + public Material Lane2Mat2 = null; + public Material Lane3Mat1 = null; + public Material Lane3Mat2 = null; + + public Material Lane1Mat1_Disabled = null; + public Material Lane1Mat2_Disabled = null; + public Material Lane1Mat1_DisabledActive = null; + public Material Lane1Mat2_DisabledActive = null; + public Material Lane2Mat1_Disabled = null; + public Material Lane2Mat2_Disabled = null; + public Material Lane2Mat1_DisabledActive = null; + public Material Lane2Mat2_DisabledActive = null; + public Material Lane2Mat1_DisabledActiveR = null; + public Material Lane2Mat2_DisabledActiveR = null; + public Material Lane3Mat1_Disabled = null; + public Material Lane3Mat2_Disabled = null; + + public int IntersectionWidth = 10; //Width of the largest of road connected + public int Lanes; + public enum IntersectionTypeEnum { ThreeWay, FourWay }; + public IntersectionTypeEnum iType = IntersectionTypeEnum.FourWay; + public bool bNode2B_LeftTurnLane = true; + public bool bNode2B_RightTurnLane = true; + public bool bNode2F_LeftTurnLane = true; + public bool bNode2F_RightTurnLane = true; + + public enum iStopTypeEnum { StopSign_AllWay, TrafficLight1, None, TrafficLight2 }; + public iStopTypeEnum iStopType = iStopTypeEnum.StopSign_AllWay; + public bool bLightsEnabled = true; + public bool bFlipped = false; + public bool bLeftTurnYieldOnGreen = true; + public RoadTypeEnum rType = RoadTypeEnum.NoTurnLane; + public enum RoadTypeEnum { NoTurnLane, TurnLane, BothTurnLanes }; + public enum LightTypeEnum { Timed, Sensors }; + public LightTypeEnum lType = LightTypeEnum.Timed; + + public bool bRegularPoleAlignment = true; + public bool bTrafficPoleStreetLight = true; + public bool bTrafficLightGray = false; + public float StreetLight_Range = 30f; + public float StreetLight_Intensity = 1f; + public Color StreetLight_Color = new Color(1f, 0.7451f, 0.27451f, 1f); + + public float GradeMod = 0.375f; + public float GradeModNegative = 0.75f; + + public int IgnoreSide = -1; + public int IgnoreCorner = -1; + public bool bFirstSpecial_First = false; + public bool bFirstSpecial_Last = false; + public bool bSecondSpecial_First = false; + public bool bSecondSpecial_Last = false; + + public float ScalingSense = 3f; + + + // A struct may be better and faster // FH 29.01.19 + public class CornerPositionMaker + { + public Vector3 position; + public Quaternion rotation; + public Vector3 DirectionFromCenter; + } + + public CornerPositionMaker[] CornerPoints; + + protected string UID; //Unique ID + + + public void SetupUniqueIdentifier() + { + if (UID == null || UID.Length < 4) + { + UID = System.Guid.NewGuid().ToString(); + } + } + + + public Vector3 CornerRR, CornerRR_Outer, CornerRR_RampOuter; + public Vector3 CornerRL, CornerRL_Outer, CornerRL_RampOuter; + public Vector3 CornerLR, CornerLR_Outer, CornerLR_RampOuter; + public Vector3 CornerLL, CornerLL_Outer, CornerLL_RampOuter; + + public Vector2 CornerRR_2D; + public Vector2 CornerRL_2D; + public Vector2 CornerLR_2D; + public Vector2 CornerLL_2D; + + public Vector3[] fCornerLR_CornerRR; + public Vector3[] fCornerLL_CornerRL; + public Vector3[] fCornerLL_CornerLR; + public Vector3[] fCornerRL_CornerRR; + + public float OddAngle, EvenAngle; + + + public bool CornerRR1 = false; + public bool CornerRR2 = false; + public bool CornerRL1 = false; + public bool CornerRL2 = false; + public bool CornerLR1 = false; + public bool CornerLR2 = false; + public bool CornerLL1 = false; + public bool CornerLL2 = false; + + public float MaxInterDistance = 0f; + public float MaxInterDistanceSQ = 0f; + public float Height = 50000f; + public float SignHeight = -2000f; + + //Traffic lights: + public GSDTrafficLightController LightsRR; + public GSDTrafficLightController LightsRL; + public GSDTrafficLightController LightsLL; + public GSDTrafficLightController LightsLR; + public float opt_FixedTime_RegularLightLength = 10f; + public float opt_FixedTime_LeftTurnLightLength = 5f; + public float opt_FixedTime_AllRedLightLength = 1f; + public float opt_FixedTime_YellowLightLength = 2f; + public bool opt_AutoUpdateIntersections = true; + public List FixedTimeSequenceList; + + +#if UNITY_EDITOR + #region "Setup" + public void Setup(GSDSplineN tNode, GSDSplineN xNode) + { + if (tNode.GSDSpline == xNode.GSDSpline) + { + bSameSpline = true; + } + + if (bSameSpline) + { + if (tNode.idOnSpline < xNode.idOnSpline) + { + Node1 = tNode; + Node2 = xNode; + } + else + { + Node1 = xNode; + Node2 = tNode; + } + } + else + { + Node1 = tNode; + Node2 = xNode; + } + + Node1.Intersection_OtherNode = Node2; + Node2.Intersection_OtherNode = Node1; + + Node1.ToggleHideFlags(true); + Node2.ToggleHideFlags(true); + + Node1UID = Node1.UID; + Node2UID = Node2.UID; + Node1.bIsIntersection = true; + Node2.bIsIntersection = true; + Node1.GSDRI = this; + Node2.GSDRI = this; + } + + + public void DeleteRelevantChildren(GSDSplineN tNode, string tString) + { + int cCount = transform.childCount; + for (int index = cCount - 1; index >= 0; index--) + { + if (transform.GetChild(index).name.ToLower().Contains(tString.ToLower())) + { + Object.DestroyImmediate(transform.GetChild(index).gameObject); + } + else if (tNode == Node1) + { + if (transform.GetChild(index).name.ToLower().Contains("centermarkers")) + { + Object.DestroyImmediate(transform.GetChild(index).gameObject); + } + } + } + } + #endregion + + + #region "Utility" + public void UpdateRoads() + { +#if UNITY_EDITOR + if (!bSameSpline) + { + GSDSplineC[] tPiggys = new GSDSplineC[1]; + tPiggys[0] = Node2.GSDSpline; + Node1.GSDSpline.tRoad.PiggyBacks = tPiggys; + Node1.GSDSpline.Setup_Trigger(); + } + else + { + Node1.GSDSpline.Setup_Trigger(); + } +#endif + } + + + GSD.Roads.GSDRoadUtil.Construction2DRect BoundsRect; + + + public void ConstructBoundsRect() + { + BoundsRect = null; + BoundsRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(CornerRR.x, CornerRR.z), new Vector2(CornerRL.x, CornerRL.z), new Vector2(CornerLR.x, CornerLR.z), new Vector2(CornerLL.x, CornerLL.z)); + } + + + public bool Contains(ref Vector3 tVect) + { + Vector2 vVect = new Vector2(tVect.x, tVect.z); + if (BoundsRect == null) + { + ConstructBoundsRect(); + } + return BoundsRect.Contains(ref vVect); + } + + + private bool ContainsLineOld(Vector3 tVect1, Vector3 tVect2, int LineDef = 30) + { + int MaxDef = LineDef; + float MaxDefF = (float) MaxDef; + + Vector3[] tVects = new Vector3[MaxDef]; + + tVects[0] = tVect1; + float mMod = 0f; + float fcounter = 1f; + for (int index = 1; index < (MaxDef - 1); index++) + { + mMod = fcounter / MaxDefF; + tVects[index] = ((tVect2 - tVect1) * mMod) + tVect1; + fcounter += 1f; + } + tVects[MaxDef - 1] = tVect2; + + Vector2 xVect = default(Vector2); + for (int index = 0; index < MaxDef; index++) + { + xVect = new Vector2(tVects[index].x, tVects[index].z); + if (BoundsRect.Contains(ref xVect)) + { + return true; + } + } + return false; + } + + + public bool ContainsLine(Vector3 tVect1, Vector3 tVect2) + { + Vector2 tVectStart = new Vector2(tVect1.x, tVect1.z); + Vector2 tVectEnd = new Vector2(tVect2.x, tVect2.z); + bool bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerRR_2D, ref CornerRL_2D); + if (bIntersects) + { + return true; + } + bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerRL_2D, ref CornerLL_2D); + if (bIntersects) + { + return true; + } + bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerLL_2D, ref CornerLR_2D); + if (bIntersects) + { + return true; + } + bIntersects = Intersects2D(ref tVectStart, ref tVectEnd, ref CornerLR_2D, ref CornerRR_2D); + return bIntersects; + } + + + // Returns true if the lines intersect, otherwise false. If the lines + // intersect, intersectionPoint holds the intersection point. + private static bool Intersects2D(ref Vector2 Line1S, ref Vector2 Line1E, ref Vector2 Line2S, ref Vector2 Line2E) + { + float firstLineSlopeX, firstLineSlopeY, secondLineSlopeX, secondLineSlopeY; + + firstLineSlopeX = Line1E.x - Line1S.x; + firstLineSlopeY = Line1E.y - Line1S.y; + + secondLineSlopeX = Line2E.x - Line2S.x; + secondLineSlopeY = Line2E.y - Line2S.y; + + float s, t; + s = (-firstLineSlopeY * (Line1S.x - Line2S.x) + firstLineSlopeX * (Line1S.y - Line2S.y)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); + t = (secondLineSlopeX * (Line1S.y - Line2S.y) - secondLineSlopeY * (Line1S.x - Line2S.x)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); + + if (s >= 0 && s <= 1 && t >= 0 && t <= 1) + { + return true; + } + return false; // No collision + } + #endregion + + + #region "Gizmos" + void OnDrawGizmos() + { + if (!bDrawGizmo) + { + return; + } + Gizmos.color = Color.blue; + Gizmos.DrawCube(transform.position + new Vector3(0f, 5f, 0f), new Vector3(2f, 11f, 2f)); + } + #endregion +#endif + + + #region "Traffic light controlling" + void Start() + { + LightsRR.Setup(bLeftTurnYieldOnGreen); + LightsRL.Setup(bLeftTurnYieldOnGreen); + LightsLL.Setup(bLeftTurnYieldOnGreen); + LightsLR.Setup(bLeftTurnYieldOnGreen); + if (lType == LightTypeEnum.Timed) + { + CreateFixedSequence(); + FixedTime_Increment(); + } + else + { + //Do your custom stuff + //In GSD Traffic addon, this will include sensor mode. + } + } + + + private void CreateFixedSequence() + { + GSDTrafficLightSequence SMaker = null; + FixedTimeSequenceList = new List(); + if (rType != RoadTypeEnum.NoTurnLane) + { + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_LeftTurnLightLength); + FixedTimeSequenceList.Add(SMaker); + } + if (rType != RoadTypeEnum.NoTurnLane) + { + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); + FixedTimeSequenceList.Add(SMaker); + } + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_RegularLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); + FixedTimeSequenceList.Add(SMaker); + + if (rType != RoadTypeEnum.NoTurnLane) + { + SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_LeftTurnLightLength); + FixedTimeSequenceList.Add(SMaker); + } + if (rType != RoadTypeEnum.NoTurnLane) + { + SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.LeftTurn, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); + FixedTimeSequenceList.Add(SMaker); + } + SMaker = new GSDTrafficLightSequence(true, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_RegularLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Regular, GSDTrafficLightController.iLightSubStatusEnum.Yellow, opt_FixedTime_YellowLightLength); + FixedTimeSequenceList.Add(SMaker); + SMaker = new GSDTrafficLightSequence(false, GSDTrafficLightController.iLightControllerEnum.Red, GSDTrafficLightController.iLightSubStatusEnum.Green, opt_FixedTime_AllRedLightLength); + FixedTimeSequenceList.Add(SMaker); + } + + + private IEnumerator TrafficLightFixedUpdate(float tTime) + { + yield return new WaitForSeconds(tTime); + FixedTime_Increment(); + } + + + int FixedTimeIndex = 0; + + + private void FixedTime_Increment() + { + GSDTrafficLightSequence SMaker = FixedTimeSequenceList[FixedTimeIndex]; + FixedTimeIndex += 1; + if (FixedTimeIndex > (FixedTimeSequenceList.Count - 1)) + { + FixedTimeIndex = 0; + } + + GSDTrafficLightController Lights1 = null; + GSDTrafficLightController Lights2 = null; + + GSDTrafficLightController Lights_outer1 = null; + GSDTrafficLightController Lights_outer2 = null; + + if (SMaker.bLightMasterPath1) + { + Lights1 = LightsRL; + Lights2 = LightsLR; + + if (bFlipped) + { + Lights_outer1 = LightsRR; + Lights_outer2 = LightsLL; + } + else + { + Lights_outer1 = LightsRR; + Lights_outer2 = LightsLL; + } + } + else + { + if (bFlipped) + { + Lights1 = LightsRR; + Lights2 = LightsLL; + } + else + { + Lights1 = LightsRR; + Lights2 = LightsLL; + } + + Lights_outer1 = LightsRL; + Lights_outer2 = LightsLR; + } + + GSDTrafficLightController.iLightControllerEnum LCE = SMaker.iLightController; + GSDTrafficLightController.iLightSubStatusEnum LCESub = SMaker.iLightSubcontroller; + + if (LCE == GSDTrafficLightController.iLightControllerEnum.Regular) + { + Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Regular, LCESub, bLightsEnabled); + Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Regular, LCESub, bLightsEnabled); + Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + } + else if (LCE == GSDTrafficLightController.iLightControllerEnum.LeftTurn) + { + Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.LeftTurn, LCESub, bLightsEnabled); + Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.LeftTurn, LCESub, bLightsEnabled); + Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.RightTurn, LCESub, bLightsEnabled); + Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.RightTurn, LCESub, bLightsEnabled); + } + else if (LCE == GSDTrafficLightController.iLightControllerEnum.Red) + { + Lights1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + Lights2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + Lights_outer1.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + Lights_outer2.UpdateLights(GSDTrafficLightController.iLightStatusEnum.Red, LCESub, bLightsEnabled); + } + + // Debug.Log ("Starting: " + SMaker.ToString()); + StartCoroutine(TrafficLightFixedUpdate(SMaker.tTime)); + } + #endregion + + +#if UNITY_EDITOR + #region "Materials" + public void ResetMaterials_All() + { + ResetMaterials_Center(false); + ResetMaterials_Ext_Stretched(false); + ResetMaterials_Ext_Tiled(false); + ResetMaterials_Lanes(false); + UpdateMaterials(); + } + + public void ResetMaterials_Center(bool bUpdate = true) + { + string tLanes = "-2L"; + Lanes = Node1.GSDSpline.tRoad.opt_Lanes; + if (Lanes == 4) + { + tLanes = "-4L"; + } + else if (Lanes == 6) + { + tLanes = "-6L"; + } + if (iType == IntersectionTypeEnum.ThreeWay) + { + tLanes += "-3"; + if (Node1.idOnSpline < 2 || Node2.idOnSpline < 2) + { + // if(bFirstSpecial_First || bFirstSpecial_Last){ //Reverse if from node 0 + tLanes += "-crev"; //stands for "Center Reversed" + // } + } + } + + if (rType == RoadTypeEnum.BothTurnLanes) + { + MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-Both" + tLanes + ".mat"); + MarkerCenter2 = null; + MarkerCenter3 = null; + } + else if (rType == RoadTypeEnum.TurnLane) + { + MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-Left" + tLanes + ".mat"); + MarkerCenter2 = null; + MarkerCenter3 = null; + } + else if (rType == RoadTypeEnum.NoTurnLane) + { + MarkerCenter1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterCenter-None" + tLanes + ".mat"); + MarkerCenter2 = null; + MarkerCenter3 = null; + } + if (bUpdate) + { UpdateMaterials(); } + } + + + public void ResetMaterials_Ext_Stretched(bool bUpdate = true) + { + string tLanes = "-2L"; + Lanes = Node1.GSDSpline.tRoad.opt_Lanes; + if (Lanes == 4) + { + tLanes = "-4L"; + } + else if (Lanes == 6) + { + tLanes = "-6L"; + } + + if (rType == RoadTypeEnum.BothTurnLanes) + { + MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-Both" + tLanes + ".mat"); + MarkerExt_Stretch2 = null; + MarkerExt_Stretch3 = null; + } + else if (rType == RoadTypeEnum.TurnLane) + { + MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-Left" + tLanes + ".mat"); + MarkerExt_Stretch2 = null; + MarkerExt_Stretch3 = null; + } + else if (rType == RoadTypeEnum.NoTurnLane) + { + MarkerExt_Stretch1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterStretch-None" + tLanes + ".mat"); + MarkerExt_Stretch2 = null; + MarkerExt_Stretch3 = null; + } + if (bUpdate) + { UpdateMaterials(); } + } + + + public void ResetMaterials_Ext_Tiled(bool bUpdate = true) + { + if (rType == RoadTypeEnum.BothTurnLanes) + { + MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); + MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + MarkerExt_Tiled3 = null; + } + else if (rType == RoadTypeEnum.TurnLane) + { + MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); + MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + MarkerExt_Tiled3 = null; + } + else if (rType == RoadTypeEnum.NoTurnLane) + { + MarkerExt_Tiled1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat"); + MarkerExt_Tiled2 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadDetailOverlay1.mat"); + MarkerExt_Tiled3 = null; + } + if (bUpdate) + { UpdateMaterials(); } + } + + + public void ResetMaterials_Lanes(bool bUpdate = true) + { + string tLanes = ""; + Lanes = Node1.GSDSpline.tRoad.opt_Lanes; + if (Lanes == 4) + { + tLanes = "-4L"; + } + else if (Lanes == 6) + { + tLanes = "-6L"; + } + + if (iType == IntersectionTypeEnum.ThreeWay) + { + Lane1Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + Lane1Mat2_Disabled = null; + if (rType == RoadTypeEnum.BothTurnLanes) + { + Lane1Mat1_DisabledActive = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterRR.mat"); + Lane1Mat2_DisabledActive = null; + Lane2Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledR.mat"); + Lane2Mat2_Disabled = null; + } + else + { + Lane2Mat1_Disabled = null; + Lane2Mat2_Disabled = null; + Lane2Mat1_DisabledActive = null; + Lane2Mat2_DisabledActive = null; + } + Lane2Mat1_DisabledActive = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter" + tLanes + ".mat"); + Lane2Mat2_DisabledActive = null; + if (rType == RoadTypeEnum.BothTurnLanes) + { + Lane2Mat1_DisabledActiveR = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); + Lane2Mat2_DisabledActiveR = null; + Lane3Mat1_Disabled = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledR.mat"); + Lane3Mat2_Disabled = null; + } + else + { + Lane2Mat1_DisabledActiveR = null; + Lane2Mat2_DisabledActiveR = null; + Lane3Mat1_Disabled = null; + Lane3Mat2_Disabled = null; + } + } + else + { + Lane1Mat1_Disabled = null; + Lane1Mat2_Disabled = null; + Lane2Mat1_Disabled = null; + Lane2Mat2_Disabled = null; + Lane2Mat1_DisabledActive = null; + Lane2Mat2_DisabledActive = null; + Lane2Mat1_DisabledActiveR = null; + Lane2Mat2_DisabledActiveR = null; + Lane3Mat1_Disabled = null; + Lane3Mat2_Disabled = null; + } + + if (rType == RoadTypeEnum.BothTurnLanes) + { + Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); + Lane0Mat2 = null; + Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); + Lane1Mat2 = null; + Lane2Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR" + tLanes + ".mat"); + Lane2Mat2 = null; + Lane3Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + Lane3Mat2 = null; + } + else if (rType == RoadTypeEnum.TurnLane) + { + Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); + Lane0Mat2 = null; + Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); + Lane1Mat2 = null; + Lane2Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR" + tLanes + ".mat"); + Lane2Mat2 = null; + Lane3Mat1 = null; + Lane3Mat2 = null; + } + else if (rType == RoadTypeEnum.NoTurnLane) + { + Lane0Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR" + tLanes + ".mat"); + Lane0Mat2 = null; + Lane1Mat1 = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR" + tLanes + ".mat"); + Lane1Mat2 = null; + Lane2Mat1 = null; + Lane2Mat2 = null; + Lane3Mat1 = null; + Lane3Mat2 = null; + } + + if (bUpdate) + { UpdateMaterials(); } + } + + + public void UpdateMaterials() + { + UpdateMaterials_Do(); + } + + + private void UpdateMaterials_Do() + { + int cCount = transform.childCount; + List MR_Ext_Stretch = new List(); + List MR_Ext_Tiled = new List(); + MeshRenderer MR_Center = null; + List MR_Lane0 = new List(); + List MR_Lane1 = new List(); + List MR_Lane2 = new List(); + List MR_Lane3 = new List(); + List MR_LaneD1 = new List(); + List MR_LaneD3 = new List(); + List MR_LaneDA2 = new List(); + List MR_LaneDAR2 = new List(); + List MR_LaneD2 = new List(); + List MR_LaneDA1 = new List(); + + string tTransName = ""; + for (int i = 0; i < cCount; i++) + { + tTransName = transform.GetChild(i).name.ToLower(); + if (tTransName.Contains("-stretchext")) + { + MR_Ext_Stretch.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("-tiledext")) + { + MR_Ext_Tiled.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("centermarkers")) + { + MR_Center = transform.GetChild(i).GetComponent(); + continue; + } + if (tTransName.Contains("lane0")) + { + MR_Lane0.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("lane1")) + { + MR_Lane1.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("lane2")) + { + MR_Lane2.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("lane3")) + { + MR_Lane3.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (iType == IntersectionTypeEnum.ThreeWay) + { + if (tTransName.Contains("laned1")) + { + MR_LaneD1.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("laned3")) + { + MR_LaneD3.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("laneda2")) + { + MR_LaneDA2.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("lanedar2")) + { + MR_LaneDAR2.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("laned2")) + { + MR_LaneD2.Add(transform.GetChild(i).GetComponent()); + continue; + } + if (tTransName.Contains("laneda1")) + { + MR_LaneDA1.Add(transform.GetChild(i).GetComponent()); + continue; + } + } + } + + if (MR_Ext_Stretch != null && MR_Ext_Stretch.Count > 0) + { + int MarkerExtStretchCounter = 0; + if (MarkerExt_Stretch1 != null) + { + MarkerExtStretchCounter += 1; + if (MarkerExt_Stretch2 != null) + { + MarkerExtStretchCounter += 1; + if (MarkerExt_Stretch3 != null) + { + MarkerExtStretchCounter += 1; + } + } + } + Material[] MarkerExtStretchMats = new Material[MarkerExtStretchCounter]; + for (int i = 0; i < MarkerExtStretchCounter; i++) + { + if (i == 0) + { + MarkerExtStretchMats[i] = MarkerExt_Stretch1; + } + else if (i == 1) + { + MarkerExtStretchMats[i] = MarkerExt_Stretch2; + } + else if (i == 2) + { + MarkerExtStretchMats[i] = MarkerExt_Stretch3; + } + } + for (int i = 0; i < MR_Ext_Stretch.Count; i++) + { + MR_Ext_Stretch[i].materials = MarkerExtStretchMats; + } + } + + if (MR_Ext_Tiled != null && MR_Ext_Tiled.Count > 0) + { + int MarkerExtTiledCounter = 0; + if (MarkerExt_Tiled1 != null) + { + MarkerExtTiledCounter += 1; + if (MarkerExt_Tiled2 != null) + { + MarkerExtTiledCounter += 1; + if (MarkerExt_Tiled3 != null) + { + MarkerExtTiledCounter += 1; + } + } + } + Material[] MarkerExtTiledMats = new Material[MarkerExtTiledCounter]; + for (int i = 0; i < MarkerExtTiledCounter; i++) + { + if (i == 0) + { + MarkerExtTiledMats[i] = MarkerExt_Tiled1; + } + else if (i == 1) + { + MarkerExtTiledMats[i] = MarkerExt_Tiled2; + } + else if (i == 2) + { + MarkerExtTiledMats[i] = MarkerExt_Tiled3; + } + } + for (int i = 0; i < MR_Ext_Tiled.Count; i++) + { + MR_Ext_Tiled[i].materials = MarkerExtTiledMats; + } + } + + if (MR_Center != null) + { + int CenterCounter = 0; + if (MarkerCenter1 != null) + { + CenterCounter += 1; + if (MarkerCenter2 != null) + { + CenterCounter += 1; + if (MarkerCenter3 != null) + { + CenterCounter += 1; + } + } + } + Material[] CenterMats = new Material[CenterCounter]; + for (int i = 0; i < CenterCounter; i++) + { + if (i == 0) + { + CenterMats[i] = MarkerCenter1; + } + else if (i == 1) + { + CenterMats[i] = MarkerCenter2; + } + else if (i == 2) + { + CenterMats[i] = MarkerCenter3; + } + } + MR_Center.materials = CenterMats; + } + + int LaneCounter = 0; + if (MR_Lane0 != null && MR_Lane0.Count > 0) + { + LaneCounter = 0; + if (Lane0Mat1 != null) + { + LaneCounter += 1; + if (Lane0Mat2 != null) + { + LaneCounter += 1; + } + } + Material[] Lane0Mats = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane0Mats[i] = Lane0Mat1; + } + else if (i == 1) + { + Lane0Mats[i] = Lane0Mat2; + } + } + for (int i = 0; i < MR_Lane0.Count; i++) + { + MR_Lane0[i].materials = Lane0Mats; + } + } + + if (MR_Lane1 != null && MR_Lane1.Count > 0) + { + LaneCounter = 0; + if (Lane1Mat1 != null) + { + LaneCounter += 1; + if (Lane1Mat2 != null) + { + LaneCounter += 1; + } + } + Material[] Lane1Mats = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane1Mats[i] = Lane1Mat1; + } + else if (i == 1) + { + Lane1Mats[i] = Lane1Mat2; + } + } + for (int i = 0; i < MR_Lane1.Count; i++) + { + MR_Lane1[i].materials = Lane1Mats; + } + } + + if (MR_Lane2 != null && MR_Lane2.Count > 0) + { + LaneCounter = 0; + if (Lane2Mat1 != null) + { + LaneCounter += 1; + if (Lane2Mat2 != null) + { + LaneCounter += 1; + } + } + Material[] Lane2Mats = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane2Mats[i] = Lane2Mat1; + } + else if (i == 1) + { + Lane2Mats[i] = Lane2Mat2; + } + } + for (int i = 0; i < MR_Lane2.Count; i++) + { + MR_Lane2[i].materials = Lane2Mats; + } + } + + if (MR_Lane3 != null && MR_Lane3.Count > 0) + { + LaneCounter = 0; + if (Lane3Mat1 != null) + { + LaneCounter += 1; + if (Lane3Mat2 != null) + { + LaneCounter += 1; + } + } + Material[] Lane3Mats = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane3Mats[i] = Lane3Mat1; + } + else if (i == 1) + { + Lane3Mats[i] = Lane3Mat2; + } + } + for (int i = 0; i < MR_Lane3.Count; i++) + { + MR_Lane3[i].materials = Lane3Mats; + } + } + + if (MR_LaneD1 != null && MR_LaneD1.Count > 0) + { + LaneCounter = 0; + if (Lane1Mat1_Disabled != null) + { + LaneCounter += 1; + if (Lane1Mat2_Disabled != null) + { + LaneCounter += 1; + } + } + Material[] Lane1Mats_Disabled = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane1Mats_Disabled[i] = Lane1Mat1_Disabled; + } + else if (i == 1) + { + Lane1Mats_Disabled[i] = Lane1Mat2_Disabled; + } + } + for (int i = 0; i < MR_LaneD1.Count; i++) + { + MR_LaneD1[i].materials = Lane1Mats_Disabled; + } + } + + if (MR_LaneD3 != null && MR_LaneD3.Count > 0) + { + LaneCounter = 0; + if (Lane3Mat1_Disabled != null) + { + LaneCounter += 1; + if (Lane3Mat2_Disabled != null) + { + LaneCounter += 1; + } + } + Material[] Lane3Mats_Disabled = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane3Mats_Disabled[i] = Lane3Mat1_Disabled; + } + else if (i == 1) + { + Lane3Mats_Disabled[i] = Lane3Mat2_Disabled; + } + } + for (int i = 0; i < MR_LaneD3.Count; i++) + { + MR_LaneD3[i].materials = Lane3Mats_Disabled; + } + } + + if (MR_LaneDA2 != null && MR_LaneDA2.Count > 0) + { + LaneCounter = 0; + if (Lane2Mat1_DisabledActive != null) + { + LaneCounter += 1; + if (Lane2Mat2_DisabledActive != null) + { + LaneCounter += 1; + } + } + Material[] Lane2Mats_DisabledActive = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane2Mats_DisabledActive[i] = Lane2Mat1_DisabledActive; + } + else if (i == 1) + { + Lane2Mats_DisabledActive[i] = Lane2Mat2_DisabledActive; + } + } + for (int i = 0; i < MR_LaneDA2.Count; i++) + { + MR_LaneDA2[i].materials = Lane2Mats_DisabledActive; + } + } + + if (MR_LaneDAR2 != null && MR_LaneDAR2.Count > 0) + { + LaneCounter = 0; + if (Lane2Mat1_DisabledActiveR != null) + { + LaneCounter += 1; + if (Lane2Mat2_DisabledActiveR != null) + { + LaneCounter += 1; + } + } + Material[] Lane2Mats_DisabledActiveR = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane2Mats_DisabledActiveR[i] = Lane2Mat1_DisabledActiveR; + } + else if (i == 1) + { + Lane2Mats_DisabledActiveR[i] = Lane2Mat2_DisabledActiveR; + } + } + for (int i = 0; i < MR_LaneDAR2.Count; i++) + { + MR_LaneDAR2[i].materials = Lane2Mats_DisabledActiveR; + } + } + + if (MR_LaneD2 != null && MR_LaneD2.Count > 0) + { + LaneCounter = 0; + if (Lane2Mat1_Disabled != null) + { + LaneCounter += 1; + if (Lane2Mat2_Disabled != null) + { + LaneCounter += 1; + } + } + Material[] Lane2Mats_Disabled = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane2Mats_Disabled[i] = Lane2Mat1_Disabled; + } + else if (i == 1) + { + Lane2Mats_Disabled[i] = Lane2Mat2_Disabled; + } + } + for (int i = 0; i < MR_LaneD2.Count; i++) + { + MR_LaneD2[i].materials = Lane2Mats_Disabled; + } + } + + + if (MR_LaneDA1 != null && MR_LaneDA1.Count > 0) + { + LaneCounter = 0; + if (Lane1Mat1_DisabledActive != null) + { + LaneCounter += 1; + if (Lane1Mat2_DisabledActive != null) + { + LaneCounter += 1; + } + } + Material[] Lane1Mats_DisabledActive = new Material[LaneCounter]; + for (int i = 0; i < LaneCounter; i++) + { + if (i == 0) + { + Lane1Mats_DisabledActive[i] = Lane1Mat1_DisabledActive; + } + else if (i == 1) + { + Lane1Mats_DisabledActive[i] = Lane1Mat2_DisabledActive; + } + } + for (int i = 0; i < MR_LaneDA1.Count; i++) + { + MR_LaneDA1[i].materials = Lane1Mats_DisabledActive; + } + } + } + #endregion + + + public void ToggleTrafficLightPoleColor() + { + Material TrafficLightMaterial = null; + if (bTrafficLightGray) + { + TrafficLightMaterial = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB2.mat"); + } + else + { + TrafficLightMaterial = GSD.Roads.GSDRoadUtilityEditor.GiveMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB1.mat"); + } + int cCount = transform.childCount; + string tName = ""; + MeshRenderer MR = null; + Material[] tMats = new Material[1]; + tMats[0] = TrafficLightMaterial; + for (int index = 0; index < cCount; index++) + { + tName = transform.GetChild(index).name.ToLower(); + if (tName.Contains("trafficlight")) + { + MR = transform.GetChild(index).GetComponent(); + MR.materials = tMats; + } + } + } + + + public void TogglePointLights(bool _bLightsEnabled) + { + bLightsEnabled = _bLightsEnabled; + int cCount = transform.childCount; + Light[] fLights = null; + Transform tTrans = null; + for (int index = 0; index < cCount; index++) + { + if (transform.GetChild(index).name.ToLower().Contains("trafficlight")) + { + tTrans = transform.GetChild(index); + int kCount = tTrans.childCount; + for (int k = 0; k < kCount; k++) + { + if (tTrans.GetChild(k).name.ToLower().Contains("streetlight")) + { + fLights = tTrans.GetChild(k).GetComponentsInChildren(); + if (fLights != null) + { + for (int j = 0; j < fLights.Length; j++) + { + fLights[j].enabled = bLightsEnabled; + fLights[j].range = StreetLight_Range; + fLights[j].intensity = StreetLight_Intensity; + fLights[j].color = StreetLight_Color; + } + } + fLights = null; + break; + } + } + } + } + } + + + public void ResetStreetLightSettings() + { + StreetLight_Range = 30f; + StreetLight_Intensity = 1f; + StreetLight_Color = new Color(1f, 0.7451f, 0.27451f, 1f); + TogglePointLights(bLightsEnabled); + } +#endif } \ No newline at end of file diff --git a/GSDRoadMeshSplinate.cs b/GSDRoadMeshSplinate.cs index d548b94b..41ecc738 100755 --- a/GSDRoadMeshSplinate.cs +++ b/GSDRoadMeshSplinate.cs @@ -1,3615 +1,4017 @@ -#region "Imports" -using UnityEngine; -#if UNITY_EDITOR -using System.Collections; -using System.Collections.Generic; -using GSD; -using System.IO; -#endif -#endregion -namespace GSD.Roads.Splination -{ - public enum AxisTypeEnum { X, Z }; - public enum CollisionTypeEnum { None, SimpleMeshTriangle, SimpleMeshTrapezoid, MeshCollision, BoxCollision }; - public enum RepeatUVTypeEnum { None, X, Y }; - -#if UNITY_EDITOR - - [System.Serializable] - public class SplinatedMeshMaker - { - public bool bNeedsUpdate = false; - public string UID = ""; - public bool bIsGSD = false; - - public Transform MasterObjTrans = null; - public GameObject CurrentSplination = null; - public string CurrentSplinationString = ""; - public GameObject CurrentSplinationCap1 = null; - public string CurrentSplinationCap1String = ""; - public GameObject CurrentSplinationCap2 = null; - public string CurrentSplinationCap2String = ""; - public float CapHeightOffset1 = 0f; - public float CapHeightOffset2 = 0f; - - public GameObject Output = null; - public Mesh tMesh = null; - public bool bMaterialOverride = false; - public Material SplinatedMaterial1 = null; - public Material SplinatedMaterial2 = null; - public string SplinatedMaterial1String = ""; - public string SplinatedMaterial2String = ""; - public float MinMaxMod = 0.002f; - public float VertexMatchingPrecision = 0.005f; - - public bool bExactSplination = false; - public bool bMatchRoadDefinition = false; - public bool bMatchRoadIncrements = true; - public bool bTrimEnd = false; - public bool bTrimStart = false; - public bool bToggle = false; - public bool bMatchTerrain = false; - public bool bIsBridge = false; - - public bool bIsStretch = false; - public bool bStretchLocOffset = false; - public bool bStretchSize = false; - public Vector3 StretchBC_LocOffset = default(Vector3); - public Vector3 StretchBC_Size = default(Vector3); - public float Stretch_UVThreshold = 0.05f; - public bool bStraightLineMatchStartEnd = false; - public bool bBCFlipX = false; - public bool bBCFlipZ = false; - - //Horizontal offsets: - public float HorizontalSep = 0f; - public AnimationCurve HorizontalCurve; - public float HorizCurve_tempchecker1 = 0f; - public float HorizCurve_tempchecker2 = 0f; - public float HorizCurve_tempchecker3 = 0f; - public float HorizCurve_tempchecker4 = 0f; - public float HorizCurve_tempchecker5 = 0f; - public float HorizCurve_tempchecker6 = 0f; - public float HorizCurve_tempchecker7 = 0f; - public float HorizCurve_tempchecker8 = 0f; - //Vertical offsets: - public float VerticalRaise = 0f; - public AnimationCurve VerticalCurve; - public float VerticalCurve_tempchecker1 = 0f; - public float VerticalCurve_tempchecker2 = 0f; - public float VerticalCurve_tempchecker3 = 0f; - public float VerticalCurve_tempchecker4 = 0f; - public float VerticalCurve_tempchecker5 = 0f; - public float VerticalCurve_tempchecker6 = 0f; - public float VerticalCurve_tempchecker7 = 0f; - public float VerticalCurve_tempchecker8 = 0f; - //Vertical cutoff - public float VerticalCutoff = 0f; - public bool bVerticalCutoff = false; - public bool bVerticalCutoffDownwards = false; - public bool bVerticalMeshCutoff_OppositeDir = false; - public float VerticalMeshCutoffOffset = 0.04f; - public bool bVerticalCutoff_MatchZero = false; - - public float RoadRaise = 0f; - public Vector3 CustomRotation = default(Vector3); - public bool bFlipRotation = false; - public bool bStatic = true; - public Vector3 StartPos = default(Vector3); - public Vector3 EndPos = default(Vector3); - public float StartTime = 0f; - public float EndTime = 1f; - public GSDSplineC tSpline = null; - public GSDSplineN tNode = null; - public AxisTypeEnum Axis = AxisTypeEnum.X; - - public float mMaxX = -1f; - public float mMinX = -1f; - public float mMaxY = -1f; - public float mMinY = -1f; - public float mMaxZ = -1f; - public float mMinZ = -1f; - - public RepeatUVTypeEnum RepeatUVType = RepeatUVTypeEnum.None; - public bool bNoCenterMode = true; - - //End objects: - public GameObject EndCapStart = null; - public GameObject EndCapEnd = null; - public GameObject EndCapStartOutput = null; - public GameObject EndCapEndOutput = null; - public string EndCapStartString = ""; - public string EndCapEndString = ""; - public bool bEndCapCustomMatchStart = true; - public bool bEndObjectsMatchGround = false; - public Vector3 EndCapCustomOffsetStart = default(Vector3); - public Vector3 EndCapCustomOffsetEnd = default(Vector3); - public Vector3 EndCapCustomRotOffsetStart = default(Vector3); - public Vector3 EndCapCustomRotOffsetEnd = new Vector3(0f, 180f, 0f); - //Endings down: - public bool bStartDown = false; - public bool bStartTypeDownOverride = false; - public float StartTypeDownOverride = 0f; - public bool bEndDown = false; - public bool bEndTypeDownOverride = false; - public float EndTypeDownOverride = 0f; - - //Collision: - public CollisionTypeEnum CollisionType = CollisionTypeEnum.SimpleMeshTriangle; - public bool bCollisionConvex = false; - public bool bSimpleCollisionAutomatic = true; - public bool bCollisionExtrude = false; - public bool bCollisionTrigger = false; - - public Vector3 CollisionBoxBL = default(Vector3); - public Vector3 CollisionBoxBR = default(Vector3); - public Vector3 CollisionBoxTL = default(Vector3); - public Vector3 CollisionBoxTR = default(Vector3); - - public Vector3 CollisionTriBL = default(Vector3); - public Vector3 CollisionTriBR = default(Vector3); - public Vector3 CollisionTriT = default(Vector3); - - public string tName = "ExtrudedObject"; - public string ThumbString = ""; - public string Desc = ""; - public string DisplayName = ""; - - public SplinatedMeshEditorMaker EM = null; - - public void Init(GSDSplineC _tSpline, GSDSplineN _tNode, Transform tTrans) - { - tSpline = _tSpline; - tNode = _tNode; - MasterObjTrans = tTrans; - SetupUniqueIdentifier(); - } - - public SplinatedMeshMaker Copy() - { - SplinatedMeshMaker SMM = new SplinatedMeshMaker(); - SMM.Init(tSpline, tNode, MasterObjTrans); - SMM.MasterObjTrans = MasterObjTrans; - SMM.bIsGSD = bIsGSD; - - SMM.CurrentSplination = CurrentSplination; - SMM.CurrentSplinationString = CurrentSplinationString; - - SMM.CurrentSplinationCap1 = CurrentSplinationCap1; - SMM.CurrentSplinationCap1String = CurrentSplinationCap1String; - SMM.CurrentSplinationCap2 = CurrentSplinationCap2; - SMM.CurrentSplinationCap2String = CurrentSplinationCap2String; - SMM.CapHeightOffset1 = CapHeightOffset1; - SMM.CapHeightOffset1 = CapHeightOffset2; - - SMM.Output = Output; - SMM.tMesh = tMesh; - SMM.bMaterialOverride = bMaterialOverride; - SMM.SplinatedMaterial1 = SplinatedMaterial1; - SMM.SplinatedMaterial2 = SplinatedMaterial2; - SMM.SplinatedMaterial1String = SplinatedMaterial1String; - SMM.SplinatedMaterial2String = SplinatedMaterial2String; - SMM.bExactSplination = bExactSplination; - SMM.bMatchRoadDefinition = bMatchRoadDefinition; - SMM.bMatchRoadIncrements = bMatchRoadIncrements; - SMM.bTrimStart = bTrimStart; - SMM.bTrimEnd = bTrimEnd; - SMM.bMatchTerrain = bMatchTerrain; - SMM.MinMaxMod = MinMaxMod; - SMM.VertexMatchingPrecision = VertexMatchingPrecision; - - SMM.bIsStretch = bIsStretch; - SMM.bStretchLocOffset = bStretchLocOffset; - SMM.bStretchSize = bStretchSize; - SMM.StretchBC_LocOffset = StretchBC_LocOffset; - SMM.StretchBC_Size = StretchBC_Size; - SMM.Stretch_UVThreshold = Stretch_UVThreshold; - SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; - SMM.bBCFlipX = bBCFlipX; - SMM.bBCFlipZ = bBCFlipZ; - - //Horizontal offsets: - SMM.HorizontalSep = HorizontalSep; - SMM.HorizontalCurve = new AnimationCurve(); - if (HorizontalCurve != null && HorizontalCurve.keys.Length > 0) - { - for (int i = 0; i < HorizontalCurve.keys.Length; i++) - { - SMM.HorizontalCurve.AddKey(HorizontalCurve.keys[i]); - } - } - //Vertical offset: - SMM.VerticalRaise = VerticalRaise; - SMM.VerticalCurve = new AnimationCurve(); - if (VerticalCurve != null && VerticalCurve.keys.Length > 0) - { - for (int i = 0; i < VerticalCurve.keys.Length; i++) - { - SMM.VerticalCurve.AddKey(VerticalCurve.keys[i]); - } - } - - //Vertical cutoff: - SMM.bVerticalCutoff = bVerticalCutoff; - SMM.VerticalCutoff = VerticalCutoff; - SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; - SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; - SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; - SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; - - SMM.RoadRaise = RoadRaise; - SMM.CustomRotation = CustomRotation; - SMM.bFlipRotation = bFlipRotation; - SMM.bStatic = bStatic; - SMM.StartTime = StartTime; - SMM.EndTime = EndTime; - SMM.StartPos = StartPos; - SMM.EndPos = EndPos; - SMM.Axis = Axis; - - SMM.RepeatUVType = RepeatUVType; - - SMM.mMaxX = mMaxX; - SMM.mMinX = mMinX; - SMM.mMaxY = mMaxY; - SMM.mMinY = mMinY; - SMM.mMaxZ = mMaxZ; - SMM.mMinZ = mMinZ; - - //End objects: - SMM.EndCapStart = EndCapStart; - SMM.EndCapStartString = EndCapStartString; - SMM.EndCapEnd = EndCapEnd; - SMM.EndCapEndString = EndCapEndString; - SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; - SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; - SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; - SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; - SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; - SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; - SMM.bIsBridge = bIsBridge; - //End down: - SMM.bStartDown = bStartDown; - SMM.bStartTypeDownOverride = bStartTypeDownOverride; - SMM.StartTypeDownOverride = StartTypeDownOverride; - SMM.bEndDown = bEndDown; - SMM.bEndTypeDownOverride = bEndTypeDownOverride; - SMM.EndTypeDownOverride = EndTypeDownOverride; - - //Collision: - SMM.CollisionType = CollisionType; - SMM.bCollisionConvex = bCollisionConvex; - SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; - SMM.bCollisionTrigger = bCollisionTrigger; - - SMM.CollisionBoxBL = CollisionBoxBL; - SMM.CollisionBoxBR = CollisionBoxBR; - SMM.CollisionBoxTL = CollisionBoxTL; - SMM.CollisionBoxTR = CollisionBoxTR; - - SMM.CollisionTriBL = CollisionTriBL; - SMM.CollisionTriBR = CollisionTriBR; - SMM.CollisionTriT = CollisionTriT; - - SMM.tName = tName; - SMM.ThumbString = ThumbString; - SMM.Desc = Desc; - SMM.DisplayName = DisplayName; - - SMM.SetupUniqueIdentifier(); - - return SMM; - } - - public void SetDefaultTimes(bool bIsEndPoint, float tTime, float tTimeNext, int idOnSpline, float tDist) - { - if (!bIsEndPoint) - { - StartTime = tTime; - EndTime = tTimeNext; - } - else - { - if (idOnSpline < 2) - { - StartTime = tTime; - EndTime = tTimeNext; - } - else - { - StartTime = tTime; - EndTime = tTime - (125f / tDist); - } - } - } - - public void UpdatePositions() - { - StartPos = tSpline.GetSplineValue(StartTime); - EndPos = tSpline.GetSplineValue(EndTime); - } - - public void SaveToLibrary(string fName = "", bool bIsDefault = false) - { - SplinatedMeshLibraryMaker SLM = new SplinatedMeshLibraryMaker(); - SLM.Setup(this); - GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); - string xPath = GSDRootUtil.Dir_GetLibrary(); - string tPath = xPath + "ESO" + tName + ".gsd"; - if (fName.Length > 0) - { - if (bIsDefault) - { - tPath = xPath + "Q/ESO" + fName + ".gsd"; - } - else - { - tPath = xPath + "ESO" + fName + ".gsd"; - } - } - GSDRootUtil.CreateXML(ref tPath, SLM); - } - - public void LoadFromLibrary(string xName, bool bIsQuickAdd = false) - { - string xPath = GSDRootUtil.Dir_GetLibrary(); - string tPath = xPath + "ESO" + xName + ".gsd"; - if (bIsQuickAdd) - { - GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); - tPath = xPath + "Q/ESO" + xName + ".gsd"; - } - SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker)GSDRootUtil.LoadXML(ref tPath); - SLM.LoadToSMM(this); - bNeedsUpdate = true; - } - - public void LoadFromLibraryWizard(string xName) - { - GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); - string xPath = GSDRootUtil.Dir_GetLibrary(); - string tPath = xPath + "W/" + xName + ".gsd"; - SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker)GSDRootUtil.LoadXML(ref tPath); - SLM.LoadToSMM(this); - bNeedsUpdate = true; - } - - public void LoadFromLibraryBulk(ref SplinatedMeshLibraryMaker SLM) - { - SLM.LoadToSMM(this); - // bNeedsUpdate = true; - } - - public static SplinatedMeshLibraryMaker SLMFromData(string tData) - { - try - { - SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker)GSDRootUtil.LoadData(ref tData); - return SLM; - } - catch - { - return null; - } - } - - public string ConvertToString() - { - SplinatedMeshLibraryMaker SLM = new SplinatedMeshLibraryMaker(); - SLM.Setup(this); - return GSDRootUtil.GetString(SLM); - } - - public static void GetLibraryFiles(out string[] tNames, out string[] tPaths, bool bIsDefault = false) - { -#if UNITY_WEBPLAYER - tNames = null; - tPaths = null; - return; -#else - - tNames = null; - tPaths = null; - DirectoryInfo info; - string xPath = GSDRootUtil.Dir_GetLibrary(); - if (bIsDefault) - { - info = new DirectoryInfo(xPath + "Q/"); - } - else - { - info = new DirectoryInfo(xPath); - } - FileInfo[] fileInfo = info.GetFiles(); - int tCount = 0; - foreach (FileInfo tInfo in fileInfo) - { - if (tInfo.Name.Contains("ESO") && tInfo.Extension.ToLower().Contains("gsd")) - { - tCount += 1; - } - } - - tNames = new string[tCount]; - tPaths = new string[tCount]; - tCount = 0; - foreach (FileInfo tInfo in fileInfo) - { - if (tInfo.Name.Contains("ESO") && tInfo.Extension.ToLower().Contains("gsd")) - { - tNames[tCount] = tInfo.Name.Replace(".gsd", "").Replace("ESO", ""); - tPaths[tCount] = tInfo.FullName; - tCount += 1; - } - } -#endif - } - - public void Kill() - { - if (Output != null) - { - Object.DestroyImmediate(Output); - } - if (EndCapStartOutput != null) - { - Object.DestroyImmediate(EndCapStartOutput); - } - if (EndCapEndOutput != null) - { - Object.DestroyImmediate(EndCapEndOutput); - } - } - - [System.Serializable] - public class SplinatedMeshLibraryMaker - { - public string CurrentSplinationString = ""; - public string CurrentSplinationCap1String = ""; - public string CurrentSplinationCap2String = ""; - public bool bIsGSD = false; - - public bool bMaterialOverride = false; - public string SplinatedMaterial1String = ""; - public string SplinatedMaterial2String = ""; - public float CapHeightOffset1 = 0f; - public float CapHeightOffset2 = 0f; - public bool bExactSplination = false; - public bool bMatchRoadDefinition = false; - public bool bMatchRoadIncrements = true; - public bool bTrimStart = false; - public bool bTrimEnd = false; - public bool bToggle = false; - public bool bMatchTerrain = false; - public float MinMaxMod = 0.002f; - public float VertexMatchingPrecision = 0.005f; - - public bool bIsStretch = false; - public bool bStretchLocOffset = false; - public bool bStretchSize = false; - public Vector3 StretchBC_LocOffset = default(Vector3); - public Vector3 StretchBC_Size = default(Vector3); - public float Stretch_UVThreshold = 0.05f; - public bool bStraightLineMatchStartEnd = false; - public bool bBCFlipX = false; - public bool bBCFlipZ = false; - - //Horizontal offsets: - public float HorizontalSep = 5f; - public AnimationCurve HorizontalCurve; - //Vertical offsets: - public float VerticalRaise = 0f; - public AnimationCurve VerticalCurve; - //Vertical cutoff: - public float VerticalCutoff = 0f; - public bool bVerticalCutoff = false; - public bool bVerticalCutoffDownwards = false; - public bool bVerticalMeshCutoff_OppositeDir = false; - public float VerticalMeshCutoffOffset = 0.04f; - public bool bVerticalCutoff_MatchZero = false; - - public float RoadRaise = 0f; - public Vector3 CustomRotation = default(Vector3); - public bool bFlipRotation = false; - public bool bStatic = true; - public float StartTime = 0f; - public float EndTime = 1f; - public int Axis = 0; - public bool bIsBridge = false; - - public float mMaxX = -1f; - public float mMinX = -1f; - public float mMaxY = -1f; - public float mMinY = -1f; - public float mMaxZ = -1f; - public float mMinZ = -1f; - - public int RepeatUVType = 0; - public bool bNoCenterMode = true; - - //End objects: - public string EndCapStartString = ""; - public string EndCapEndString = ""; - public bool bEndCapCustomMatchStart = true; - public Vector3 EndCapCustomOffsetStart = default(Vector3); - public Vector3 EndCapCustomOffsetEnd = default(Vector3); - public Vector3 EndCapCustomRotOffsetStart = default(Vector3); - public Vector3 EndCapCustomRotOffsetEnd = default(Vector3); - public bool bEndObjectsMatchGround = false; - //Endings down: - public bool bStartDown = false; - public bool bStartTypeDownOverride = false; - public float StartTypeDownOverride = 0f; - public bool bEndDown = false; - public bool bEndTypeDownOverride = false; - public float EndTypeDownOverride = 0f; - - //Collision: - public int CollisionType = 0; - public bool bCollisionConvex = false; - public bool bSimpleCollisionAutomatic = true; - public bool bCollisionTrigger = false; - - public Vector3 CollisionBoxBL = default(Vector3); - public Vector3 CollisionBoxBR = default(Vector3); - public Vector3 CollisionBoxTL = default(Vector3); - public Vector3 CollisionBoxTR = default(Vector3); - - public Vector3 CollisionTriBL = default(Vector3); - public Vector3 CollisionTriBR = default(Vector3); - public Vector3 CollisionTriT = default(Vector3); - - public string tName = "ExtrudedObject"; - public string ThumbString = ""; - public string Desc = ""; - public string DisplayName = ""; - - public void Setup(SplinatedMeshMaker SMM) - { - CurrentSplinationString = SMM.CurrentSplinationString; - if (SMM.CurrentSplinationCap1 == null) - { - CurrentSplinationCap1String = ""; - } - else - { - CurrentSplinationCap1String = SMM.CurrentSplinationCap1String; - } - - if (SMM.CurrentSplinationCap2 == null) - { - CurrentSplinationCap2String = ""; - } - else - { - CurrentSplinationCap2String = SMM.CurrentSplinationCap2String; - } - bIsGSD = SMM.bIsGSD; - - CapHeightOffset1 = SMM.CapHeightOffset1; - CapHeightOffset2 = SMM.CapHeightOffset2; - - bMaterialOverride = SMM.bMaterialOverride; - SplinatedMaterial1String = SMM.SplinatedMaterial1String; - SplinatedMaterial2String = SMM.SplinatedMaterial2String; - bExactSplination = SMM.bExactSplination; - bMatchRoadDefinition = SMM.bMatchRoadDefinition; - bMatchRoadIncrements = SMM.bMatchRoadIncrements; - bTrimStart = SMM.bTrimStart; - bTrimEnd = SMM.bTrimEnd; - bMatchTerrain = SMM.bMatchTerrain; - MinMaxMod = SMM.MinMaxMod; - bIsBridge = SMM.bIsBridge; - VertexMatchingPrecision = SMM.VertexMatchingPrecision; - - bIsStretch = SMM.bIsStretch; - bStretchLocOffset = SMM.bStretchLocOffset; - bStretchSize = SMM.bStretchSize; - StretchBC_LocOffset = SMM.StretchBC_LocOffset; - StretchBC_Size = SMM.StretchBC_Size; - Stretch_UVThreshold = SMM.Stretch_UVThreshold; - bStraightLineMatchStartEnd = SMM.bStraightLineMatchStartEnd; - bBCFlipX = SMM.bBCFlipX; - bBCFlipZ = SMM.bBCFlipZ; - - //Horizontal offsets: - HorizontalSep = SMM.HorizontalSep; - HorizontalCurve = SMM.HorizontalCurve; - //Vertical offset: - VerticalRaise = SMM.VerticalRaise; - VerticalCurve = SMM.VerticalCurve; - //Vertical cutoff - VerticalCutoff = SMM.VerticalCutoff; - bVerticalCutoff = SMM.bVerticalCutoff; - bVerticalCutoffDownwards = SMM.bVerticalCutoffDownwards; - bVerticalMeshCutoff_OppositeDir = SMM.bVerticalMeshCutoff_OppositeDir; - VerticalMeshCutoffOffset = SMM.VerticalMeshCutoffOffset; - bVerticalCutoff_MatchZero = SMM.bVerticalCutoff_MatchZero; - - RoadRaise = SMM.RoadRaise; - CustomRotation = SMM.CustomRotation; - bFlipRotation = SMM.bFlipRotation; - bStatic = SMM.bStatic; - StartTime = SMM.StartTime; - EndTime = SMM.EndTime; - Axis = (int)SMM.Axis; - - RepeatUVType = (int)SMM.RepeatUVType; - - mMaxX = SMM.mMaxX; - mMinX = SMM.mMinX; - mMaxY = SMM.mMaxY; - mMinY = SMM.mMinY; - mMaxZ = SMM.mMaxZ; - mMinZ = SMM.mMinZ; - - //End objects: - if (SMM.EndCapStart == null) - { - EndCapStartString = ""; - } - else - { - EndCapStartString = SMM.EndCapStartString; - } - if (SMM.EndCapEnd == null) - { - EndCapEndString = ""; - } - else - { - EndCapEndString = SMM.EndCapEndString; - } - bEndCapCustomMatchStart = SMM.bEndCapCustomMatchStart; - EndCapCustomOffsetStart = SMM.EndCapCustomOffsetStart; - EndCapCustomOffsetEnd = SMM.EndCapCustomOffsetEnd; - EndCapCustomRotOffsetStart = SMM.EndCapCustomRotOffsetStart; - EndCapCustomRotOffsetEnd = SMM.EndCapCustomRotOffsetEnd; - bEndObjectsMatchGround = SMM.bEndObjectsMatchGround; - //Endings down: - bStartDown = SMM.bStartDown; - bStartTypeDownOverride = SMM.bStartTypeDownOverride; - StartTypeDownOverride = SMM.StartTypeDownOverride; - bEndDown = SMM.bEndDown; - bEndTypeDownOverride = SMM.bEndTypeDownOverride; - EndTypeDownOverride = SMM.EndTypeDownOverride; - - //Collision: - CollisionType = (int)SMM.CollisionType; - bCollisionConvex = SMM.bCollisionConvex; - bSimpleCollisionAutomatic = SMM.bSimpleCollisionAutomatic; - bCollisionTrigger = SMM.bCollisionTrigger; - - CollisionBoxBL = SMM.CollisionBoxBL; - CollisionBoxBR = SMM.CollisionBoxBR; - CollisionBoxTL = SMM.CollisionBoxTL; - CollisionBoxTR = SMM.CollisionBoxTR; - - CollisionTriBL = SMM.CollisionTriBL; - CollisionTriBR = SMM.CollisionTriBR; - CollisionTriT = SMM.CollisionTriT; - - tName = SMM.tName; - ThumbString = SMM.ThumbString; - Desc = SMM.Desc; - DisplayName = SMM.DisplayName; - } - - public void LoadToSMM(SplinatedMeshMaker SMM) - { -#if UNITY_EDITOR - SMM.CurrentSplinationString = CurrentSplinationString; - SMM.CurrentSplination = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationString, typeof(GameObject)); - - SMM.CurrentSplinationCap1String = CurrentSplinationCap1String; - if (CurrentSplinationCap1String != null && CurrentSplinationCap1String.Length > 1) - { - SMM.CurrentSplinationCap1 = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap1String, typeof(GameObject)); - } - - SMM.CurrentSplinationCap2String = CurrentSplinationCap2String; - if (CurrentSplinationCap2String != null && CurrentSplinationCap2String.Length > 1) - { - SMM.CurrentSplinationCap2 = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap2String, typeof(GameObject)); - } - - SMM.CapHeightOffset1 = CapHeightOffset1; - SMM.CapHeightOffset2 = CapHeightOffset2; - - SMM.bMaterialOverride = bMaterialOverride; - SMM.SplinatedMaterial1String = SplinatedMaterial1String; - SMM.SplinatedMaterial2String = SplinatedMaterial2String; - - if (bMaterialOverride) - { - if (SplinatedMaterial1String != null && SplinatedMaterial1String.Length > 0) - { - SMM.SplinatedMaterial1 = (Material)UnityEditor.AssetDatabase.LoadAssetAtPath(SplinatedMaterial1String, typeof(Material)); - } - if (SplinatedMaterial2String != null && SplinatedMaterial2String.Length > 0) - { - SMM.SplinatedMaterial2 = (Material)UnityEditor.AssetDatabase.LoadAssetAtPath(SplinatedMaterial2String, typeof(Material)); - } - } - - SMM.bIsGSD = bIsGSD; - SMM.bExactSplination = bExactSplination; - SMM.bMatchRoadDefinition = bMatchRoadDefinition; - SMM.bMatchRoadIncrements = bMatchRoadIncrements; - SMM.bTrimStart = bTrimStart; - SMM.bTrimEnd = bTrimEnd; - SMM.bMatchTerrain = bMatchTerrain; - SMM.MinMaxMod = MinMaxMod; - SMM.bIsBridge = bIsBridge; - SMM.VertexMatchingPrecision = VertexMatchingPrecision; - - SMM.bIsStretch = bIsStretch; - SMM.bStretchLocOffset = bStretchLocOffset; - SMM.bStretchSize = bStretchSize; - SMM.StretchBC_LocOffset = StretchBC_LocOffset; - SMM.StretchBC_Size = StretchBC_Size; - SMM.Stretch_UVThreshold = Stretch_UVThreshold; - SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; - SMM.bBCFlipX = bBCFlipX; - SMM.bBCFlipZ = bBCFlipZ; - - //Horizontal offsets: - SMM.HorizontalSep = HorizontalSep; - SMM.HorizontalCurve = HorizontalCurve; - //Vertical offset: - SMM.VerticalRaise = VerticalRaise; - SMM.VerticalCurve = VerticalCurve; - //Vertical cutoff: - SMM.VerticalCutoff = VerticalCutoff; - SMM.bVerticalCutoff = bVerticalCutoff; - SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; - SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; - SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; - SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; - - SMM.RoadRaise = RoadRaise; - SMM.CustomRotation = CustomRotation; - SMM.bFlipRotation = bFlipRotation; - SMM.bStatic = bStatic; - SMM.StartTime = StartTime; - SMM.EndTime = EndTime; - SMM.Axis = (AxisTypeEnum)Axis; - - SMM.RepeatUVType = (RepeatUVTypeEnum)RepeatUVType; - - SMM.mMaxX = mMaxX; - SMM.mMinX = mMinX; - SMM.mMaxY = mMaxY; - SMM.mMinY = mMinY; - SMM.mMaxZ = mMaxZ; - SMM.mMinZ = mMinZ; - - //Ending objects: - SMM.EndCapStartString = EndCapStartString; - SMM.EndCapEndString = EndCapEndString; - if (EndCapStartString != null && EndCapStartString.Length > 0) - { - SMM.EndCapStart = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(EndCapStartString, typeof(GameObject)); - } - if (EndCapEndString != null && EndCapEndString.Length > 0) - { - SMM.EndCapEnd = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(EndCapEndString, typeof(GameObject)); - } - SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; - SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; - SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; - SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; - SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; - SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; - - //Endings down: - SMM.bStartDown = bStartDown; - SMM.bStartTypeDownOverride = bStartTypeDownOverride; - SMM.StartTypeDownOverride = StartTypeDownOverride; - SMM.bEndDown = bEndDown; - SMM.bEndTypeDownOverride = bEndTypeDownOverride; - SMM.EndTypeDownOverride = EndTypeDownOverride; - - //Collision: - SMM.CollisionType = (CollisionTypeEnum)CollisionType; - SMM.bCollisionConvex = bCollisionConvex; - SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; - SMM.bCollisionTrigger = bCollisionTrigger; - - SMM.CollisionBoxBL = CollisionBoxBL; - SMM.CollisionBoxBR = CollisionBoxBR; - SMM.CollisionBoxTL = CollisionBoxTL; - SMM.CollisionBoxTR = CollisionBoxTR; - - SMM.CollisionTriBL = CollisionTriBL; - SMM.CollisionTriBR = CollisionTriBR; - SMM.CollisionTriT = CollisionTriT; - - SMM.tName = tName; - SMM.ThumbString = ThumbString; - SMM.Desc = Desc; - SMM.DisplayName = DisplayName; -#endif - } - } - - - public class SplinatedMeshEditorMaker - { - public GameObject CurrentSplination = null; - public GameObject CurrentSplinationCap1 = null; - public GameObject CurrentSplinationCap2 = null; - - public bool bMaterialOverride = false; - public Material SplinatedMaterial1 = null; - public Material SplinatedMaterial2 = null; - public float CapHeightOffset1 = 0f; - public float CapHeightOffset2 = 0f; - public bool bExactSplination = false; - public bool bMatchRoadDefinition = false; - public bool bMatchRoadIncrements = true; - public bool bTrimStart = false; - public bool bTrimEnd = false; - public bool bToggle = false; - public bool bMatchTerrain = false; - public float MinMaxMod = 0.002f; - public float VertexMatchingPrecision = 0.005f; - - public bool bIsStretch = false; - public bool bStretchLocOffset = false; - public bool bStretchSize = false; - public Vector3 StretchBC_LocOffset = default(Vector3); - public Vector3 StretchBC_Size = default(Vector3); - public float Stretch_UVThreshold = 0.05f; - public bool bStraightLineMatchStartEnd = false; - public bool bBCFlipX = false; - public bool bBCFlipZ = false; - - //Horizontal offsets: - public float HorizontalSep = 5f; - public AnimationCurve HorizontalCurve; - //Vertical offsets: - public float VerticalRaise = 0f; - public AnimationCurve VerticalCurve; - //Vertical cutoff: - public float VerticalCutoff = 0f; - public bool bVerticalCutoff = false; - public bool bVerticalCutoffDownwards = false; - public bool bVerticalMeshCutoff_OppositeDir = false; - public float VerticalMeshCutoffOffset = 0.04f; - public bool bVerticalCutoff_MatchZero = false; - - public float RoadRaise = 0f; - public Vector3 CustomRotation = default(Vector3); - public bool bFlipRotation = false; - public bool bStatic = true; - public float StartTime = 0f; - public float EndTime = 1f; - public AxisTypeEnum Axis = AxisTypeEnum.X; - public bool bIsBridge = false; - - public RepeatUVTypeEnum RepeatUVType = RepeatUVTypeEnum.None; - public bool bNoCenterMode = true; - - //End objects: - public GameObject EndCapStart = null; - public GameObject EndCapEnd = null; - public bool bEndCapCustomMatchStart = true; - public Vector3 EndCapCustomOffsetStart = default(Vector3); - public Vector3 EndCapCustomOffsetEnd = default(Vector3); - public Vector3 EndCapCustomRotOffsetStart = default(Vector3); - public Vector3 EndCapCustomRotOffsetEnd = default(Vector3); - public bool bEndObjectsMatchGround = false; - //Endings down: - public bool bStartDown = false; - public bool bStartTypeDownOverride = false; - public float StartTypeDownOverride = 0f; - public bool bEndDown = false; - public bool bEndTypeDownOverride = false; - public float EndTypeDownOverride = 0f; - - //Collision: - public CollisionTypeEnum CollisionType = CollisionTypeEnum.SimpleMeshTriangle; - public bool bCollisionConvex = false; - public bool bSimpleCollisionAutomatic = true; - public bool bCollisionTrigger = false; - - public Vector3 CollisionBoxBL = default(Vector3); - public Vector3 CollisionBoxBR = default(Vector3); - public Vector3 CollisionBoxTL = default(Vector3); - public Vector3 CollisionBoxTR = default(Vector3); - - public Vector3 CollisionTriBL = default(Vector3); - public Vector3 CollisionTriBR = default(Vector3); - public Vector3 CollisionTriT = default(Vector3); - - public string tName = "ExtrudedObject"; - - public void Setup(SplinatedMeshMaker SMM) - { - CurrentSplination = SMM.CurrentSplination; - CurrentSplinationCap1 = SMM.CurrentSplinationCap1; - CurrentSplinationCap2 = SMM.CurrentSplinationCap2; - - CapHeightOffset1 = SMM.CapHeightOffset1; - CapHeightOffset2 = SMM.CapHeightOffset2; - - bMaterialOverride = SMM.bMaterialOverride; - SplinatedMaterial1 = SMM.SplinatedMaterial1; - SplinatedMaterial2 = SMM.SplinatedMaterial2; - bExactSplination = SMM.bExactSplination; - bMatchRoadDefinition = SMM.bMatchRoadDefinition; - bMatchRoadIncrements = SMM.bMatchRoadIncrements; - bTrimStart = SMM.bTrimStart; - bTrimEnd = SMM.bTrimEnd; - bMatchTerrain = SMM.bMatchTerrain; - MinMaxMod = SMM.MinMaxMod; - bIsBridge = SMM.bIsBridge; - VertexMatchingPrecision = SMM.VertexMatchingPrecision; - - bIsStretch = SMM.bIsStretch; - bStretchLocOffset = SMM.bStretchLocOffset; - bStretchSize = SMM.bStretchSize; - StretchBC_LocOffset = SMM.StretchBC_LocOffset; - StretchBC_Size = SMM.StretchBC_Size; - Stretch_UVThreshold = SMM.Stretch_UVThreshold; - bStraightLineMatchStartEnd = SMM.bStraightLineMatchStartEnd; - bBCFlipX = SMM.bBCFlipX; - bBCFlipZ = SMM.bBCFlipZ; - - //Horizontal offsets: - HorizontalSep = SMM.HorizontalSep; - HorizontalCurve = SMM.HorizontalCurve; - //Vertical offset: - VerticalRaise = SMM.VerticalRaise; - VerticalCurve = SMM.VerticalCurve; - //Vertical cutoff - VerticalCutoff = SMM.VerticalCutoff; - bVerticalCutoff = SMM.bVerticalCutoff; - bVerticalCutoffDownwards = SMM.bVerticalCutoffDownwards; - bVerticalMeshCutoff_OppositeDir = SMM.bVerticalMeshCutoff_OppositeDir; - VerticalMeshCutoffOffset = SMM.VerticalMeshCutoffOffset; - bVerticalCutoff_MatchZero = SMM.bVerticalCutoff_MatchZero; - - RoadRaise = SMM.RoadRaise; - CustomRotation = SMM.CustomRotation; - bFlipRotation = SMM.bFlipRotation; - bStatic = SMM.bStatic; - StartTime = SMM.StartTime; - EndTime = SMM.EndTime; - Axis = SMM.Axis; - - RepeatUVType = SMM.RepeatUVType; - - //End objects: - EndCapStart = SMM.EndCapStart; - EndCapEnd = SMM.EndCapEnd; - - bEndCapCustomMatchStart = SMM.bEndCapCustomMatchStart; - EndCapCustomOffsetStart = SMM.EndCapCustomOffsetStart; - EndCapCustomOffsetEnd = SMM.EndCapCustomOffsetEnd; - EndCapCustomRotOffsetStart = SMM.EndCapCustomRotOffsetStart; - EndCapCustomRotOffsetEnd = SMM.EndCapCustomRotOffsetEnd; - bEndObjectsMatchGround = SMM.bEndObjectsMatchGround; - //Endings down: - bStartDown = SMM.bStartDown; - bStartTypeDownOverride = SMM.bStartTypeDownOverride; - StartTypeDownOverride = SMM.StartTypeDownOverride; - bEndDown = SMM.bEndDown; - bEndTypeDownOverride = SMM.bEndTypeDownOverride; - EndTypeDownOverride = SMM.EndTypeDownOverride; - - //Collision: - CollisionType = SMM.CollisionType; - bCollisionConvex = SMM.bCollisionConvex; - bSimpleCollisionAutomatic = SMM.bSimpleCollisionAutomatic; - bCollisionTrigger = SMM.bCollisionTrigger; - - CollisionBoxBL = SMM.CollisionBoxBL; - CollisionBoxBR = SMM.CollisionBoxBR; - CollisionBoxTL = SMM.CollisionBoxTL; - CollisionBoxTR = SMM.CollisionBoxTR; - - CollisionTriBL = SMM.CollisionTriBL; - CollisionTriBR = SMM.CollisionTriBR; - CollisionTriT = SMM.CollisionTriT; - - tName = SMM.tName; - } - - public void LoadToSMM(SplinatedMeshMaker SMM) - { -#if UNITY_EDITOR - SMM.CurrentSplination = CurrentSplination; // (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationString,typeof(GameObject)); - SMM.CurrentSplinationCap1 = CurrentSplinationCap1;// (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap1String,typeof(GameObject)); - SMM.CurrentSplinationCap2 = CurrentSplinationCap2;// (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap2String,typeof(GameObject)); - - SMM.CapHeightOffset1 = CapHeightOffset1; - SMM.CapHeightOffset2 = CapHeightOffset2; - - SMM.bMaterialOverride = bMaterialOverride; - - SMM.SplinatedMaterial1 = SplinatedMaterial1; - SMM.SplinatedMaterial2 = SplinatedMaterial2; - - SMM.bExactSplination = bExactSplination; - SMM.bMatchRoadDefinition = bMatchRoadDefinition; - SMM.bMatchRoadIncrements = bMatchRoadIncrements; - SMM.bTrimStart = bTrimStart; - SMM.bTrimEnd = bTrimEnd; - SMM.bMatchTerrain = bMatchTerrain; - SMM.MinMaxMod = MinMaxMod; - SMM.bIsBridge = bIsBridge; - SMM.VertexMatchingPrecision = VertexMatchingPrecision; - - SMM.bIsStretch = bIsStretch; - SMM.bStretchLocOffset = bStretchLocOffset; - SMM.bStretchSize = bStretchSize; - SMM.StretchBC_LocOffset = StretchBC_LocOffset; - SMM.StretchBC_Size = StretchBC_Size; - SMM.Stretch_UVThreshold = Stretch_UVThreshold; - SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; - SMM.bBCFlipX = bBCFlipX; - SMM.bBCFlipZ = bBCFlipZ; - - //Horizontal offsets: - SMM.HorizontalSep = HorizontalSep; - SMM.HorizontalCurve = HorizontalCurve; - //Vertical offset: - SMM.VerticalRaise = VerticalRaise; - SMM.VerticalCurve = VerticalCurve; - //Vertical cutoff: - SMM.VerticalCutoff = VerticalCutoff; - SMM.bVerticalCutoff = bVerticalCutoff; - SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; - SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; - SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; - SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; - - SMM.RoadRaise = RoadRaise; - SMM.CustomRotation = CustomRotation; - SMM.bFlipRotation = bFlipRotation; - SMM.bStatic = bStatic; - SMM.StartTime = StartTime; - SMM.EndTime = EndTime; - SMM.Axis = Axis; - - SMM.RepeatUVType = RepeatUVType; - - //Ending objects: - SMM.EndCapStart = EndCapStart; - SMM.EndCapEnd = EndCapEnd; - - SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; - SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; - SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; - SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; - SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; - SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; - - //Endings down: - SMM.bStartDown = bStartDown; - SMM.bStartTypeDownOverride = bStartTypeDownOverride; - SMM.StartTypeDownOverride = StartTypeDownOverride; - SMM.bEndDown = bEndDown; - SMM.bEndTypeDownOverride = bEndTypeDownOverride; - SMM.EndTypeDownOverride = EndTypeDownOverride; - - //Collision: - SMM.CollisionType = CollisionType; - SMM.bCollisionConvex = bCollisionConvex; - SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; - SMM.bCollisionTrigger = bCollisionTrigger; - - SMM.CollisionBoxBL = CollisionBoxBL; - SMM.CollisionBoxBR = CollisionBoxBR; - SMM.CollisionBoxTL = CollisionBoxTL; - SMM.CollisionBoxTR = CollisionBoxTR; - - SMM.CollisionTriBL = CollisionTriBL; - SMM.CollisionTriBR = CollisionTriBR; - SMM.CollisionTriT = CollisionTriT; - - SMM.tName = tName; -#endif - } - - public bool IsEqualToSMM(SplinatedMeshMaker SMM) - { - if (SMM.CurrentSplination != CurrentSplination) { return false; } - if (SMM.CurrentSplinationCap1 != CurrentSplinationCap1) { return false; } - if (SMM.CurrentSplinationCap2 != CurrentSplinationCap2) { return false; } - - if (!GSDRootUtil.IsApproximately(SMM.CapHeightOffset1, CapHeightOffset1, 0.0001f)) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.CapHeightOffset2, CapHeightOffset2, 0.0001f)) { return false; } - - if (SMM.bMaterialOverride != bMaterialOverride) { return false; } - - if (SMM.SplinatedMaterial1 != SplinatedMaterial1) { return false; } - if (SMM.SplinatedMaterial2 != SplinatedMaterial2) { return false; } - - if (SMM.bExactSplination != bExactSplination) { return false; } - if (SMM.bMatchRoadDefinition != bMatchRoadDefinition) { return false; } - if (SMM.bMatchRoadIncrements != bMatchRoadIncrements) { return false; } - if (SMM.bTrimStart != bTrimStart) { return false; } - if (SMM.bTrimEnd != bTrimEnd) { return false; } - if (SMM.bMatchTerrain != bMatchTerrain) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.MinMaxMod, MinMaxMod, 0.0001f)) { return false; } - if (SMM.bIsBridge != bIsBridge) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.VertexMatchingPrecision, VertexMatchingPrecision, 0.0001f)) { return false; } - - if (SMM.bIsStretch != bIsStretch) { return false; } - if (SMM.bStretchLocOffset != bStretchLocOffset) { return false; } - if (SMM.bStretchSize != bStretchSize) { return false; } - if (SMM.StretchBC_LocOffset != StretchBC_LocOffset) { return false; } - if (SMM.StretchBC_Size != StretchBC_Size) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.Stretch_UVThreshold, Stretch_UVThreshold, 0.0001f)) { return false; } - if (SMM.bStraightLineMatchStartEnd != bStraightLineMatchStartEnd) { return false; } - if (SMM.bBCFlipX != bBCFlipX) { return false; } - if (SMM.bBCFlipZ != bBCFlipZ) { return false; } - - //Horizontal offsets: - if (!GSDRootUtil.IsApproximately(SMM.HorizontalSep, HorizontalSep, 0.0001f)) { return false; } - if (SMM.HorizontalCurve != HorizontalCurve) { return false; } - //Vertical offset: - if (!GSDRootUtil.IsApproximately(SMM.VerticalRaise, VerticalRaise, 0.0001f)) { return false; } - if (SMM.VerticalCurve != VerticalCurve) { return false; } - //Vertical cutoff: - if (!GSDRootUtil.IsApproximately(SMM.VerticalCutoff, VerticalCutoff, 0.0001f)) { return false; } - if (SMM.bVerticalCutoff != bVerticalCutoff) { return false; } - if (SMM.bVerticalCutoffDownwards != bVerticalCutoffDownwards) { return false; } - if (SMM.bVerticalMeshCutoff_OppositeDir != bVerticalMeshCutoff_OppositeDir) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.VerticalMeshCutoffOffset, VerticalMeshCutoffOffset, 0.0001f)) { return false; } - if (SMM.bVerticalCutoff_MatchZero != bVerticalCutoff_MatchZero) { return false; } - - if (!GSDRootUtil.IsApproximately(SMM.RoadRaise, RoadRaise, 0.0001f)) { return false; } - if (SMM.CustomRotation != CustomRotation) { return false; } - if (SMM.bFlipRotation != bFlipRotation) { return false; } - if (SMM.bStatic != bStatic) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.StartTime, StartTime, 0.0001f)) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.EndTime, EndTime, 0.0001f)) { return false; } - if (SMM.Axis != Axis) { return false; } - - if (SMM.RepeatUVType != RepeatUVType) { return false; } - - //Ending objects: - if (SMM.EndCapStart != EndCapStart) { return false; } - if (SMM.EndCapEnd != EndCapEnd) { return false; } - - if (SMM.bEndCapCustomMatchStart != bEndCapCustomMatchStart) { return false; } - if (SMM.EndCapCustomOffsetStart != EndCapCustomOffsetStart) { return false; } - if (SMM.EndCapCustomOffsetEnd != EndCapCustomOffsetEnd) { return false; } - if (SMM.EndCapCustomRotOffsetStart != EndCapCustomRotOffsetStart) { return false; } - if (SMM.EndCapCustomRotOffsetEnd != EndCapCustomRotOffsetEnd) { return false; } - if (SMM.bEndObjectsMatchGround != bEndObjectsMatchGround) { return false; } - - //Endings down: - if (SMM.bStartDown != bStartDown) { return false; } - if (SMM.bStartTypeDownOverride != bStartTypeDownOverride) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.StartTypeDownOverride, StartTypeDownOverride, 0.0001f)) { return false; } - if (SMM.bEndDown != bEndDown) { return false; } - if (SMM.bEndTypeDownOverride != bEndTypeDownOverride) { return false; } - if (!GSDRootUtil.IsApproximately(SMM.EndTypeDownOverride, EndTypeDownOverride, 0.0001f)) { return false; } - - //Collision: - if (SMM.CollisionType != CollisionType) { return false; } - if (SMM.bCollisionConvex != bCollisionConvex) { return false; } - if (SMM.bSimpleCollisionAutomatic != bSimpleCollisionAutomatic) { return false; } - if (SMM.bCollisionTrigger != bCollisionTrigger) { return false; } - - if (SMM.CollisionBoxBL != CollisionBoxBL) { return false; } - if (SMM.CollisionBoxBR != CollisionBoxBR) { return false; } - if (SMM.CollisionBoxTL != CollisionBoxTL) { return false; } - if (SMM.CollisionBoxTR != CollisionBoxTR) { return false; } - - if (SMM.CollisionTriBL != CollisionTriBL) { return false; } - if (SMM.CollisionTriBR != CollisionTriBR) { return false; } - if (SMM.CollisionTriT != CollisionTriT) { return false; } - - if (string.CompareOrdinal(SMM.tName, tName) != 0) { return false; } - - return true; - } - } - - - #region "Static util" - public void SetupUniqueIdentifier() - { - if (UID == null || UID.Length < 4) - { - UID = System.Guid.NewGuid().ToString(); - } - } - - public static Vector3 GetVector3Average(Vector3[] tVects) - { - int tCount = tVects.Length; - Vector3 mVect = default(Vector3); - for (int i = 0; i < tCount; i++) - { - mVect += tVects[i]; - } - mVect /= tCount; - return mVect; - } - - private static bool FloatsNear(float tNear, float tVal1, float tVal2) - { - if (GSDRootUtil.IsApproximately(tVal1, tVal2, tNear)) { return true; } - - if (tVal1 < (tVal2 + tNear) && tVal1 > (tVal2 - tNear)) - { - return true; - } - if (tVal2 < (tVal1 + tNear) && tVal2 > (tVal1 - tNear)) - { - return true; - } - return false; - } - - private static int[] GetCollisionTris_Tri(int MeshCount, int cTriCount, int cCount) - { - int tCounter = 0; - int[] tTris = new int[cTriCount * 3]; - - //Front side: ** - tTris[tCounter] = 0; tCounter += 1; - tTris[tCounter] = 2; tCounter += 1; - tTris[tCounter] = 1; tCounter += 1; - int tMod = -1; - for (int i = 0; i < (MeshCount); i++) - { - tMod = (i * 3); - //Bottom side: *** - tTris[tCounter] = 1 + tMod; tCounter += 1; - tTris[tCounter] = 4 + tMod; tCounter += 1; - tTris[tCounter] = 0 + tMod; tCounter += 1; - tTris[tCounter] = 4 + tMod; tCounter += 1; - tTris[tCounter] = 3 + tMod; tCounter += 1; - tTris[tCounter] = 0 + tMod; tCounter += 1; - //Left side: *** - tTris[tCounter] = 3 + tMod; tCounter += 1; - tTris[tCounter] = 5 + tMod; tCounter += 1; - tTris[tCounter] = 0 + tMod; tCounter += 1; - tTris[tCounter] = 5 + tMod; tCounter += 1; - tTris[tCounter] = 2 + tMod; tCounter += 1; - tTris[tCounter] = 0 + tMod; tCounter += 1; - //Right side: *** - tTris[tCounter] = 1 + tMod; tCounter += 1; - tTris[tCounter] = 2 + tMod; tCounter += 1; - tTris[tCounter] = 4 + tMod; tCounter += 1; - tTris[tCounter] = 2 + tMod; tCounter += 1; - tTris[tCounter] = 5 + tMod; tCounter += 1; - tTris[tCounter] = 4 + tMod; tCounter += 1; - } - //Back side: ** - tTris[tCounter] = cCount - 2; tCounter += 1; - tTris[tCounter] = cCount - 1; tCounter += 1; - tTris[tCounter] = cCount - 3; tCounter += 1; - - return tTris; - } - - private static int[] GetCollisionTris_Box(int MeshCount, int cTriCount, int cCount) - { - int tCounter = 0; - int[] tTris = new int[cTriCount * 3]; - - //Front side: *** - tTris[tCounter] = 0; tCounter += 1; - tTris[tCounter] = 2; tCounter += 1; - tTris[tCounter] = 1; tCounter += 1; - tTris[tCounter] = 2; tCounter += 1; - tTris[tCounter] = 3; tCounter += 1; - tTris[tCounter] = 1; tCounter += 1; - - int tMod = -1; - for (int i = 0; i < (MeshCount); i++) - { - tMod = (i * 4); - //Bottom side: *** - tTris[tCounter] = tMod + 1; tCounter += 1; - tTris[tCounter] = tMod + 5; tCounter += 1; - tTris[tCounter] = tMod + 0; tCounter += 1; - tTris[tCounter] = tMod + 5; tCounter += 1; - tTris[tCounter] = tMod + 4; tCounter += 1; - tTris[tCounter] = tMod + 0; tCounter += 1; - //Top side: *** - tTris[tCounter] = tMod + 2; tCounter += 1; - tTris[tCounter] = tMod + 6; tCounter += 1; - tTris[tCounter] = tMod + 3; tCounter += 1; - tTris[tCounter] = tMod + 6; tCounter += 1; - tTris[tCounter] = tMod + 7; tCounter += 1; - tTris[tCounter] = tMod + 3; tCounter += 1; - //Left side: *** - tTris[tCounter] = tMod + 4; tCounter += 1; - tTris[tCounter] = tMod + 6; tCounter += 1; - tTris[tCounter] = tMod + 0; tCounter += 1; - tTris[tCounter] = tMod + 6; tCounter += 1; - tTris[tCounter] = tMod + 2; tCounter += 1; - tTris[tCounter] = tMod + 0; tCounter += 1; - //Right side: *** - tTris[tCounter] = tMod + 1; tCounter += 1; - tTris[tCounter] = tMod + 3; tCounter += 1; - tTris[tCounter] = tMod + 5; tCounter += 1; - tTris[tCounter] = tMod + 3; tCounter += 1; - tTris[tCounter] = tMod + 7; tCounter += 1; - tTris[tCounter] = tMod + 5; tCounter += 1; - } - - //Back side: *** - tTris[tCounter] = cCount - 3; tCounter += 1; - tTris[tCounter] = cCount - 1; tCounter += 1; - tTris[tCounter] = cCount - 4; tCounter += 1; - tTris[tCounter] = cCount - 1; tCounter += 1; - tTris[tCounter] = cCount - 2; tCounter += 1; - tTris[tCounter] = cCount - 4; tCounter += 1; - - return tTris; - } - - private static bool IsApproxTwoThirds(ref Vector3 V1, Vector3 V2, float Precision = 0.005f) - { - int cCount = 0; - if (GSDRootUtil.IsApproximately(V1.x, V2.x, Precision)) - { - cCount += 1; - } - if (GSDRootUtil.IsApproximately(V1.y, V2.y, Precision)) - { - cCount += 1; - } - if (GSDRootUtil.IsApproximately(V1.z, V2.z, Precision)) - { - cCount += 1; - } - - if (cCount == 2) - { - return true; - } - else - { - return false; - } - } - - private static bool IsApproxWithNeg(ref Vector3 V1, ref Vector3 V2) - { - int cCount = 0; - bool bXMatch = false; - bool bYMatch = false; - bool bZMatch = false; - - if (GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) - { - cCount += 1; - bXMatch = true; - } - if (GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) - { - cCount += 1; - bYMatch = true; - } - if (GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) - { - cCount += 1; - bZMatch = true; - } - - if (cCount == 2) - { - if (!bXMatch && GSDRootUtil.IsApproximately(V1.x, V2.x * -1f, 0.02f)) - { - return true; - } - else if (!bYMatch && GSDRootUtil.IsApproximately(V1.y, V2.y * -1f, 0.02f)) - { - return true; - } - else if (!bZMatch && GSDRootUtil.IsApproximately(V1.z, V2.z * -1f, 0.02f)) - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - - private static bool V3EqualToNone(Vector3 V1) - { - if (!GSDRootUtil.IsApproximately(V1.x, 0f, 0.0001f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.y, 0f, 0.0001f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.z, 0f, 0.0001f)) - { - return false; - } - return true; - } - - private static bool V3EqualNormal(Vector3 V1, Vector3 V2) - { - if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.01f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.01f)) - { - return false; - } - if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.01f)) - { - return false; - } - return true; - } - - private static bool IsApproxExtruded(ref Vector3 V1, ref Vector3 V2, bool bIsZAxis) - { - if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) - { - return false; - } - - if (bIsZAxis) - { - if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) - { - return false; - } - } - else - { - if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) - { - return false; - } - } - - return true; - } - - private static float GetVHeightAtXY(ref Vector3 tVect1, ref Vector3 tVect2, ref Vector3 tVect3) - { - Vector2 tVect2D1 = new Vector2(tVect1.x, tVect1.z); - Vector2 tVect2D2 = new Vector2(tVect2.x, tVect2.z); - Vector2 tVect2D3 = new Vector2(tVect3.x, tVect3.z); - - float tDist1 = Vector2.Distance(tVect2D1, tVect2D3); - float tDist2 = Vector2.Distance(tVect2D2, tVect2D3); - float tDistSum = tDist1 + tDist2; - - float CloseTo1 = (tDist1 / tDistSum); - - Vector3 tVect = ((tVect2 - tVect1) * CloseTo1) + tVect1; - - return tVect.y; - } - #endregion - - - public void Setup(bool bGetStrings = false, bool bCollect = true) - { -#if UNITY_EDITOR - GameObject[] tObj = new GameObject[5]; - try - { - SplinateMesh_Do(bGetStrings, ref tObj, bCollect); - } - catch (System.Exception e) - { - if (tObj != null) - { - for (int i = 0; i < 5; i++) - { - if (tObj[i] != null) - { - Object.DestroyImmediate(tObj[i]); - } - } - } - throw e; - } -#endif - } - private void SplinateMesh_Do(bool bGetStrings, ref GameObject[] ErrortObj, bool bCollect) - { -#if UNITY_EDITOR - bNeedsUpdate = false; - SetupUniqueIdentifier(); - - //Buffers: - Vector3 tVect1 = default(Vector3); - Vector3 tVect2 = default(Vector3); - Vector3 tDir = default(Vector3); - Vector3 xVect = default(Vector3); - // Vector3 oVect = default(Vector3); - // Quaternion tRot = default(Quaternion); - float tFloat1 = default(float); - // float tFloat2 = default(float); - // float tFloat3 = default(float); - // int tCount = -1; - - StartTime = tSpline.GetClosestParam(StartPos); - EndTime = tSpline.GetClosestParam(EndPos); - - if (EndTime < StartTime) - { - EndTime = tNode.NextTime; - EndPos = tSpline.GetSplineValue(EndTime, false); - } - if (EndTime > 0.99995f) - { - EndTime = 0.99995f; - EndPos = tSpline.GetSplineValue(EndTime, false); - } - - Kill(); - if (HorizontalCurve == null) - { - HorizontalCurve = new AnimationCurve(); - HorizontalCurve.AddKey(0f, 1f); - HorizontalCurve.AddKey(1f, 1f); - } - if (VerticalCurve == null) - { - VerticalCurve = new AnimationCurve(); - VerticalCurve.AddKey(0f, 1f); - VerticalCurve.AddKey(1f, 1f); - } - - // bool bIsLeft = false; - // if(HorizontalSep < 0f){ - // bIsLeft = true; - // } - - //Setup strings: - if (bGetStrings) - { - CurrentSplinationString = GSDRootUtil.GetPrefabString(CurrentSplination); - if (CurrentSplinationCap1 != null) { CurrentSplinationCap1String = GSDRootUtil.GetPrefabString(CurrentSplinationCap1); } - if (CurrentSplinationCap2 != null) { CurrentSplinationCap2String = GSDRootUtil.GetPrefabString(CurrentSplinationCap2); } - if (EndCapStart != null) { EndCapStartString = GSDRootUtil.GetPrefabString(EndCapStart); } - if (EndCapEnd != null) { EndCapEndString = GSDRootUtil.GetPrefabString(EndCapEnd); } - if (SplinatedMaterial1 != null) { SplinatedMaterial1String = UnityEditor.AssetDatabase.GetAssetPath(SplinatedMaterial1); } - if (SplinatedMaterial2 != null) { SplinatedMaterial2String = UnityEditor.AssetDatabase.GetAssetPath(SplinatedMaterial2); } - } - - if (CurrentSplination == null) { return; } - GameObject tObj = (GameObject)GameObject.Instantiate(CurrentSplination); - ErrortObj[0] = tObj; - - GameObject EndCapStartObj = null; - GameObject EndCapEndObj = null; - if (EndCapStart != null) - { - EndCapStartObj = (GameObject)GameObject.Instantiate(EndCapStart); - ErrortObj[1] = EndCapStartObj; - } - if (EndCapEnd != null) - { - EndCapEndObj = (GameObject)GameObject.Instantiate(EndCapEnd); - ErrortObj[2] = EndCapEndObj; - } - - GameObject Cap1 = null; - GameObject Cap2 = null; - if (bFlipRotation) - { - if (CurrentSplinationCap2 != null) - { - Cap1 = (GameObject)GameObject.Instantiate(CurrentSplinationCap2); - ErrortObj[3] = Cap1; - } - if (CurrentSplinationCap1 != null) - { - Cap2 = (GameObject)GameObject.Instantiate(CurrentSplinationCap1); - ErrortObj[4] = Cap2; - } - } - else - { - if (CurrentSplinationCap1 != null) - { - Cap1 = (GameObject)GameObject.Instantiate(CurrentSplinationCap1); - ErrortObj[3] = Cap1; - } - if (CurrentSplinationCap2 != null) - { - Cap2 = (GameObject)GameObject.Instantiate(CurrentSplinationCap2); - ErrortObj[4] = Cap2; - } - } - - MeshFilter MF = null; - Mesh CapMesh1 = null; - Mesh CapMesh2 = null; - HashSet tCapMatchIndices1 = new HashSet(); - HashSet tCapMatchIndices2 = new HashSet(); - if (Cap1 != null) - { - MF = Cap1.GetComponent(); - CapMesh1 = MF.sharedMesh; - } - if (Cap2 != null) - { - MF = Cap2.GetComponent(); - CapMesh2 = MF.sharedMesh; - } - - MF = tObj.GetComponent(); - tMesh = MF.sharedMesh; - - // Quaternion OrigRot = tObj.transform.rotation; - if (bFlipRotation) - { - tVect1 = new Vector3(0f, 180f, 0f); - tObj.transform.Rotate(tVect1, Space.World); - if (Cap1 != null) { Cap1.transform.Rotate(tVect1, Space.World); } - if (Cap2 != null) { Cap2.transform.Rotate(tVect1, Space.World); } - } - tObj.transform.Rotate(CustomRotation, Space.World); - if (Cap1 != null) { Cap1.transform.Rotate(CustomRotation, Space.World); } - if (Cap2 != null) { Cap2.transform.Rotate(CustomRotation, Space.World); } - - if (tMesh == null) - { - GameObject.DestroyImmediate(tObj); - Debug.LogError("Mesh was null"); - return; - } - - Vector3[] CapOrigVerts1 = null; - Vector3[] CapOrigVerts2 = null; - int CapOrigMVL1 = 0; - int CapOrigMVL2 = 0; - if (CapMesh1 != null) - { - CapOrigVerts1 = CapMesh1.vertices; - CapOrigMVL1 = CapOrigVerts1.Length; - } - if (CapMesh2 != null) - { - CapOrigVerts2 = CapMesh2.vertices; - CapOrigMVL2 = CapOrigVerts2.Length; - } - - Vector3[] OrigVerts = tMesh.vertices; - int OrigMVL = OrigVerts.Length; - - //Transform vertices: - Vector3[] OrigNormals = tMesh.normals; - bool bCheckingNormal = true; - for (int i = 0; i < OrigMVL; i++) - { - OrigVerts[i] = tObj.transform.TransformPoint(OrigVerts[i]); - if (bCheckingNormal) - { - if (!V3EqualToNone(OrigNormals[i])) - { - bCheckingNormal = false; - } - } - } - //If no normals on base mesh, recalc them - if (bCheckingNormal) - { - tMesh.RecalculateNormals(); - OrigNormals = tMesh.normals; - } - //Cap mesh: - Vector3[] CapOrigNormals1 = null; - Vector3[] CapOrigNormals2 = null; - int[] CapOrigTris1 = null; - int[] CapOrigTris2 = null; - Vector2[] CapOrigUV1 = null; - Vector2[] CapOrigUV2 = null; - int CapTriCount1 = 0; - int CapTriCount2 = 0; - if (CapMesh1 != null) - { - for (int i = 0; i < CapOrigMVL1; i++) - { - CapOrigVerts1[i] = Cap1.transform.TransformPoint(CapOrigVerts1[i]); - } - - float[] oMinMaxX = new float[CapOrigMVL1]; - float[] oMinMaxY = new float[CapOrigMVL1]; - float[] oMinMaxZ = new float[CapOrigMVL1]; - for (int i = 0; i < CapOrigMVL1; i++) - { - oMinMaxX[i] = CapOrigVerts1[i].x; - oMinMaxY[i] = CapOrigVerts1[i].y; - oMinMaxZ[i] = CapOrigVerts1[i].z; - } - // float oMinX = Mathf.Min(oMinMaxX); - float oMaxX = Mathf.Max(oMinMaxX); - // float oMinY = Mathf.Min(oMinMaxY); - // float oMaxY = Mathf.Max(oMinMaxY); - // float oMinZ = Mathf.Min(oMinMaxZ); - float oMaxZ = Mathf.Max(oMinMaxZ); - - for (int i = 0; i < CapOrigMVL1; i++) - { - if (Axis == AxisTypeEnum.Z) - { - if (GSDRootUtil.IsApproximately(CapOrigVerts1[i].z, oMaxZ, MinMaxMod)) - { - tCapMatchIndices1.Add(i); - } - } - else - { - if (GSDRootUtil.IsApproximately(CapOrigVerts1[i].x, oMaxX, MinMaxMod)) - { - tCapMatchIndices1.Add(i); - } - } - } - - CapMesh1.RecalculateNormals(); - CapOrigTris1 = CapMesh1.triangles; - CapOrigUV1 = CapMesh1.uv; - CapTriCount1 = CapOrigTris1.Length; - CapOrigNormals1 = CapMesh1.normals; - } - if (CapMesh2 != null) - { - for (int i = 0; i < CapOrigMVL2; i++) - { - CapOrigVerts2[i] = Cap2.transform.TransformPoint(CapOrigVerts2[i]); - } - - float[] oMinMaxX = new float[CapOrigMVL2]; - float[] oMinMaxY = new float[CapOrigMVL2]; - float[] oMinMaxZ = new float[CapOrigMVL2]; - for (int i = 0; i < CapOrigMVL2; i++) - { - oMinMaxX[i] = CapOrigVerts2[i].x; - oMinMaxY[i] = CapOrigVerts2[i].y; - oMinMaxZ[i] = CapOrigVerts2[i].z; - } - float oMinX = Mathf.Min(oMinMaxX); - // float oMaxX = Mathf.Max(oMinMaxX); - // float oMinY = Mathf.Min(oMinMaxY); - // float oMaxY = Mathf.Max(oMinMaxY); - float oMinZ = Mathf.Min(oMinMaxZ); - // float oMaxZ = Mathf.Max(oMinMaxZ); - - for (int i = 0; i < CapOrigMVL2; i++) - { - if (Axis == AxisTypeEnum.Z) - { - if (GSDRootUtil.IsApproximately(CapOrigVerts2[i].z, oMinZ, MinMaxMod)) - { - tCapMatchIndices2.Add(i); - } - } - else - { - if (GSDRootUtil.IsApproximately(CapOrigVerts2[i].x, oMinX, MinMaxMod)) - { - tCapMatchIndices2.Add(i); - } - } - } - - CapMesh2.RecalculateNormals(); - CapOrigTris2 = CapMesh2.triangles; - CapOrigUV2 = CapMesh2.uv; - CapTriCount2 = CapOrigTris2.Length; - CapOrigNormals2 = CapMesh2.normals; - } - - int[] OrigTris = tMesh.triangles; - int OrigTriCount = OrigTris.Length; - Vector2[] OrigUV = tMesh.uv; - float[] tMinMax = new float[OrigMVL]; - float[] tMinMaxX = new float[OrigMVL]; - float[] tMinMaxY = new float[OrigMVL]; - float[] tMinMaxZ = new float[OrigMVL]; - float[] tMinMaxUV = null; - if (RepeatUVType != RepeatUVTypeEnum.None) - { - tMinMaxUV = new float[OrigMVL]; - } - for (int i = 0; i < OrigMVL; i++) - { - if (Axis == AxisTypeEnum.X) - { - tMinMax[i] = OrigVerts[i].x; - } - else - { - tMinMax[i] = OrigVerts[i].z; - } - tMinMaxX[i] = OrigVerts[i].x; - tMinMaxY[i] = OrigVerts[i].y; - tMinMaxZ[i] = OrigVerts[i].z; - if (RepeatUVType == RepeatUVTypeEnum.X) - { - tMinMaxUV[i] = OrigUV[i].x; - } - else if (RepeatUVType == RepeatUVTypeEnum.Y) - { - tMinMaxUV[i] = OrigUV[i].y; - } - } - - float mMax = Mathf.Max(tMinMax); - float mMin = Mathf.Min(tMinMax); - float mMaxX = Mathf.Max(tMinMaxX); - float mMinX = Mathf.Min(tMinMaxX); - float mMaxY = Mathf.Max(tMinMaxY); - float mMinY = Mathf.Min(tMinMaxY); - float mMaxZ = Mathf.Max(tMinMaxZ); - float mMinZ = Mathf.Min(tMinMaxZ); - float mMinUV = -1f; - float mMaxUV = -1f; - float mUVDiff = -1f; - if (RepeatUVType != RepeatUVTypeEnum.None) - { - mMinUV = Mathf.Min(tMinMaxUV); - mMaxUV = Mathf.Max(tMinMaxUV); - mUVDiff = mMaxUV - mMinUV; - } - float mMaxDiff = mMax - mMin; - float mMaxHeight = mMaxY - mMinY; - float mMaxThreshold = mMax - MinMaxMod; - float mMinThreshold = mMin + MinMaxMod; - List MinVectorIndices = new List(); - List MaxVectorIndices = new List(); - List MiddleVectorIndicies = new List(); - float tBuffer = 0f; - for (int i = 0; i < OrigMVL; i++) - { - if (Axis == AxisTypeEnum.X) - { - tBuffer = OrigVerts[i].x; - } - else - { - tBuffer = OrigVerts[i].z; - } - - if (tBuffer > mMaxThreshold) - { - MaxVectorIndices.Add(i); - } - else if (tBuffer < mMinThreshold) - { - MinVectorIndices.Add(i); - } - else - { - MiddleVectorIndicies.Add(i); - } - } - int MiddleCount = MiddleVectorIndicies.Count; - - //Match up min/max vertices: - Dictionary MatchingIndices = new Dictionary(); - Dictionary MatchingIndices_Min = new Dictionary(); - Dictionary> MatchingIndices_Min_Cap = new Dictionary>(); - Dictionary> MatchingIndices_Max_Cap = new Dictionary>(); - int tCount1 = MaxVectorIndices.Count; - int tCount2 = MinVectorIndices.Count; - int tIntBuffer1 = -1; - int tIntBuffer2 = -1; - int tIntBuffer3 = -1; - int tIntBuffer4 = -1; - // Dictionary UVStep = null; - // if(RepeatUVType != RepeatUVTypeEnum.None){ - // UVStep = new Dictionary(); - // } - List AlreadyAddedList = new List(); - for (int i = 0; i < tCount1; i++) - { - tIntBuffer1 = MaxVectorIndices[i]; - tVect1 = OrigVerts[tIntBuffer1]; - - bool bAdded = false; - for (int j = 0; j < OrigTriCount; j += 3) - { - if (OrigTris[j] == tIntBuffer1) - { - tIntBuffer3 = OrigTris[j + 1]; - tIntBuffer4 = OrigTris[j + 2]; - } - else if (OrigTris[j + 1] == tIntBuffer1) - { - tIntBuffer3 = OrigTris[j]; - tIntBuffer4 = OrigTris[j + 2]; - } - else if (OrigTris[j + 2] == tIntBuffer1) - { - tIntBuffer3 = OrigTris[j]; - tIntBuffer4 = OrigTris[j + 1]; - } - else - { - continue; - } - if (MinVectorIndices.Contains(tIntBuffer3)) - { - for (int k = 0; k < tCount2; k++) - { - tIntBuffer2 = MinVectorIndices[k]; - if (tIntBuffer2 == tIntBuffer3) - { - if (AlreadyAddedList.Contains(tIntBuffer2)) { break; } - if (IsApproxTwoThirds(ref tVect1, OrigVerts[tIntBuffer2], VertexMatchingPrecision)) - { - MatchingIndices.Add(tIntBuffer1, tIntBuffer2); - AlreadyAddedList.Add(tIntBuffer2); - MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); - bAdded = true; - break; - } - } - } - } - if (!bAdded && MinVectorIndices.Contains(tIntBuffer4)) - { - for (int k = 0; k < tCount2; k++) - { - tIntBuffer2 = MinVectorIndices[k]; - if (tIntBuffer2 == tIntBuffer4) - { - if (AlreadyAddedList.Contains(tIntBuffer2)) { break; } - if (IsApproxTwoThirds(ref tVect1, OrigVerts[tIntBuffer2], VertexMatchingPrecision)) - { - MatchingIndices.Add(tIntBuffer1, tIntBuffer2); - AlreadyAddedList.Add(tIntBuffer2); - MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); - bAdded = true; - break; - } - } - } - } - if (bAdded) { break; } - } - } - - //Tris don't match, so need further refinement: - if (MatchingIndices.Count < MaxVectorIndices.Count) - { - bool bIsZAxis = (Axis == AxisTypeEnum.Z); - for (int i = 0; i < tCount1; i++) - { - tIntBuffer1 = MaxVectorIndices[i]; - if (MatchingIndices.ContainsKey(tIntBuffer1)) { continue; } - tVect1 = OrigVerts[tIntBuffer1]; - if (Axis == AxisTypeEnum.Z) - { - for (int j = 0; j < tCount2; j++) - { - tIntBuffer2 = MinVectorIndices[j]; - if (!AlreadyAddedList.Contains(tIntBuffer2)) - { - tVect2 = OrigVerts[tIntBuffer2]; - if (IsApproxExtruded(ref tVect1, ref tVect2, bIsZAxis) && V3EqualNormal(OrigNormals[tIntBuffer1], OrigNormals[tIntBuffer2])) - { - MatchingIndices.Add(tIntBuffer1, tIntBuffer2); - AlreadyAddedList.Add(tIntBuffer2); - MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); - break; - } - } - } - } - } - } - - //Caps: - if (CapMesh1 != null) - { - bool bDidAdd = false; - foreach (KeyValuePair KVP in MatchingIndices_Min) - { - List tList = new List(); - tVect1 = OrigVerts[KVP.Key]; - for (int i = 0; i < CapOrigMVL1; i++) - { - if (tCapMatchIndices1.Contains(i) && IsApproxTwoThirds(ref tVect1, CapOrigVerts1[i], VertexMatchingPrecision)) - { - tList.Add(i); - bDidAdd = true; - } - } - MatchingIndices_Min_Cap.Add(KVP.Key, tList); - } - if (!bDidAdd) - { - try - { - Debug.LogWarning("Start cap error (still processing extrusion, ignoring start cap). No matching vertices found for start cap. Most likely the cap mesh is aligned improperly or along the wrong axis relative to the main mesh."); - } - catch - { - - } - if (Cap1 != null) - { - Object.DestroyImmediate(Cap1); - } - CapMesh1 = null; - CapOrigMVL1 = 0; - CapTriCount1 = 0; - } - } - if (CapMesh2 != null) - { - bool bDidAdd = false; - foreach (KeyValuePair KVP in MatchingIndices) - { - List tList = new List(); - tVect1 = OrigVerts[KVP.Key]; - for (int i = 0; i < CapOrigMVL2; i++) - { - if (tCapMatchIndices2.Contains(i) && IsApproxTwoThirds(ref tVect1, CapOrigVerts2[i], VertexMatchingPrecision)) - { - tList.Add(i); - bDidAdd = true; - } - } - MatchingIndices_Max_Cap.Add(KVP.Key, tList); - } - if (!bDidAdd) - { - try - { - Debug.LogError("End cap error (still processing extrusion, ignoring end cap). No matching vertices found for end cap. Most likely the cap mesh is aligned improperly or along the wrong axis relative to the main mesh."); - } - catch - { - - } - if (Cap2 != null) { Object.DestroyImmediate(Cap2); } - CapMesh2 = null; - CapOrigMVL2 = 0; - CapTriCount2 = 0; - } - } - - //Road definition matching: - if (bMatchRoadDefinition) - { - float RoadDefStart = (tSpline.tRoad.opt_RoadDefinition / 2f) * -1; - float UVChange = tSpline.tRoad.opt_RoadDefinition / mMaxDiff; - foreach (KeyValuePair KVP in MatchingIndices) - { - //Vertex change: - if (Axis == AxisTypeEnum.X) - { - OrigVerts[KVP.Value].x = RoadDefStart; - OrigVerts[KVP.Key].x = (OrigVerts[KVP.Value].x + tSpline.tRoad.opt_RoadDefinition); - } - else if (Axis == AxisTypeEnum.Z) - { - OrigVerts[KVP.Value].z = RoadDefStart; - OrigVerts[KVP.Key].z = (OrigVerts[KVP.Value].z + tSpline.tRoad.opt_RoadDefinition); - } - //UV Change: - if (RepeatUVType == RepeatUVTypeEnum.X) - { - OrigUV[KVP.Key].x *= UVChange; - } - else if (RepeatUVType == RepeatUVTypeEnum.Y) - { - OrigUV[KVP.Key].y *= UVChange; - } - } - - //Settings: - tMinMaxUV = new float[OrigMVL]; - tMinMax = new float[OrigMVL]; - tMinMaxX = new float[OrigMVL]; - tMinMaxY = new float[OrigMVL]; - tMinMaxZ = new float[OrigMVL]; - for (int i = 0; i < OrigMVL; i++) - { - if (Axis == AxisTypeEnum.X) - { - tMinMax[i] = OrigVerts[i].x; - } - else - { - tMinMax[i] = OrigVerts[i].z; - } - tMinMaxX[i] = OrigVerts[i].x; - tMinMaxY[i] = OrigVerts[i].y; - tMinMaxZ[i] = OrigVerts[i].z; - if (RepeatUVType == RepeatUVTypeEnum.X) - { - tMinMaxUV[i] = OrigUV[i].x; - } - else if (RepeatUVType == RepeatUVTypeEnum.Y) - { - tMinMaxUV[i] = OrigUV[i].y; - } - } - //UV Changes: - mMax = Mathf.Max(tMinMax); - mMin = Mathf.Min(tMinMax); - mMaxX = Mathf.Max(tMinMaxX); - mMinX = Mathf.Min(tMinMaxX); - mMaxY = Mathf.Max(tMinMaxY); - mMinY = Mathf.Min(tMinMaxY); - mMaxZ = Mathf.Max(tMinMaxZ); - mMinZ = Mathf.Min(tMinMaxZ); - mMinUV = -1f; - mMaxUV = -1f; - mUVDiff = -1f; - if (RepeatUVType != RepeatUVTypeEnum.None) - { - mMinUV = Mathf.Min(tMinMaxUV); - mMaxUV = Mathf.Max(tMinMaxUV); - mUVDiff = mMaxUV - mMinUV; - } - mMaxDiff = mMax - mMin; - mMaxHeight = mMaxY - mMinY; - mMaxThreshold = mMax - MinMaxMod; - mMinThreshold = mMin + MinMaxMod; - } - - //For vert reverse cut: - int VertCutTriIndex1 = -1; - int VertCutTriIndex2 = -1; - if (bVerticalMeshCutoff_OppositeDir) - { - float[] tMatchingMaxY = new float[MatchingIndices.Count]; - int tempcount141 = 0; - foreach (KeyValuePair KVP in MatchingIndices) - { - tMatchingMaxY[tempcount141] = OrigVerts[KVP.Key].y; - tempcount141 += 1; - } - - float tMatchingMaxY_f = Mathf.Max(tMatchingMaxY); - foreach (KeyValuePair KVP in MatchingIndices) - { - if (GSDRootUtil.IsApproximately(OrigVerts[KVP.Key].y, tMatchingMaxY_f, 0.0001f)) - { - VertCutTriIndex1 = KVP.Key; - VertCutTriIndex2 = KVP.Value; - break; - } - } - } - - - //Set auto simple collision points: - if (bSimpleCollisionAutomatic) - { - if (Axis == AxisTypeEnum.X) - { - CollisionTriBL = new Vector3(mMinX, mMinY, mMinZ); - CollisionTriBR = new Vector3(mMinX, mMinY, mMaxZ); - CollisionTriT = new Vector3(mMinX, mMaxY, ((mMaxZ - mMinZ) * 0.5f) + mMinZ); - } - else if (Axis == AxisTypeEnum.Z) - { - CollisionTriBL = new Vector3(mMinX, mMinY, mMinZ); - CollisionTriBR = new Vector3(mMaxX, mMinY, mMinZ); - CollisionTriT = new Vector3(((mMaxX - mMinX) * 0.5f) + mMinX, mMaxY, mMinZ); - } - - if (Axis == AxisTypeEnum.X) - { - CollisionBoxBL = new Vector3(mMinX, mMinY, mMinZ); - CollisionBoxBR = new Vector3(mMinX, mMinY, mMaxZ); - CollisionBoxTL = new Vector3(mMinX, mMaxY, mMinZ); - CollisionBoxTR = new Vector3(mMinX, mMaxY, mMaxZ); - } - else if (Axis == AxisTypeEnum.Z) - { - CollisionBoxBL = new Vector3(mMinX, mMinY, mMinZ); - CollisionBoxBR = new Vector3(mMaxX, mMinY, mMinZ); - CollisionBoxTL = new Vector3(mMinX, mMaxY, mMinZ); - CollisionBoxTR = new Vector3(mMaxX, mMaxY, mMinZ); - } - } - - Vector3[] tVerts = null; - Vector2[] tUV = null; - - //Get the vector series that this mesh is interpolated on: - List tTimes = new List(); - float cTime = StartTime; - - - tTimes.Add(cTime); - int SpamGuard = 5000; - int SpamGuardCounter = 0; - float pDiffTime = EndTime - StartTime; - float CurrentH = 0f; - float fHeight = 0f; - // Vector3 tStartPos = tSpline.GetSplineValue(StartTime); - // Vector3 tEndPos = tSpline.GetSplineValue(EndTime); - - while (cTime < EndTime && SpamGuardCounter < SpamGuard) - { - tSpline.GetSplineValue_Both(cTime, out tVect1, out tDir); - fHeight = HorizontalCurve.Evaluate((cTime - StartTime) / pDiffTime); - CurrentH = fHeight * HorizontalSep; - - if (CurrentH < 0f) - { - CurrentH *= -1f; - tVect1 = (tVect1 + new Vector3(CurrentH * -tDir.normalized.z, 0, CurrentH * tDir.normalized.x)); - } - else if (CurrentH > 0f) - { - tVect1 = (tVect1 + new Vector3(CurrentH * tDir.normalized.z, 0, CurrentH * -tDir.normalized.x)); - } - - xVect = (tDir.normalized * mMaxDiff) + tVect1; - - cTime = tSpline.GetClosestParam(xVect, false, false); - if (cTime > EndTime) - { - cTime = EndTime; - } - tTimes.Add(cTime); - SpamGuardCounter += 1; - } - if (bTrimStart) - { - tTimes.RemoveAt(0); - } - else if (bTrimEnd) - { - tTimes.RemoveAt(tTimes.Count - 1); - } - int vSeriesCount = tTimes.Count; - - //Dynamic vertical and horiz: - List DynamicVerticalRaise = null; - List DynamicHoriz = null; - DynamicVerticalRaise = new List(); - DynamicHoriz = new List(); - float tStartTime = tTimes[0]; - float tEndTime = tTimes[vSeriesCount - 1]; - // float tDiffTime = tEndTime - tStartTime; - // float cDiff = 0f; - - float jDistance = 0f; - float jStartDistance = tSpline.TranslateParamToDist(tStartTime); - float jEndDistance = tSpline.TranslateParamToDist(tEndTime); - float jDistanceDiff = jEndDistance - jStartDistance; - // float jLastTime = 0f; - float jCurrTime = 0f; - // float jStep = 0.02f / tSpline.distance; - // Vector3 jVect1 = default(Vector3); - // Vector3 jVect2 = default(Vector3); - // float prevFHeight = 0f; - // bool basfsafa = false; - for (int i = 0; i < vSeriesCount; i++) - { - // cDiff = tTimes[i] - tStartTime; - // cDiff = cDiff / tDiffTime; - - //Vertical curve: - if (VerticalCurve.keys == null || VerticalCurve.length < 1) - { - fHeight = 1f; - } - else - { - jDistance = tSpline.TranslateParamToDist(tTimes[i]); - jCurrTime = (jDistance - jStartDistance) / jDistanceDiff; - fHeight = VerticalCurve.Evaluate(jCurrTime); - } - DynamicVerticalRaise.Add(fHeight); - - //Horizontal curve: - if (HorizontalCurve.keys == null || HorizontalCurve.length < 1) - { - fHeight = 1f; - } - else - { - fHeight = HorizontalCurve.Evaluate(jCurrTime); - } - DynamicHoriz.Add(fHeight); - } - - Vector3[] VectorSeries = new Vector3[vSeriesCount]; - Vector3[] VectorSeriesTangents = new Vector3[vSeriesCount]; - // bool bIsCenter = GSDRootUtil.IsApproximately(HorizontalSep,0f,0.02f); - float tIntStrength = 0f; - float tIntHeight = 0f; - GSDRoadIntersection GSDRI = null; - bool bIsPastInter = false; - GSDSplineN xNode = null; - List tOrigHeights = new List(); - - // List xTerrains = null; - // List tTerrainRects = null; - // int TerrainCount = 0; - // if(bMatchTerrain){ - // tTerrainRects = new List(); - // xTerrains = new List(); - // Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); - // GSD.Roads.GSDRoadUtil.Construction2DRect tTerrainRect = null; - // Vector2 tPos2D = default(Vector2); - // Vector2 P1,P2,P3,P4; - // foreach(Terrain xTerrain in tTerrains){ - // tPos2D = new Vector2(xTerrain.transform.position.x,xTerrain.transform.position.z); - // P1 = new Vector2(0f,0f) + tPos2D; - // P2 = new Vector2(0f,xTerrain.terrainData.size.y) + tPos2D; - // P3 = new Vector2(xTerrain.terrainData.size.x,xTerrain.terrainData.size.y) + tPos2D; - // P4 = new Vector2(xTerrain.terrainData.size.x,0f) + tPos2D; - // tTerrainRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(P1,P2,P3,P4,xTerrain.transform.position.y); - // tTerrainRects.Add(tTerrainRect); - // xTerrains.Add(xTerrain); - // TerrainCount+=1; - // } - // } - - // Vector2 temp2DVect = default(Vector2); - Ray tRay = default(Ray); - RaycastHit[] tRayHit = null; - float[] tRayYs = null; - for (int i = 0; i < vSeriesCount; i++) - { - cTime = tTimes[i]; - tSpline.GetSplineValue_Both(cTime, out tVect1, out tVect2); - tOrigHeights.Add(tVect1.y); - - //Horizontal offset: - CurrentH = DynamicHoriz[i] * HorizontalSep; - - if (CurrentH < 0f) - { - CurrentH *= -1f; - tVect1 = (tVect1 + new Vector3(CurrentH * -tVect2.normalized.z, 0, CurrentH * tVect2.normalized.x)); - } - else if (CurrentH > 0f) - { - tVect1 = (tVect1 + new Vector3(CurrentH * tVect2.normalized.z, 0, CurrentH * -tVect2.normalized.x)); - } - - tIntStrength = tSpline.IntersectionStrength(ref tVect1, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref cTime, ref xNode); - - if (GSDRootUtil.IsApproximately(tIntStrength, 1f, 0.0001f)) - { - tVect1.y = tIntHeight; - } - else if (!GSDRootUtil.IsApproximately(tIntStrength, 0f, 0.001f)) - { - tVect1.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect1.y); - } - - //Terrain matching: - if (bMatchTerrain) - { - // temp2DVect = new Vector2(tVect1.x,tVect1.z); - // for(int j=0;j 0) - { - tRayYs = new float[tRayHit.Length]; - for (int g = 0; g < tRayHit.Length; g++) - { - tRayYs[g] = tRayHit[g].point.y; - } - tVect1.y = Mathf.Max(tRayYs); - } - } - - tVect1.y += (DynamicVerticalRaise[i] * VerticalRaise); - - VectorSeries[i] = tVect1; - VectorSeriesTangents[i] = tVect2; - } - int MeshCount = (vSeriesCount - 1); - - // float yDiff = 0f; - // float tDistance = 0f; - int MVL = MeshCount * OrigMVL; -#if UNITY_2017_3_OR_NEWER - if (MVL > 4000000) - { - throw new System.Exception("Over 4000000 vertices detected, exiting extrusion. Try switching splination axis and make sure your imported FBX file has proper import scale. Make sure the mesh isn't too small and make sure the distance isn't too large."); - } -#else - if(MVL > 64900){ - throw new System.Exception("Over 65000 vertices detected, exiting extrusion. Try switching splination axis and make sure your imported FBX file has proper import scale. Make sure the mesh isn't too small and make sure the distance isn't too large."); - } -#endif - int MaxCount = MaxVectorIndices.Count; - int MinCount = MinVectorIndices.Count; - int TriCount = MeshCount * OrigTriCount; - // int MatchCount = MatchingIndices.Count; - tVerts = new Vector3[MVL]; - tUV = new Vector2[MVL]; - int[] tTris = new int[TriCount]; - Vector3[] tNormals = new Vector3[MVL]; - int vManuver = 0; - int vManuver_Prev = 0; - int TriManuver = 0; - Vector3[] cVerts = null; - int[] cTris = null; - int cCount = -1; - int cTriCount = -1; - bool bSimpleCollisionOn = false; - float tOrigHeightBuffer = 0f; - float tFloat5 = 0f; - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts = new Vector3[3 * (MeshCount + 1)]; - cCount = cVerts.Length; - cTriCount = (6 * cCount) + 2; - bSimpleCollisionOn = true; - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts = new Vector3[4 * (MeshCount + 1)]; - cCount = cVerts.Length; - cTriCount = (8 * cCount) + 4; - bSimpleCollisionOn = true; - } - - // List tTriList = null; - // GSD.Roads.GSDRoadUtil.Construction3DTri VertOppCutTri = null; - // int VertCutBufferIndex1 = -1; - // int VertCutBufferIndex2 = -1; - Vector3 VertCutBuffer1 = default(Vector3); - Vector3 VertCutBuffer2 = default(Vector3); - Vector3 VertCutBuffer3 = default(Vector3); - float tOrigHeightBuffer_Orig = 0f; - // if(bVerticalMeshCutoff_OppositeDir){ - // tTriList = new List(); - // } - - if (bIsStretch) - { - DoStretch(ref OrigVerts, ref OrigUV, ref OrigTris, ref MaxVectorIndices, ref MinVectorIndices, mMaxDiff, out tVerts, out tUV, out tNormals, out tTris); - goto StretchSkip; - } - - //Main loop: - Matrix4x4 tMatrix = new Matrix4x4(); - for (int j = 0; j < MeshCount; j++) - { - TriManuver = j * OrigTriCount; - vManuver = j * OrigMVL; - vManuver_Prev = (j - 1) * OrigMVL; - - if (!bIsStretch) - { - tVect1 = VectorSeries[j]; - tVect2 = VectorSeries[j + 1]; - } - - // yDiff = tVect2.y - tVect1.y; - // tDistance = Vector3.Distance(tVect1,tVect2); - - // if(j==0){ tStartPos = tVect1; } - // if(j==(MeshCount-1)){ tEndPos = tVect1; } - - if (bExactSplination && MiddleCount < 2) - { - tDir = (tVect2 - tVect1).normalized; - } - else - { - tDir = VectorSeriesTangents[j].normalized; - } - - tOrigHeightBuffer = tOrigHeights[j] + VerticalCutoff; - tOrigHeightBuffer_Orig = tOrigHeights[j]; - tMatrix.SetTRS(tVect1, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); - - //Rotate and set vertex positions: - for (int i = 0; i < OrigMVL; i++) - { - xVect = OrigVerts[i]; - tVerts[vManuver + i] = tMatrix.MultiplyPoint3x4(xVect); - // tVerts[vManuver+i] = (Quaternion.LookRotation(tDir)*xVect) + tVect1; - - //UV: - tUV[vManuver + i] = OrigUV[i]; - - //Vertical cutoff: - if (bVerticalCutoff) - { - if (MiddleVectorIndicies.Contains(i)) - { - tFloat5 = tVerts[vManuver + i].y; - if (bVerticalCutoffDownwards) - { - if (bVerticalCutoff_MatchZero) - { - if (tFloat5 < tOrigHeightBuffer_Orig) - { - tVerts[vManuver + i].y = tOrigHeightBuffer_Orig; - } - } - else - { - if (tFloat5 < tOrigHeightBuffer) - { - tVerts[vManuver + i].y = tOrigHeightBuffer; - } - } - - tFloat1 = (tOrigHeightBuffer_Orig - tOrigHeightBuffer) / mMaxHeight; - tUV[vManuver + i].x *= tFloat1; - - } - else - { - if (bVerticalCutoff_MatchZero) - { - if (tFloat5 > tOrigHeightBuffer_Orig) - { - tVerts[vManuver + i].y = tOrigHeightBuffer_Orig; - } - } - else - { - if (tFloat5 > tOrigHeightBuffer) - { - tVerts[vManuver + i].y = tOrigHeightBuffer; - } - } - - tFloat1 = (tOrigHeightBuffer - tOrigHeightBuffer_Orig) / mMaxHeight; - tUV[vManuver + i].x *= tFloat1; - } - } - } - } - - if (RepeatUVType != RepeatUVTypeEnum.None) - { - for (int i = 0; i < MaxCount; i++) - { - tIntBuffer1 = MaxVectorIndices[i]; - if (RepeatUVType == RepeatUVTypeEnum.X) - { - tUV[vManuver + tIntBuffer1].x = mUVDiff * (j + 1); - } - else - { - tUV[vManuver + tIntBuffer1].y = mUVDiff * (j + 1); - } - } - for (int i = 0; i < MinCount; i++) - { - tIntBuffer1 = MinVectorIndices[i]; - if (RepeatUVType == RepeatUVTypeEnum.X) - { - tUV[vManuver + tIntBuffer1].x = mUVDiff * j; - } - else - { - tUV[vManuver + tIntBuffer1].y = mUVDiff * j; - } - } - } - - //Simple collision (triangle or trap): - if (bSimpleCollisionOn) - { - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts[0 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBL); - cVerts[1 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBR); - cVerts[2 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriT); - - // cVerts[0+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriBL) + tVect1; - // cVerts[1+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriBR) + tVect1; - // cVerts[2+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriT) + tVect1; - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts[0 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBL); - cVerts[1 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBR); - cVerts[2 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTL); - cVerts[3 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTR); - - // cVerts[0+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxBL) + tVect1; - // cVerts[1+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxBR) + tVect1; - // cVerts[2+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxTL) + tVect1; - // cVerts[3+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxTR) + tVect1; - } - - if (j == (MeshCount - 1)) - { - Vector3 tAdd = default(Vector3); - if (Axis == AxisTypeEnum.X) - { - tAdd = new Vector3(mMaxDiff * -1f, 0f, 0f); - } - else - { - tAdd = new Vector3(0f, 0f, mMaxDiff); - } - - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts[0 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBL + tAdd); - cVerts[1 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBR + tAdd); - cVerts[2 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriT + tAdd); - - // cVerts[0+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriBL + tAdd)) + tVect1; - // cVerts[1+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriBR + tAdd)) + tVect1; - // cVerts[2+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriT + tAdd)) + tVect1; - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts[0 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBL + tAdd); - cVerts[1 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBR + tAdd); - cVerts[2 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTL + tAdd); - cVerts[3 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTR + tAdd); - - // cVerts[0+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxBL + tAdd)) + tVect1; - // cVerts[1+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxBR + tAdd)) + tVect1; - // cVerts[2+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxTL + tAdd)) + tVect1; - // cVerts[3+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxTR + tAdd)) + tVect1; - } - } - } - - //If j > 0, the previous max vects need to match current min vects: - Vector3 mVect = default(Vector3); - if (j > 0) - { - // foreach(KeyValuePair KVP in MatchingIndices){ - // tNormals[vManuver+KVP.Key] = tNormals[KVP.Value]; - // } - foreach (KeyValuePair KVP in MatchingIndices_Min) - { - mVect = tVerts[vManuver + KVP.Key] - tVerts[vManuver_Prev + KVP.Value]; - tVerts[vManuver + KVP.Key] = tVerts[vManuver_Prev + KVP.Value]; - } - - for (int g = 0; g < MinVectorIndices.Count; g++) - { - if (!MatchingIndices_Min.ContainsKey(MinVectorIndices[g])) - { - tVerts[vManuver + MinVectorIndices[g]] -= mVect; - } - } - - //Simple collision (triangle or trap): - if (bSimpleCollisionOn) - { - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts[0 + (j * 3)] -= mVect; - cVerts[1 + (j * 3)] -= mVect; - cVerts[2 + (j * 3)] -= mVect; - - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts[0 + (j * 4)] -= mVect; - cVerts[1 + (j * 4)] -= mVect; - cVerts[2 + (j * 4)] -= mVect; - cVerts[3 + (j * 4)] -= mVect; - } - } - } - - //Triangles: - for (int i = 0; i < OrigTriCount; i++) - { - tTris[i + TriManuver] = OrigTris[i] + vManuver; - } - - //Vert cut reverse: - if (bVerticalCutoff) - { - if (bVerticalMeshCutoff_OppositeDir) - { - VertCutBuffer1 = tVerts[vManuver + VertCutTriIndex1]; - VertCutBuffer2 = tVerts[vManuver + VertCutTriIndex2]; - - for (int i = 0; i < MiddleCount; i++) - { - VertCutBuffer3 = tVerts[vManuver + MiddleVectorIndicies[i]]; - - if (!bVerticalCutoffDownwards) - { - tBuffer = GetVHeightAtXY(ref VertCutBuffer1, ref VertCutBuffer2, ref VertCutBuffer3) + VerticalMeshCutoffOffset; - if (VertCutBuffer3.y < tBuffer) - { - tVerts[vManuver + MiddleVectorIndicies[i]].y = tBuffer; - } - } - else - { - tBuffer = GetVHeightAtXY(ref VertCutBuffer1, ref VertCutBuffer2, ref VertCutBuffer3) - VerticalMeshCutoffOffset; - if (VertCutBuffer3.y > tBuffer) - { - tVerts[vManuver + MiddleVectorIndicies[i]].y = tBuffer; - } - } - } - } - } - - - //Ending push down: - if (bStartDown) - { - tFloat1 = mMaxHeight * 1.05f; - if (bStartTypeDownOverride) - { - tFloat1 = StartTypeDownOverride; - } - if (j == 0) - { - for (int i = 0; i < MinCount; i++) - { - tIntBuffer1 = MinVectorIndices[i]; - tVerts[vManuver + tIntBuffer1].y -= tFloat1; - } - - float tTotalDistDown = 0f; - Vector3 pVect1 = default(Vector3); - Vector3 pVect2 = default(Vector3); - foreach (KeyValuePair KVP in MatchingIndices) - { - pVect1 = tVerts[vManuver + KVP.Key]; - pVect2 = tVerts[vManuver + KVP.Value]; - tTotalDistDown = Vector3.Distance(pVect1, pVect2); - break; - } - - for (int i = 0; i < MiddleCount; i++) - { - tIntBuffer1 = MiddleVectorIndicies[i]; - float tDistTo1 = Vector3.Distance(tVerts[vManuver + tIntBuffer1], pVect1); - tVerts[vManuver + tIntBuffer1].y -= (tFloat1 * (tDistTo1 / tTotalDistDown)); - } - - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts[0 + (j * 3)].y -= tFloat1; - cVerts[1 + (j * 3)].y -= tFloat1; - cVerts[2 + (j * 3)].y -= tFloat1; - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts[0 + (j * 4)].y -= tFloat1; - cVerts[1 + (j * 4)].y -= tFloat1; - cVerts[2 + (j * 4)].y -= tFloat1; - cVerts[3 + (j * 4)].y -= tFloat1; - } - } - } - - if (bEndDown) - { - tFloat1 = mMaxHeight * 1.05f; - if (bEndTypeDownOverride) - { - tFloat1 = EndTypeDownOverride; - } - if (j == (MeshCount - 1)) - { - for (int i = 0; i < MaxCount; i++) - { - tIntBuffer1 = MaxVectorIndices[i]; - tVerts[vManuver + tIntBuffer1].y -= tFloat1; - } - - float tTotalDistDown = 0f; - Vector3 pVect1 = default(Vector3); - Vector3 pVect2 = default(Vector3); - foreach (KeyValuePair KVP in MatchingIndices) - { - pVect1 = tVerts[vManuver + KVP.Key]; - pVect2 = tVerts[vManuver + KVP.Value]; - tTotalDistDown = Vector3.Distance(pVect1, pVect2); - break; - } - - for (int i = 0; i < MiddleCount; i++) - { - tIntBuffer1 = MiddleVectorIndicies[i]; - float tDistTo1 = Vector3.Distance(tVerts[vManuver + tIntBuffer1], pVect2); - tVerts[vManuver + tIntBuffer1].y -= (tFloat1 * (tDistTo1 / tTotalDistDown)); - } - - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cVerts[0 + ((j + 1) * 3)].y -= tFloat1; - cVerts[1 + ((j + 1) * 3)].y -= tFloat1; - cVerts[2 + ((j + 1) * 3)].y -= tFloat1; - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cVerts[0 + ((j + 1) * 4)].y -= tFloat1; - cVerts[1 + ((j + 1) * 4)].y -= tFloat1; - cVerts[2 + ((j + 1) * 4)].y -= tFloat1; - cVerts[3 + ((j + 1) * 4)].y -= tFloat1; - } - } - } - - //Ending objects: - if (j == 0 && EndCapStartObj != null) - { - if (bEndCapCustomMatchStart && MinVectorIndices.Count > 0) - { - Vector3[] bVerts = new Vector3[MinVectorIndices.Count]; - for (int g = 0; g < MinVectorIndices.Count; g++) - { - bVerts[g] = tVerts[vManuver + MinVectorIndices[g]]; - } - Vector3 tVect5 = GetVector3Average(bVerts); - Vector3 tVect6 = tSpline.GetSplineValue(tSpline.GetClosestParam(tVect5, false, false), false); - tVect5.y = tVect6.y; - EndCapStartObj.transform.position = tVect5; - } - else - { - EndCapStartObj.transform.position = tVect1; - } - - if (bEndObjectsMatchGround) - { - tRay = default(Ray); - tRayHit = null; - float tHitY = 0f; - // int tHitIndex = 0; - Vector3 HitVect = EndCapStartObj.transform.position; - tRay = new Ray(HitVect + new Vector3(0f, 1f, 0f), Vector3.down); - tRayHit = Physics.RaycastAll(tRay); - if (tRayHit.Length > 0) - { - tRayYs = new float[tRayHit.Length]; - for (int g = 0; g < tRayHit.Length; g++) - { - if (g == 0) - { - tHitY = tRayHit[g].point.y; - // tHitIndex=0; - } - else - { - if (tRayHit[g].point.y > tHitY) - { - tHitY = tRayHit[g].point.y; - // tHitIndex = g; - } - } - } - HitVect.y = tHitY; - EndCapStartObj.transform.position = HitVect; - } - } - EndCapStartObj.transform.rotation = Quaternion.LookRotation(tDir); - EndCapStartObj.transform.Rotate(EndCapCustomRotOffsetStart, Space.World); - EndCapStartObj.transform.position += EndCapCustomOffsetStart; - - } - else if (j == (MeshCount - 1) && EndCapEndObj != null) - { - if (bEndCapCustomMatchStart && MaxVectorIndices.Count > 0) - { - Vector3[] bVerts = new Vector3[MaxVectorIndices.Count]; - for (int g = 0; g < MaxVectorIndices.Count; g++) - { - bVerts[g] = tVerts[vManuver + MaxVectorIndices[g]]; - } - Vector3 tVect5 = GetVector3Average(bVerts); - Vector3 tVect6 = tSpline.GetSplineValue(tSpline.GetClosestParam(tVect5, false, false), false); - if (!float.IsNaN(tVect6.y)) - { - tVect5.y = tVect6.y; - } - EndCapEndObj.transform.position = tVect5; - } - else - { - EndCapEndObj.transform.position = tVect2; - } - - if (bEndObjectsMatchGround) - { - tRay = default(Ray); - tRayHit = null; - float tHitY = 0f; - // int tHitIndex = 0; - Vector3 HitVect = EndCapEndObj.transform.position; - tRay = new Ray(HitVect + new Vector3(0f, 1f, 0f), Vector3.down); - tRayHit = Physics.RaycastAll(tRay); - - if (tRayHit.Length > 0) - { - tRayYs = new float[tRayHit.Length]; - for (int g = 0; g < tRayHit.Length; g++) - { - if (g == 0) - { - tHitY = tRayHit[g].point.y; - // tHitIndex=0; - } - else - { - if (tRayHit[g].point.y > tHitY) - { - tHitY = tRayHit[g].point.y; - // tHitIndex = g; - } - } - } - HitVect.y = tHitY; - EndCapEndObj.transform.position = HitVect; - } - } - EndCapEndObj.transform.rotation = Quaternion.LookRotation(tDir); - EndCapEndObj.transform.Rotate(EndCapCustomRotOffsetEnd, Space.World); - EndCapEndObj.transform.position += EndCapCustomOffsetEnd; - } - } - - StretchSkip: - if (bIsStretch) { vManuver = 0; } - - //End/Start for stretch: - if (bIsStretch) - { - //Ending objects: - if (EndCapStartObj != null) - { - tVect1 = tVerts[MinVectorIndices[0]]; - tFloat1 = tSpline.GetClosestParam(tVect1); - tVect2 = tSpline.GetSplineValue(tFloat1, false); - tVect1.y = tVect2.y; - - EndCapStartObj.transform.position = tVect1; - EndCapStartObj.transform.rotation = Quaternion.LookRotation(tDir); - EndCapStartObj.transform.Rotate(EndCapCustomRotOffsetStart, Space.World); - EndCapStartObj.transform.position += EndCapCustomOffsetStart; - } - if (EndCapEndObj != null) - { - tVect1 = tVerts[MaxVectorIndices[0]]; - tFloat1 = tSpline.GetClosestParam(tVect1); - tVect2 = tSpline.GetSplineValue(tFloat1, false); - tVect1.y = tVect2.y; - - EndCapEndObj.transform.position = tVect1; - EndCapEndObj.transform.rotation = Quaternion.LookRotation(tDir); - EndCapEndObj.transform.Rotate(EndCapCustomRotOffsetEnd, Space.World); - EndCapEndObj.transform.position += EndCapCustomOffsetEnd; - } - } - - if (bSimpleCollisionOn && !bIsStretch) - { - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - cTris = GetCollisionTris_Tri(MeshCount, cTriCount, cCount); - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - cTris = GetCollisionTris_Box(MeshCount, cTriCount, cCount); - } - } - - if (CapMesh1 != null) - { - Vector3[] cap1_verts = new Vector3[CapOrigMVL1]; - System.Array.Copy(CapOrigVerts1, cap1_verts, CapOrigMVL1); - int[] cap1_tris = new int[CapTriCount1]; - System.Array.Copy(CapOrigTris1, cap1_tris, CapTriCount1); - Vector2[] cap1_uv = new Vector2[CapOrigMVL1]; - System.Array.Copy(CapOrigUV1, cap1_uv, CapOrigMVL1); - Vector3[] cap1_normals = new Vector3[CapOrigMVL1]; - System.Array.Copy(CapOrigNormals1, cap1_normals, CapOrigMVL1); - bool[] cap1_hit = new bool[CapOrigMVL1]; - bool bcapstart = true; - float tHeight = 0f; - - foreach (KeyValuePair> KVP in MatchingIndices_Min_Cap) - { - int wCount = KVP.Value.Count; - for (int i = 0; i < wCount; i++) - { - if (bcapstart) - { - tVect1 = cap1_verts[KVP.Value[i]] - tVerts[KVP.Key]; - } - cap1_verts[KVP.Value[i]] = tVerts[KVP.Key]; - cap1_hit[KVP.Value[i]] = true; - if (bcapstart) - { - tHeight = tSpline.GetSplineValue(tSpline.GetClosestParam(cap1_verts[KVP.Value[i]]), false).y; - bcapstart = false; - } - } - } - - float tParam = 0f; - for (int i = 0; i < CapOrigMVL1; i++) - { - if (!cap1_hit[i]) - { - cap1_verts[i] -= tVect1; - tParam = tSpline.GetClosestParam(cap1_verts[i]); - tVect2 = tSpline.GetSplineValue(tParam, false); - cap1_verts[i].y -= (tHeight - tVect2.y); - cap1_verts[i].y += CapHeightOffset1; - } - } - - Vector3[] nVerts = new Vector3[CapOrigMVL1 + tVerts.Length]; - Vector3[] nNormals = new Vector3[CapOrigMVL1 + tNormals.Length]; - int[] nTris = new int[CapTriCount1 + tTris.Length]; - Vector2[] nUV = new Vector2[CapOrigMVL1 + tUV.Length]; - int OldTriCount = tTris.Length; - int OldMVL = tVerts.Length; - - System.Array.Copy(cap1_verts, nVerts, CapOrigMVL1); - System.Array.Copy(cap1_normals, nNormals, CapOrigMVL1); - System.Array.Copy(cap1_tris, nTris, CapTriCount1); - System.Array.Copy(cap1_uv, nUV, CapOrigMVL1); - - System.Array.Copy(tVerts, 0, nVerts, CapOrigMVL1, OldMVL); - System.Array.Copy(tNormals, 0, nNormals, CapOrigMVL1, OldMVL); - System.Array.Copy(tTris, 0, nTris, CapTriCount1, OldTriCount); - System.Array.Copy(tUV, 0, nUV, CapOrigMVL1, OldMVL); - - for (int i = CapTriCount1; i < (CapTriCount1 + OldTriCount); i++) - { - nTris[i] += CapOrigMVL1; - } - - tVerts = nVerts; - tTris = nTris; - tNormals = nNormals; - tUV = nUV; - } - - if (CapMesh2 != null) - { - Vector3[] cap2_verts = new Vector3[CapOrigMVL2]; - System.Array.Copy(CapOrigVerts2, cap2_verts, CapOrigMVL2); - int[] cap2_tris = new int[CapTriCount2]; - System.Array.Copy(CapOrigTris2, cap2_tris, CapTriCount2); - Vector2[] cap2_uv = new Vector2[CapOrigMVL2]; - System.Array.Copy(CapOrigUV2, cap2_uv, CapOrigMVL2); - Vector3[] cap2_normals = new Vector3[CapOrigMVL2]; - System.Array.Copy(CapOrigNormals2, cap2_normals, CapOrigMVL2); - bool[] cap2_hit = new bool[CapOrigMVL2]; - bool bcapstart = true; - float tHeight = 0f; - - foreach (KeyValuePair> KVP in MatchingIndices_Max_Cap) - { - int wCount = KVP.Value.Count; - for (int i = 0; i < wCount; i++) - { - if (bcapstart) - { - tVect1 = cap2_verts[KVP.Value[i]] - tVerts[vManuver + KVP.Key + CapOrigMVL1]; - } - cap2_verts[KVP.Value[i]] = tVerts[vManuver + KVP.Key + CapOrigMVL1]; - cap2_hit[KVP.Value[i]] = true; - - if (bcapstart) - { - tHeight = tSpline.GetSplineValue(tSpline.GetClosestParam(cap2_verts[KVP.Value[i]]), false).y; - bcapstart = false; - } - } - } - - float tParam = 0f; - for (int i = 0; i < CapOrigMVL2; i++) - { - - if (!cap2_hit[i]) - { - cap2_verts[i] -= tVect1; - tParam = tSpline.GetClosestParam(cap2_verts[i]); - tVect2 = tSpline.GetSplineValue(tParam, false); - cap2_verts[i].y -= (tHeight - tVect2.y); - cap2_verts[i].y += CapHeightOffset2; - } - } - - Vector3[] nVerts = new Vector3[CapOrigMVL2 + tVerts.Length]; - Vector3[] nNormals = new Vector3[CapOrigMVL2 + tNormals.Length]; - int[] nTris = new int[CapTriCount2 + tTris.Length]; - Vector2[] nUV = new Vector2[CapOrigMVL2 + tUV.Length]; - int OldTriCount = tTris.Length; - int OldMVL = tVerts.Length; - - System.Array.Copy(tVerts, 0, nVerts, 0, OldMVL); - System.Array.Copy(tNormals, 0, nNormals, 0, OldMVL); - System.Array.Copy(tTris, 0, nTris, 0, OldTriCount); - System.Array.Copy(tUV, 0, nUV, 0, OldMVL); - - System.Array.Copy(cap2_verts, 0, nVerts, OldMVL, CapOrigMVL2); - System.Array.Copy(cap2_normals, 0, nNormals, OldMVL, CapOrigMVL2); - System.Array.Copy(cap2_tris, 0, nTris, OldTriCount, CapTriCount2); - System.Array.Copy(cap2_uv, 0, nUV, OldMVL, CapOrigMVL2); - - for (int i = OldTriCount; i < nTris.Length; i++) - { - nTris[i] += OldMVL; - } - - tVerts = nVerts; - tTris = nTris; - tNormals = nNormals; - tUV = nUV; - } - - int tVertCount = tVerts.Length; - for (int i = 0; i < tVertCount; i++) - { - tVerts[i] -= tNode.pos; - } - if (cVerts != null) - { - int cVertCount = cVerts.Length; - for (int i = 0; i < cVertCount; i++) - { - cVerts[i] -= tNode.pos; - } - } - - //Mesh creation: - Mesh xMesh = new Mesh(); - xMesh.vertices = tVerts; - xMesh.triangles = tTris; - xMesh.normals = tNormals; - xMesh.uv = tUV; - xMesh.RecalculateNormals(); - tNormals = xMesh.normals; - Vector3 tAvgNormal = default(Vector3); - tIntBuffer1 = 0; - if (!bIsStretch) - { - for (int j = 1; j < MeshCount; j++) - { - vManuver = j * OrigMVL; - vManuver_Prev = (j - 1) * OrigMVL; - if (CapMesh1 != null) { tIntBuffer1 = CapOrigMVL1; } - foreach (KeyValuePair KVP in MatchingIndices_Min) - { - tAvgNormal = (tNormals[tIntBuffer1 + vManuver + KVP.Key] + tNormals[tIntBuffer1 + vManuver_Prev + KVP.Value]) * 0.5f; - tNormals[tIntBuffer1 + vManuver + KVP.Key] = tAvgNormal; - tNormals[tIntBuffer1 + vManuver_Prev + KVP.Key] = tAvgNormal; - } - } - xMesh.normals = tNormals; - } - xMesh.tangents = GSDRootUtil.ProcessTangents(tTris, tNormals, tUV, tVerts); - - if (tName == null || tName.Length < 1) - { - tName = "ExtrudedMesh"; - } - - Output = new GameObject(tName); - Output.transform.position = tNode.pos; - - MF = Output.AddComponent(); - MF.sharedMesh = xMesh; - - if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) - { - SaveMesh(ref xMesh, false); - } - - //Colliders: - MeshCollider MC = null; - if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) - { - MC = Output.AddComponent(); - Mesh cMesh = new Mesh(); - cMesh.vertices = cVerts; - cMesh.triangles = cTris; - cMesh.normals = new Vector3[cVerts.Length]; - if (MC != null) { MC.sharedMesh = cMesh; } - if (MC != null) - { - MC.convex = bCollisionConvex; - MC.isTrigger = bCollisionTrigger; - if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) - { - cMesh.uv = new Vector2[cVerts.Length]; - cMesh.tangents = GSDRootUtil.ProcessTangents(cTris, cMesh.normals, cMesh.uv, cVerts); - SaveMesh(ref cMesh, true); - } - } - } - else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) - { - MC = Output.AddComponent(); - Mesh cMesh = new Mesh(); - cMesh.vertices = cVerts; - cMesh.triangles = cTris; - cMesh.normals = new Vector3[cVerts.Length]; - if (MC != null) { MC.sharedMesh = cMesh; } - if (MC != null) - { - MC.convex = bCollisionConvex; - MC.isTrigger = bCollisionTrigger; - if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) - { - cMesh.uv = new Vector2[cVerts.Length]; - cMesh.tangents = GSDRootUtil.ProcessTangents(cTris, cMesh.normals, cMesh.uv, cVerts); - SaveMesh(ref cMesh, true); - } - } - } - else if (CollisionType == CollisionTypeEnum.MeshCollision) - { - MC = Output.AddComponent(); - if (MC != null) { MC.sharedMesh = xMesh; } - if (MC != null) - { - MC.convex = bCollisionConvex; - MC.isTrigger = bCollisionTrigger; - } - } - else if (CollisionType == CollisionTypeEnum.BoxCollision) - { - //Primitive collider: - GameObject BC_Obj = new GameObject("Primitive"); - BoxCollider BC = BC_Obj.AddComponent(); - BC_Obj.transform.position = tNode.pos; - BC_Obj.transform.rotation = Quaternion.LookRotation(tNode.tangent); - - Vector3 BCCenter = default(Vector3); - // if(bStraightLineMatchStartEnd){ - // if(tNode.bIsBridge && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null){ - // BCCenter = ((tNode.pos - tNode.BridgeCounterpartNode.pos)*0.5f)+tNode.BridgeCounterpartNode.pos; - // }else if(tNode.idOnSpline < (tSpline.GetNodeCount()-1)){ - // BCCenter = ((tNode.pos - tSpline.mNodes[tNode.idOnSpline+1].pos)*0.5f)+tSpline.mNodes[tNode.idOnSpline+1].pos; - // }else{ - // - // } - // BCCenter.y -= VerticalRaise; - // BCCenter.y -= (mMaxHeight*0.5f); - // }else{ - Vector3 POS = default(Vector3); - tSpline.GetSplineValue_Both(StartTime, out tVect1, out POS); - //Goes right if not neg: - tVect1 = (tVect1 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); - tSpline.GetSplineValue_Both(EndTime, out tVect2, out POS); - tVect2 = (tVect2 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); - tVect1.y += VerticalRaise; - tVect2.y += VerticalRaise; - BCCenter = ((tVect1 - tVect2) * 0.5f) + tVect2; - BCCenter.y += ((mMinY + mMaxY) * 0.5f); - // } - - BCCenter -= tNode.pos; - BCCenter.z *= -1f; - - if (bBCFlipX) - { - BCCenter.z *= -1f; - } - if (bBCFlipZ) - { - BCCenter.x *= -1f; - } - - // - - Vector3 BCCenter2 = new Vector3(BCCenter.z, BCCenter.y, BCCenter.x); - - - BCCenter2 += StretchBC_LocOffset; - - - BC.center = BCCenter2; - - tFloat1 = Vector3.Distance(tNode.pos, tNode.BridgeCounterpartNode.pos); - - if (bStretchSize) - { - BC.size = StretchBC_Size; - } - else - { - if (Axis == AxisTypeEnum.X) - { - BC.size = new Vector3(tFloat1, mMaxHeight, (mMaxZ - mMinZ)); - } - else - { - BC.size = new Vector3((mMaxX - mMinX), mMaxHeight, tFloat1); - } - StretchBC_Size = BC.size; - } - BC_Obj.transform.parent = Output.transform; - } - - - //Use prefab mats if no material override: - MeshRenderer MR = Output.AddComponent(); - if (SplinatedMaterial1 == null && !bMaterialOverride) - { - MeshRenderer PrefabMR = tObj.GetComponent(); - if (PrefabMR != null && PrefabMR.sharedMaterials != null) - { - MR.materials = PrefabMR.sharedMaterials; - } - } - else - { - //Else, use override mats: - tIntBuffer1 = 0; - if (SplinatedMaterial1 != null) - { - tIntBuffer1 += 1; - if (SplinatedMaterial2 != null) - { - tIntBuffer1 += 1; - } - } - if (tIntBuffer1 > 0) - { - Material[] tMats = new Material[tIntBuffer1]; - if (SplinatedMaterial1 != null) - { - tMats[0] = SplinatedMaterial1; - if (SplinatedMaterial2 != null) - { - tMats[1] = SplinatedMaterial2; - } - } - MR.materials = tMats; - } - } - - mMaxX = mMaxX * 1.5f; - mMinX = mMinX * 1.5f; - mMaxY = mMaxY * 1.5f; - mMinY = mMinY * 1.5f; - mMaxZ = mMaxZ * 1.5f; - mMinZ = mMinZ * 1.5f; - - StartPos = tSpline.GetSplineValue(StartTime); - EndPos = tSpline.GetSplineValue(EndTime); - - //Destroy the instantiated prefab: - if (tObj != null) { Object.DestroyImmediate(tObj); } - if (Cap1 != null) { Object.DestroyImmediate(Cap1); } - if (Cap2 != null) { Object.DestroyImmediate(Cap2); } - - Material[] fMats = MR.sharedMaterials; - - //Set the new object with the specified vertical raise: - Output.transform.name = tName; - Output.transform.parent = MasterObjTrans; - if (EndCapStartObj != null) - { - EndCapStartObj.transform.parent = Output.transform; - EndCapStartOutput = EndCapStartObj; - - MeshRenderer eMR = EndCapStartObj.GetComponent(); - if (eMR == null) { eMR = EndCapStartObj.AddComponent(); } - if (eMR.sharedMaterials == null || (eMR.sharedMaterial != null && eMR.sharedMaterial.name.ToLower().Contains("default-diffuse"))) - { - eMR.sharedMaterials = fMats; - } - } - if (EndCapEndObj != null) - { - EndCapEndObj.transform.parent = Output.transform; - EndCapEndOutput = EndCapEndObj; - MeshRenderer eMR = EndCapEndObj.GetComponent(); - if (eMR == null) { eMR = EndCapEndObj.AddComponent(); } - if (eMR.sharedMaterials == null || (eMR.sharedMaterial != null && eMR.sharedMaterial.name.ToLower().Contains("default-diffuse"))) - { - eMR.sharedMaterials = fMats; - } - } - - if (bCollect) - { - tNode.GSDSpline.tRoad.bTriggerGC = true; - } -#endif - } - - private void SaveMesh(ref Mesh tMesh, bool bIsCollider) - { -#if UNITY_EDITOR - if (!tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) { return; } - //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); - string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; - tSceneName = tSceneName.Replace("/", ""); - tSceneName = tSceneName.Replace(".", ""); - string tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Extrusions/"; - string tRoadName = tNode.GSDSpline.tRoad.transform.name; - string FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + ".asset"; - if (bIsCollider) - { - FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + "-collider.asset"; - } - - string xPath = Application.dataPath.Replace("/Assets", "/" + tFolderName); - if (!System.IO.Directory.Exists(xPath)) - { - System.IO.Directory.CreateDirectory(xPath); - } - - - UnityEditor.AssetDatabase.CreateAsset(tMesh, FinalName); - UnityEditor.AssetDatabase.SaveAssets(); -#endif - } - - void DoStretch(ref Vector3[] OrigVerts, ref Vector2[] OrigUV, ref int[] OrigTris, ref List MaxVectorIndices, ref List MinVectorIndices, float mMaxDiff, out Vector3[] tVerts, out Vector2[] tUV, out Vector3[] tNormals, out int[] tTris) - { - Vector3 tVect1 = tNode.pos; - Vector3 tVect2 = default(Vector3); - - // if(bStraightLineMatchStartEnd){ - // if(tNode.bIsBridge && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null){ - // tVect2 = tNode.BridgeCounterpartNode.pos; - // }else if(tNode.idOnSpline < (tSpline.GetNodeCount()-1)){ - // tVect2 = tSpline.mNodes[tNode.idOnSpline+1].pos; - // } - // } - - Vector3 POS = default(Vector3); - Vector3 tDir = tNode.tangent; - - // if(!bStraightLineMatchStartEnd){ - tSpline.GetSplineValue_Both(StartTime, out tVect1, out POS); - //Goes right if not neg: - tVect1 = (tVect1 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); - - tSpline.GetSplineValue_Both(EndTime, out tVect2, out POS); - tVect2 = (tVect2 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); - - tVect1.y += VerticalRaise; - tVect2.y += VerticalRaise; - - tDir = tSpline.GetSplineValue(StartTime, true); - // } - - Matrix4x4 tMatrixStart = new Matrix4x4(); - Matrix4x4 tMatrixEnd = new Matrix4x4(); - int OrigMVL = OrigVerts.Length; - - tVerts = new Vector3[OrigMVL]; - tUV = new Vector2[OrigMVL]; - tNormals = new Vector3[OrigMVL]; - tTris = new int[OrigTris.Length]; - System.Array.Copy(OrigVerts, tVerts, OrigMVL); - System.Array.Copy(OrigTris, tTris, OrigTris.Length); - System.Array.Copy(OrigUV, tUV, OrigMVL); - - tMatrixStart.SetTRS(tVect1, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); - tMatrixEnd.SetTRS(tVect2, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); - - //Rotate and set vertex positions: - float NewDiff = Vector3.Distance(tVect1, tVect2); - float UVMod = NewDiff / mMaxDiff; - Vector3 xVect = default(Vector3); - for (int i = 0; i < OrigMVL; i++) - { - xVect = OrigVerts[i]; - if (MaxVectorIndices.Contains(i)) - { - tVerts[i] = tMatrixEnd.MultiplyPoint3x4(xVect); - } - else - { - tVerts[i] = tMatrixStart.MultiplyPoint3x4(xVect); - } - - if (RepeatUVType == RepeatUVTypeEnum.X) - { - if (OrigUV[i].x > Stretch_UVThreshold) - { - tUV[i].x = OrigUV[i].x * UVMod; - } - } - else - { - if (OrigUV[i].y > Stretch_UVThreshold) - { - tUV[i].y = OrigUV[i].y * UVMod; - } - } - } - } - - Vector3 GetAverageNormalToGround(GameObject tObj) - { - Ray tRay = default(Ray); - RaycastHit[] tRayHit = null; - float tHitY = 0f; - int tHitIndex = 0; - Vector3 tHitNormal = default(Vector3); - - Bounds tBounds = tObj.GetComponent().sharedMesh.bounds; - - Vector3[] tVects = new Vector3[8]; - tVects[0] = tBounds.min; - tVects[1] = tBounds.max; - tVects[2] = new Vector3(tVects[0].x, tVects[0].y, tVects[1].z); - tVects[3] = new Vector3(tVects[0].x, tVects[1].y, tVects[0].z); - tVects[4] = new Vector3(tVects[1].x, tVects[0].y, tVects[0].z); - tVects[5] = new Vector3(tVects[0].x, tVects[1].y, tVects[1].z); - tVects[6] = new Vector3(tVects[1].x, tVects[0].y, tVects[1].z); - tVects[7] = new Vector3(tVects[1].x, tVects[1].y, tVects[0].z); - - List xVects = new List(); - - for (int i = 0; i < 8; i++) - { - tRay = new Ray(tVects[i] + new Vector3(0f, 1f, 0f), Vector3.down); - tRayHit = Physics.RaycastAll(tRay); - tHitIndex = -1; - tHitY = -1f; - if (tRayHit.Length > 0) - { - for (int g = 0; g < tRayHit.Length; g++) - { - if (g == 0) - { - tHitY = tRayHit[g].point.y; - tHitIndex = 0; - } - else - { - if (tRayHit[g].point.y > tHitY) - { - tHitY = tRayHit[g].point.y; - tHitIndex = g; - } - } - } - xVects.Add(tRayHit[tHitIndex].normal); - } - } - - - for (int i = 0; i < xVects.Count; i++) - { - tHitNormal += xVects[i]; - } - tHitNormal /= xVects.Count; - - return tHitNormal; - } - } - -#endif -} +#region "Imports" +using UnityEngine; +#if UNITY_EDITOR +using System.Collections; +using System.Collections.Generic; +using GSD; +using System.IO; +#endif +#endregion + + +namespace GSD.Roads.Splination +{ + public enum AxisTypeEnum { X, Z }; + public enum CollisionTypeEnum { None, SimpleMeshTriangle, SimpleMeshTrapezoid, MeshCollision, BoxCollision }; + public enum RepeatUVTypeEnum { None, X, Y }; + +#if UNITY_EDITOR + + + [System.Serializable] + public class SplinatedMeshMaker + { + public bool bNeedsUpdate = false; + public string UID = ""; + public bool bIsGSD = false; + + public Transform MasterObjTrans = null; + public GameObject CurrentSplination = null; + public string CurrentSplinationString = ""; + public GameObject CurrentSplinationCap1 = null; + public string CurrentSplinationCap1String = ""; + public GameObject CurrentSplinationCap2 = null; + public string CurrentSplinationCap2String = ""; + public float CapHeightOffset1 = 0f; + public float CapHeightOffset2 = 0f; + + public GameObject Output = null; + public Mesh tMesh = null; + public bool bMaterialOverride = false; + public Material SplinatedMaterial1 = null; + public Material SplinatedMaterial2 = null; + public string SplinatedMaterial1String = ""; + public string SplinatedMaterial2String = ""; + public float MinMaxMod = 0.002f; + public float VertexMatchingPrecision = 0.005f; + + public bool bExactSplination = false; + public bool bMatchRoadDefinition = false; + public bool bMatchRoadIncrements = true; + public bool bTrimEnd = false; + public bool bTrimStart = false; + public bool bToggle = false; + public bool bMatchTerrain = false; + public bool bIsBridge = false; + + public bool bIsStretch = false; + public bool bStretchLocOffset = false; + public bool bStretchSize = false; + public Vector3 StretchBC_LocOffset = default(Vector3); + public Vector3 StretchBC_Size = default(Vector3); + public float Stretch_UVThreshold = 0.05f; + public bool bStraightLineMatchStartEnd = false; + public bool bBCFlipX = false; + public bool bBCFlipZ = false; + + + #region Horizontal offsets: + public float HorizontalSep = 0f; + public AnimationCurve HorizontalCurve; + public float HorizCurve_tempchecker1 = 0f; + public float HorizCurve_tempchecker2 = 0f; + public float HorizCurve_tempchecker3 = 0f; + public float HorizCurve_tempchecker4 = 0f; + public float HorizCurve_tempchecker5 = 0f; + public float HorizCurve_tempchecker6 = 0f; + public float HorizCurve_tempchecker7 = 0f; + public float HorizCurve_tempchecker8 = 0f; + #endregion + + + #region Vertical offsets: + public float VerticalRaise = 0f; + public AnimationCurve VerticalCurve; + public float VerticalCurve_tempchecker1 = 0f; + public float VerticalCurve_tempchecker2 = 0f; + public float VerticalCurve_tempchecker3 = 0f; + public float VerticalCurve_tempchecker4 = 0f; + public float VerticalCurve_tempchecker5 = 0f; + public float VerticalCurve_tempchecker6 = 0f; + public float VerticalCurve_tempchecker7 = 0f; + public float VerticalCurve_tempchecker8 = 0f; + #endregion + + + #region Vertical cutoff + public float VerticalCutoff = 0f; + public bool bVerticalCutoff = false; + public bool bVerticalCutoffDownwards = false; + public bool bVerticalMeshCutoff_OppositeDir = false; + public float VerticalMeshCutoffOffset = 0.04f; + public bool bVerticalCutoff_MatchZero = false; + #endregion + + + public float RoadRaise = 0f; + public Vector3 CustomRotation = default(Vector3); + public bool bFlipRotation = false; + public bool bStatic = true; + public Vector3 StartPos = default(Vector3); + public Vector3 EndPos = default(Vector3); + public float StartTime = 0f; + public float EndTime = 1f; + public GSDSplineC tSpline = null; + public GSDSplineN tNode = null; + public AxisTypeEnum Axis = AxisTypeEnum.X; + + public float mMaxX = -1f; + public float mMinX = -1f; + public float mMaxY = -1f; + public float mMinY = -1f; + public float mMaxZ = -1f; + public float mMinZ = -1f; + + public RepeatUVTypeEnum RepeatUVType = RepeatUVTypeEnum.None; + public bool bNoCenterMode = true; + + + #region End objects: + public GameObject EndCapStart = null; + public GameObject EndCapEnd = null; + public GameObject EndCapStartOutput = null; + public GameObject EndCapEndOutput = null; + public string EndCapStartString = ""; + public string EndCapEndString = ""; + public bool bEndCapCustomMatchStart = true; + public bool bEndObjectsMatchGround = false; + public Vector3 EndCapCustomOffsetStart = default(Vector3); + public Vector3 EndCapCustomOffsetEnd = default(Vector3); + public Vector3 EndCapCustomRotOffsetStart = default(Vector3); + public Vector3 EndCapCustomRotOffsetEnd = new Vector3(0f, 180f, 0f); + #endregion + + + #region Endings down: + public bool bStartDown = false; + public bool bStartTypeDownOverride = false; + public float StartTypeDownOverride = 0f; + public bool bEndDown = false; + public bool bEndTypeDownOverride = false; + public float EndTypeDownOverride = 0f; + #endregion + + + #region Collision: + public CollisionTypeEnum CollisionType = CollisionTypeEnum.SimpleMeshTriangle; + public bool bCollisionConvex = false; + public bool bSimpleCollisionAutomatic = true; + public bool bCollisionExtrude = false; + public bool bCollisionTrigger = false; + + public Vector3 CollisionBoxBL = default(Vector3); + public Vector3 CollisionBoxBR = default(Vector3); + public Vector3 CollisionBoxTL = default(Vector3); + public Vector3 CollisionBoxTR = default(Vector3); + + public Vector3 CollisionTriBL = default(Vector3); + public Vector3 CollisionTriBR = default(Vector3); + public Vector3 CollisionTriT = default(Vector3); + #endregion + + + public string tName = "ExtrudedObject"; + public string ThumbString = ""; + public string Desc = ""; + public string DisplayName = ""; + + public SplinatedMeshEditorMaker EM = null; + + + public void Init(GSDSplineC _tSpline, GSDSplineN _tNode, Transform tTrans) + { + tSpline = _tSpline; + tNode = _tNode; + MasterObjTrans = tTrans; + SetupUniqueIdentifier(); + } + + + public SplinatedMeshMaker Copy() + { + SplinatedMeshMaker SMM = new SplinatedMeshMaker(); + SMM.Init(tSpline, tNode, MasterObjTrans); + SMM.MasterObjTrans = MasterObjTrans; + SMM.bIsGSD = bIsGSD; + + SMM.CurrentSplination = CurrentSplination; + SMM.CurrentSplinationString = CurrentSplinationString; + + SMM.CurrentSplinationCap1 = CurrentSplinationCap1; + SMM.CurrentSplinationCap1String = CurrentSplinationCap1String; + SMM.CurrentSplinationCap2 = CurrentSplinationCap2; + SMM.CurrentSplinationCap2String = CurrentSplinationCap2String; + SMM.CapHeightOffset1 = CapHeightOffset1; + SMM.CapHeightOffset1 = CapHeightOffset2; + + SMM.Output = Output; + SMM.tMesh = tMesh; + SMM.bMaterialOverride = bMaterialOverride; + SMM.SplinatedMaterial1 = SplinatedMaterial1; + SMM.SplinatedMaterial2 = SplinatedMaterial2; + SMM.SplinatedMaterial1String = SplinatedMaterial1String; + SMM.SplinatedMaterial2String = SplinatedMaterial2String; + SMM.bExactSplination = bExactSplination; + SMM.bMatchRoadDefinition = bMatchRoadDefinition; + SMM.bMatchRoadIncrements = bMatchRoadIncrements; + SMM.bTrimStart = bTrimStart; + SMM.bTrimEnd = bTrimEnd; + SMM.bMatchTerrain = bMatchTerrain; + SMM.MinMaxMod = MinMaxMod; + SMM.VertexMatchingPrecision = VertexMatchingPrecision; + + SMM.bIsStretch = bIsStretch; + SMM.bStretchLocOffset = bStretchLocOffset; + SMM.bStretchSize = bStretchSize; + SMM.StretchBC_LocOffset = StretchBC_LocOffset; + SMM.StretchBC_Size = StretchBC_Size; + SMM.Stretch_UVThreshold = Stretch_UVThreshold; + SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; + SMM.bBCFlipX = bBCFlipX; + SMM.bBCFlipZ = bBCFlipZ; + + //Horizontal offsets: + SMM.HorizontalSep = HorizontalSep; + SMM.HorizontalCurve = new AnimationCurve(); + if (HorizontalCurve != null && HorizontalCurve.keys.Length > 0) + { + for (int i = 0; i < HorizontalCurve.keys.Length; i++) + { + SMM.HorizontalCurve.AddKey(HorizontalCurve.keys[i]); + } + } + //Vertical offset: + SMM.VerticalRaise = VerticalRaise; + SMM.VerticalCurve = new AnimationCurve(); + if (VerticalCurve != null && VerticalCurve.keys.Length > 0) + { + for (int i = 0; i < VerticalCurve.keys.Length; i++) + { + SMM.VerticalCurve.AddKey(VerticalCurve.keys[i]); + } + } + + //Vertical cutoff: + SMM.bVerticalCutoff = bVerticalCutoff; + SMM.VerticalCutoff = VerticalCutoff; + SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; + SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; + SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; + SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; + + SMM.RoadRaise = RoadRaise; + SMM.CustomRotation = CustomRotation; + SMM.bFlipRotation = bFlipRotation; + SMM.bStatic = bStatic; + SMM.StartTime = StartTime; + SMM.EndTime = EndTime; + SMM.StartPos = StartPos; + SMM.EndPos = EndPos; + SMM.Axis = Axis; + + SMM.RepeatUVType = RepeatUVType; + + SMM.mMaxX = mMaxX; + SMM.mMinX = mMinX; + SMM.mMaxY = mMaxY; + SMM.mMinY = mMinY; + SMM.mMaxZ = mMaxZ; + SMM.mMinZ = mMinZ; + + //End objects: + SMM.EndCapStart = EndCapStart; + SMM.EndCapStartString = EndCapStartString; + SMM.EndCapEnd = EndCapEnd; + SMM.EndCapEndString = EndCapEndString; + SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; + SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; + SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; + SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; + SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; + SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; + SMM.bIsBridge = bIsBridge; + //End down: + SMM.bStartDown = bStartDown; + SMM.bStartTypeDownOverride = bStartTypeDownOverride; + SMM.StartTypeDownOverride = StartTypeDownOverride; + SMM.bEndDown = bEndDown; + SMM.bEndTypeDownOverride = bEndTypeDownOverride; + SMM.EndTypeDownOverride = EndTypeDownOverride; + + //Collision: + SMM.CollisionType = CollisionType; + SMM.bCollisionConvex = bCollisionConvex; + SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; + SMM.bCollisionTrigger = bCollisionTrigger; + + SMM.CollisionBoxBL = CollisionBoxBL; + SMM.CollisionBoxBR = CollisionBoxBR; + SMM.CollisionBoxTL = CollisionBoxTL; + SMM.CollisionBoxTR = CollisionBoxTR; + + SMM.CollisionTriBL = CollisionTriBL; + SMM.CollisionTriBR = CollisionTriBR; + SMM.CollisionTriT = CollisionTriT; + + SMM.tName = tName; + SMM.ThumbString = ThumbString; + SMM.Desc = Desc; + SMM.DisplayName = DisplayName; + + SMM.SetupUniqueIdentifier(); + + return SMM; + } + + + public void SetDefaultTimes(bool bIsEndPoint, float tTime, float tTimeNext, int idOnSpline, float tDist) + { + if (!bIsEndPoint) + { + StartTime = tTime; + EndTime = tTimeNext; + } + else + { + if (idOnSpline < 2) + { + StartTime = tTime; + EndTime = tTimeNext; + } + else + { + StartTime = tTime; + EndTime = tTime - (125f / tDist); + } + } + } + + + public void UpdatePositions() + { + StartPos = tSpline.GetSplineValue(StartTime); + EndPos = tSpline.GetSplineValue(EndTime); + } + + + public void SaveToLibrary(string fName = "", bool bIsDefault = false) + { + SplinatedMeshLibraryMaker SLM = new SplinatedMeshLibraryMaker(); + SLM.Setup(this); + GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); + string xPath = GSDRootUtil.Dir_GetLibrary(); + string tPath = xPath + "ESO" + tName + ".gsd"; + if (fName.Length > 0) + { + if (bIsDefault) + { + tPath = xPath + "Q/ESO" + fName + ".gsd"; + } + else + { + tPath = xPath + "ESO" + fName + ".gsd"; + } + } + GSDRootUtil.CreateXML(ref tPath, SLM); + } + + + public void LoadFromLibrary(string xName, bool bIsQuickAdd = false) + { + string xPath = GSDRootUtil.Dir_GetLibrary(); + string tPath = xPath + "ESO" + xName + ".gsd"; + if (bIsQuickAdd) + { + GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); + tPath = xPath + "Q/ESO" + xName + ".gsd"; + } + SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker) GSDRootUtil.LoadXML(ref tPath); + SLM.LoadToSMM(this); + bNeedsUpdate = true; + } + + + public void LoadFromLibraryWizard(string xName) + { + GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); + string xPath = GSDRootUtil.Dir_GetLibrary(); + string tPath = xPath + "W/" + xName + ".gsd"; + SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker) GSDRootUtil.LoadXML(ref tPath); + SLM.LoadToSMM(this); + bNeedsUpdate = true; + } + + + public void LoadFromLibraryBulk(ref SplinatedMeshLibraryMaker SLM) + { + SLM.LoadToSMM(this); + // bNeedsUpdate = true; + } + + + public static SplinatedMeshLibraryMaker SLMFromData(string tData) + { + try + { + SplinatedMeshLibraryMaker SLM = (SplinatedMeshLibraryMaker) GSDRootUtil.LoadData(ref tData); + return SLM; + } + catch + { + return null; + } + } + + + public string ConvertToString() + { + SplinatedMeshLibraryMaker SLM = new SplinatedMeshLibraryMaker(); + SLM.Setup(this); + return GSDRootUtil.GetString(SLM); + } + + + public static void GetLibraryFiles(out string[] tNames, out string[] tPaths, bool bIsDefault = false) + { +#if UNITY_WEBPLAYER + tNames = null; + tPaths = null; + return; +#else + + tNames = null; + tPaths = null; + DirectoryInfo info; + string xPath = GSDRootUtil.Dir_GetLibrary(); + if (bIsDefault) + { + info = new DirectoryInfo(xPath + "Q/"); + } + else + { + info = new DirectoryInfo(xPath); + } + FileInfo[] fileInfo = info.GetFiles(); + int tCount = 0; + foreach (FileInfo tInfo in fileInfo) + { + if (tInfo.Name.Contains("ESO") && tInfo.Extension.ToLower().Contains("gsd")) + { + tCount += 1; + } + } + + tNames = new string[tCount]; + tPaths = new string[tCount]; + tCount = 0; + foreach (FileInfo tInfo in fileInfo) + { + if (tInfo.Name.Contains("ESO") && tInfo.Extension.ToLower().Contains("gsd")) + { + tNames[tCount] = tInfo.Name.Replace(".gsd", "").Replace("ESO", ""); + tPaths[tCount] = tInfo.FullName; + tCount += 1; + } + } +#endif + } + + + public void Kill() + { + if (Output != null) + { + Object.DestroyImmediate(Output); + } + if (EndCapStartOutput != null) + { + Object.DestroyImmediate(EndCapStartOutput); + } + if (EndCapEndOutput != null) + { + Object.DestroyImmediate(EndCapEndOutput); + } + } + + + [System.Serializable] + public class SplinatedMeshLibraryMaker + { + public string CurrentSplinationString = ""; + public string CurrentSplinationCap1String = ""; + public string CurrentSplinationCap2String = ""; + public bool bIsGSD = false; + + public bool bMaterialOverride = false; + public string SplinatedMaterial1String = ""; + public string SplinatedMaterial2String = ""; + public float CapHeightOffset1 = 0f; + public float CapHeightOffset2 = 0f; + public bool bExactSplination = false; + public bool bMatchRoadDefinition = false; + public bool bMatchRoadIncrements = true; + public bool bTrimStart = false; + public bool bTrimEnd = false; + public bool bToggle = false; + public bool bMatchTerrain = false; + public float MinMaxMod = 0.002f; + public float VertexMatchingPrecision = 0.005f; + + public bool bIsStretch = false; + public bool bStretchLocOffset = false; + public bool bStretchSize = false; + public Vector3 StretchBC_LocOffset = default(Vector3); + public Vector3 StretchBC_Size = default(Vector3); + public float Stretch_UVThreshold = 0.05f; + public bool bStraightLineMatchStartEnd = false; + public bool bBCFlipX = false; + public bool bBCFlipZ = false; + + //Horizontal offsets: + public float HorizontalSep = 5f; + public AnimationCurve HorizontalCurve; + //Vertical offsets: + public float VerticalRaise = 0f; + public AnimationCurve VerticalCurve; + //Vertical cutoff: + public float VerticalCutoff = 0f; + public bool bVerticalCutoff = false; + public bool bVerticalCutoffDownwards = false; + public bool bVerticalMeshCutoff_OppositeDir = false; + public float VerticalMeshCutoffOffset = 0.04f; + public bool bVerticalCutoff_MatchZero = false; + + public float RoadRaise = 0f; + public Vector3 CustomRotation = default(Vector3); + public bool bFlipRotation = false; + public bool bStatic = true; + public float StartTime = 0f; + public float EndTime = 1f; + public int Axis = 0; + public bool bIsBridge = false; + + public float mMaxX = -1f; + public float mMinX = -1f; + public float mMaxY = -1f; + public float mMinY = -1f; + public float mMaxZ = -1f; + public float mMinZ = -1f; + + public int RepeatUVType = 0; + public bool bNoCenterMode = true; + + //End objects: + public string EndCapStartString = ""; + public string EndCapEndString = ""; + public bool bEndCapCustomMatchStart = true; + public Vector3 EndCapCustomOffsetStart = default(Vector3); + public Vector3 EndCapCustomOffsetEnd = default(Vector3); + public Vector3 EndCapCustomRotOffsetStart = default(Vector3); + public Vector3 EndCapCustomRotOffsetEnd = default(Vector3); + public bool bEndObjectsMatchGround = false; + //Endings down: + public bool bStartDown = false; + public bool bStartTypeDownOverride = false; + public float StartTypeDownOverride = 0f; + public bool bEndDown = false; + public bool bEndTypeDownOverride = false; + public float EndTypeDownOverride = 0f; + + //Collision: + public int CollisionType = 0; + public bool bCollisionConvex = false; + public bool bSimpleCollisionAutomatic = true; + public bool bCollisionTrigger = false; + + public Vector3 CollisionBoxBL = default(Vector3); + public Vector3 CollisionBoxBR = default(Vector3); + public Vector3 CollisionBoxTL = default(Vector3); + public Vector3 CollisionBoxTR = default(Vector3); + + public Vector3 CollisionTriBL = default(Vector3); + public Vector3 CollisionTriBR = default(Vector3); + public Vector3 CollisionTriT = default(Vector3); + + public string tName = "ExtrudedObject"; + public string ThumbString = ""; + public string Desc = ""; + public string DisplayName = ""; + + public void Setup(SplinatedMeshMaker SMM) + { + CurrentSplinationString = SMM.CurrentSplinationString; + if (SMM.CurrentSplinationCap1 == null) + { + CurrentSplinationCap1String = ""; + } + else + { + CurrentSplinationCap1String = SMM.CurrentSplinationCap1String; + } + + if (SMM.CurrentSplinationCap2 == null) + { + CurrentSplinationCap2String = ""; + } + else + { + CurrentSplinationCap2String = SMM.CurrentSplinationCap2String; + } + bIsGSD = SMM.bIsGSD; + + CapHeightOffset1 = SMM.CapHeightOffset1; + CapHeightOffset2 = SMM.CapHeightOffset2; + + bMaterialOverride = SMM.bMaterialOverride; + SplinatedMaterial1String = SMM.SplinatedMaterial1String; + SplinatedMaterial2String = SMM.SplinatedMaterial2String; + bExactSplination = SMM.bExactSplination; + bMatchRoadDefinition = SMM.bMatchRoadDefinition; + bMatchRoadIncrements = SMM.bMatchRoadIncrements; + bTrimStart = SMM.bTrimStart; + bTrimEnd = SMM.bTrimEnd; + bMatchTerrain = SMM.bMatchTerrain; + MinMaxMod = SMM.MinMaxMod; + bIsBridge = SMM.bIsBridge; + VertexMatchingPrecision = SMM.VertexMatchingPrecision; + + bIsStretch = SMM.bIsStretch; + bStretchLocOffset = SMM.bStretchLocOffset; + bStretchSize = SMM.bStretchSize; + StretchBC_LocOffset = SMM.StretchBC_LocOffset; + StretchBC_Size = SMM.StretchBC_Size; + Stretch_UVThreshold = SMM.Stretch_UVThreshold; + bStraightLineMatchStartEnd = SMM.bStraightLineMatchStartEnd; + bBCFlipX = SMM.bBCFlipX; + bBCFlipZ = SMM.bBCFlipZ; + + //Horizontal offsets: + HorizontalSep = SMM.HorizontalSep; + HorizontalCurve = SMM.HorizontalCurve; + //Vertical offset: + VerticalRaise = SMM.VerticalRaise; + VerticalCurve = SMM.VerticalCurve; + //Vertical cutoff + VerticalCutoff = SMM.VerticalCutoff; + bVerticalCutoff = SMM.bVerticalCutoff; + bVerticalCutoffDownwards = SMM.bVerticalCutoffDownwards; + bVerticalMeshCutoff_OppositeDir = SMM.bVerticalMeshCutoff_OppositeDir; + VerticalMeshCutoffOffset = SMM.VerticalMeshCutoffOffset; + bVerticalCutoff_MatchZero = SMM.bVerticalCutoff_MatchZero; + + RoadRaise = SMM.RoadRaise; + CustomRotation = SMM.CustomRotation; + bFlipRotation = SMM.bFlipRotation; + bStatic = SMM.bStatic; + StartTime = SMM.StartTime; + EndTime = SMM.EndTime; + Axis = (int) SMM.Axis; + + RepeatUVType = (int) SMM.RepeatUVType; + + mMaxX = SMM.mMaxX; + mMinX = SMM.mMinX; + mMaxY = SMM.mMaxY; + mMinY = SMM.mMinY; + mMaxZ = SMM.mMaxZ; + mMinZ = SMM.mMinZ; + + //End objects: + if (SMM.EndCapStart == null) + { + EndCapStartString = ""; + } + else + { + EndCapStartString = SMM.EndCapStartString; + } + if (SMM.EndCapEnd == null) + { + EndCapEndString = ""; + } + else + { + EndCapEndString = SMM.EndCapEndString; + } + bEndCapCustomMatchStart = SMM.bEndCapCustomMatchStart; + EndCapCustomOffsetStart = SMM.EndCapCustomOffsetStart; + EndCapCustomOffsetEnd = SMM.EndCapCustomOffsetEnd; + EndCapCustomRotOffsetStart = SMM.EndCapCustomRotOffsetStart; + EndCapCustomRotOffsetEnd = SMM.EndCapCustomRotOffsetEnd; + bEndObjectsMatchGround = SMM.bEndObjectsMatchGround; + //Endings down: + bStartDown = SMM.bStartDown; + bStartTypeDownOverride = SMM.bStartTypeDownOverride; + StartTypeDownOverride = SMM.StartTypeDownOverride; + bEndDown = SMM.bEndDown; + bEndTypeDownOverride = SMM.bEndTypeDownOverride; + EndTypeDownOverride = SMM.EndTypeDownOverride; + + //Collision: + CollisionType = (int) SMM.CollisionType; + bCollisionConvex = SMM.bCollisionConvex; + bSimpleCollisionAutomatic = SMM.bSimpleCollisionAutomatic; + bCollisionTrigger = SMM.bCollisionTrigger; + + CollisionBoxBL = SMM.CollisionBoxBL; + CollisionBoxBR = SMM.CollisionBoxBR; + CollisionBoxTL = SMM.CollisionBoxTL; + CollisionBoxTR = SMM.CollisionBoxTR; + + CollisionTriBL = SMM.CollisionTriBL; + CollisionTriBR = SMM.CollisionTriBR; + CollisionTriT = SMM.CollisionTriT; + + tName = SMM.tName; + ThumbString = SMM.ThumbString; + Desc = SMM.Desc; + DisplayName = SMM.DisplayName; + } + + public void LoadToSMM(SplinatedMeshMaker SMM) + { +#if UNITY_EDITOR + SMM.CurrentSplinationString = CurrentSplinationString; + SMM.CurrentSplination = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationString, typeof(GameObject)); + + SMM.CurrentSplinationCap1String = CurrentSplinationCap1String; + if (CurrentSplinationCap1String != null && CurrentSplinationCap1String.Length > 1) + { + SMM.CurrentSplinationCap1 = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap1String, typeof(GameObject)); + } + + SMM.CurrentSplinationCap2String = CurrentSplinationCap2String; + if (CurrentSplinationCap2String != null && CurrentSplinationCap2String.Length > 1) + { + SMM.CurrentSplinationCap2 = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap2String, typeof(GameObject)); + } + + SMM.CapHeightOffset1 = CapHeightOffset1; + SMM.CapHeightOffset2 = CapHeightOffset2; + + SMM.bMaterialOverride = bMaterialOverride; + SMM.SplinatedMaterial1String = SplinatedMaterial1String; + SMM.SplinatedMaterial2String = SplinatedMaterial2String; + + if (bMaterialOverride) + { + if (SplinatedMaterial1String != null && SplinatedMaterial1String.Length > 0) + { + SMM.SplinatedMaterial1 = (Material) UnityEditor.AssetDatabase.LoadAssetAtPath(SplinatedMaterial1String, typeof(Material)); + } + if (SplinatedMaterial2String != null && SplinatedMaterial2String.Length > 0) + { + SMM.SplinatedMaterial2 = (Material) UnityEditor.AssetDatabase.LoadAssetAtPath(SplinatedMaterial2String, typeof(Material)); + } + } + + SMM.bIsGSD = bIsGSD; + SMM.bExactSplination = bExactSplination; + SMM.bMatchRoadDefinition = bMatchRoadDefinition; + SMM.bMatchRoadIncrements = bMatchRoadIncrements; + SMM.bTrimStart = bTrimStart; + SMM.bTrimEnd = bTrimEnd; + SMM.bMatchTerrain = bMatchTerrain; + SMM.MinMaxMod = MinMaxMod; + SMM.bIsBridge = bIsBridge; + SMM.VertexMatchingPrecision = VertexMatchingPrecision; + + SMM.bIsStretch = bIsStretch; + SMM.bStretchLocOffset = bStretchLocOffset; + SMM.bStretchSize = bStretchSize; + SMM.StretchBC_LocOffset = StretchBC_LocOffset; + SMM.StretchBC_Size = StretchBC_Size; + SMM.Stretch_UVThreshold = Stretch_UVThreshold; + SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; + SMM.bBCFlipX = bBCFlipX; + SMM.bBCFlipZ = bBCFlipZ; + + //Horizontal offsets: + SMM.HorizontalSep = HorizontalSep; + SMM.HorizontalCurve = HorizontalCurve; + //Vertical offset: + SMM.VerticalRaise = VerticalRaise; + SMM.VerticalCurve = VerticalCurve; + //Vertical cutoff: + SMM.VerticalCutoff = VerticalCutoff; + SMM.bVerticalCutoff = bVerticalCutoff; + SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; + SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; + SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; + SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; + + SMM.RoadRaise = RoadRaise; + SMM.CustomRotation = CustomRotation; + SMM.bFlipRotation = bFlipRotation; + SMM.bStatic = bStatic; + SMM.StartTime = StartTime; + SMM.EndTime = EndTime; + SMM.Axis = (AxisTypeEnum) Axis; + + SMM.RepeatUVType = (RepeatUVTypeEnum) RepeatUVType; + + SMM.mMaxX = mMaxX; + SMM.mMinX = mMinX; + SMM.mMaxY = mMaxY; + SMM.mMinY = mMinY; + SMM.mMaxZ = mMaxZ; + SMM.mMinZ = mMinZ; + + //Ending objects: + SMM.EndCapStartString = EndCapStartString; + SMM.EndCapEndString = EndCapEndString; + if (EndCapStartString != null && EndCapStartString.Length > 0) + { + SMM.EndCapStart = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(EndCapStartString, typeof(GameObject)); + } + if (EndCapEndString != null && EndCapEndString.Length > 0) + { + SMM.EndCapEnd = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(EndCapEndString, typeof(GameObject)); + } + SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; + SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; + SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; + SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; + SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; + SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; + + //Endings down: + SMM.bStartDown = bStartDown; + SMM.bStartTypeDownOverride = bStartTypeDownOverride; + SMM.StartTypeDownOverride = StartTypeDownOverride; + SMM.bEndDown = bEndDown; + SMM.bEndTypeDownOverride = bEndTypeDownOverride; + SMM.EndTypeDownOverride = EndTypeDownOverride; + + //Collision: + SMM.CollisionType = (CollisionTypeEnum) CollisionType; + SMM.bCollisionConvex = bCollisionConvex; + SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; + SMM.bCollisionTrigger = bCollisionTrigger; + + SMM.CollisionBoxBL = CollisionBoxBL; + SMM.CollisionBoxBR = CollisionBoxBR; + SMM.CollisionBoxTL = CollisionBoxTL; + SMM.CollisionBoxTR = CollisionBoxTR; + + SMM.CollisionTriBL = CollisionTriBL; + SMM.CollisionTriBR = CollisionTriBR; + SMM.CollisionTriT = CollisionTriT; + + SMM.tName = tName; + SMM.ThumbString = ThumbString; + SMM.Desc = Desc; + SMM.DisplayName = DisplayName; +#endif + } + } + + + public class SplinatedMeshEditorMaker + { + public GameObject CurrentSplination = null; + public GameObject CurrentSplinationCap1 = null; + public GameObject CurrentSplinationCap2 = null; + + public bool bMaterialOverride = false; + public Material SplinatedMaterial1 = null; + public Material SplinatedMaterial2 = null; + public float CapHeightOffset1 = 0f; + public float CapHeightOffset2 = 0f; + public bool bExactSplination = false; + public bool bMatchRoadDefinition = false; + public bool bMatchRoadIncrements = true; + public bool bTrimStart = false; + public bool bTrimEnd = false; + public bool bToggle = false; + public bool bMatchTerrain = false; + public float MinMaxMod = 0.002f; + public float VertexMatchingPrecision = 0.005f; + + public bool bIsStretch = false; + public bool bStretchLocOffset = false; + public bool bStretchSize = false; + public Vector3 StretchBC_LocOffset = default(Vector3); + public Vector3 StretchBC_Size = default(Vector3); + public float Stretch_UVThreshold = 0.05f; + public bool bStraightLineMatchStartEnd = false; + public bool bBCFlipX = false; + public bool bBCFlipZ = false; + + //Horizontal offsets: + public float HorizontalSep = 5f; + public AnimationCurve HorizontalCurve; + //Vertical offsets: + public float VerticalRaise = 0f; + public AnimationCurve VerticalCurve; + //Vertical cutoff: + public float VerticalCutoff = 0f; + public bool bVerticalCutoff = false; + public bool bVerticalCutoffDownwards = false; + public bool bVerticalMeshCutoff_OppositeDir = false; + public float VerticalMeshCutoffOffset = 0.04f; + public bool bVerticalCutoff_MatchZero = false; + + public float RoadRaise = 0f; + public Vector3 CustomRotation = default(Vector3); + public bool bFlipRotation = false; + public bool bStatic = true; + public float StartTime = 0f; + public float EndTime = 1f; + public AxisTypeEnum Axis = AxisTypeEnum.X; + public bool bIsBridge = false; + + public RepeatUVTypeEnum RepeatUVType = RepeatUVTypeEnum.None; + public bool bNoCenterMode = true; + + //End objects: + public GameObject EndCapStart = null; + public GameObject EndCapEnd = null; + public bool bEndCapCustomMatchStart = true; + public Vector3 EndCapCustomOffsetStart = default(Vector3); + public Vector3 EndCapCustomOffsetEnd = default(Vector3); + public Vector3 EndCapCustomRotOffsetStart = default(Vector3); + public Vector3 EndCapCustomRotOffsetEnd = default(Vector3); + public bool bEndObjectsMatchGround = false; + //Endings down: + public bool bStartDown = false; + public bool bStartTypeDownOverride = false; + public float StartTypeDownOverride = 0f; + public bool bEndDown = false; + public bool bEndTypeDownOverride = false; + public float EndTypeDownOverride = 0f; + + //Collision: + public CollisionTypeEnum CollisionType = CollisionTypeEnum.SimpleMeshTriangle; + public bool bCollisionConvex = false; + public bool bSimpleCollisionAutomatic = true; + public bool bCollisionTrigger = false; + + public Vector3 CollisionBoxBL = default(Vector3); + public Vector3 CollisionBoxBR = default(Vector3); + public Vector3 CollisionBoxTL = default(Vector3); + public Vector3 CollisionBoxTR = default(Vector3); + + public Vector3 CollisionTriBL = default(Vector3); + public Vector3 CollisionTriBR = default(Vector3); + public Vector3 CollisionTriT = default(Vector3); + + public string tName = "ExtrudedObject"; + + public void Setup(SplinatedMeshMaker SMM) + { + CurrentSplination = SMM.CurrentSplination; + CurrentSplinationCap1 = SMM.CurrentSplinationCap1; + CurrentSplinationCap2 = SMM.CurrentSplinationCap2; + + CapHeightOffset1 = SMM.CapHeightOffset1; + CapHeightOffset2 = SMM.CapHeightOffset2; + + bMaterialOverride = SMM.bMaterialOverride; + SplinatedMaterial1 = SMM.SplinatedMaterial1; + SplinatedMaterial2 = SMM.SplinatedMaterial2; + bExactSplination = SMM.bExactSplination; + bMatchRoadDefinition = SMM.bMatchRoadDefinition; + bMatchRoadIncrements = SMM.bMatchRoadIncrements; + bTrimStart = SMM.bTrimStart; + bTrimEnd = SMM.bTrimEnd; + bMatchTerrain = SMM.bMatchTerrain; + MinMaxMod = SMM.MinMaxMod; + bIsBridge = SMM.bIsBridge; + VertexMatchingPrecision = SMM.VertexMatchingPrecision; + + bIsStretch = SMM.bIsStretch; + bStretchLocOffset = SMM.bStretchLocOffset; + bStretchSize = SMM.bStretchSize; + StretchBC_LocOffset = SMM.StretchBC_LocOffset; + StretchBC_Size = SMM.StretchBC_Size; + Stretch_UVThreshold = SMM.Stretch_UVThreshold; + bStraightLineMatchStartEnd = SMM.bStraightLineMatchStartEnd; + bBCFlipX = SMM.bBCFlipX; + bBCFlipZ = SMM.bBCFlipZ; + + //Horizontal offsets: + HorizontalSep = SMM.HorizontalSep; + HorizontalCurve = SMM.HorizontalCurve; + //Vertical offset: + VerticalRaise = SMM.VerticalRaise; + VerticalCurve = SMM.VerticalCurve; + //Vertical cutoff + VerticalCutoff = SMM.VerticalCutoff; + bVerticalCutoff = SMM.bVerticalCutoff; + bVerticalCutoffDownwards = SMM.bVerticalCutoffDownwards; + bVerticalMeshCutoff_OppositeDir = SMM.bVerticalMeshCutoff_OppositeDir; + VerticalMeshCutoffOffset = SMM.VerticalMeshCutoffOffset; + bVerticalCutoff_MatchZero = SMM.bVerticalCutoff_MatchZero; + + RoadRaise = SMM.RoadRaise; + CustomRotation = SMM.CustomRotation; + bFlipRotation = SMM.bFlipRotation; + bStatic = SMM.bStatic; + StartTime = SMM.StartTime; + EndTime = SMM.EndTime; + Axis = SMM.Axis; + + RepeatUVType = SMM.RepeatUVType; + + //End objects: + EndCapStart = SMM.EndCapStart; + EndCapEnd = SMM.EndCapEnd; + + bEndCapCustomMatchStart = SMM.bEndCapCustomMatchStart; + EndCapCustomOffsetStart = SMM.EndCapCustomOffsetStart; + EndCapCustomOffsetEnd = SMM.EndCapCustomOffsetEnd; + EndCapCustomRotOffsetStart = SMM.EndCapCustomRotOffsetStart; + EndCapCustomRotOffsetEnd = SMM.EndCapCustomRotOffsetEnd; + bEndObjectsMatchGround = SMM.bEndObjectsMatchGround; + //Endings down: + bStartDown = SMM.bStartDown; + bStartTypeDownOverride = SMM.bStartTypeDownOverride; + StartTypeDownOverride = SMM.StartTypeDownOverride; + bEndDown = SMM.bEndDown; + bEndTypeDownOverride = SMM.bEndTypeDownOverride; + EndTypeDownOverride = SMM.EndTypeDownOverride; + + //Collision: + CollisionType = SMM.CollisionType; + bCollisionConvex = SMM.bCollisionConvex; + bSimpleCollisionAutomatic = SMM.bSimpleCollisionAutomatic; + bCollisionTrigger = SMM.bCollisionTrigger; + + CollisionBoxBL = SMM.CollisionBoxBL; + CollisionBoxBR = SMM.CollisionBoxBR; + CollisionBoxTL = SMM.CollisionBoxTL; + CollisionBoxTR = SMM.CollisionBoxTR; + + CollisionTriBL = SMM.CollisionTriBL; + CollisionTriBR = SMM.CollisionTriBR; + CollisionTriT = SMM.CollisionTriT; + + tName = SMM.tName; + } + + public void LoadToSMM(SplinatedMeshMaker SMM) + { +#if UNITY_EDITOR + SMM.CurrentSplination = CurrentSplination; // (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationString,typeof(GameObject)); + SMM.CurrentSplinationCap1 = CurrentSplinationCap1;// (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap1String,typeof(GameObject)); + SMM.CurrentSplinationCap2 = CurrentSplinationCap2;// (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(CurrentSplinationCap2String,typeof(GameObject)); + + SMM.CapHeightOffset1 = CapHeightOffset1; + SMM.CapHeightOffset2 = CapHeightOffset2; + + SMM.bMaterialOverride = bMaterialOverride; + + SMM.SplinatedMaterial1 = SplinatedMaterial1; + SMM.SplinatedMaterial2 = SplinatedMaterial2; + + SMM.bExactSplination = bExactSplination; + SMM.bMatchRoadDefinition = bMatchRoadDefinition; + SMM.bMatchRoadIncrements = bMatchRoadIncrements; + SMM.bTrimStart = bTrimStart; + SMM.bTrimEnd = bTrimEnd; + SMM.bMatchTerrain = bMatchTerrain; + SMM.MinMaxMod = MinMaxMod; + SMM.bIsBridge = bIsBridge; + SMM.VertexMatchingPrecision = VertexMatchingPrecision; + + SMM.bIsStretch = bIsStretch; + SMM.bStretchLocOffset = bStretchLocOffset; + SMM.bStretchSize = bStretchSize; + SMM.StretchBC_LocOffset = StretchBC_LocOffset; + SMM.StretchBC_Size = StretchBC_Size; + SMM.Stretch_UVThreshold = Stretch_UVThreshold; + SMM.bStraightLineMatchStartEnd = bStraightLineMatchStartEnd; + SMM.bBCFlipX = bBCFlipX; + SMM.bBCFlipZ = bBCFlipZ; + + //Horizontal offsets: + SMM.HorizontalSep = HorizontalSep; + SMM.HorizontalCurve = HorizontalCurve; + //Vertical offset: + SMM.VerticalRaise = VerticalRaise; + SMM.VerticalCurve = VerticalCurve; + //Vertical cutoff: + SMM.VerticalCutoff = VerticalCutoff; + SMM.bVerticalCutoff = bVerticalCutoff; + SMM.bVerticalCutoffDownwards = bVerticalCutoffDownwards; + SMM.bVerticalMeshCutoff_OppositeDir = bVerticalMeshCutoff_OppositeDir; + SMM.VerticalMeshCutoffOffset = VerticalMeshCutoffOffset; + SMM.bVerticalCutoff_MatchZero = bVerticalCutoff_MatchZero; + + SMM.RoadRaise = RoadRaise; + SMM.CustomRotation = CustomRotation; + SMM.bFlipRotation = bFlipRotation; + SMM.bStatic = bStatic; + SMM.StartTime = StartTime; + SMM.EndTime = EndTime; + SMM.Axis = Axis; + + SMM.RepeatUVType = RepeatUVType; + + //Ending objects: + SMM.EndCapStart = EndCapStart; + SMM.EndCapEnd = EndCapEnd; + + SMM.bEndCapCustomMatchStart = bEndCapCustomMatchStart; + SMM.EndCapCustomOffsetStart = EndCapCustomOffsetStart; + SMM.EndCapCustomOffsetEnd = EndCapCustomOffsetEnd; + SMM.EndCapCustomRotOffsetStart = EndCapCustomRotOffsetStart; + SMM.EndCapCustomRotOffsetEnd = EndCapCustomRotOffsetEnd; + SMM.bEndObjectsMatchGround = bEndObjectsMatchGround; + + //Endings down: + SMM.bStartDown = bStartDown; + SMM.bStartTypeDownOverride = bStartTypeDownOverride; + SMM.StartTypeDownOverride = StartTypeDownOverride; + SMM.bEndDown = bEndDown; + SMM.bEndTypeDownOverride = bEndTypeDownOverride; + SMM.EndTypeDownOverride = EndTypeDownOverride; + + //Collision: + SMM.CollisionType = CollisionType; + SMM.bCollisionConvex = bCollisionConvex; + SMM.bSimpleCollisionAutomatic = bSimpleCollisionAutomatic; + SMM.bCollisionTrigger = bCollisionTrigger; + + SMM.CollisionBoxBL = CollisionBoxBL; + SMM.CollisionBoxBR = CollisionBoxBR; + SMM.CollisionBoxTL = CollisionBoxTL; + SMM.CollisionBoxTR = CollisionBoxTR; + + SMM.CollisionTriBL = CollisionTriBL; + SMM.CollisionTriBR = CollisionTriBR; + SMM.CollisionTriT = CollisionTriT; + + SMM.tName = tName; +#endif + } + + public bool IsEqualToSMM(SplinatedMeshMaker SMM) + { + if (SMM.CurrentSplination != CurrentSplination) + { + return false; + } + if (SMM.CurrentSplinationCap1 != CurrentSplinationCap1) + { + return false; + } + if (SMM.CurrentSplinationCap2 != CurrentSplinationCap2) + { + return false; + } + + if (!GSDRootUtil.IsApproximately(SMM.CapHeightOffset1, CapHeightOffset1, 0.0001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.CapHeightOffset2, CapHeightOffset2, 0.0001f)) + { + return false; + } + + if (SMM.bMaterialOverride != bMaterialOverride) + { + return false; + } + + if (SMM.SplinatedMaterial1 != SplinatedMaterial1) + { + return false; + } + if (SMM.SplinatedMaterial2 != SplinatedMaterial2) + { + return false; + } + + if (SMM.bExactSplination != bExactSplination) + { + return false; + } + if (SMM.bMatchRoadDefinition != bMatchRoadDefinition) + { + return false; + } + if (SMM.bMatchRoadIncrements != bMatchRoadIncrements) + { + return false; + } + if (SMM.bTrimStart != bTrimStart) + { + return false; + } + if (SMM.bTrimEnd != bTrimEnd) + { + return false; + } + if (SMM.bMatchTerrain != bMatchTerrain) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.MinMaxMod, MinMaxMod, 0.0001f)) + { + return false; + } + if (SMM.bIsBridge != bIsBridge) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.VertexMatchingPrecision, VertexMatchingPrecision, 0.0001f)) + { + return false; + } + + if (SMM.bIsStretch != bIsStretch) + { + return false; + } + if (SMM.bStretchLocOffset != bStretchLocOffset) + { + return false; + } + if (SMM.bStretchSize != bStretchSize) + { + return false; + } + if (SMM.StretchBC_LocOffset != StretchBC_LocOffset) + { + return false; + } + if (SMM.StretchBC_Size != StretchBC_Size) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.Stretch_UVThreshold, Stretch_UVThreshold, 0.0001f)) + { + return false; + } + if (SMM.bStraightLineMatchStartEnd != bStraightLineMatchStartEnd) + { + return false; + } + if (SMM.bBCFlipX != bBCFlipX) + { + return false; + } + if (SMM.bBCFlipZ != bBCFlipZ) + { + return false; + } + + //Horizontal offsets: + if (!GSDRootUtil.IsApproximately(SMM.HorizontalSep, HorizontalSep, 0.0001f)) + { + return false; + } + if (SMM.HorizontalCurve != HorizontalCurve) + { + return false; + } + //Vertical offset: + if (!GSDRootUtil.IsApproximately(SMM.VerticalRaise, VerticalRaise, 0.0001f)) + { + return false; + } + if (SMM.VerticalCurve != VerticalCurve) + { + return false; + } + //Vertical cutoff: + if (!GSDRootUtil.IsApproximately(SMM.VerticalCutoff, VerticalCutoff, 0.0001f)) + { + return false; + } + if (SMM.bVerticalCutoff != bVerticalCutoff) + { + return false; + } + if (SMM.bVerticalCutoffDownwards != bVerticalCutoffDownwards) + { + return false; + } + if (SMM.bVerticalMeshCutoff_OppositeDir != bVerticalMeshCutoff_OppositeDir) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.VerticalMeshCutoffOffset, VerticalMeshCutoffOffset, 0.0001f)) + { + return false; + } + if (SMM.bVerticalCutoff_MatchZero != bVerticalCutoff_MatchZero) + { + return false; + } + + if (!GSDRootUtil.IsApproximately(SMM.RoadRaise, RoadRaise, 0.0001f)) + { + return false; + } + if (SMM.CustomRotation != CustomRotation) + { + return false; + } + if (SMM.bFlipRotation != bFlipRotation) + { + return false; + } + if (SMM.bStatic != bStatic) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.StartTime, StartTime, 0.0001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.EndTime, EndTime, 0.0001f)) + { + return false; + } + if (SMM.Axis != Axis) + { + return false; + } + + if (SMM.RepeatUVType != RepeatUVType) + { + return false; + } + + //Ending objects: + if (SMM.EndCapStart != EndCapStart) + { + return false; + } + if (SMM.EndCapEnd != EndCapEnd) + { + return false; + } + + if (SMM.bEndCapCustomMatchStart != bEndCapCustomMatchStart) + { + return false; + } + if (SMM.EndCapCustomOffsetStart != EndCapCustomOffsetStart) + { + return false; + } + if (SMM.EndCapCustomOffsetEnd != EndCapCustomOffsetEnd) + { + return false; + } + if (SMM.EndCapCustomRotOffsetStart != EndCapCustomRotOffsetStart) + { + return false; + } + if (SMM.EndCapCustomRotOffsetEnd != EndCapCustomRotOffsetEnd) + { + return false; + } + if (SMM.bEndObjectsMatchGround != bEndObjectsMatchGround) + { + return false; + } + + //Endings down: + if (SMM.bStartDown != bStartDown) + { + return false; + } + if (SMM.bStartTypeDownOverride != bStartTypeDownOverride) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.StartTypeDownOverride, StartTypeDownOverride, 0.0001f)) + { + return false; + } + if (SMM.bEndDown != bEndDown) + { + return false; + } + if (SMM.bEndTypeDownOverride != bEndTypeDownOverride) + { + return false; + } + if (!GSDRootUtil.IsApproximately(SMM.EndTypeDownOverride, EndTypeDownOverride, 0.0001f)) + { + return false; + } + + //Collision: + if (SMM.CollisionType != CollisionType) + { + return false; + } + if (SMM.bCollisionConvex != bCollisionConvex) + { + return false; + } + if (SMM.bSimpleCollisionAutomatic != bSimpleCollisionAutomatic) + { + return false; + } + if (SMM.bCollisionTrigger != bCollisionTrigger) + { + return false; + } + + if (SMM.CollisionBoxBL != CollisionBoxBL) + { + return false; + } + if (SMM.CollisionBoxBR != CollisionBoxBR) + { + return false; + } + if (SMM.CollisionBoxTL != CollisionBoxTL) + { + return false; + } + if (SMM.CollisionBoxTR != CollisionBoxTR) + { + return false; + } + + if (SMM.CollisionTriBL != CollisionTriBL) + { + return false; + } + if (SMM.CollisionTriBR != CollisionTriBR) + { + return false; + } + if (SMM.CollisionTriT != CollisionTriT) + { + return false; + } + + if (string.CompareOrdinal(SMM.tName, tName) != 0) + { + return false; + } + + return true; + } + } + + + #region "Static util" + public void SetupUniqueIdentifier() + { + if (UID == null || UID.Length < 4) + { + UID = System.Guid.NewGuid().ToString(); + } + } + + + public static Vector3 GetVector3Average(Vector3[] tVects) + { + int tCount = tVects.Length; + Vector3 mVect = default(Vector3); + for (int index = 0; index < tCount; index++) + { + mVect += tVects[index]; + } + mVect /= tCount; + return mVect; + } + + + private static bool FloatsNear(float tNear, float tVal1, float tVal2) + { + if (GSDRootUtil.IsApproximately(tVal1, tVal2, tNear)) + { + return true; + } + + if (tVal1 < (tVal2 + tNear) && tVal1 > (tVal2 - tNear)) + { + return true; + } + if (tVal2 < (tVal1 + tNear) && tVal2 > (tVal1 - tNear)) + { + return true; + } + return false; + } + + + private static int[] GetCollisionTris_Tri(int MeshCount, int cTriCount, int cCount) + { + int tCounter = 0; + int[] tTris = new int[cTriCount * 3]; + + //Front side: ** + tTris[tCounter] = 0; + tCounter += 1; + tTris[tCounter] = 2; + tCounter += 1; + tTris[tCounter] = 1; + tCounter += 1; + int tMod = -1; + for (int index = 0; index < (MeshCount); index++) + { + tMod = (index * 3); + //Bottom side: *** + tTris[tCounter] = 1 + tMod; + tCounter += 1; + tTris[tCounter] = 4 + tMod; + tCounter += 1; + tTris[tCounter] = 0 + tMod; + tCounter += 1; + tTris[tCounter] = 4 + tMod; + tCounter += 1; + tTris[tCounter] = 3 + tMod; + tCounter += 1; + tTris[tCounter] = 0 + tMod; + tCounter += 1; + //Left side: *** + tTris[tCounter] = 3 + tMod; + tCounter += 1; + tTris[tCounter] = 5 + tMod; + tCounter += 1; + tTris[tCounter] = 0 + tMod; + tCounter += 1; + tTris[tCounter] = 5 + tMod; + tCounter += 1; + tTris[tCounter] = 2 + tMod; + tCounter += 1; + tTris[tCounter] = 0 + tMod; + tCounter += 1; + //Right side: *** + tTris[tCounter] = 1 + tMod; + tCounter += 1; + tTris[tCounter] = 2 + tMod; + tCounter += 1; + tTris[tCounter] = 4 + tMod; + tCounter += 1; + tTris[tCounter] = 2 + tMod; + tCounter += 1; + tTris[tCounter] = 5 + tMod; + tCounter += 1; + tTris[tCounter] = 4 + tMod; + tCounter += 1; + } + //Back side: ** + tTris[tCounter] = cCount - 2; + tCounter += 1; + tTris[tCounter] = cCount - 1; + tCounter += 1; + tTris[tCounter] = cCount - 3; + tCounter += 1; + + return tTris; + } + + + private static int[] GetCollisionTris_Box(int MeshCount, int cTriCount, int cCount) + { + int tCounter = 0; + int[] tTris = new int[cTriCount * 3]; + + //Front side: *** + tTris[tCounter] = 0; + tCounter += 1; + tTris[tCounter] = 2; + tCounter += 1; + tTris[tCounter] = 1; + tCounter += 1; + tTris[tCounter] = 2; + tCounter += 1; + tTris[tCounter] = 3; + tCounter += 1; + tTris[tCounter] = 1; + tCounter += 1; + + int tMod = -1; + for (int index = 0; index < (MeshCount); index++) + { + tMod = (index * 4); + //Bottom side: *** + tTris[tCounter] = tMod + 1; + tCounter += 1; + tTris[tCounter] = tMod + 5; + tCounter += 1; + tTris[tCounter] = tMod + 0; + tCounter += 1; + tTris[tCounter] = tMod + 5; + tCounter += 1; + tTris[tCounter] = tMod + 4; + tCounter += 1; + tTris[tCounter] = tMod + 0; + tCounter += 1; + //Top side: *** + tTris[tCounter] = tMod + 2; + tCounter += 1; + tTris[tCounter] = tMod + 6; + tCounter += 1; + tTris[tCounter] = tMod + 3; + tCounter += 1; + tTris[tCounter] = tMod + 6; + tCounter += 1; + tTris[tCounter] = tMod + 7; + tCounter += 1; + tTris[tCounter] = tMod + 3; + tCounter += 1; + //Left side: *** + tTris[tCounter] = tMod + 4; + tCounter += 1; + tTris[tCounter] = tMod + 6; + tCounter += 1; + tTris[tCounter] = tMod + 0; + tCounter += 1; + tTris[tCounter] = tMod + 6; + tCounter += 1; + tTris[tCounter] = tMod + 2; + tCounter += 1; + tTris[tCounter] = tMod + 0; + tCounter += 1; + //Right side: *** + tTris[tCounter] = tMod + 1; + tCounter += 1; + tTris[tCounter] = tMod + 3; + tCounter += 1; + tTris[tCounter] = tMod + 5; + tCounter += 1; + tTris[tCounter] = tMod + 3; + tCounter += 1; + tTris[tCounter] = tMod + 7; + tCounter += 1; + tTris[tCounter] = tMod + 5; + tCounter += 1; + } + + //Back side: *** + tTris[tCounter] = cCount - 3; + tCounter += 1; + tTris[tCounter] = cCount - 1; + tCounter += 1; + tTris[tCounter] = cCount - 4; + tCounter += 1; + tTris[tCounter] = cCount - 1; + tCounter += 1; + tTris[tCounter] = cCount - 2; + tCounter += 1; + tTris[tCounter] = cCount - 4; + tCounter += 1; + + return tTris; + } + + + private static bool IsApproxTwoThirds(ref Vector3 V1, Vector3 V2, float Precision = 0.005f) + { + int cCount = 0; + if (GSDRootUtil.IsApproximately(V1.x, V2.x, Precision)) + { + cCount += 1; + } + if (GSDRootUtil.IsApproximately(V1.y, V2.y, Precision)) + { + cCount += 1; + } + if (GSDRootUtil.IsApproximately(V1.z, V2.z, Precision)) + { + cCount += 1; + } + + if (cCount == 2) + { + return true; + } + else + { + return false; + } + } + + + private static bool IsApproxWithNeg(ref Vector3 V1, ref Vector3 V2) + { + int cCount = 0; + bool bXMatch = false; + bool bYMatch = false; + bool bZMatch = false; + + if (GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) + { + cCount += 1; + bXMatch = true; + } + if (GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) + { + cCount += 1; + bYMatch = true; + } + if (GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) + { + cCount += 1; + bZMatch = true; + } + + if (cCount == 2) + { + if (!bXMatch && GSDRootUtil.IsApproximately(V1.x, V2.x * -1f, 0.02f)) + { + return true; + } + else if (!bYMatch && GSDRootUtil.IsApproximately(V1.y, V2.y * -1f, 0.02f)) + { + return true; + } + else if (!bZMatch && GSDRootUtil.IsApproximately(V1.z, V2.z * -1f, 0.02f)) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + + + private static bool V3EqualToNone(Vector3 V1) + { + if (!GSDRootUtil.IsApproximately(V1.x, 0f, 0.0001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.y, 0f, 0.0001f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.z, 0f, 0.0001f)) + { + return false; + } + return true; + } + + + private static bool V3EqualNormal(Vector3 V1, Vector3 V2) + { + if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.01f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.01f)) + { + return false; + } + if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.01f)) + { + return false; + } + return true; + } + + + private static bool IsApproxExtruded(ref Vector3 V1, ref Vector3 V2, bool bIsZAxis) + { + if (!GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) + { + return false; + } + + if (bIsZAxis) + { + if (!GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) + { + return false; + } + } + else + { + if (!GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) + { + return false; + } + } + + return true; + } + + + private static float GetVHeightAtXY(ref Vector3 tVect1, ref Vector3 tVect2, ref Vector3 tVect3) + { + Vector2 tVect2D1 = new Vector2(tVect1.x, tVect1.z); + Vector2 tVect2D2 = new Vector2(tVect2.x, tVect2.z); + Vector2 tVect2D3 = new Vector2(tVect3.x, tVect3.z); + + float tDist1 = Vector2.Distance(tVect2D1, tVect2D3); + float tDist2 = Vector2.Distance(tVect2D2, tVect2D3); + float tDistSum = tDist1 + tDist2; + + float CloseTo1 = (tDist1 / tDistSum); + + Vector3 tVect = ((tVect2 - tVect1) * CloseTo1) + tVect1; + + return tVect.y; + } + #endregion + + + public void Setup(bool bGetStrings = false, bool bCollect = true) + { +#if UNITY_EDITOR + GameObject[] tObj = new GameObject[5]; + try + { + SplinateMesh_Do(bGetStrings, ref tObj, bCollect); + } + catch (System.Exception exception) + { + if (tObj != null) + { + for (int index = 0; index < 5; index++) + { + if (tObj[index] != null) + { + Object.DestroyImmediate(tObj[index]); + } + } + } + throw exception; + } +#endif + } + + + private void SplinateMesh_Do(bool bGetStrings, ref GameObject[] ErrortObj, bool bCollect) + { +#if UNITY_EDITOR + bNeedsUpdate = false; + SetupUniqueIdentifier(); + + //Buffers: + Vector3 tVect1 = default(Vector3); + Vector3 tVect2 = default(Vector3); + Vector3 tDir = default(Vector3); + Vector3 xVect = default(Vector3); + // Vector3 oVect = default(Vector3); + // Quaternion tRot = default(Quaternion); + float tFloat1 = default(float); + // float tFloat2 = default(float); + // float tFloat3 = default(float); + // int tCount = -1; + + StartTime = tSpline.GetClosestParam(StartPos); + EndTime = tSpline.GetClosestParam(EndPos); + + if (EndTime < StartTime) + { + EndTime = tNode.NextTime; + EndPos = tSpline.GetSplineValue(EndTime, false); + } + if (EndTime > 0.99995f) + { + EndTime = 0.99995f; + EndPos = tSpline.GetSplineValue(EndTime, false); + } + + Kill(); + if (HorizontalCurve == null) + { + HorizontalCurve = new AnimationCurve(); + HorizontalCurve.AddKey(0f, 1f); + HorizontalCurve.AddKey(1f, 1f); + } + if (VerticalCurve == null) + { + VerticalCurve = new AnimationCurve(); + VerticalCurve.AddKey(0f, 1f); + VerticalCurve.AddKey(1f, 1f); + } + + // bool bIsLeft = false; + // if(HorizontalSep < 0f){ + // bIsLeft = true; + // } + + //Setup strings: + if (bGetStrings) + { + CurrentSplinationString = GSDRootUtil.GetPrefabString(CurrentSplination); + if (CurrentSplinationCap1 != null) + { + CurrentSplinationCap1String = GSDRootUtil.GetPrefabString(CurrentSplinationCap1); + } + if (CurrentSplinationCap2 != null) + { + CurrentSplinationCap2String = GSDRootUtil.GetPrefabString(CurrentSplinationCap2); + } + if (EndCapStart != null) + { + EndCapStartString = GSDRootUtil.GetPrefabString(EndCapStart); + } + if (EndCapEnd != null) + { + EndCapEndString = GSDRootUtil.GetPrefabString(EndCapEnd); + } + if (SplinatedMaterial1 != null) + { + SplinatedMaterial1String = UnityEditor.AssetDatabase.GetAssetPath(SplinatedMaterial1); + } + if (SplinatedMaterial2 != null) + { + SplinatedMaterial2String = UnityEditor.AssetDatabase.GetAssetPath(SplinatedMaterial2); + } + } + + if (CurrentSplination == null) + { + return; + } + GameObject tObj = (GameObject) GameObject.Instantiate(CurrentSplination); + ErrortObj[0] = tObj; + + GameObject EndCapStartObj = null; + GameObject EndCapEndObj = null; + if (EndCapStart != null) + { + EndCapStartObj = (GameObject) GameObject.Instantiate(EndCapStart); + ErrortObj[1] = EndCapStartObj; + } + if (EndCapEnd != null) + { + EndCapEndObj = (GameObject) GameObject.Instantiate(EndCapEnd); + ErrortObj[2] = EndCapEndObj; + } + + GameObject Cap1 = null; + GameObject Cap2 = null; + if (bFlipRotation) + { + if (CurrentSplinationCap2 != null) + { + Cap1 = (GameObject) GameObject.Instantiate(CurrentSplinationCap2); + ErrortObj[3] = Cap1; + } + if (CurrentSplinationCap1 != null) + { + Cap2 = (GameObject) GameObject.Instantiate(CurrentSplinationCap1); + ErrortObj[4] = Cap2; + } + } + else + { + if (CurrentSplinationCap1 != null) + { + Cap1 = (GameObject) GameObject.Instantiate(CurrentSplinationCap1); + ErrortObj[3] = Cap1; + } + if (CurrentSplinationCap2 != null) + { + Cap2 = (GameObject) GameObject.Instantiate(CurrentSplinationCap2); + ErrortObj[4] = Cap2; + } + } + + MeshFilter MF = null; + Mesh CapMesh1 = null; + Mesh CapMesh2 = null; + HashSet tCapMatchIndices1 = new HashSet(); + HashSet tCapMatchIndices2 = new HashSet(); + if (Cap1 != null) + { + MF = Cap1.GetComponent(); + CapMesh1 = MF.sharedMesh; + } + if (Cap2 != null) + { + MF = Cap2.GetComponent(); + CapMesh2 = MF.sharedMesh; + } + + MF = tObj.GetComponent(); + tMesh = MF.sharedMesh; + + // Quaternion OrigRot = tObj.transform.rotation; + if (bFlipRotation) + { + tVect1 = new Vector3(0f, 180f, 0f); + tObj.transform.Rotate(tVect1, Space.World); + if (Cap1 != null) + { + Cap1.transform.Rotate(tVect1, Space.World); + } + if (Cap2 != null) + { + Cap2.transform.Rotate(tVect1, Space.World); + } + } + tObj.transform.Rotate(CustomRotation, Space.World); + if (Cap1 != null) + { + Cap1.transform.Rotate(CustomRotation, Space.World); + } + if (Cap2 != null) + { + Cap2.transform.Rotate(CustomRotation, Space.World); + } + + if (tMesh == null) + { + GameObject.DestroyImmediate(tObj); + Debug.LogError("Mesh was null"); + return; + } + + Vector3[] CapOrigVerts1 = null; + Vector3[] CapOrigVerts2 = null; + int CapOrigMVL1 = 0; + int CapOrigMVL2 = 0; + if (CapMesh1 != null) + { + CapOrigVerts1 = CapMesh1.vertices; + CapOrigMVL1 = CapOrigVerts1.Length; + } + if (CapMesh2 != null) + { + CapOrigVerts2 = CapMesh2.vertices; + CapOrigMVL2 = CapOrigVerts2.Length; + } + + Vector3[] OrigVerts = tMesh.vertices; + int OrigMVL = OrigVerts.Length; + + //Transform vertices: + Vector3[] OrigNormals = tMesh.normals; + bool bCheckingNormal = true; + for (int index = 0; index < OrigMVL; index++) + { + OrigVerts[index] = tObj.transform.TransformPoint(OrigVerts[index]); + if (bCheckingNormal) + { + if (!V3EqualToNone(OrigNormals[index])) + { + bCheckingNormal = false; + } + } + } + //If no normals on base mesh, recalc them + if (bCheckingNormal) + { + tMesh.RecalculateNormals(); + OrigNormals = tMesh.normals; + } + //Cap mesh: + Vector3[] CapOrigNormals1 = null; + Vector3[] CapOrigNormals2 = null; + int[] CapOrigTris1 = null; + int[] CapOrigTris2 = null; + Vector2[] CapOrigUV1 = null; + Vector2[] CapOrigUV2 = null; + int CapTriCount1 = 0; + int CapTriCount2 = 0; + if (CapMesh1 != null) + { + for (int index = 0; index < CapOrigMVL1; index++) + { + CapOrigVerts1[index] = Cap1.transform.TransformPoint(CapOrigVerts1[index]); + } + + float[] oMinMaxX = new float[CapOrigMVL1]; + float[] oMinMaxY = new float[CapOrigMVL1]; + float[] oMinMaxZ = new float[CapOrigMVL1]; + for (int i = 0; i < CapOrigMVL1; i++) + { + oMinMaxX[i] = CapOrigVerts1[i].x; + oMinMaxY[i] = CapOrigVerts1[i].y; + oMinMaxZ[i] = CapOrigVerts1[i].z; + } + // float oMinX = Mathf.Min(oMinMaxX); + float oMaxX = Mathf.Max(oMinMaxX); + // float oMinY = Mathf.Min(oMinMaxY); + // float oMaxY = Mathf.Max(oMinMaxY); + // float oMinZ = Mathf.Min(oMinMaxZ); + float oMaxZ = Mathf.Max(oMinMaxZ); + + for (int index = 0; index < CapOrigMVL1; index++) + { + if (Axis == AxisTypeEnum.Z) + { + if (GSDRootUtil.IsApproximately(CapOrigVerts1[index].z, oMaxZ, MinMaxMod)) + { + tCapMatchIndices1.Add(index); + } + } + else + { + if (GSDRootUtil.IsApproximately(CapOrigVerts1[index].x, oMaxX, MinMaxMod)) + { + tCapMatchIndices1.Add(index); + } + } + } + + CapMesh1.RecalculateNormals(); + CapOrigTris1 = CapMesh1.triangles; + CapOrigUV1 = CapMesh1.uv; + CapTriCount1 = CapOrigTris1.Length; + CapOrigNormals1 = CapMesh1.normals; + } + if (CapMesh2 != null) + { + for (int index = 0; index < CapOrigMVL2; index++) + { + CapOrigVerts2[index] = Cap2.transform.TransformPoint(CapOrigVerts2[index]); + } + + float[] oMinMaxX = new float[CapOrigMVL2]; + float[] oMinMaxY = new float[CapOrigMVL2]; + float[] oMinMaxZ = new float[CapOrigMVL2]; + for (int index = 0; index < CapOrigMVL2; index++) + { + oMinMaxX[index] = CapOrigVerts2[index].x; + oMinMaxY[index] = CapOrigVerts2[index].y; + oMinMaxZ[index] = CapOrigVerts2[index].z; + } + float oMinX = Mathf.Min(oMinMaxX); + // float oMaxX = Mathf.Max(oMinMaxX); + // float oMinY = Mathf.Min(oMinMaxY); + // float oMaxY = Mathf.Max(oMinMaxY); + float oMinZ = Mathf.Min(oMinMaxZ); + // float oMaxZ = Mathf.Max(oMinMaxZ); + + for (int index = 0; index < CapOrigMVL2; index++) + { + if (Axis == AxisTypeEnum.Z) + { + if (GSDRootUtil.IsApproximately(CapOrigVerts2[index].z, oMinZ, MinMaxMod)) + { + tCapMatchIndices2.Add(index); + } + } + else + { + if (GSDRootUtil.IsApproximately(CapOrigVerts2[index].x, oMinX, MinMaxMod)) + { + tCapMatchIndices2.Add(index); + } + } + } + + CapMesh2.RecalculateNormals(); + CapOrigTris2 = CapMesh2.triangles; + CapOrigUV2 = CapMesh2.uv; + CapTriCount2 = CapOrigTris2.Length; + CapOrigNormals2 = CapMesh2.normals; + } + + int[] OrigTris = tMesh.triangles; + int OrigTriCount = OrigTris.Length; + Vector2[] OrigUV = tMesh.uv; + float[] tMinMax = new float[OrigMVL]; + float[] tMinMaxX = new float[OrigMVL]; + float[] tMinMaxY = new float[OrigMVL]; + float[] tMinMaxZ = new float[OrigMVL]; + float[] tMinMaxUV = null; + if (RepeatUVType != RepeatUVTypeEnum.None) + { + tMinMaxUV = new float[OrigMVL]; + } + for (int i = 0; i < OrigMVL; i++) + { + if (Axis == AxisTypeEnum.X) + { + tMinMax[i] = OrigVerts[i].x; + } + else + { + tMinMax[i] = OrigVerts[i].z; + } + tMinMaxX[i] = OrigVerts[i].x; + tMinMaxY[i] = OrigVerts[i].y; + tMinMaxZ[i] = OrigVerts[i].z; + if (RepeatUVType == RepeatUVTypeEnum.X) + { + tMinMaxUV[i] = OrigUV[i].x; + } + else if (RepeatUVType == RepeatUVTypeEnum.Y) + { + tMinMaxUV[i] = OrigUV[i].y; + } + } + + float mMax = Mathf.Max(tMinMax); + float mMin = Mathf.Min(tMinMax); + float mMaxX = Mathf.Max(tMinMaxX); + float mMinX = Mathf.Min(tMinMaxX); + float mMaxY = Mathf.Max(tMinMaxY); + float mMinY = Mathf.Min(tMinMaxY); + float mMaxZ = Mathf.Max(tMinMaxZ); + float mMinZ = Mathf.Min(tMinMaxZ); + float mMinUV = -1f; + float mMaxUV = -1f; + float mUVDiff = -1f; + if (RepeatUVType != RepeatUVTypeEnum.None) + { + mMinUV = Mathf.Min(tMinMaxUV); + mMaxUV = Mathf.Max(tMinMaxUV); + mUVDiff = mMaxUV - mMinUV; + } + float mMaxDiff = mMax - mMin; + float mMaxHeight = mMaxY - mMinY; + float mMaxThreshold = mMax - MinMaxMod; + float mMinThreshold = mMin + MinMaxMod; + List MinVectorIndices = new List(); + List MaxVectorIndices = new List(); + List MiddleVectorIndicies = new List(); + float tBuffer = 0f; + for (int index = 0; index < OrigMVL; index++) + { + if (Axis == AxisTypeEnum.X) + { + tBuffer = OrigVerts[index].x; + } + else + { + tBuffer = OrigVerts[index].z; + } + + if (tBuffer > mMaxThreshold) + { + MaxVectorIndices.Add(index); + } + else if (tBuffer < mMinThreshold) + { + MinVectorIndices.Add(index); + } + else + { + MiddleVectorIndicies.Add(index); + } + } + int MiddleCount = MiddleVectorIndicies.Count; + + //Match up min/max vertices: + Dictionary MatchingIndices = new Dictionary(); + Dictionary MatchingIndices_Min = new Dictionary(); + Dictionary> MatchingIndices_Min_Cap = new Dictionary>(); + Dictionary> MatchingIndices_Max_Cap = new Dictionary>(); + int tCount1 = MaxVectorIndices.Count; + int tCount2 = MinVectorIndices.Count; + int tIntBuffer1 = -1; + int tIntBuffer2 = -1; + int tIntBuffer3 = -1; + int tIntBuffer4 = -1; + // Dictionary UVStep = null; + // if(RepeatUVType != RepeatUVTypeEnum.None){ + // UVStep = new Dictionary(); + // } + List AlreadyAddedList = new List(); + for (int index = 0; index < tCount1; index++) + { + tIntBuffer1 = MaxVectorIndices[index]; + tVect1 = OrigVerts[tIntBuffer1]; + + bool bAdded = false; + for (int j = 0; j < OrigTriCount; j += 3) + { + if (OrigTris[j] == tIntBuffer1) + { + tIntBuffer3 = OrigTris[j + 1]; + tIntBuffer4 = OrigTris[j + 2]; + } + else if (OrigTris[j + 1] == tIntBuffer1) + { + tIntBuffer3 = OrigTris[j]; + tIntBuffer4 = OrigTris[j + 2]; + } + else if (OrigTris[j + 2] == tIntBuffer1) + { + tIntBuffer3 = OrigTris[j]; + tIntBuffer4 = OrigTris[j + 1]; + } + else + { + continue; + } + if (MinVectorIndices.Contains(tIntBuffer3)) + { + for (int k = 0; k < tCount2; k++) + { + tIntBuffer2 = MinVectorIndices[k]; + if (tIntBuffer2 == tIntBuffer3) + { + if (AlreadyAddedList.Contains(tIntBuffer2)) + { + break; + } + if (IsApproxTwoThirds(ref tVect1, OrigVerts[tIntBuffer2], VertexMatchingPrecision)) + { + MatchingIndices.Add(tIntBuffer1, tIntBuffer2); + AlreadyAddedList.Add(tIntBuffer2); + MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); + bAdded = true; + break; + } + } + } + } + if (!bAdded && MinVectorIndices.Contains(tIntBuffer4)) + { + for (int k = 0; k < tCount2; k++) + { + tIntBuffer2 = MinVectorIndices[k]; + if (tIntBuffer2 == tIntBuffer4) + { + if (AlreadyAddedList.Contains(tIntBuffer2)) + { + break; + } + if (IsApproxTwoThirds(ref tVect1, OrigVerts[tIntBuffer2], VertexMatchingPrecision)) + { + MatchingIndices.Add(tIntBuffer1, tIntBuffer2); + AlreadyAddedList.Add(tIntBuffer2); + MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); + bAdded = true; + break; + } + } + } + } + if (bAdded) + { + break; + } + } + } + + //Tris don't match, so need further refinement: + if (MatchingIndices.Count < MaxVectorIndices.Count) + { + bool bIsZAxis = (Axis == AxisTypeEnum.Z); + for (int index = 0; index < tCount1; index++) + { + tIntBuffer1 = MaxVectorIndices[index]; + if (MatchingIndices.ContainsKey(tIntBuffer1)) + { + continue; + } + tVect1 = OrigVerts[tIntBuffer1]; + if (Axis == AxisTypeEnum.Z) + { + for (int j = 0; j < tCount2; j++) + { + tIntBuffer2 = MinVectorIndices[j]; + if (!AlreadyAddedList.Contains(tIntBuffer2)) + { + tVect2 = OrigVerts[tIntBuffer2]; + if (IsApproxExtruded(ref tVect1, ref tVect2, bIsZAxis) && V3EqualNormal(OrigNormals[tIntBuffer1], OrigNormals[tIntBuffer2])) + { + MatchingIndices.Add(tIntBuffer1, tIntBuffer2); + AlreadyAddedList.Add(tIntBuffer2); + MatchingIndices_Min.Add(tIntBuffer2, tIntBuffer1); + break; + } + } + } + } + } + } + + //Caps: + if (CapMesh1 != null) + { + bool bDidAdd = false; + foreach (KeyValuePair KVP in MatchingIndices_Min) + { + List tList = new List(); + tVect1 = OrigVerts[KVP.Key]; + for (int index = 0; index < CapOrigMVL1; index++) + { + if (tCapMatchIndices1.Contains(index) && IsApproxTwoThirds(ref tVect1, CapOrigVerts1[index], VertexMatchingPrecision)) + { + tList.Add(index); + bDidAdd = true; + } + } + MatchingIndices_Min_Cap.Add(KVP.Key, tList); + } + if (!bDidAdd) + { + try + { + Debug.LogWarning("Start cap error (still processing extrusion, ignoring start cap). No matching vertices found for start cap. Most likely the cap mesh is aligned improperly or along the wrong axis relative to the main mesh."); + } + catch + { + + } + if (Cap1 != null) + { + Object.DestroyImmediate(Cap1); + } + CapMesh1 = null; + CapOrigMVL1 = 0; + CapTriCount1 = 0; + } + } + if (CapMesh2 != null) + { + bool bDidAdd = false; + foreach (KeyValuePair KVP in MatchingIndices) + { + List tList = new List(); + tVect1 = OrigVerts[KVP.Key]; + for (int index = 0; index < CapOrigMVL2; index++) + { + if (tCapMatchIndices2.Contains(index) && IsApproxTwoThirds(ref tVect1, CapOrigVerts2[index], VertexMatchingPrecision)) + { + tList.Add(index); + bDidAdd = true; + } + } + MatchingIndices_Max_Cap.Add(KVP.Key, tList); + } + if (!bDidAdd) + { + try + { + Debug.LogError("End cap error (still processing extrusion, ignoring end cap). No matching vertices found for end cap. Most likely the cap mesh is aligned improperly or along the wrong axis relative to the main mesh."); + } + catch + { + + } + if (Cap2 != null) + { + Object.DestroyImmediate(Cap2); + } + CapMesh2 = null; + CapOrigMVL2 = 0; + CapTriCount2 = 0; + } + } + + //Road definition matching: + if (bMatchRoadDefinition) + { + float RoadDefStart = (tSpline.tRoad.opt_RoadDefinition / 2f) * -1; + float UVChange = tSpline.tRoad.opt_RoadDefinition / mMaxDiff; + foreach (KeyValuePair KVP in MatchingIndices) + { + //Vertex change: + if (Axis == AxisTypeEnum.X) + { + OrigVerts[KVP.Value].x = RoadDefStart; + OrigVerts[KVP.Key].x = (OrigVerts[KVP.Value].x + tSpline.tRoad.opt_RoadDefinition); + } + else if (Axis == AxisTypeEnum.Z) + { + OrigVerts[KVP.Value].z = RoadDefStart; + OrigVerts[KVP.Key].z = (OrigVerts[KVP.Value].z + tSpline.tRoad.opt_RoadDefinition); + } + //UV Change: + if (RepeatUVType == RepeatUVTypeEnum.X) + { + OrigUV[KVP.Key].x *= UVChange; + } + else if (RepeatUVType == RepeatUVTypeEnum.Y) + { + OrigUV[KVP.Key].y *= UVChange; + } + } + + //Settings: + tMinMaxUV = new float[OrigMVL]; + tMinMax = new float[OrigMVL]; + tMinMaxX = new float[OrigMVL]; + tMinMaxY = new float[OrigMVL]; + tMinMaxZ = new float[OrigMVL]; + for (int index = 0; index < OrigMVL; index++) + { + if (Axis == AxisTypeEnum.X) + { + tMinMax[index] = OrigVerts[index].x; + } + else + { + tMinMax[index] = OrigVerts[index].z; + } + tMinMaxX[index] = OrigVerts[index].x; + tMinMaxY[index] = OrigVerts[index].y; + tMinMaxZ[index] = OrigVerts[index].z; + if (RepeatUVType == RepeatUVTypeEnum.X) + { + tMinMaxUV[index] = OrigUV[index].x; + } + else if (RepeatUVType == RepeatUVTypeEnum.Y) + { + tMinMaxUV[index] = OrigUV[index].y; + } + } + //UV Changes: + mMax = Mathf.Max(tMinMax); + mMin = Mathf.Min(tMinMax); + mMaxX = Mathf.Max(tMinMaxX); + mMinX = Mathf.Min(tMinMaxX); + mMaxY = Mathf.Max(tMinMaxY); + mMinY = Mathf.Min(tMinMaxY); + mMaxZ = Mathf.Max(tMinMaxZ); + mMinZ = Mathf.Min(tMinMaxZ); + mMinUV = -1f; + mMaxUV = -1f; + mUVDiff = -1f; + if (RepeatUVType != RepeatUVTypeEnum.None) + { + mMinUV = Mathf.Min(tMinMaxUV); + mMaxUV = Mathf.Max(tMinMaxUV); + mUVDiff = mMaxUV - mMinUV; + } + mMaxDiff = mMax - mMin; + mMaxHeight = mMaxY - mMinY; + mMaxThreshold = mMax - MinMaxMod; + mMinThreshold = mMin + MinMaxMod; + } + + //For vert reverse cut: + int VertCutTriIndex1 = -1; + int VertCutTriIndex2 = -1; + if (bVerticalMeshCutoff_OppositeDir) + { + float[] tMatchingMaxY = new float[MatchingIndices.Count]; + int tempcount141 = 0; + foreach (KeyValuePair KVP in MatchingIndices) + { + tMatchingMaxY[tempcount141] = OrigVerts[KVP.Key].y; + tempcount141 += 1; + } + + float tMatchingMaxY_f = Mathf.Max(tMatchingMaxY); + foreach (KeyValuePair KVP in MatchingIndices) + { + if (GSDRootUtil.IsApproximately(OrigVerts[KVP.Key].y, tMatchingMaxY_f, 0.0001f)) + { + VertCutTriIndex1 = KVP.Key; + VertCutTriIndex2 = KVP.Value; + break; + } + } + } + + + //Set auto simple collision points: + if (bSimpleCollisionAutomatic) + { + if (Axis == AxisTypeEnum.X) + { + CollisionTriBL = new Vector3(mMinX, mMinY, mMinZ); + CollisionTriBR = new Vector3(mMinX, mMinY, mMaxZ); + CollisionTriT = new Vector3(mMinX, mMaxY, ((mMaxZ - mMinZ) * 0.5f) + mMinZ); + } + else if (Axis == AxisTypeEnum.Z) + { + CollisionTriBL = new Vector3(mMinX, mMinY, mMinZ); + CollisionTriBR = new Vector3(mMaxX, mMinY, mMinZ); + CollisionTriT = new Vector3(((mMaxX - mMinX) * 0.5f) + mMinX, mMaxY, mMinZ); + } + + if (Axis == AxisTypeEnum.X) + { + CollisionBoxBL = new Vector3(mMinX, mMinY, mMinZ); + CollisionBoxBR = new Vector3(mMinX, mMinY, mMaxZ); + CollisionBoxTL = new Vector3(mMinX, mMaxY, mMinZ); + CollisionBoxTR = new Vector3(mMinX, mMaxY, mMaxZ); + } + else if (Axis == AxisTypeEnum.Z) + { + CollisionBoxBL = new Vector3(mMinX, mMinY, mMinZ); + CollisionBoxBR = new Vector3(mMaxX, mMinY, mMinZ); + CollisionBoxTL = new Vector3(mMinX, mMaxY, mMinZ); + CollisionBoxTR = new Vector3(mMaxX, mMaxY, mMinZ); + } + } + + Vector3[] tVerts = null; + Vector2[] tUV = null; + + //Get the vector series that this mesh is interpolated on: + List tTimes = new List(); + float cTime = StartTime; + + + tTimes.Add(cTime); + int SpamGuard = 5000; + int SpamGuardCounter = 0; + float pDiffTime = EndTime - StartTime; + float CurrentH = 0f; + float fHeight = 0f; + // Vector3 tStartPos = tSpline.GetSplineValue(StartTime); + // Vector3 tEndPos = tSpline.GetSplineValue(EndTime); + + while (cTime < EndTime && SpamGuardCounter < SpamGuard) + { + tSpline.GetSplineValue_Both(cTime, out tVect1, out tDir); + fHeight = HorizontalCurve.Evaluate((cTime - StartTime) / pDiffTime); + CurrentH = fHeight * HorizontalSep; + + if (CurrentH < 0f) + { + CurrentH *= -1f; + tVect1 = (tVect1 + new Vector3(CurrentH * -tDir.normalized.z, 0, CurrentH * tDir.normalized.x)); + } + else if (CurrentH > 0f) + { + tVect1 = (tVect1 + new Vector3(CurrentH * tDir.normalized.z, 0, CurrentH * -tDir.normalized.x)); + } + + xVect = (tDir.normalized * mMaxDiff) + tVect1; + + cTime = tSpline.GetClosestParam(xVect, false, false); + if (cTime > EndTime) + { + cTime = EndTime; + } + tTimes.Add(cTime); + SpamGuardCounter += 1; + } + if (bTrimStart) + { + tTimes.RemoveAt(0); + } + else if (bTrimEnd) + { + tTimes.RemoveAt(tTimes.Count - 1); + } + int vSeriesCount = tTimes.Count; + + //Dynamic vertical and horiz: + List DynamicVerticalRaise = null; + List DynamicHoriz = null; + DynamicVerticalRaise = new List(); + DynamicHoriz = new List(); + float tStartTime = tTimes[0]; + float tEndTime = tTimes[vSeriesCount - 1]; + // float tDiffTime = tEndTime - tStartTime; + // float cDiff = 0f; + + float jDistance = 0f; + float jStartDistance = tSpline.TranslateParamToDist(tStartTime); + float jEndDistance = tSpline.TranslateParamToDist(tEndTime); + float jDistanceDiff = jEndDistance - jStartDistance; + // float jLastTime = 0f; + float jCurrTime = 0f; + // float jStep = 0.02f / tSpline.distance; + // Vector3 jVect1 = default(Vector3); + // Vector3 jVect2 = default(Vector3); + // float prevFHeight = 0f; + // bool basfsafa = false; + for (int i = 0; i < vSeriesCount; i++) + { + // cDiff = tTimes[i] - tStartTime; + // cDiff = cDiff / tDiffTime; + + //Vertical curve: + if (VerticalCurve.keys == null || VerticalCurve.length < 1) + { + fHeight = 1f; + } + else + { + jDistance = tSpline.TranslateParamToDist(tTimes[i]); + jCurrTime = (jDistance - jStartDistance) / jDistanceDiff; + fHeight = VerticalCurve.Evaluate(jCurrTime); + } + DynamicVerticalRaise.Add(fHeight); + + //Horizontal curve: + if (HorizontalCurve.keys == null || HorizontalCurve.length < 1) + { + fHeight = 1f; + } + else + { + fHeight = HorizontalCurve.Evaluate(jCurrTime); + } + DynamicHoriz.Add(fHeight); + } + + Vector3[] VectorSeries = new Vector3[vSeriesCount]; + Vector3[] VectorSeriesTangents = new Vector3[vSeriesCount]; + // bool bIsCenter = GSDRootUtil.IsApproximately(HorizontalSep,0f,0.02f); + float tIntStrength = 0f; + float tIntHeight = 0f; + GSDRoadIntersection GSDRI = null; + bool bIsPastInter = false; + GSDSplineN xNode = null; + List tOrigHeights = new List(); + + // List xTerrains = null; + // List tTerrainRects = null; + // int TerrainCount = 0; + // if(bMatchTerrain){ + // tTerrainRects = new List(); + // xTerrains = new List(); + // Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); + // GSD.Roads.GSDRoadUtil.Construction2DRect tTerrainRect = null; + // Vector2 tPos2D = default(Vector2); + // Vector2 P1,P2,P3,P4; + // foreach(Terrain xTerrain in tTerrains){ + // tPos2D = new Vector2(xTerrain.transform.position.x,xTerrain.transform.position.z); + // P1 = new Vector2(0f,0f) + tPos2D; + // P2 = new Vector2(0f,xTerrain.terrainData.size.y) + tPos2D; + // P3 = new Vector2(xTerrain.terrainData.size.x,xTerrain.terrainData.size.y) + tPos2D; + // P4 = new Vector2(xTerrain.terrainData.size.x,0f) + tPos2D; + // tTerrainRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(P1,P2,P3,P4,xTerrain.transform.position.y); + // tTerrainRects.Add(tTerrainRect); + // xTerrains.Add(xTerrain); + // TerrainCount+=1; + // } + // } + + // Vector2 temp2DVect = default(Vector2); + Ray tRay = default(Ray); + RaycastHit[] tRayHit = null; + float[] tRayYs = null; + for (int i = 0; i < vSeriesCount; i++) + { + cTime = tTimes[i]; + tSpline.GetSplineValue_Both(cTime, out tVect1, out tVect2); + tOrigHeights.Add(tVect1.y); + + //Horizontal offset: + CurrentH = DynamicHoriz[i] * HorizontalSep; + + if (CurrentH < 0f) + { + CurrentH *= -1f; + tVect1 = (tVect1 + new Vector3(CurrentH * -tVect2.normalized.z, 0, CurrentH * tVect2.normalized.x)); + } + else if (CurrentH > 0f) + { + tVect1 = (tVect1 + new Vector3(CurrentH * tVect2.normalized.z, 0, CurrentH * -tVect2.normalized.x)); + } + + tIntStrength = tSpline.IntersectionStrength(ref tVect1, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref cTime, ref xNode); + + if (GSDRootUtil.IsApproximately(tIntStrength, 1f, 0.0001f)) + { + tVect1.y = tIntHeight; + } + else if (!GSDRootUtil.IsApproximately(tIntStrength, 0f, 0.001f)) + { + tVect1.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect1.y); + } + + //Terrain matching: + if (bMatchTerrain) + { + // temp2DVect = new Vector2(tVect1.x,tVect1.z); + // for(int j=0;j 0) + { + tRayYs = new float[tRayHit.Length]; + for (int g = 0; g < tRayHit.Length; g++) + { + tRayYs[g] = tRayHit[g].point.y; + } + tVect1.y = Mathf.Max(tRayYs); + } + } + + tVect1.y += (DynamicVerticalRaise[i] * VerticalRaise); + + VectorSeries[i] = tVect1; + VectorSeriesTangents[i] = tVect2; + } + int MeshCount = (vSeriesCount - 1); + + // float yDiff = 0f; + // float tDistance = 0f; + int MVL = MeshCount * OrigMVL; +#if UNITY_2017_3_OR_NEWER + if (MVL > 4000000) + { + throw new System.Exception("Over 4000000 vertices detected, exiting extrusion. Try switching splination axis and make sure your imported FBX file has proper import scale. Make sure the mesh isn't too small and make sure the distance isn't too large."); + } +#else + if(MVL > 64900){ + throw new System.Exception("Over 65000 vertices detected, exiting extrusion. Try switching splination axis and make sure your imported FBX file has proper import scale. Make sure the mesh isn't too small and make sure the distance isn't too large."); + } +#endif + int MaxCount = MaxVectorIndices.Count; + int MinCount = MinVectorIndices.Count; + int TriCount = MeshCount * OrigTriCount; + // int MatchCount = MatchingIndices.Count; + tVerts = new Vector3[MVL]; + tUV = new Vector2[MVL]; + int[] tTris = new int[TriCount]; + Vector3[] tNormals = new Vector3[MVL]; + int vManuver = 0; + int vManuver_Prev = 0; + int TriManuver = 0; + Vector3[] cVerts = null; + int[] cTris = null; + int cCount = -1; + int cTriCount = -1; + bool bSimpleCollisionOn = false; + float tOrigHeightBuffer = 0f; + float tFloat5 = 0f; + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts = new Vector3[3 * (MeshCount + 1)]; + cCount = cVerts.Length; + cTriCount = (6 * cCount) + 2; + bSimpleCollisionOn = true; + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts = new Vector3[4 * (MeshCount + 1)]; + cCount = cVerts.Length; + cTriCount = (8 * cCount) + 4; + bSimpleCollisionOn = true; + } + + // List tTriList = null; + // GSD.Roads.GSDRoadUtil.Construction3DTri VertOppCutTri = null; + // int VertCutBufferIndex1 = -1; + // int VertCutBufferIndex2 = -1; + Vector3 VertCutBuffer1 = default(Vector3); + Vector3 VertCutBuffer2 = default(Vector3); + Vector3 VertCutBuffer3 = default(Vector3); + float tOrigHeightBuffer_Orig = 0f; + // if(bVerticalMeshCutoff_OppositeDir){ + // tTriList = new List(); + // } + + if (bIsStretch) + { + DoStretch(ref OrigVerts, ref OrigUV, ref OrigTris, ref MaxVectorIndices, ref MinVectorIndices, mMaxDiff, out tVerts, out tUV, out tNormals, out tTris); + goto StretchSkip; + } + + //Main loop: + Matrix4x4 tMatrix = new Matrix4x4(); + for (int j = 0; j < MeshCount; j++) + { + TriManuver = j * OrigTriCount; + vManuver = j * OrigMVL; + vManuver_Prev = (j - 1) * OrigMVL; + + if (!bIsStretch) + { + tVect1 = VectorSeries[j]; + tVect2 = VectorSeries[j + 1]; + } + + // yDiff = tVect2.y - tVect1.y; + // tDistance = Vector3.Distance(tVect1,tVect2); + + // if(j==0){ tStartPos = tVect1; } + // if(j==(MeshCount-1)){ tEndPos = tVect1; } + + if (bExactSplination && MiddleCount < 2) + { + tDir = (tVect2 - tVect1).normalized; + } + else + { + tDir = VectorSeriesTangents[j].normalized; + } + + tOrigHeightBuffer = tOrigHeights[j] + VerticalCutoff; + tOrigHeightBuffer_Orig = tOrigHeights[j]; + tMatrix.SetTRS(tVect1, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); + + //Rotate and set vertex positions: + for (int index = 0; index < OrigMVL; index++) + { + xVect = OrigVerts[index]; + tVerts[vManuver + index] = tMatrix.MultiplyPoint3x4(xVect); + // tVerts[vManuver+i] = (Quaternion.LookRotation(tDir)*xVect) + tVect1; + + //UV: + tUV[vManuver + index] = OrigUV[index]; + + //Vertical cutoff: + if (bVerticalCutoff) + { + if (MiddleVectorIndicies.Contains(index)) + { + tFloat5 = tVerts[vManuver + index].y; + if (bVerticalCutoffDownwards) + { + if (bVerticalCutoff_MatchZero) + { + if (tFloat5 < tOrigHeightBuffer_Orig) + { + tVerts[vManuver + index].y = tOrigHeightBuffer_Orig; + } + } + else + { + if (tFloat5 < tOrigHeightBuffer) + { + tVerts[vManuver + index].y = tOrigHeightBuffer; + } + } + + tFloat1 = (tOrigHeightBuffer_Orig - tOrigHeightBuffer) / mMaxHeight; + tUV[vManuver + index].x *= tFloat1; + + } + else + { + if (bVerticalCutoff_MatchZero) + { + if (tFloat5 > tOrigHeightBuffer_Orig) + { + tVerts[vManuver + index].y = tOrigHeightBuffer_Orig; + } + } + else + { + if (tFloat5 > tOrigHeightBuffer) + { + tVerts[vManuver + index].y = tOrigHeightBuffer; + } + } + + tFloat1 = (tOrigHeightBuffer - tOrigHeightBuffer_Orig) / mMaxHeight; + tUV[vManuver + index].x *= tFloat1; + } + } + } + } + + if (RepeatUVType != RepeatUVTypeEnum.None) + { + for (int index = 0; index < MaxCount; index++) + { + tIntBuffer1 = MaxVectorIndices[index]; + if (RepeatUVType == RepeatUVTypeEnum.X) + { + tUV[vManuver + tIntBuffer1].x = mUVDiff * (j + 1); + } + else + { + tUV[vManuver + tIntBuffer1].y = mUVDiff * (j + 1); + } + } + for (int index = 0; index < MinCount; index++) + { + tIntBuffer1 = MinVectorIndices[index]; + if (RepeatUVType == RepeatUVTypeEnum.X) + { + tUV[vManuver + tIntBuffer1].x = mUVDiff * j; + } + else + { + tUV[vManuver + tIntBuffer1].y = mUVDiff * j; + } + } + } + + //Simple collision (triangle or trap): + if (bSimpleCollisionOn) + { + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts[0 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBL); + cVerts[1 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBR); + cVerts[2 + (j * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriT); + + // cVerts[0+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriBL) + tVect1; + // cVerts[1+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriBR) + tVect1; + // cVerts[2+(j*3)] = (Quaternion.LookRotation(tDir)*CollisionTriT) + tVect1; + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts[0 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBL); + cVerts[1 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBR); + cVerts[2 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTL); + cVerts[3 + (j * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTR); + + // cVerts[0+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxBL) + tVect1; + // cVerts[1+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxBR) + tVect1; + // cVerts[2+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxTL) + tVect1; + // cVerts[3+(j*4)] = (Quaternion.LookRotation(tDir)*CollisionBoxTR) + tVect1; + } + + if (j == (MeshCount - 1)) + { + Vector3 tAdd = default(Vector3); + if (Axis == AxisTypeEnum.X) + { + tAdd = new Vector3(mMaxDiff * -1f, 0f, 0f); + } + else + { + tAdd = new Vector3(0f, 0f, mMaxDiff); + } + + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts[0 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBL + tAdd); + cVerts[1 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriBR + tAdd); + cVerts[2 + ((j + 1) * 3)] = tMatrix.MultiplyPoint3x4(CollisionTriT + tAdd); + + // cVerts[0+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriBL + tAdd)) + tVect1; + // cVerts[1+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriBR + tAdd)) + tVect1; + // cVerts[2+((j+1)*3)] = (Quaternion.LookRotation(tDir)*(CollisionTriT + tAdd)) + tVect1; + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts[0 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBL + tAdd); + cVerts[1 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxBR + tAdd); + cVerts[2 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTL + tAdd); + cVerts[3 + ((j + 1) * 4)] = tMatrix.MultiplyPoint3x4(CollisionBoxTR + tAdd); + + // cVerts[0+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxBL + tAdd)) + tVect1; + // cVerts[1+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxBR + tAdd)) + tVect1; + // cVerts[2+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxTL + tAdd)) + tVect1; + // cVerts[3+((j+1)*4)] = (Quaternion.LookRotation(tDir)*(CollisionBoxTR + tAdd)) + tVect1; + } + } + } + + //If j > 0, the previous max vects need to match current min vects: + Vector3 mVect = default(Vector3); + if (j > 0) + { + // foreach(KeyValuePair KVP in MatchingIndices){ + // tNormals[vManuver+KVP.Key] = tNormals[KVP.Value]; + // } + foreach (KeyValuePair KVP in MatchingIndices_Min) + { + mVect = tVerts[vManuver + KVP.Key] - tVerts[vManuver_Prev + KVP.Value]; + tVerts[vManuver + KVP.Key] = tVerts[vManuver_Prev + KVP.Value]; + } + + for (int g = 0; g < MinVectorIndices.Count; g++) + { + if (!MatchingIndices_Min.ContainsKey(MinVectorIndices[g])) + { + tVerts[vManuver + MinVectorIndices[g]] -= mVect; + } + } + + //Simple collision (triangle or trap): + if (bSimpleCollisionOn) + { + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts[0 + (j * 3)] -= mVect; + cVerts[1 + (j * 3)] -= mVect; + cVerts[2 + (j * 3)] -= mVect; + + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts[0 + (j * 4)] -= mVect; + cVerts[1 + (j * 4)] -= mVect; + cVerts[2 + (j * 4)] -= mVect; + cVerts[3 + (j * 4)] -= mVect; + } + } + } + + //Triangles: + for (int index = 0; index < OrigTriCount; index++) + { + tTris[index + TriManuver] = OrigTris[index] + vManuver; + } + + //Vert cut reverse: + if (bVerticalCutoff) + { + if (bVerticalMeshCutoff_OppositeDir) + { + VertCutBuffer1 = tVerts[vManuver + VertCutTriIndex1]; + VertCutBuffer2 = tVerts[vManuver + VertCutTriIndex2]; + + for (int index = 0; index < MiddleCount; index++) + { + VertCutBuffer3 = tVerts[vManuver + MiddleVectorIndicies[index]]; + + if (!bVerticalCutoffDownwards) + { + tBuffer = GetVHeightAtXY(ref VertCutBuffer1, ref VertCutBuffer2, ref VertCutBuffer3) + VerticalMeshCutoffOffset; + if (VertCutBuffer3.y < tBuffer) + { + tVerts[vManuver + MiddleVectorIndicies[index]].y = tBuffer; + } + } + else + { + tBuffer = GetVHeightAtXY(ref VertCutBuffer1, ref VertCutBuffer2, ref VertCutBuffer3) - VerticalMeshCutoffOffset; + if (VertCutBuffer3.y > tBuffer) + { + tVerts[vManuver + MiddleVectorIndicies[index]].y = tBuffer; + } + } + } + } + } + + + //Ending push down: + if (bStartDown) + { + tFloat1 = mMaxHeight * 1.05f; + if (bStartTypeDownOverride) + { + tFloat1 = StartTypeDownOverride; + } + if (j == 0) + { + for (int index = 0; index < MinCount; index++) + { + tIntBuffer1 = MinVectorIndices[index]; + tVerts[vManuver + tIntBuffer1].y -= tFloat1; + } + + float tTotalDistDown = 0f; + Vector3 pVect1 = default(Vector3); + Vector3 pVect2 = default(Vector3); + foreach (KeyValuePair KVP in MatchingIndices) + { + pVect1 = tVerts[vManuver + KVP.Key]; + pVect2 = tVerts[vManuver + KVP.Value]; + tTotalDistDown = Vector3.Distance(pVect1, pVect2); + break; + } + + for (int index = 0; index < MiddleCount; index++) + { + tIntBuffer1 = MiddleVectorIndicies[index]; + float tDistTo1 = Vector3.Distance(tVerts[vManuver + tIntBuffer1], pVect1); + tVerts[vManuver + tIntBuffer1].y -= (tFloat1 * (tDistTo1 / tTotalDistDown)); + } + + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts[0 + (j * 3)].y -= tFloat1; + cVerts[1 + (j * 3)].y -= tFloat1; + cVerts[2 + (j * 3)].y -= tFloat1; + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts[0 + (j * 4)].y -= tFloat1; + cVerts[1 + (j * 4)].y -= tFloat1; + cVerts[2 + (j * 4)].y -= tFloat1; + cVerts[3 + (j * 4)].y -= tFloat1; + } + } + } + + if (bEndDown) + { + tFloat1 = mMaxHeight * 1.05f; + if (bEndTypeDownOverride) + { + tFloat1 = EndTypeDownOverride; + } + if (j == (MeshCount - 1)) + { + for (int index = 0; index < MaxCount; index++) + { + tIntBuffer1 = MaxVectorIndices[index]; + tVerts[vManuver + tIntBuffer1].y -= tFloat1; + } + + float tTotalDistDown = 0f; + Vector3 pVect1 = default(Vector3); + Vector3 pVect2 = default(Vector3); + foreach (KeyValuePair KVP in MatchingIndices) + { + pVect1 = tVerts[vManuver + KVP.Key]; + pVect2 = tVerts[vManuver + KVP.Value]; + tTotalDistDown = Vector3.Distance(pVect1, pVect2); + break; + } + + for (int i = 0; i < MiddleCount; i++) + { + tIntBuffer1 = MiddleVectorIndicies[i]; + float tDistTo1 = Vector3.Distance(tVerts[vManuver + tIntBuffer1], pVect2); + tVerts[vManuver + tIntBuffer1].y -= (tFloat1 * (tDistTo1 / tTotalDistDown)); + } + + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cVerts[0 + ((j + 1) * 3)].y -= tFloat1; + cVerts[1 + ((j + 1) * 3)].y -= tFloat1; + cVerts[2 + ((j + 1) * 3)].y -= tFloat1; + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cVerts[0 + ((j + 1) * 4)].y -= tFloat1; + cVerts[1 + ((j + 1) * 4)].y -= tFloat1; + cVerts[2 + ((j + 1) * 4)].y -= tFloat1; + cVerts[3 + ((j + 1) * 4)].y -= tFloat1; + } + } + } + + //Ending objects: + if (j == 0 && EndCapStartObj != null) + { + if (bEndCapCustomMatchStart && MinVectorIndices.Count > 0) + { + Vector3[] bVerts = new Vector3[MinVectorIndices.Count]; + for (int g = 0; g < MinVectorIndices.Count; g++) + { + bVerts[g] = tVerts[vManuver + MinVectorIndices[g]]; + } + Vector3 tVect5 = GetVector3Average(bVerts); + Vector3 tVect6 = tSpline.GetSplineValue(tSpline.GetClosestParam(tVect5, false, false), false); + tVect5.y = tVect6.y; + EndCapStartObj.transform.position = tVect5; + } + else + { + EndCapStartObj.transform.position = tVect1; + } + + if (bEndObjectsMatchGround) + { + tRay = default(Ray); + tRayHit = null; + float tHitY = 0f; + // int tHitIndex = 0; + Vector3 HitVect = EndCapStartObj.transform.position; + tRay = new Ray(HitVect + new Vector3(0f, 1f, 0f), Vector3.down); + tRayHit = Physics.RaycastAll(tRay); + if (tRayHit.Length > 0) + { + tRayYs = new float[tRayHit.Length]; + for (int g = 0; g < tRayHit.Length; g++) + { + if (g == 0) + { + tHitY = tRayHit[g].point.y; + // tHitIndex=0; + } + else + { + if (tRayHit[g].point.y > tHitY) + { + tHitY = tRayHit[g].point.y; + // tHitIndex = g; + } + } + } + HitVect.y = tHitY; + EndCapStartObj.transform.position = HitVect; + } + } + EndCapStartObj.transform.rotation = Quaternion.LookRotation(tDir); + EndCapStartObj.transform.Rotate(EndCapCustomRotOffsetStart, Space.World); + EndCapStartObj.transform.position += EndCapCustomOffsetStart; + + } + else if (j == (MeshCount - 1) && EndCapEndObj != null) + { + if (bEndCapCustomMatchStart && MaxVectorIndices.Count > 0) + { + Vector3[] bVerts = new Vector3[MaxVectorIndices.Count]; + for (int g = 0; g < MaxVectorIndices.Count; g++) + { + bVerts[g] = tVerts[vManuver + MaxVectorIndices[g]]; + } + Vector3 tVect5 = GetVector3Average(bVerts); + Vector3 tVect6 = tSpline.GetSplineValue(tSpline.GetClosestParam(tVect5, false, false), false); + if (!float.IsNaN(tVect6.y)) + { + tVect5.y = tVect6.y; + } + EndCapEndObj.transform.position = tVect5; + } + else + { + EndCapEndObj.transform.position = tVect2; + } + + if (bEndObjectsMatchGround) + { + tRay = default(Ray); + tRayHit = null; + float tHitY = 0f; + // int tHitIndex = 0; + Vector3 HitVect = EndCapEndObj.transform.position; + tRay = new Ray(HitVect + new Vector3(0f, 1f, 0f), Vector3.down); + tRayHit = Physics.RaycastAll(tRay); + + if (tRayHit.Length > 0) + { + tRayYs = new float[tRayHit.Length]; + for (int g = 0; g < tRayHit.Length; g++) + { + if (g == 0) + { + tHitY = tRayHit[g].point.y; + // tHitIndex=0; + } + else + { + if (tRayHit[g].point.y > tHitY) + { + tHitY = tRayHit[g].point.y; + // tHitIndex = g; + } + } + } + HitVect.y = tHitY; + EndCapEndObj.transform.position = HitVect; + } + } + EndCapEndObj.transform.rotation = Quaternion.LookRotation(tDir); + EndCapEndObj.transform.Rotate(EndCapCustomRotOffsetEnd, Space.World); + EndCapEndObj.transform.position += EndCapCustomOffsetEnd; + } + } + + StretchSkip: + if (bIsStretch) + { + vManuver = 0; + } + + //End/Start for stretch: + if (bIsStretch) + { + //Ending objects: + if (EndCapStartObj != null) + { + tVect1 = tVerts[MinVectorIndices[0]]; + tFloat1 = tSpline.GetClosestParam(tVect1); + tVect2 = tSpline.GetSplineValue(tFloat1, false); + tVect1.y = tVect2.y; + + EndCapStartObj.transform.position = tVect1; + EndCapStartObj.transform.rotation = Quaternion.LookRotation(tDir); + EndCapStartObj.transform.Rotate(EndCapCustomRotOffsetStart, Space.World); + EndCapStartObj.transform.position += EndCapCustomOffsetStart; + } + if (EndCapEndObj != null) + { + tVect1 = tVerts[MaxVectorIndices[0]]; + tFloat1 = tSpline.GetClosestParam(tVect1); + tVect2 = tSpline.GetSplineValue(tFloat1, false); + tVect1.y = tVect2.y; + + EndCapEndObj.transform.position = tVect1; + EndCapEndObj.transform.rotation = Quaternion.LookRotation(tDir); + EndCapEndObj.transform.Rotate(EndCapCustomRotOffsetEnd, Space.World); + EndCapEndObj.transform.position += EndCapCustomOffsetEnd; + } + } + + if (bSimpleCollisionOn && !bIsStretch) + { + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + cTris = GetCollisionTris_Tri(MeshCount, cTriCount, cCount); + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + cTris = GetCollisionTris_Box(MeshCount, cTriCount, cCount); + } + } + + if (CapMesh1 != null) + { + Vector3[] cap1_verts = new Vector3[CapOrigMVL1]; + System.Array.Copy(CapOrigVerts1, cap1_verts, CapOrigMVL1); + int[] cap1_tris = new int[CapTriCount1]; + System.Array.Copy(CapOrigTris1, cap1_tris, CapTriCount1); + Vector2[] cap1_uv = new Vector2[CapOrigMVL1]; + System.Array.Copy(CapOrigUV1, cap1_uv, CapOrigMVL1); + Vector3[] cap1_normals = new Vector3[CapOrigMVL1]; + System.Array.Copy(CapOrigNormals1, cap1_normals, CapOrigMVL1); + bool[] cap1_hit = new bool[CapOrigMVL1]; + bool bcapstart = true; + float tHeight = 0f; + + foreach (KeyValuePair> KVP in MatchingIndices_Min_Cap) + { + int wCount = KVP.Value.Count; + for (int index = 0; index < wCount; index++) + { + if (bcapstart) + { + tVect1 = cap1_verts[KVP.Value[index]] - tVerts[KVP.Key]; + } + cap1_verts[KVP.Value[index]] = tVerts[KVP.Key]; + cap1_hit[KVP.Value[index]] = true; + if (bcapstart) + { + tHeight = tSpline.GetSplineValue(tSpline.GetClosestParam(cap1_verts[KVP.Value[index]]), false).y; + bcapstart = false; + } + } + } + + float tParam = 0f; + for (int index = 0; index < CapOrigMVL1; index++) + { + if (!cap1_hit[index]) + { + cap1_verts[index] -= tVect1; + tParam = tSpline.GetClosestParam(cap1_verts[index]); + tVect2 = tSpline.GetSplineValue(tParam, false); + cap1_verts[index].y -= (tHeight - tVect2.y); + cap1_verts[index].y += CapHeightOffset1; + } + } + + Vector3[] nVerts = new Vector3[CapOrigMVL1 + tVerts.Length]; + Vector3[] nNormals = new Vector3[CapOrigMVL1 + tNormals.Length]; + int[] nTris = new int[CapTriCount1 + tTris.Length]; + Vector2[] nUV = new Vector2[CapOrigMVL1 + tUV.Length]; + int OldTriCount = tTris.Length; + int OldMVL = tVerts.Length; + + System.Array.Copy(cap1_verts, nVerts, CapOrigMVL1); + System.Array.Copy(cap1_normals, nNormals, CapOrigMVL1); + System.Array.Copy(cap1_tris, nTris, CapTriCount1); + System.Array.Copy(cap1_uv, nUV, CapOrigMVL1); + + System.Array.Copy(tVerts, 0, nVerts, CapOrigMVL1, OldMVL); + System.Array.Copy(tNormals, 0, nNormals, CapOrigMVL1, OldMVL); + System.Array.Copy(tTris, 0, nTris, CapTriCount1, OldTriCount); + System.Array.Copy(tUV, 0, nUV, CapOrigMVL1, OldMVL); + + for (int index = CapTriCount1; index < (CapTriCount1 + OldTriCount); index++) + { + nTris[index] += CapOrigMVL1; + } + + tVerts = nVerts; + tTris = nTris; + tNormals = nNormals; + tUV = nUV; + } + + if (CapMesh2 != null) + { + Vector3[] cap2_verts = new Vector3[CapOrigMVL2]; + System.Array.Copy(CapOrigVerts2, cap2_verts, CapOrigMVL2); + int[] cap2_tris = new int[CapTriCount2]; + System.Array.Copy(CapOrigTris2, cap2_tris, CapTriCount2); + Vector2[] cap2_uv = new Vector2[CapOrigMVL2]; + System.Array.Copy(CapOrigUV2, cap2_uv, CapOrigMVL2); + Vector3[] cap2_normals = new Vector3[CapOrigMVL2]; + System.Array.Copy(CapOrigNormals2, cap2_normals, CapOrigMVL2); + bool[] cap2_hit = new bool[CapOrigMVL2]; + bool bcapstart = true; + float tHeight = 0f; + + foreach (KeyValuePair> KVP in MatchingIndices_Max_Cap) + { + int wCount = KVP.Value.Count; + for (int index = 0; index < wCount; index++) + { + if (bcapstart) + { + tVect1 = cap2_verts[KVP.Value[index]] - tVerts[vManuver + KVP.Key + CapOrigMVL1]; + } + cap2_verts[KVP.Value[index]] = tVerts[vManuver + KVP.Key + CapOrigMVL1]; + cap2_hit[KVP.Value[index]] = true; + + if (bcapstart) + { + tHeight = tSpline.GetSplineValue(tSpline.GetClosestParam(cap2_verts[KVP.Value[index]]), false).y; + bcapstart = false; + } + } + } + + float tParam = 0f; + for (int index = 0; index < CapOrigMVL2; index++) + { + + if (!cap2_hit[index]) + { + cap2_verts[index] -= tVect1; + tParam = tSpline.GetClosestParam(cap2_verts[index]); + tVect2 = tSpline.GetSplineValue(tParam, false); + cap2_verts[index].y -= (tHeight - tVect2.y); + cap2_verts[index].y += CapHeightOffset2; + } + } + + Vector3[] nVerts = new Vector3[CapOrigMVL2 + tVerts.Length]; + Vector3[] nNormals = new Vector3[CapOrigMVL2 + tNormals.Length]; + int[] nTris = new int[CapTriCount2 + tTris.Length]; + Vector2[] nUV = new Vector2[CapOrigMVL2 + tUV.Length]; + int OldTriCount = tTris.Length; + int OldMVL = tVerts.Length; + + System.Array.Copy(tVerts, 0, nVerts, 0, OldMVL); + System.Array.Copy(tNormals, 0, nNormals, 0, OldMVL); + System.Array.Copy(tTris, 0, nTris, 0, OldTriCount); + System.Array.Copy(tUV, 0, nUV, 0, OldMVL); + + System.Array.Copy(cap2_verts, 0, nVerts, OldMVL, CapOrigMVL2); + System.Array.Copy(cap2_normals, 0, nNormals, OldMVL, CapOrigMVL2); + System.Array.Copy(cap2_tris, 0, nTris, OldTriCount, CapTriCount2); + System.Array.Copy(cap2_uv, 0, nUV, OldMVL, CapOrigMVL2); + + for (int index = OldTriCount; index < nTris.Length; index++) + { + nTris[index] += OldMVL; + } + + tVerts = nVerts; + tTris = nTris; + tNormals = nNormals; + tUV = nUV; + } + + int tVertCount = tVerts.Length; + for (int index = 0; index < tVertCount; index++) + { + tVerts[index] -= tNode.pos; + } + if (cVerts != null) + { + int cVertCount = cVerts.Length; + for (int index = 0; index < cVertCount; index++) + { + cVerts[index] -= tNode.pos; + } + } + + //Mesh creation: + Mesh xMesh = new Mesh(); + xMesh.vertices = tVerts; + xMesh.triangles = tTris; + xMesh.normals = tNormals; + xMesh.uv = tUV; + xMesh.RecalculateNormals(); + tNormals = xMesh.normals; + Vector3 tAvgNormal = default(Vector3); + tIntBuffer1 = 0; + if (!bIsStretch) + { + for (int j = 1; j < MeshCount; j++) + { + vManuver = j * OrigMVL; + vManuver_Prev = (j - 1) * OrigMVL; + if (CapMesh1 != null) + { + tIntBuffer1 = CapOrigMVL1; + } + foreach (KeyValuePair KVP in MatchingIndices_Min) + { + tAvgNormal = (tNormals[tIntBuffer1 + vManuver + KVP.Key] + tNormals[tIntBuffer1 + vManuver_Prev + KVP.Value]) * 0.5f; + tNormals[tIntBuffer1 + vManuver + KVP.Key] = tAvgNormal; + tNormals[tIntBuffer1 + vManuver_Prev + KVP.Key] = tAvgNormal; + } + } + xMesh.normals = tNormals; + } + xMesh.tangents = GSDRootUtil.ProcessTangents(tTris, tNormals, tUV, tVerts); + + if (tName == null || tName.Length < 1) + { + tName = "ExtrudedMesh"; + } + + Output = new GameObject(tName); + Output.transform.position = tNode.pos; + + MF = Output.AddComponent(); + MF.sharedMesh = xMesh; + + if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) + { + SaveMesh(ref xMesh, false); + } + + //Colliders: + MeshCollider MC = null; + if (CollisionType == CollisionTypeEnum.SimpleMeshTriangle) + { + MC = Output.AddComponent(); + Mesh cMesh = new Mesh(); + cMesh.vertices = cVerts; + cMesh.triangles = cTris; + cMesh.normals = new Vector3[cVerts.Length]; + if (MC != null) + { + MC.sharedMesh = cMesh; + } + if (MC != null) + { + MC.convex = bCollisionConvex; + MC.isTrigger = bCollisionTrigger; + if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) + { + cMesh.uv = new Vector2[cVerts.Length]; + cMesh.tangents = GSDRootUtil.ProcessTangents(cTris, cMesh.normals, cMesh.uv, cVerts); + SaveMesh(ref cMesh, true); + } + } + } + else if (CollisionType == CollisionTypeEnum.SimpleMeshTrapezoid) + { + MC = Output.AddComponent(); + Mesh cMesh = new Mesh(); + cMesh.vertices = cVerts; + cMesh.triangles = cTris; + cMesh.normals = new Vector3[cVerts.Length]; + if (MC != null) + { + MC.sharedMesh = cMesh; + } + if (MC != null) + { + MC.convex = bCollisionConvex; + MC.isTrigger = bCollisionTrigger; + if (tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) + { + cMesh.uv = new Vector2[cVerts.Length]; + cMesh.tangents = GSDRootUtil.ProcessTangents(cTris, cMesh.normals, cMesh.uv, cVerts); + SaveMesh(ref cMesh, true); + } + } + } + else if (CollisionType == CollisionTypeEnum.MeshCollision) + { + MC = Output.AddComponent(); + if (MC != null) + { + MC.sharedMesh = xMesh; + } + if (MC != null) + { + MC.convex = bCollisionConvex; + MC.isTrigger = bCollisionTrigger; + } + } + else if (CollisionType == CollisionTypeEnum.BoxCollision) + { + //Primitive collider: + GameObject BC_Obj = new GameObject("Primitive"); + BoxCollider BC = BC_Obj.AddComponent(); + BC_Obj.transform.position = tNode.pos; + BC_Obj.transform.rotation = Quaternion.LookRotation(tNode.tangent); + + Vector3 BCCenter = default(Vector3); + // if(bStraightLineMatchStartEnd){ + // if(tNode.bIsBridge && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null){ + // BCCenter = ((tNode.pos - tNode.BridgeCounterpartNode.pos)*0.5f)+tNode.BridgeCounterpartNode.pos; + // }else if(tNode.idOnSpline < (tSpline.GetNodeCount()-1)){ + // BCCenter = ((tNode.pos - tSpline.mNodes[tNode.idOnSpline+1].pos)*0.5f)+tSpline.mNodes[tNode.idOnSpline+1].pos; + // }else{ + // + // } + // BCCenter.y -= VerticalRaise; + // BCCenter.y -= (mMaxHeight*0.5f); + // }else{ + Vector3 POS = default(Vector3); + tSpline.GetSplineValue_Both(StartTime, out tVect1, out POS); + //Goes right if not neg: + tVect1 = (tVect1 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); + tSpline.GetSplineValue_Both(EndTime, out tVect2, out POS); + tVect2 = (tVect2 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); + tVect1.y += VerticalRaise; + tVect2.y += VerticalRaise; + BCCenter = ((tVect1 - tVect2) * 0.5f) + tVect2; + BCCenter.y += ((mMinY + mMaxY) * 0.5f); + // } + + BCCenter -= tNode.pos; + BCCenter.z *= -1f; + + if (bBCFlipX) + { + BCCenter.z *= -1f; + } + if (bBCFlipZ) + { + BCCenter.x *= -1f; + } + + // + + Vector3 BCCenter2 = new Vector3(BCCenter.z, BCCenter.y, BCCenter.x); + + + BCCenter2 += StretchBC_LocOffset; + + + BC.center = BCCenter2; + + tFloat1 = Vector3.Distance(tNode.pos, tNode.BridgeCounterpartNode.pos); + + if (bStretchSize) + { + BC.size = StretchBC_Size; + } + else + { + if (Axis == AxisTypeEnum.X) + { + BC.size = new Vector3(tFloat1, mMaxHeight, (mMaxZ - mMinZ)); + } + else + { + BC.size = new Vector3((mMaxX - mMinX), mMaxHeight, tFloat1); + } + StretchBC_Size = BC.size; + } + BC_Obj.transform.parent = Output.transform; + } + + + //Use prefab mats if no material override: + MeshRenderer MR = Output.AddComponent(); + if (SplinatedMaterial1 == null && !bMaterialOverride) + { + MeshRenderer PrefabMR = tObj.GetComponent(); + if (PrefabMR != null && PrefabMR.sharedMaterials != null) + { + MR.materials = PrefabMR.sharedMaterials; + } + } + else + { + //Else, use override mats: + tIntBuffer1 = 0; + if (SplinatedMaterial1 != null) + { + tIntBuffer1 += 1; + if (SplinatedMaterial2 != null) + { + tIntBuffer1 += 1; + } + } + if (tIntBuffer1 > 0) + { + Material[] tMats = new Material[tIntBuffer1]; + if (SplinatedMaterial1 != null) + { + tMats[0] = SplinatedMaterial1; + if (SplinatedMaterial2 != null) + { + tMats[1] = SplinatedMaterial2; + } + } + MR.materials = tMats; + } + } + + mMaxX = mMaxX * 1.5f; + mMinX = mMinX * 1.5f; + mMaxY = mMaxY * 1.5f; + mMinY = mMinY * 1.5f; + mMaxZ = mMaxZ * 1.5f; + mMinZ = mMinZ * 1.5f; + + StartPos = tSpline.GetSplineValue(StartTime); + EndPos = tSpline.GetSplineValue(EndTime); + + //Destroy the instantiated prefab: + if (tObj != null) + { + Object.DestroyImmediate(tObj); + } + if (Cap1 != null) + { + Object.DestroyImmediate(Cap1); + } + if (Cap2 != null) + { + Object.DestroyImmediate(Cap2); + } + + Material[] fMats = MR.sharedMaterials; + + //Set the new object with the specified vertical raise: + Output.transform.name = tName; + Output.transform.parent = MasterObjTrans; + if (EndCapStartObj != null) + { + EndCapStartObj.transform.parent = Output.transform; + EndCapStartOutput = EndCapStartObj; + + MeshRenderer eMR = EndCapStartObj.GetComponent(); + if (eMR == null) + { + eMR = EndCapStartObj.AddComponent(); + } + if (eMR.sharedMaterials == null || (eMR.sharedMaterial != null && eMR.sharedMaterial.name.ToLower().Contains("default-diffuse"))) + { + eMR.sharedMaterials = fMats; + } + } + if (EndCapEndObj != null) + { + EndCapEndObj.transform.parent = Output.transform; + EndCapEndOutput = EndCapEndObj; + MeshRenderer eMR = EndCapEndObj.GetComponent(); + if (eMR == null) + { + eMR = EndCapEndObj.AddComponent(); + } + if (eMR.sharedMaterials == null || (eMR.sharedMaterial != null && eMR.sharedMaterial.name.ToLower().Contains("default-diffuse"))) + { + eMR.sharedMaterials = fMats; + } + } + + if (bCollect) + { + tNode.GSDSpline.tRoad.bTriggerGC = true; + } +#endif + } + + + private void SaveMesh(ref Mesh tMesh, bool bIsCollider) + { +#if UNITY_EDITOR + if (!tNode.GSDSpline.tRoad.GSDRS.opt_bSaveMeshes) + { + return; + } + //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); + string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; + tSceneName = tSceneName.Replace("/", ""); + tSceneName = tSceneName.Replace(".", ""); + string tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Extrusions/"; + string tRoadName = tNode.GSDSpline.tRoad.transform.name; + string FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + ".asset"; + if (bIsCollider) + { + FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + "-collider.asset"; + } + + string xPath = Application.dataPath.Replace("/Assets", "/" + tFolderName); + if (!System.IO.Directory.Exists(xPath)) + { + System.IO.Directory.CreateDirectory(xPath); + } + + + UnityEditor.AssetDatabase.CreateAsset(tMesh, FinalName); + UnityEditor.AssetDatabase.SaveAssets(); +#endif + } + + + void DoStretch(ref Vector3[] OrigVerts, ref Vector2[] OrigUV, ref int[] OrigTris, ref List MaxVectorIndices, ref List MinVectorIndices, float mMaxDiff, out Vector3[] tVerts, out Vector2[] tUV, out Vector3[] tNormals, out int[] tTris) + { + Vector3 tVect1 = tNode.pos; + Vector3 tVect2 = default(Vector3); + + // if(bStraightLineMatchStartEnd){ + // if(tNode.bIsBridge && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null){ + // tVect2 = tNode.BridgeCounterpartNode.pos; + // }else if(tNode.idOnSpline < (tSpline.GetNodeCount()-1)){ + // tVect2 = tSpline.mNodes[tNode.idOnSpline+1].pos; + // } + // } + + Vector3 POS = default(Vector3); + Vector3 tDir = tNode.tangent; + + // if(!bStraightLineMatchStartEnd){ + tSpline.GetSplineValue_Both(StartTime, out tVect1, out POS); + //Goes right if not neg: + tVect1 = (tVect1 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); + + tSpline.GetSplineValue_Both(EndTime, out tVect2, out POS); + tVect2 = (tVect2 + new Vector3(HorizontalSep * POS.normalized.z, 0, HorizontalSep * -POS.normalized.x)); + + tVect1.y += VerticalRaise; + tVect2.y += VerticalRaise; + + tDir = tSpline.GetSplineValue(StartTime, true); + // } + + Matrix4x4 tMatrixStart = new Matrix4x4(); + Matrix4x4 tMatrixEnd = new Matrix4x4(); + int OrigMVL = OrigVerts.Length; + + tVerts = new Vector3[OrigMVL]; + tUV = new Vector2[OrigMVL]; + tNormals = new Vector3[OrigMVL]; + tTris = new int[OrigTris.Length]; + System.Array.Copy(OrigVerts, tVerts, OrigMVL); + System.Array.Copy(OrigTris, tTris, OrigTris.Length); + System.Array.Copy(OrigUV, tUV, OrigMVL); + + tMatrixStart.SetTRS(tVect1, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); + tMatrixEnd.SetTRS(tVect2, Quaternion.LookRotation(tDir), new Vector3(1f, 1f, 1f)); + + //Rotate and set vertex positions: + float NewDiff = Vector3.Distance(tVect1, tVect2); + float UVMod = NewDiff / mMaxDiff; + Vector3 xVect = default(Vector3); + for (int index = 0; index < OrigMVL; index++) + { + xVect = OrigVerts[index]; + if (MaxVectorIndices.Contains(index)) + { + tVerts[index] = tMatrixEnd.MultiplyPoint3x4(xVect); + } + else + { + tVerts[index] = tMatrixStart.MultiplyPoint3x4(xVect); + } + + if (RepeatUVType == RepeatUVTypeEnum.X) + { + if (OrigUV[index].x > Stretch_UVThreshold) + { + tUV[index].x = OrigUV[index].x * UVMod; + } + } + else + { + if (OrigUV[index].y > Stretch_UVThreshold) + { + tUV[index].y = OrigUV[index].y * UVMod; + } + } + } + } + + + Vector3 GetAverageNormalToGround(GameObject tObj) + { + Ray tRay = default(Ray); + RaycastHit[] tRayHit = null; + float tHitY = 0f; + int tHitIndex = 0; + Vector3 tHitNormal = default(Vector3); + + Bounds tBounds = tObj.GetComponent().sharedMesh.bounds; + + Vector3[] tVects = new Vector3[8]; + tVects[0] = tBounds.min; + tVects[1] = tBounds.max; + tVects[2] = new Vector3(tVects[0].x, tVects[0].y, tVects[1].z); + tVects[3] = new Vector3(tVects[0].x, tVects[1].y, tVects[0].z); + tVects[4] = new Vector3(tVects[1].x, tVects[0].y, tVects[0].z); + tVects[5] = new Vector3(tVects[0].x, tVects[1].y, tVects[1].z); + tVects[6] = new Vector3(tVects[1].x, tVects[0].y, tVects[1].z); + tVects[7] = new Vector3(tVects[1].x, tVects[1].y, tVects[0].z); + + List xVects = new List(); + + for (int index = 0; index < 8; index++) + { + tRay = new Ray(tVects[index] + new Vector3(0f, 1f, 0f), Vector3.down); + tRayHit = Physics.RaycastAll(tRay); + tHitIndex = -1; + tHitY = -1f; + if (tRayHit.Length > 0) + { + for (int g = 0; g < tRayHit.Length; g++) + { + if (g == 0) + { + tHitY = tRayHit[g].point.y; + tHitIndex = 0; + } + else + { + if (tRayHit[g].point.y > tHitY) + { + tHitY = tRayHit[g].point.y; + tHitIndex = g; + } + } + } + xVects.Add(tRayHit[tHitIndex].normal); + } + } + + + for (int index = 0; index < xVects.Count; index++) + { + tHitNormal += xVects[index]; + } + tHitNormal /= xVects.Count; + + return tHitNormal; + } + } + +#endif +} \ No newline at end of file diff --git a/GSDRoadSystem.cs b/GSDRoadSystem.cs index 2e74a139..e34cdd6c 100755 --- a/GSDRoadSystem.cs +++ b/GSDRoadSystem.cs @@ -1,117 +1,129 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections; -#endif - -public class GSDRoadSystem : MonoBehaviour -{ - public static string AssetBasePath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + ""; -#if UNITY_EDITOR - - public bool opt_bMultithreading = true; - public bool opt_bSaveMeshes = false; - public bool opt_bAllowRoadUpdates = true; - - public GameObject AddRoad(bool bForceSelect = false) - { - GSDRoad[] tObj = GetComponentsInChildren(); - int NewRoadNumber = (tObj.Length + 1); - - //Road: - GameObject tRoadObj = new GameObject("Road" + NewRoadNumber.ToString()); - UnityEditor.Undo.RegisterCreatedObjectUndo(tRoadObj, "Created road"); - tRoadObj.transform.parent = transform; - GSDRoad tRoad = tRoadObj.AddComponent(); - - //Spline: - GameObject tSplineObj = new GameObject("Spline"); - tSplineObj.transform.parent = tRoad.transform; - tRoad.GSDSpline = tSplineObj.AddComponent(); - tRoad.GSDSpline.mSplineRoot = tSplineObj; - tRoad.GSDSpline.tRoad = tRoad; - tRoad.GSDSplineObj = tSplineObj; - tRoad.GSDRS = this; - tRoad.SetupUniqueIdentifier(); - - tRoad.ConstructRoad_ResetTerrainHistory(); - - if (bForceSelect) - { - UnityEditor.Selection.activeGameObject = tRoadObj; - } - - return tRoadObj; - } - - public Camera EditorPlayCamera = null; - public void EditorCameraSetSingle() - { - if (EditorPlayCamera == null) - { - Camera[] EditorCams = (Camera[])GameObject.FindObjectsOfType(typeof(Camera)); - if (EditorCams != null && EditorCams.Length == 1) - { - EditorPlayCamera = EditorCams[0]; - } - } - } - - public void UpdateAllRoads() - { - GSDRoad[] tRoadObjs = GetComponentsInChildren(); - // int i=0; - - int RoadCount = tRoadObjs.Length; - - GSDRoad tRoad = null; - GSDSplineC[] tPiggys = null; - if (RoadCount > 1) - { - tPiggys = new GSDSplineC[RoadCount]; - for (int h = 0; h < RoadCount; h++) - { - tRoad = tRoadObjs[h]; - tPiggys[h] = tRoad.GSDSpline; - } - } - - tRoad = tRoadObjs[0]; - if (tPiggys != null && tPiggys.Length > 0) - { - tRoad.PiggyBacks = tPiggys; - } - tRoad.UpdateRoad(); - } - - //Workaround for submission rules: - public void UpdateAllRoads_MultiThreadOptions() - { - GSDRoad[] tRoadObjs = (GSDRoad[])GetComponentsInChildren(); - int RoadCount = tRoadObjs.Length; - GSDRoad tRoad = null; - for (int h = 0; h < RoadCount; h++) - { - tRoad = tRoadObjs[h]; - if (tRoad != null) - { - tRoad.opt_bMultithreading = opt_bMultithreading; - } - } - } - //Workaround for submission rules: - public void UpdateAllRoads_SaveMeshesAsAssetsOptions() - { - GSDRoad[] tRoadObjs = (GSDRoad[])GetComponentsInChildren(); - int RoadCount = tRoadObjs.Length; - GSDRoad tRoad = null; - for (int h = 0; h < RoadCount; h++) - { - tRoad = tRoadObjs[h]; - if (tRoad != null) - { - tRoad.opt_bSaveMeshes = opt_bSaveMeshes; - } - } - } -#endif +#region "Imports" +using UnityEngine; +#if UNITY_EDITOR +using System.Collections; +#endif +#endregion + + + +public class GSDRoadSystem : MonoBehaviour +{ + public static string AssetBasePath = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + ""; +#if UNITY_EDITOR + + public bool opt_bMultithreading = true; + public bool opt_bSaveMeshes = false; + public bool opt_bAllowRoadUpdates = true; + + + public GameObject AddRoad(bool bForceSelect = false) + { + GSDRoad[] tObj = GetComponentsInChildren(); + int NewRoadNumber = (tObj.Length + 1); + + //Road: + GameObject tRoadObj = new GameObject("Road" + NewRoadNumber.ToString()); + UnityEditor.Undo.RegisterCreatedObjectUndo(tRoadObj, "Created road"); + tRoadObj.transform.parent = transform; + GSDRoad tRoad = tRoadObj.AddComponent(); + + //Spline: + GameObject tSplineObj = new GameObject("Spline"); + tSplineObj.transform.parent = tRoad.transform; + tRoad.GSDSpline = tSplineObj.AddComponent(); + tRoad.GSDSpline.mSplineRoot = tSplineObj; + tRoad.GSDSpline.tRoad = tRoad; + tRoad.GSDSplineObj = tSplineObj; + tRoad.GSDRS = this; + tRoad.SetupUniqueIdentifier(); + + tRoad.ConstructRoad_ResetTerrainHistory(); + + if (bForceSelect) + { + UnityEditor.Selection.activeGameObject = tRoadObj; + } + + return tRoadObj; + } + + + public Camera EditorPlayCamera = null; + + + public void EditorCameraSetSingle() + { + if (EditorPlayCamera == null) + { + Camera[] EditorCams = (Camera[]) GameObject.FindObjectsOfType(typeof(Camera)); + if (EditorCams != null && EditorCams.Length == 1) + { + EditorPlayCamera = EditorCams[0]; + } + } + } + + + public void UpdateAllRoads() + { + GSDRoad[] tRoadObjs = GetComponentsInChildren(); + // int i=0; + + int RoadCount = tRoadObjs.Length; + + GSDRoad tRoad = null; + GSDSplineC[] tPiggys = null; + if (RoadCount > 1) + { + tPiggys = new GSDSplineC[RoadCount]; + for (int h = 0; h < RoadCount; h++) + { + tRoad = tRoadObjs[h]; + tPiggys[h] = tRoad.GSDSpline; + } + } + + tRoad = tRoadObjs[0]; + if (tPiggys != null && tPiggys.Length > 0) + { + tRoad.PiggyBacks = tPiggys; + } + tRoad.UpdateRoad(); + } + + + //Workaround for submission rules: + public void UpdateAllRoads_MultiThreadOptions() + { + GSDRoad[] tRoadObjs = (GSDRoad[]) GetComponentsInChildren(); + int RoadCount = tRoadObjs.Length; + GSDRoad tRoad = null; + for (int h = 0; h < RoadCount; h++) + { + tRoad = tRoadObjs[h]; + if (tRoad != null) + { + tRoad.opt_bMultithreading = opt_bMultithreading; + } + } + } + + + //Workaround for submission rules: + public void UpdateAllRoads_SaveMeshesAsAssetsOptions() + { + GSDRoad[] tRoadObjs = (GSDRoad[]) GetComponentsInChildren(); + int RoadCount = tRoadObjs.Length; + GSDRoad tRoad = null; + for (int h = 0; h < RoadCount; h++) + { + tRoad = tRoadObjs[h]; + if (tRoad != null) + { + tRoad.opt_bSaveMeshes = opt_bSaveMeshes; + } + } + } +#endif } \ No newline at end of file diff --git a/GSDRoadUtility.cs b/GSDRoadUtility.cs index 3bbf1ec1..2296f90d 100755 --- a/GSDRoadUtility.cs +++ b/GSDRoadUtility.cs @@ -1,7612 +1,8355 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -using System.Collections; -using System.IO; -using System.Text; -using System.Runtime.Serialization.Formatters.Binary; -using System.Runtime.Serialization; -#endif -namespace GSD.Roads -{ - //Generic http://www.fhwa.dot.gov/bridge/bridgerail/br053504.cfm - public enum RailingTypeEnum { None, Generic1, Generic2, K_Rail, WBeam }; - public enum RailingSubTypeEnum { Both, Left, Right }; - public enum SignPlacementSubTypeEnum { Center, Left, Right }; - public enum CenterDividerTypeEnum { None, K_Rail, KRail_Blinds, Wire, Markers }; - public enum EndCapTypeEnum { None, WBeam, Barrels3Static, Barrels3Rigid, Barrels7Static, Barrels7Rigid }; - public enum RoadUpdateTypeEnum { Full, Intersection, Railing, CenterDivider, Bridges }; - public enum AxisTypeEnum { X, Y, Z }; - -#if UNITY_EDITOR - public static class GSDConstruction - { - private static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - private static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - - public static GSDSplineN CreateNode(GSDRoad RS, bool bSpecialEndNode = false, Vector3 vSpecialLoc = default(Vector3), bool bInterNode = false) - { - Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); - GameObject tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); - if (!bInterNode) - { - UnityEditor.Undo.RegisterCreatedObjectUndo(tNodeObj, "Created node"); - } - GSDSplineN tNode = tNodeObj.AddComponent(); - - if (bSpecialEndNode) - { - tNode.bSpecialEndNode = true; - tNodeObj.transform.position = vSpecialLoc; - } - else - { - tNodeObj.transform.position = RS.Editor_MousePos; - //This helps prevent double clicks: - int mCount = RS.GSDSpline.GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - if (Vector3.Distance(RS.Editor_MousePos, RS.GSDSpline.mNodes[i].pos) < 5f) - { - Object.DestroyImmediate(tNodeObj); - return null; - } - } - //End double click prevention - } - Vector3 xVect = tNodeObj.transform.position; - if (xVect.y < 0.03f) { xVect.y = 0.03f; } - tNodeObj.transform.position = xVect; - - tNodeObj.transform.parent = RS.GSDSplineObj.transform; - tNode.idOnSpline = RS.GSDSpline.GetNodeCount() + 1; - tNode.GSDSpline = RS.GSDSpline; - - //Enforce max road grade: - if (RS.opt_bMaxGradeEnabled && !bSpecialEndNode) - { - tNode.EnsureGradeValidity(-1, true); - } - - if (!bInterNode && !bSpecialEndNode) - { - RS.UpdateRoad(); - } - return tNode; - } - //Insert - //Detect closest node (if end node, auto select other node) - //Determine which node is closest (up or down) on spline - //Place node, adjust all id on splines - //Setup spline - public static GSDSplineN InsertNode(GSDRoad RS, bool bForcedLoc = false, Vector3 ForcedLoc = default(Vector3), bool bIsPreNode = false, int InsertIndex = -1, bool bSpecialEndNode = false, bool bInterNode = false) - { - GameObject tNodeObj; - Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); - if (!bForcedLoc) - { - tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); - } - else if (bForcedLoc && !bSpecialEndNode) - { - tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString() + "Ignore"); - } - else - { - tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); - } - if (!bInterNode) - { - UnityEditor.Undo.RegisterCreatedObjectUndo(tNodeObj, "Inserted node"); - } - - if (!bForcedLoc) - { - tNodeObj.transform.position = RS.Editor_MousePos; - - //This helps prevent double clicks: - int mCount = RS.GSDSpline.GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - if (Vector3.Distance(RS.Editor_MousePos, RS.GSDSpline.mNodes[i].pos) < 15f) - { - Object.DestroyImmediate(tNodeObj); - return null; - } - } - //End double click prevention - } - else - { - tNodeObj.transform.position = ForcedLoc; - } - Vector3 xVect = tNodeObj.transform.position; - if (xVect.y < 0.03f) { xVect.y = 0.03f; } - tNodeObj.transform.position = xVect; - tNodeObj.transform.parent = RS.GSDSplineObj.transform; - - int cCount = RS.GSDSpline.mNodes.Count; - // float mDistance = 50000f; - // float tDistance = 0f; - - float tParam; - if (!bForcedLoc) - { - tParam = RS.GSDSpline.GetClosestParam(RS.Editor_MousePos, false, true); - } - else - { - tParam = RS.GSDSpline.GetClosestParam(ForcedLoc, false, true); - } - bool bEndInsert = false; - bool bZeroInsert = false; - int iStart = 0; - if (GSDRootUtil.IsApproximately(tParam, 0f, 0.0001f)) - { - bZeroInsert = true; - iStart = 0; - } - else if (GSDRootUtil.IsApproximately(tParam, 1f, 0.0001f)) - { - bEndInsert = true; - } - - if (bForcedLoc) - { - iStart = InsertIndex; - } - else - { - for (int i = 0; i < cCount; i++) - { - GSDSplineN xNode = RS.GSDSpline.mNodes[i]; - if (!bZeroInsert && !bEndInsert) - { - if (tParam > xNode.tTime) - { - iStart = xNode.idOnSpline + 1; - } - } - } - } - - if (bEndInsert) - { - iStart = RS.GSDSpline.mNodes.Count; - } - else - { - for (int i = iStart; i < cCount; i++) - { - RS.GSDSpline.mNodes[i].idOnSpline += 1; - } - } - - GSDSplineN tNode = tNodeObj.AddComponent(); - if (bForcedLoc && !bSpecialEndNode) - { - tNode.bIsBridge = true; - tNode.bIgnore = true; - // tNode.bIsBridge_PreNode = bIsPreNode; - // tNode.bIsBridge_PostNode = !bIsPreNode; - } - tNode.GSDSpline = RS.GSDSpline; - tNode.idOnSpline = iStart; - tNode.bSpecialEndNode = bSpecialEndNode; - if (!bForcedLoc) - { - tNode.pos = RS.Editor_MousePos; - } - else - { - tNode.pos = ForcedLoc; - } - - RS.GSDSpline.mNodes.Insert(iStart, tNode); - - //Enforce maximum road grade: - if (!bForcedLoc && !bSpecialEndNode && RS.opt_bMaxGradeEnabled) - { - tNode.EnsureGradeValidity(iStart); - } - - if (!bInterNode && !bSpecialEndNode) - { - if (!bForcedLoc) - { - RS.UpdateRoad(); - } - } - - return tNode; - } - } - - public static class GSDTerraforming - { - 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 cI = 0; - public int TerrainMaxIndex; - - //Details: - public int DetailLayersCount; - - public List MainDetailsX; - public List MainDetailsY; - - public List> DetailsX; - public List> DetailsY; - public List> OldDetailsValue; - // public Dictionary DetailValues; - public int[] DetailsI; - public float DetailToHeightRatio; - - - - - - // public Dictionary DetailHasProcessed; - - public HashSet DetailHasProcessed; - - - - // public List> OldDetailsValue; - - public int DetailMaxIndex; - public HashSet DetailLayersSkip; - - //Trees - public List TreesCurrent; - public List TreesOld; - public int TreesI; - public int TreeSize; - - public Vector3 TerrainSize; - public Vector3 TerrainPos; - public int GSDID; - - 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; - } - } - - private static void CheckAllTerrains() - { - Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); - GSDTerrain TID; - GameObject tObj; - foreach (Terrain tTerrain in tTerrains) - { - tObj = tTerrain.transform.gameObject; - TID = tObj.GetComponent(); - if (TID == null) - { - TID = tObj.AddComponent(); - } - TID.CheckID(); - } - } - - public static void CheckAllTerrainsHeight0() - { - CheckAllTerrains(); - Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); - foreach (Terrain tTerrain in tTerrains) - { - if (!GSDRootUtil.IsApproximately(tTerrain.transform.position.y, 0f, 0.0001f)) - { - Vector3 tVect = tTerrain.transform.position; - tVect.y = 0f; - tTerrain.transform.position = tVect; - } - } - } - - public static void ProcessRoad_Terrain_Hook1(GSDSplineC tSpline, GSDRoad tRoad, bool bMultithreaded = true) - { - ProcessRoad_Terrain_Hook1_Do(ref tSpline, ref tRoad, bMultithreaded); - } - private static void ProcessRoad_Terrain_Hook1_Do(ref GSDSplineC tSpline, ref GSDRoad tRoad, bool bMultithreaded) - { - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_Terrain_Hook1_Do"); } - //First lets make sure all terrains have GSD shit on them: - CheckAllTerrains(); - - //Reset the terrain: - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("TerrainsReset"); } - GSDTerraforming.TerrainsReset(tRoad); - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - float heightDistance = tRoad.opt_MatchHeightsDistance; - // float treeDistance = tRoad.opt_ClearTreesDistance; - float detailDistance = tRoad.opt_ClearDetailsDistance; - - Dictionary TempTerrainDict = new Dictionary(); - //Populate dictionary: - Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); - GSDTerrain TID; - int aSize = 0; - int dSize = 0; - TempTerrainData TTD; - bool bContains = false; - GSDRoadUtil.Construction2DRect tRect = null; - // GSDRoadUtil.Construction2DRect rRect = null; - foreach (Terrain tTerrain in tTerrains) - { - if (tTerrain.terrainData == null) - continue; - tRect = GetTerrainBounds(tTerrain); - bContains = false; - //Debug.Log(tTerrain.transform.name + " bounds: " + tRect.ToStringGSD()); - //Debug.Log(" Road bounds: " + tSpline.RoadV0 + "," + tSpline.RoadV1 + "," + tSpline.RoadV2 + "," + tSpline.RoadV3); - - if (bContains != true && tRect.Contains(ref tSpline.RoadV0)) - { - bContains = true; - } - else if (bContains != true && tRect.Contains(ref tSpline.RoadV1)) - { - bContains = true; - } - else if (bContains != true && tRect.Contains(ref tSpline.RoadV2)) - { - bContains = true; - } - else if (bContains != true && tRect.Contains(ref tSpline.RoadV3)) - { - bContains = true; - } - else - { - int mCount3 = tRoad.GSDSpline.GetNodeCount(); - Vector2 tVect2D_321 = default(Vector2); - for (int i = 0; i < mCount3; i++) - { - tVect2D_321 = new Vector2(tRoad.GSDSpline.mNodes[i].pos.x, tRoad.GSDSpline.mNodes[i].pos.z); - if (tRect.Contains(ref tVect2D_321)) - { - bContains = true; - break; - } - } - - if (!bContains) - { - float tDef = 5f / tSpline.distance; - Vector2 x2D = default(Vector2); - Vector3 x3D = default(Vector3); - for (float i = 0f; i <= 1f; i += tDef) - { - x3D = tSpline.GetSplineValue(i); - x2D = new Vector2(x3D.x, x3D.z); - if (tRect.Contains(ref x2D)) - { - bContains = true; - break; - } - } - } - } - - // rRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(tSpline.RoadV0,tSpline.RoadV1,tSpline.RoadV2,tSpline.RoadV3); - - - if (bContains && !TempTerrainDict.ContainsKey(tTerrain)) - { - TTD = new TempTerrainData(); - TTD.HM = tTerrain.terrainData.heightmapResolution; - TTD.HMHeight = tTerrain.terrainData.heightmapHeight; - TTD.heights = tTerrain.terrainData.GetHeights(0, 0, tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight); - TTD.HMRatio = TTD.HM / tTerrain.terrainData.size.x; - TTD.MetersPerHM = tTerrain.terrainData.size.x / tTerrain.terrainData.heightmapResolution; - float DetailRatio = tTerrain.terrainData.detailResolution / tTerrain.terrainData.size.x; - - //Heights: - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("Heights"); } - if (tRoad.opt_HeightModEnabled) - { - aSize = (int)tSpline.distance * ((int)(heightDistance * 1.65f * TTD.HMRatio) + 2); - if (aSize > (tTerrain.terrainData.heightmapResolution * tTerrain.terrainData.heightmapResolution)) - { - aSize = tTerrain.terrainData.heightmapResolution * tTerrain.terrainData.heightmapResolution; - } - TTD.cX = new ushort[aSize]; - TTD.cY = new ushort[aSize]; - TTD.oldH = new float[aSize]; - TTD.cH = new float[aSize]; - TTD.cI = 0; - TTD.TerrainMaxIndex = tTerrain.terrainData.heightmapResolution; - TTD.TerrainSize = tTerrain.terrainData.size; - TTD.TerrainPos = tTerrain.transform.position; - TTD.tHeights = new bool[tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight]; - TID = tTerrain.transform.gameObject.GetComponent(); - if (TID != null) - { - TTD.GSDID = TID.GSDID; - TempTerrainDict.Add(tTerrain, TTD); - } - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - //Details: - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("Details"); } - if (tRoad.opt_DetailModEnabled) - { - // TTD.DetailValues = new Dictionary(); - TTD.DetailLayersCount = tTerrain.terrainData.detailPrototypes.Length; - // TTD.DetailHasProcessed = new Dictionary(); - TTD.DetailHasProcessed = new HashSet(); - TTD.MainDetailsX = new List(); - TTD.MainDetailsY = new List(); - TTD.DetailsI = new int[TTD.DetailLayersCount]; - TTD.DetailToHeightRatio = (float)((float)tTerrain.terrainData.detailResolution) / ((float)tTerrain.terrainData.heightmapResolution); - TTD.DetailMaxIndex = tTerrain.terrainData.detailResolution; - TTD.DetailLayersSkip = new HashSet(); - - // Get all of layer zero. - // int[] mMinMaxDetailEntryCount = new int[TTD.DetailLayersCount]; - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("DetailValues"); } - // Vector3 bVect = default(Vector3); - // Vector2 bVect2D = default(Vector2); - // int DetailRes = tTerrain.terrainData.detailResolution; - // for(int i=0;i 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]); - // } - // } - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } - - - dSize = (int)tSpline.distance * ((int)(detailDistance * 3f * DetailRatio) + 2); - if (dSize > (tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution)) - { - dSize = tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution; - } - - // TTD.DetailsX = new List(); - // TTD.DetailsY = new List(); - // TTD.OldDetailsValue = new List(); - TTD.DetailsX = new List>(); - TTD.DetailsY = new List>(); - TTD.OldDetailsValue = new List>(); - // TTD.DetailHasProcessed = new List>(); - - for (int i = 0; i < TTD.DetailLayersCount; i++) - { - // if(TTD.DetailLayersSkip.Contains(i)){ - // TTD.DetailsX.Add(new ushort[0]); - // TTD.DetailsY.Add(new ushort[0]); - // TTD.OldDetailsValue.Add(new ushort[0]); - // continue; - // } - // int detailentrycount = (int)((float)mMinMaxDetailEntryCount[i] * 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()); - TTD.DetailsY.Add(new List()); - TTD.OldDetailsValue.Add(new List()); - } - - - // TTD.DetailsX = new ushort[TTD.DetailLayersCount,dSize]; - // TTD.DetailsY = new ushort[TTD.DetailLayersCount,dSize]; - // TTD.OldDetailsValue = new ushort[TTD.DetailLayersCount,dSize]; - - - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - //Trees: - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("Trees"); } - if (tRoad.opt_TreeModEnabled) - { - // TTD.TreesCurrent = tTerrain.terrainData.treeInstances; - TTD.TreesCurrent = new List(tTerrain.terrainData.treeInstances); - TTD.TreeSize = TTD.TreesCurrent.Count; - TTD.TreesI = 0; - TTD.TreesOld = new List(); - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - } - } - - //Figure out relevant TTD to spline: - List EditorTTDList = new List(); - if (TempTerrainDict != null) - { - foreach (Terrain tTerrain in tTerrains) - { - if (TempTerrainDict.ContainsKey(tTerrain)) - { - EditorTTDList.Add(TempTerrainDict[tTerrain]); - } - } - } - - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - //Start job now, for each relevant TTD: - tRoad.EditorTerrainCalcs(ref EditorTTDList); - if (bMultithreaded) - { - GSD.Threaded.TerrainCalcs tJob = new GSD.Threaded.TerrainCalcs(); - tJob.Setup(ref EditorTTDList, tSpline, tRoad); - tRoad.TerrainCalcsJob = tJob; - tJob.Start(); - } - else - { - GSD.Threaded.TerrainCalcs_Static.RunMe(ref EditorTTDList, tSpline, tRoad); - } - } - - public static GSDRoadUtil.Construction2DRect GetTerrainBounds(Terrain tTerrain) - { - float terrainWidth = tTerrain.terrainData.size.x; - float terrainLength = tTerrain.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 = tTerrain.transform.TransformPoint(X0); - X1 = tTerrain.transform.TransformPoint(X1); - X2 = tTerrain.transform.TransformPoint(X2); - X3 = tTerrain.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 GSDRoadUtil.Construction2DRect(P0, P1, P2, P3, tTerrain.transform.position.y); - } - - public static void ProcessRoad_Terrain_Hook2(GSDSplineC tSpline, ref List TTDList) - { - if (tSpline.tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_Terrain_Hook2"); } - ProcessRoad_Terrain_Hook2_Do(ref tSpline, ref TTDList); - if (tSpline.tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - } - private static void ProcessRoad_Terrain_Hook2_Do(ref GSDSplineC tSpline, ref List TTDList) - { - if (!tSpline.tRoad.opt_TreeModEnabled && !tSpline.tRoad.opt_HeightModEnabled && !tSpline.tRoad.opt_DetailModEnabled) - { - //Exit if no mod taking place. - return; - } - Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); - Terrain tTerrain; - int[,] tDetails = null; - int IntBufferX = 0; - int IntBufferY = 0; - int tVal = 0; - // ushort Invalid = 16384; - foreach (TempTerrainData TTD in TTDList) - { - foreach (GSDTerrain TID in TIDs) - { - if (TID.GSDID == TTD.GSDID) - { - tTerrain = TID.transform.gameObject.GetComponent(); - if (tTerrain != null) - { - //Details: - if (tSpline.tRoad.opt_DetailModEnabled) - { - for (int i = 0; i < TTD.DetailLayersCount; i++) - { - // 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(i) || TTD.MainDetailsX == null || TTD.MainDetailsX.Count < 1) { continue; } - tDetails = tTerrain.terrainData.GetDetailLayer(0, 0, TTD.DetailMaxIndex, TTD.DetailMaxIndex, i); - - 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[i].Add((ushort)IntBufferX); - TTD.DetailsY[i].Add((ushort)IntBufferY); - TTD.OldDetailsValue[i].Add((ushort)tVal); - tDetails[IntBufferX, IntBufferY] = 0; - } - } - TTD.DetailsI[i] = TTD.DetailsX[i].Count; - - tTerrain.terrainData.SetDetailLayer(0, 0, i, tDetails); - tDetails = null; - TTD.DetailHasProcessed = null; - } - TTD.MainDetailsX = null; - TTD.MainDetailsY = null; - System.GC.Collect(); - } - //Trees: - if (tSpline.tRoad.opt_TreeModEnabled && TTD.TreesCurrent != null && TTD.TreesI > 0) - { - tTerrain.terrainData.treeInstances = TTD.TreesCurrent.ToArray(); - } - //Heights: - if (tSpline.tRoad.opt_HeightModEnabled && TTD.heights != null && TTD.cI > 0) - { - //Do heights last to trigger collisions and stuff properly: - tTerrain.terrainData.SetHeights(0, 0, TTD.heights); - } - } - } - } - } - } - - public static void TerrainsReset(GSDRoad tRoad) - { - TerrainsReset_Do(ref tRoad); - } - private static void TerrainsReset_Do(ref GSDRoad tRoad) - { - if (tRoad.TerrainHistory == null) { return; } - if (tRoad.TerrainHistory.Count < 1) { return; } - - Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); - float[,] heights; - int[,] tDetails; - int ArrayCount; - foreach (GSDTerrainHistoryMaker TH in tRoad.TerrainHistory) - { - Terrain tTerrain = null; - foreach (GSDTerrain TID in TIDs) - { - if (TID.GSDID == TH.TID) - { - tTerrain = TID.tTerrain; - } - } - if (!tTerrain) - { - continue; - } - - //Heights: - if (TH.x1 != null) - { - heights = tTerrain.terrainData.GetHeights(0, 0, tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight); - ArrayCount = TH.cI; - for (int i = 0; i < ArrayCount; i++) - { - heights[TH.x1[i], TH.y1[i]] = TH.h[i]; - } - tTerrain.terrainData.SetHeights(0, 0, heights); - } - //Details: - if (TH.DetailsI != null && TH.DetailsX != null && TH.DetailsY != null && TH.DetailsOldValue != null) - { - int RealLayerCount = tTerrain.terrainData.detailPrototypes.Length; - int StartIndex = 0; - int EndIndex = 0; - for (int i = 0; i < TH.DetailLayersCount; i++) - { - if (i >= RealLayerCount) { break; } - if (TH.DetailsX.Length <= i) { break; } - if (TH.DetailsY.Length <= i) { break; } - if (TH.DetailsX == null || TH.DetailsY == null || TH.DetailsI == null || TH.DetailsX.Length < 1) - { - continue; - } - - tDetails = tTerrain.terrainData.GetDetailLayer(0, 0, tTerrain.terrainData.detailWidth, tTerrain.terrainData.detailHeight, i); - ArrayCount = TH.DetailsI[i]; - 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; - tTerrain.terrainData.SetDetailLayer(0, 0, i, tDetails); - tDetails = null; - } - } - //Trees: - TreeInstance[] xTress = TH.MakeTrees(); - if (xTress != null) - { - ArrayCount = xTress.Length; - if (ArrayCount > 0 && TH.TreesOld != null) - { - int TerrainTreeCount = tTerrain.terrainData.treeInstances.Length; ; - TreeInstance[] tTrees = new TreeInstance[ArrayCount + TerrainTreeCount]; - System.Array.Copy(tTerrain.terrainData.treeInstances, 0, tTrees, 0, TerrainTreeCount); - System.Array.Copy(xTress, 0, tTrees, TerrainTreeCount, ArrayCount); - tTerrain.terrainData.treeInstances = tTrees; - } - xTress = null; - } - } - System.GC.Collect(); - } - } - - [System.Serializable] - public class GSDTerrainHistoryMaker - { - public int TID; - //Heights: - public int[] x1; - public int[] y1; - public float[] h; - public int cI; - public bool bHeightHistoryEnabled; - //Details: - public int DetailLayersCount; - - public int[] DetailsX; - public int[] DetailsY; - public int[] DetailsOldValue; - public int[] DetailsI; - - public bool bDetailHistoryEnabled; - //Trees: - public GSDTreeInstance[] TreesOld; - public int TreesI; - public bool bTreeHistoryEnabled; - public bool bDestroyMe = false; - - public void Nullify() - { - //Heights: - x1 = null; - y1 = null; - h = null; - DetailsX = null; - DetailsY = null; - DetailsOldValue = null; - DetailsI = null; - //Trees: - TreesOld = null; - } - - [System.Serializable] - public class GSDTreeInstance - { - public float colorR;//4 - public float colorG;//8 - public float colorB;//12 - public float colorA;//16 - public float heightScale;//20 - public float lightmapColorR;//24 - public float lightmapColorG;//28 - public float lightmapColorB;//32 - public float lightmapColorA;//36 - public float positionX;//40 - public float positionY;//44 - public float positionZ;//48 - public int prototypeIndex;//52 - public float widthScale;//56 - } - - public void MakeGSDTrees(ref List tTrees) - { - int tSize = tTrees.Count; - TreesOld = new GSDTreeInstance[tSize]; - GSDTreeInstance tTree = null; - TreeInstance xTree; - for (int i = 0; i < tSize; i++) - { - xTree = tTrees[i]; - tTree = new GSDTreeInstance(); - 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; - TreesOld[i] = tTree; - } - } - - public TreeInstance[] MakeTrees() - { - if (TreesOld == null || TreesOld.Length < 1) { return null; } - int tSize = TreesOld.Length; - TreeInstance[] tTrees = new TreeInstance[tSize]; - GSDTreeInstance tTree = null; - TreeInstance xTree; - for (int i = 0; i < tSize; i++) - { - tTree = TreesOld[i]; - 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[i] = xTree; - } - return tTrees; - } - - 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 (h != null) { tSize += (h.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 (DetailsI != null) { tSize += (DetailsI.Length * 4); tSize += 20; } - tSize += 1; - //Trees: - if (TreesOld != null) { tSize += (TreesOld.Length * 56); tSize += 20; } - tSize += 4; - tSize += 1; - tSize += 1; - - return tSize; - } - } - - public class RoadConstructorBufferMaker - { - public GSDRoad tRoad; - - public List RoadVectors; - public List ShoulderR_Vectors; - public List ShoulderL_Vectors; - - public int[] tris; - public int[] tris_ShoulderR; - public int[] tris_ShoulderL; - - public Vector3[] normals; - public Vector3[] normals_ShoulderR; - public Vector3[] normals_ShoulderL; - public List normals_ShoulderR_averageStartIndexes; - public List normals_ShoulderL_averageStartIndexes; - - public Vector2[] uv; - public Vector2[] uv2; - public Vector2[] uv_SR; - public Vector2[] uv_SL; - - public Vector4[] tangents; - public Vector4[] tangents2; - public Vector4[] tangents_SR; - public Vector4[] tangents_SL; - - public List> cut_RoadVectors; - public List cut_RoadVectorsHome; - public List> cut_ShoulderR_Vectors; - public List> cut_ShoulderL_Vectors; - public List cut_ShoulderR_VectorsHome; - public List cut_ShoulderL_VectorsHome; - public List cut_tris; - public List cut_tris_ShoulderR; - public List cut_tris_ShoulderL; - public List cut_normals; - public List cut_normals_ShoulderR; - public List cut_normals_ShoulderL; - public List cut_uv; - public List cut_uv_SR; - public List cut_uv_SL; - public List cut_tangents; - public List cut_tangents_SR; - public List cut_tangents_SL; - - public List cut_uv_world; - public List cut_uv_SR_world; - public List cut_uv_SL_world; - public List cut_tangents_world; - public List cut_tangents_SR_world; - public List cut_tangents_SL_world; - - //Road connections: - public List RoadConnections_verts; - public List RoadConnections_tris; - public List RoadConnections_normals; - public List RoadConnections_uv; - public List RoadConnections_tangents; - - //Back lanes: - public List iBLane0s; - public List iBLane1s; - public List iBLane1s_IsMiddleLane; - public List iBLane2s; - public List iBLane3s; - //Front lanes: - public List iFLane0s; - public List iFLane1s; - public List iFLane1s_IsMiddleLane; - public List iFLane2s; - public List iFLane3s; - //Main plates: - public List iBMainPlates; - public List iFMainPlates; - //Marker plates: - public List iBMarkerPlates; - public List iFMarkerPlates; - - //Back lanes: - public List iBLane0s_tris; - public List iBLane1s_tris; - public List iBLane2s_tris; - public List iBLane3s_tris; - //Front lanes: - public List iFLane0s_tris; - public List iFLane1s_tris; - public List iFLane2s_tris; - public List iFLane3s_tris; - //Main plates: - public List iBMainPlates_tris; - public List iFMainPlates_tris; - //Marker plates: - public List iBMarkerPlates_tris; - public List iFMarkerPlates_tris; - - //Back lanes: - public List iBLane0s_normals; - public List iBLane1s_normals; - public List iBLane2s_normals; - public List iBLane3s_normals; - //Front lanes: - public List iFLane0s_normals; - public List iFLane1s_normals; - public List iFLane2s_normals; - public List iFLane3s_normals; - //Main plates: - public List iBMainPlates_normals; - public List iFMainPlates_normals; - //Marker plates: - public List iBMarkerPlates_normals; - public List iFMarkerPlates_normals; - - //Back lanes: - public List iBLane0s_tID; - public List iBLane1s_tID; - public List iBLane2s_tID; - public List iBLane3s_tID; - //Front lanes: - public List iFLane0s_tID; - public List iFLane1s_tID; - public List iFLane2s_tID; - public List iFLane3s_tID; - //Main plates: - public List iBMainPlates_tID; - public List iFMainPlates_tID; - //Marker plates: - public List iBMarkerPlates_tID; - public List iFMarkerPlates_tID; - - //Back lanes: - public List iBLane0s_nID; - public List iBLane1s_nID; - public List iBLane2s_nID; - public List iBLane3s_nID; - //Front lanes: - public List iFLane0s_nID; - public List iFLane1s_nID; - public List iFLane2s_nID; - public List iFLane3s_nID; - //Main plates: - public List iBMainPlates_nID; - public List iFMainPlates_nID; - //Marker plates: - public List iBMarkerPlates_nID; - public List iFMarkerPlates_nID; - - //Back lanes: - public List iBLane0s_uv; - public List iBLane1s_uv; - public List iBLane2s_uv; - public List iBLane3s_uv; - //Front lanes: - public List iFLane0s_uv; - public List iFLane1s_uv; - public List iFLane2s_uv; - public List iFLane3s_uv; - //Main plates: - public List iBMainPlates_uv; - public List iFMainPlates_uv; - public List iBMainPlates_uv2; - public List iFMainPlates_uv2; - //Marker plates: - public List iBMarkerPlates_uv; - public List iFMarkerPlates_uv; - - //Back lanes: - public List iBLane0s_tangents; - public List iBLane1s_tangents; - public List iBLane2s_tangents; - public List iBLane3s_tangents; - //Front lanes: - public List iFLane0s_tangents; - public List iFLane1s_tangents; - public List iFLane2s_tangents; - public List iFLane3s_tangents; - //Main plates: - public List iBMainPlates_tangents; - public List iFMainPlates_tangents; - public List iBMainPlates_tangents2; - public List iFMainPlates_tangents2; - //Marker plates: - public List iBMarkerPlates_tangents; - public List iFMarkerPlates_tangents; - - public Terrain tTerrain; - - public List tIntersectionBounds; - public HashSet ImmuneVects; - - public Mesh tMesh; - public Mesh tMesh_SR; - public Mesh tMesh_SL; - public bool tMeshSkip = false; - public bool tMesh_SRSkip = false; - public bool tMesh_SLSkip = false; - public List tMesh_RoadCuts; - public List tMesh_SRCuts; - public List tMesh_SLCuts; - public List tMesh_RoadCuts_world; - public List tMesh_SRCuts_world; - public List tMesh_SLCuts_world; - - public List tMesh_RoadConnections; - - public List tMesh_iBLanes0; - public List tMesh_iBLanes1; - public List tMesh_iBLanes2; - public List tMesh_iBLanes3; - public List tMesh_iFLanes0; - public List tMesh_iFLanes1; - public List tMesh_iFLanes2; - public List tMesh_iFLanes3; - public List tMesh_iBMainPlates; - public List tMesh_iFMainPlates; - public List tMesh_iBMarkerPlates; - public List tMesh_iFMarkerPlates; - - public RoadUpdateTypeEnum tUpdateType; - - public bool bRoadOn = true; - public bool bTerrainOn = true; - public bool bBridgesOn = true; - public bool bInterseOn = true; - - public List RoadCuts; - public List RoadCutNodes; - public List ShoulderCutsR; - public List ShoulderCutsRNodes; - public List ShoulderCutsL; - public List ShoulderCutsLNodes; - - public enum SaveMeshTypeEnum { Road, Shoulder, Intersection, Railing, Center, Bridge, RoadCut, SCut, BSCut, RoadConn }; - - public RoadConstructorBufferMaker(GSDRoad _tRoad, RoadUpdateTypeEnum _tUpdateType) - { - tUpdateType = _tUpdateType; - bRoadOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); - bTerrainOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); - bBridgesOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Bridges); - bInterseOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection); - - tRoad = _tRoad; - Nullify(); - RoadVectors = new List(); - ShoulderR_Vectors = new List(); - ShoulderL_Vectors = new List(); - normals_ShoulderR_averageStartIndexes = new List(); - normals_ShoulderL_averageStartIndexes = new List(); - - cut_RoadVectors = new List>(); - cut_RoadVectorsHome = new List(); - cut_ShoulderR_Vectors = new List>(); - cut_ShoulderL_Vectors = new List>(); - cut_ShoulderR_VectorsHome = new List(); - cut_ShoulderL_VectorsHome = new List(); - cut_tris = new List(); - cut_tris_ShoulderR = new List(); - cut_tris_ShoulderL = new List(); - cut_normals = new List(); - cut_normals_ShoulderR = new List(); - cut_normals_ShoulderL = new List(); - cut_uv = new List(); - cut_uv_SR = new List(); - cut_uv_SL = new List(); - cut_tangents = new List(); - cut_tangents_SR = new List(); - cut_tangents_SL = new List(); - - cut_uv_world = new List(); - cut_uv_SR_world = new List(); - cut_uv_SL_world = new List(); - cut_tangents_world = new List(); - cut_tangents_SR_world = new List(); - cut_tangents_SL_world = new List(); - - RoadCutNodes = new List(); - ShoulderCutsRNodes = new List(); - ShoulderCutsLNodes = new List(); - - RoadConnections_verts = new List(); - RoadConnections_tris = new List(); - RoadConnections_normals = new List(); - RoadConnections_uv = new List(); - RoadConnections_tangents = new List(); - - RoadCuts = new List(); - ShoulderCutsR = new List(); - ShoulderCutsL = new List(); - - //if(bInterseOn){ - //Back lanes: - iBLane0s = new List(); - iBLane1s = new List(); - iBLane2s = new List(); - iBLane3s = new List(); - //Front lanes: - iFLane0s = new List(); - iFLane1s = new List(); - iFLane2s = new List(); - iFLane3s = new List(); - //Main plates: - iBMainPlates = new List(); - iFMainPlates = new List(); - //Marker plates: - iBMarkerPlates = new List(); - iFMarkerPlates = new List(); - - //Back lanes: - iBLane0s_tris = new List(); - iBLane1s_tris = new List(); - iBLane2s_tris = new List(); - iBLane3s_tris = new List(); - //Front lanes: - iFLane0s_tris = new List(); - iFLane1s_tris = new List(); - iFLane2s_tris = new List(); - iFLane3s_tris = new List(); - //Main plates: - iBMainPlates_tris = new List(); - iFMainPlates_tris = new List(); - //Marker plates: - iBMarkerPlates_tris = new List(); - iFMarkerPlates_tris = new List(); - - //Back lanes: - iBLane0s_normals = new List(); - iBLane1s_normals = new List(); - iBLane2s_normals = new List(); - iBLane3s_normals = new List(); - //Front lanes: - iFLane0s_normals = new List(); - iFLane1s_normals = new List(); - iFLane2s_normals = new List(); - iFLane3s_normals = new List(); - //Main plates: - iBMainPlates_normals = new List(); - iFMainPlates_normals = new List(); - //Marker plates: - iBMarkerPlates_normals = new List(); - iFMarkerPlates_normals = new List(); - - //Back lanes: - iBLane0s_uv = new List(); - iBLane1s_uv = new List(); - iBLane2s_uv = new List(); - iBLane3s_uv = new List(); - //Front lanes: - iFLane0s_uv = new List(); - iFLane1s_uv = new List(); - iFLane2s_uv = new List(); - iFLane3s_uv = new List(); - //Main plates: - iBMainPlates_uv = new List(); - iFMainPlates_uv = new List(); - iBMainPlates_uv2 = new List(); - iFMainPlates_uv2 = new List(); - //Marker plates: - iBMarkerPlates_uv = new List(); - iFMarkerPlates_uv = new List(); - - //Back lanes: - iBLane0s_tangents = new List(); - iBLane1s_tangents = new List(); - iBLane2s_tangents = new List(); - iBLane3s_tangents = new List(); - //Front lanes: - iFLane0s_tangents = new List(); - iFLane1s_tangents = new List(); - iFLane2s_tangents = new List(); - iFLane3s_tangents = new List(); - //Main plates: - iBMainPlates_tangents = new List(); - iFMainPlates_tangents = new List(); - iBMainPlates_tangents2 = new List(); - iFMainPlates_tangents2 = new List(); - //Marker plates: - iBMarkerPlates_tangents = new List(); - iFMarkerPlates_tangents = new List(); - - iFLane1s_IsMiddleLane = new List(); - iBLane1s_IsMiddleLane = new List(); - - //Back lanes: - iBLane0s_tID = new List(); - iBLane1s_tID = new List(); - iBLane2s_tID = new List(); - iBLane3s_tID = new List(); - //Front lanes: - iFLane0s_tID = new List(); - iFLane1s_tID = new List(); - iFLane2s_tID = new List(); - iFLane3s_tID = new List(); - //Main plates: - iBMainPlates_tID = new List(); - iFMainPlates_tID = new List(); - //Marker plates: - iBMarkerPlates_tID = new List(); - iFMarkerPlates_tID = new List(); - - iBLane0s_nID = new List(); - iBLane1s_nID = new List(); - iBLane2s_nID = new List(); - iBLane3s_nID = new List(); - //Front lanes: - iFLane0s_nID = new List(); - iFLane1s_nID = new List(); - iFLane2s_nID = new List(); - iFLane3s_nID = new List(); - //Main plates: - iBMainPlates_nID = new List(); - iFMainPlates_nID = new List(); - //Marker plates: - iBMarkerPlates_nID = new List(); - iFMarkerPlates_nID = new List(); - //} - - tTerrain = null; - - tMesh = new Mesh(); - tMesh_SR = new Mesh(); - tMesh_SL = new Mesh(); - tMesh_RoadCuts = new List(); - tMesh_SRCuts = new List(); - tMesh_SLCuts = new List(); - tMesh_RoadCuts_world = new List(); - tMesh_SRCuts_world = new List(); - tMesh_SLCuts_world = new List(); - - tMesh_RoadConnections = new List(); - - //if(bInterseOn){ - tMesh_iBLanes0 = new List(); - tMesh_iBLanes1 = new List(); - tMesh_iBLanes2 = new List(); - tMesh_iBLanes3 = new List(); - tMesh_iFLanes0 = new List(); - tMesh_iFLanes1 = new List(); - tMesh_iFLanes2 = new List(); - tMesh_iFLanes3 = new List(); - tMesh_iBMainPlates = new List(); - tMesh_iFMainPlates = new List(); - tMesh_iBMarkerPlates = new List(); - tMesh_iFMarkerPlates = new List(); - tIntersectionBounds = new List(); - ImmuneVects = new HashSet(); - //} - - InitGameObjects(); - } - - #region "Init and nullify" - private void InitGameObjects() - { - //Destry past objects: - if (tRoad.MainMeshes != null) - { - MeshFilter[] MFArray = tRoad.MainMeshes.GetComponentsInChildren(); - MeshCollider[] MCArray = tRoad.MainMeshes.GetComponentsInChildren(); - - int MFArrayCount = MFArray.Length; - int MCArrayCount = MCArray.Length; - for (int i = (MFArrayCount - 1); i > -1; i--) - { - MFArray[i].sharedMesh = null; - } - for (int i = (MCArrayCount - 1); i > -1; i--) - { - MCArray[i].sharedMesh = null; - } - - Object.DestroyImmediate(tRoad.MainMeshes); - } - - //Main mesh object: - tRoad.MainMeshes = new GameObject("MainMeshes"); - tRoad.MainMeshes.transform.parent = tRoad.transform; - - //Road and shoulders: - tRoad.MeshRoad = new GameObject("RoadMesh"); - tRoad.MeshShoR = new GameObject("ShoulderR"); - tRoad.MeshShoL = new GameObject("ShoulderL"); - tRoad.MeshRoad.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshShoR.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshShoL.transform.parent = tRoad.MainMeshes.transform; - - //Intersections: - tRoad.MeshiLanes = new GameObject("MeshiLanes"); - tRoad.MeshiLanes0 = new GameObject("MeshiLanes0"); - tRoad.MeshiLanes1 = new GameObject("MeshiLanes1"); - tRoad.MeshiLanes2 = new GameObject("MeshiLanes2"); - tRoad.MeshiLanes3 = new GameObject("MeshiLanes3"); - tRoad.MeshiMainPlates = new GameObject("MeshiMainPlates"); - tRoad.MeshiMarkerPlates = new GameObject("MeshiMarkerPlates"); - tRoad.MeshiLanes.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiLanes0.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiLanes1.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiLanes2.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiLanes3.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiMainPlates.transform.parent = tRoad.MainMeshes.transform; - tRoad.MeshiMarkerPlates.transform.parent = tRoad.MainMeshes.transform; - } - - public void Nullify() - { - RoadVectors = null; - ShoulderR_Vectors = null; - ShoulderL_Vectors = null; - tris = null; - normals = null; - uv = null; - uv_SR = null; - uv_SL = null; - tangents = null; - tangents_SR = null; - tangents_SL = null; - tTerrain = null; - tIntersectionBounds = null; - ImmuneVects = null; - iBLane0s = null; - iBLane1s = null; - iBLane2s = null; - iBLane3s = null; - iFLane0s = null; - iFLane1s = null; - iFLane2s = null; - iFLane3s = null; - iBMainPlates = null; - iFMainPlates = null; - iBMarkerPlates = null; - iFMarkerPlates = null; - tMesh = null; - tMesh_SR = null; - tMesh_SL = null; - if (tMesh_iBLanes0 != null) { tMesh_iBLanes0.Clear(); tMesh_iBLanes0 = null; } - if (tMesh_iBLanes1 != null) { tMesh_iBLanes1.Clear(); tMesh_iBLanes1 = null; } - if (tMesh_iBLanes2 != null) { tMesh_iBLanes2.Clear(); tMesh_iBLanes2 = null; } - if (tMesh_iBLanes3 != null) { tMesh_iBLanes3.Clear(); tMesh_iBLanes3 = null; } - if (tMesh_iFLanes0 != null) { tMesh_iFLanes0.Clear(); tMesh_iFLanes0 = null; } - if (tMesh_iFLanes1 != null) { tMesh_iFLanes1.Clear(); tMesh_iFLanes1 = null; } - if (tMesh_iFLanes2 != null) { tMesh_iFLanes2.Clear(); tMesh_iFLanes2 = null; } - if (tMesh_iFLanes3 != null) { tMesh_iFLanes3.Clear(); tMesh_iFLanes3 = null; } - if (tMesh_iBMainPlates != null) { tMesh_iBMainPlates.Clear(); tMesh_iBMainPlates = null; } - if (tMesh_iFMainPlates != null) { tMesh_iFMainPlates.Clear(); tMesh_iFMainPlates = null; } - if (tMesh_iBMarkerPlates != null) { tMesh_iBMarkerPlates.Clear(); tMesh_iBMarkerPlates = null; } - if (tMesh_iFMarkerPlates != null) { tMesh_iFMarkerPlates.Clear(); tMesh_iFMarkerPlates = null; } - tMesh_RoadConnections = null; - - iFLane1s_IsMiddleLane = null; - iBLane1s_IsMiddleLane = null; - - RoadConnections_verts = null; - RoadConnections_tris = null; - RoadConnections_normals = null; - RoadConnections_uv = null; - RoadConnections_tangents = null; - - if (cut_uv_world != null) { cut_uv_world.Clear(); cut_uv_world = null; } - if (cut_uv_SR_world != null) { cut_uv_SR_world.Clear(); cut_uv_SR_world = null; } - if (cut_uv_SL_world != null) { cut_uv_SL_world.Clear(); cut_uv_SL_world = null; } - if (cut_tangents_world != null) { cut_tangents_world.Clear(); cut_tangents_world = null; } - if (cut_tangents_SR_world != null) { cut_tangents_SR_world.Clear(); cut_tangents_SR_world = null; } - if (cut_tangents_SL_world != null) { cut_tangents_SL_world.Clear(); cut_tangents_SL_world = null; } - - - tMesh = null; - tMesh_SR = null; - tMesh_SL = null; - tMesh_SR = null; - tMesh_SL = null; - tMesh_RoadCuts = null; - tMesh_SRCuts = null; - tMesh_SLCuts = null; - tMesh_RoadCuts_world = null; - tMesh_SRCuts_world = null; - tMesh_SLCuts_world = null; - } - #endregion - - #region "Mesh Setup1" - public void MeshSetup1() - { - MeshSetup1_Do(); - } - - /// - /// Creates meshes and assigns vertices, triangles and normals. If multithreading enabled, this occurs inbetween threaded jobs since unity library can't be used in threads. - /// - private void MeshSetup1_Do() - { - Mesh MeshBuffer = null; - - if (bInterseOn) - { - MeshSetup1_IntersectionObjectsSetup(); - } - - if (bRoadOn) - { - //Main road: - if (RoadVectors.Count < 64000) - { - if (tMesh == null) { tMesh = new Mesh(); } - tMesh = MeshSetup1_Helper(ref tMesh, RoadVectors.ToArray(), ref tris, ref normals); - tMeshSkip = false; - } - else - { - tMeshSkip = true; - } - - //Right shoulder: - if (ShoulderR_Vectors.Count < 64000) - { - if (tMesh_SR == null) { tMesh_SR = new Mesh(); } - tMesh_SR = MeshSetup1_Helper(ref tMesh_SR, ShoulderR_Vectors.ToArray(), ref tris_ShoulderR, ref normals_ShoulderR); - tMesh_SRSkip = false; - } - else - { - tMesh_SRSkip = true; - } - - //Left shoulder: - if (ShoulderL_Vectors.Count < 64000) - { - if (tMesh_SL == null) { tMesh_SL = new Mesh(); } - tMesh_SL = MeshSetup1_Helper(ref tMesh_SL, ShoulderL_Vectors.ToArray(), ref tris_ShoulderL, ref normals_ShoulderL); - tMesh_SLSkip = false; - } - else - { - tMesh_SLSkip = true; - } - - if (RoadConnections_verts.Count > 0) - { - Mesh qMesh = null; - for (int i = 0; i < RoadConnections_verts.Count; i++) - { - qMesh = new Mesh(); - qMesh.vertices = RoadConnections_verts[i]; - qMesh.triangles = RoadConnections_tris[i]; - qMesh.normals = RoadConnections_normals[i]; - qMesh.uv = RoadConnections_uv[i]; - qMesh.RecalculateNormals(); - RoadConnections_normals[i] = qMesh.normals; - tMesh_RoadConnections.Add(qMesh); - } - } - - - if ((tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts) && RoadCuts.Count > 0) - { - int[] tTris = null; - Vector3[] tNormals = null; - int cCount = cut_RoadVectors.Count; - for (int i = 0; i < cCount; i++) - { - tTris = cut_tris[i]; - tNormals = cut_normals[i]; - MeshBuffer = new Mesh(); - tMesh_RoadCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_RoadVectors[i].ToArray(), ref tTris, ref tNormals)); - MeshBuffer = new Mesh(); - tMesh_RoadCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_RoadVectors[i].ToArray(), ref tTris, ref tNormals)); - cut_normals[i] = tNormals; - tMeshSkip = true; - } - } - if (tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) - { - int[] tTris = null; - Vector3[] tNormals = null; - int rCount = cut_ShoulderR_Vectors.Count; - for (int i = 0; i < rCount; i++) - { - tTris = cut_tris_ShoulderR[i]; - tNormals = cut_normals_ShoulderR[i]; - MeshBuffer = new Mesh(); - tMesh_SRCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderR_Vectors[i].ToArray(), ref tTris, ref tNormals)); - MeshBuffer = new Mesh(); - tMesh_SRCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderR_Vectors[i].ToArray(), ref tTris, ref tNormals)); - cut_normals_ShoulderR[i] = tNormals; - tMesh_SRSkip = true; - } - if (rCount <= 0) - { - tMesh_SRSkip = false; - } - int lCount = cut_ShoulderL_Vectors.Count; - for (int i = 0; i < lCount; i++) - { - tTris = cut_tris_ShoulderL[i]; - tNormals = cut_normals_ShoulderL[i]; - MeshBuffer = new Mesh(); - tMesh_SLCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderL_Vectors[i].ToArray(), ref tTris, ref tNormals)); - MeshBuffer = new Mesh(); - tMesh_SLCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderL_Vectors[i].ToArray(), ref tTris, ref tNormals)); - cut_normals_ShoulderL[i] = tNormals; - tMesh_SLSkip = true; - } - if (lCount <= 0) - { - tMesh_SLSkip = false; - } - } - } - - if (bInterseOn) - { - MeshSetup1_IntersectionParts(); - } - - MeshBuffer = null; - } - - #region "Intersection for MeshSetup1" - private void MeshSetup1_IntersectionObjectsSetup() - { - int mCount = tRoad.GSDSpline.GetNodeCount(); - List tGSDRIs = new List(); - for (int i = 0; i < mCount; i++) - { - if (tRoad.GSDSpline.mNodes[i].bIsIntersection) - { - if (!tGSDRIs.Contains(tRoad.GSDSpline.mNodes[i].GSDRI)) - { - tGSDRIs.Add(tRoad.GSDSpline.mNodes[i].GSDRI); - } - } - } - - //Cleanups: - foreach (GSDRoadIntersection GSDRI in tGSDRIs) - { - GSDIntersectionObjects.CleanupIntersectionObjects(GSDRI.transform.gameObject); - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDIntersectionObjects.CreateStopSignsAllWay(GSDRI.transform.gameObject, true); - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1) - { - GSDIntersectionObjects.CreateTrafficLightBases(GSDRI.transform.gameObject, true); - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.None) - { - //Do nothing. - } - } - } - - private void MeshSetup1_IntersectionParts() - { - int mCount = tRoad.GSDSpline.GetNodeCount(); - bool bHasInter = false; - for (int i = 0; i < mCount; i++) - { - if (tRoad.GSDSpline.mNodes[i].bIsIntersection) - { - bHasInter = true; - break; - } - } - if (!bHasInter) - { - return; - } - - int vCount = -1; - Mesh MeshBuffer = null; - Vector3[] tNormals = null; - int[] tTris = null; - //Back lanes: - vCount = iBLane0s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iBLane0s_normals[i]; - tTris = iBLane0s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane0s[i], ref tTris, ref tNormals); - tMesh_iBLanes0.Add(MeshBuffer); - } - vCount = iBLane1s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iBLane1s_normals[i]; - tTris = iBLane1s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane1s[i], ref tTris, ref tNormals); - tMesh_iBLanes1.Add(MeshBuffer); - } - vCount = iBLane2s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iBLane2s_normals[i]; - tTris = iBLane2s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane2s[i], ref tTris, ref tNormals); - tMesh_iBLanes2.Add(MeshBuffer); - } - vCount = iBLane3s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iBLane3s_normals[i]; - tTris = iBLane3s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane3s[i], ref tTris, ref tNormals); - tMesh_iBLanes3.Add(MeshBuffer); - } - //Front lanes: - vCount = iFLane0s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iFLane0s_normals[i]; - tTris = iFLane0s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane0s[i], ref tTris, ref tNormals); - tMesh_iFLanes0.Add(MeshBuffer); - } - vCount = iFLane1s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iFLane1s_normals[i]; - tTris = iFLane1s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane1s[i], ref tTris, ref tNormals); - tMesh_iFLanes1.Add(MeshBuffer); - } - vCount = iFLane2s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iFLane2s_normals[i]; - tTris = iFLane2s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane2s[i], ref tTris, ref tNormals); - tMesh_iFLanes2.Add(MeshBuffer); - } - vCount = iFLane3s.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iFLane3s_normals[i]; - tTris = iFLane3s_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane3s[i], ref tTris, ref tNormals); - tMesh_iFLanes3.Add(MeshBuffer); - } - //Main plates: - vCount = iBMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iBMainPlates_normals[i]; - tTris = iBMainPlates_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBMainPlates[i], ref tTris, ref tNormals); - tMesh_iBMainPlates.Add(MeshBuffer); - } - vCount = iFMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - tNormals = iFMainPlates_normals[i]; - tTris = iFMainPlates_tris[i]; - MeshBuffer = new Mesh(); - MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFMainPlates[i], ref tTris, ref tNormals); - tMesh_iFMainPlates.Add(MeshBuffer); - } - - MeshBuffer = null; - } - #endregion - - private Mesh MeshSetup1_Helper(ref Mesh xMesh, Vector3[] verts, ref int[] tris, ref Vector3[] normals) - { - xMesh.vertices = verts; - xMesh.triangles = tris; - xMesh.normals = normals; - xMesh.RecalculateNormals(); - normals = xMesh.normals; - // xMesh.hideFlags = HideFlags.DontSave; - return xMesh; - } - #endregion - - #region "Mesh Setup2" - public void MeshSetup2() - { - MeshSetup2_Do(); - } - - /// - /// Assigns UV and tangents to meshes. If multithreading enabled, this occurs after the last threaded job since unity library can't be used in threads. - /// - private void MeshSetup2_Do() - { - Mesh MeshMainBuffer = null; - Mesh MeshMarkerBuffer = null; - - if (bRoadOn) - { - //If road cuts is off, full size UVs: - if ((!tRoad.opt_bRoadCuts && !tRoad.opt_bDynamicCuts) || (RoadCuts == null || RoadCuts.Count <= 0)) - { - if (tMesh != null) - { - tMesh = MeshSetup2_Helper(ref tMesh, uv, tangents, ref tRoad.MeshRoad, true); - SaveMesh(SaveMeshTypeEnum.Road, tMesh, tRoad, tRoad.MeshRoad.transform.name); - - Vector3[] ooVerts = new Vector3[tMesh.vertexCount]; - int[] ooTris = new int[tMesh.triangles.Length]; - Vector3[] ooNormals = new Vector3[tMesh.normals.Length]; - Vector2[] ooUV = new Vector2[uv2.Length]; - Vector4[] ooTangents = new Vector4[tangents2.Length]; - - System.Array.Copy(tMesh.vertices, ooVerts, ooVerts.Length); - System.Array.Copy(tMesh.triangles, ooTris, ooTris.Length); - System.Array.Copy(tMesh.normals, ooNormals, ooNormals.Length); - System.Array.Copy(uv2, ooUV, ooUV.Length); - System.Array.Copy(tangents2, ooTangents, ooTangents.Length); - - Mesh pMesh = new Mesh(); - pMesh.vertices = ooVerts; - pMesh.triangles = ooTris; - pMesh.normals = ooNormals; - pMesh.uv = ooUV; - pMesh.tangents = ooTangents; - - GameObject gObj = new GameObject("Pavement"); - pMesh = MeshSetup2_Helper(ref pMesh, uv2, tangents2, ref gObj, false); - gObj.transform.parent = tRoad.MeshRoad.transform; //Road markers stored on parent "MeshRoad" game object, with a "Pavement" child game object storing the asphalt. - SaveMesh(SaveMeshTypeEnum.Road, pMesh, tRoad, gObj.transform.name); - } - } - else - { - //If road cuts, change it to one material (pavement) with world mapping - int cCount = cut_RoadVectors.Count; - // Vector2[] tUV; - GameObject CreatedMainObj; - GameObject CreatedMarkerObj; - for (int i = 0; i < cCount; i++) - { - CreatedMainObj = null; - MeshMainBuffer = tMesh_RoadCuts_world[i]; - if (MeshMainBuffer != null) - { - MeshSetup2_Helper_RoadCuts(i, ref MeshMainBuffer, cut_uv_world[i], cut_tangents_world[i], ref tRoad.MeshRoad, false, out CreatedMainObj); - SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMainBuffer, tRoad, "RoadCut" + i.ToString()); - } - - CreatedMarkerObj = null; - MeshMarkerBuffer = tMesh_RoadCuts[i]; - bool bHasMats = false; - if (MeshMarkerBuffer != null) - { - bHasMats = MeshSetup2_Helper_RoadCuts(i, ref MeshMarkerBuffer, cut_uv[i], cut_tangents[i], ref CreatedMainObj, true, out CreatedMarkerObj); - if (bHasMats) - { - SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMarkerBuffer, tRoad, "RoadCutMarker" + i.ToString()); - } - else - { - //Destroy if no marker materials: - Object.DestroyImmediate(CreatedMarkerObj); - Object.DestroyImmediate(MeshMarkerBuffer); - } - } - } - - //Remove main mesh stuff if necessary: - if (tRoad.MeshRoad != null) - { - MeshCollider tMC = tRoad.MeshRoad.GetComponent(); - MeshRenderer tMR = tRoad.MeshRoad.GetComponent(); - if (tMC != null) - { - Object.DestroyImmediate(tMC); - } - if (tMR != null) - { - Object.DestroyImmediate(tMR); - } - } - if (tMesh != null) - { - Object.DestroyImmediate(tMesh); - } - } - - //Shoulders: - if (tRoad.opt_bShouldersEnabled) - { - if ((!tRoad.opt_bShoulderCuts && !tRoad.opt_bDynamicCuts) || (ShoulderCutsL == null || cut_ShoulderL_Vectors.Count <= 0)) - { - //Right road shoulder: - if (tMesh_SR != null) - { - tMesh_SR = MeshSetup2_Helper(ref tMesh_SR, uv_SR, tangents_SR, ref tRoad.MeshShoR, false, true); - SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SR, tRoad, tRoad.MeshShoR.transform.name); - } - - //Left road shoulder: - if (tMesh_SL != null) - { - tMesh_SL = MeshSetup2_Helper(ref tMesh_SL, uv_SL, tangents_SL, ref tRoad.MeshShoL, false, true); - SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SL, tRoad, tRoad.MeshShoL.transform.name); - } - } - else - { - GameObject CreatedMainObj; - GameObject CreatedMarkerObj; - int rCount = cut_ShoulderR_Vectors.Count; - for (int i = 0; i < rCount; i++) - { - bool bHasMats = false; - CreatedMainObj = null; - MeshMainBuffer = tMesh_SRCuts_world[i]; - if (MeshMainBuffer != null) - { - MeshSetup2_Helper_CutsShoulder(i, ref MeshMainBuffer, cut_uv_SR_world[i], cut_tangents_SR_world[i], ref tRoad.MeshShoR, false, false, out CreatedMainObj); - SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, tRoad, "SCutR" + i.ToString()); - } - - CreatedMarkerObj = null; - MeshMarkerBuffer = tMesh_SRCuts[i]; - if (MeshMarkerBuffer != null) - { - bHasMats = MeshSetup2_Helper_CutsShoulder(i, ref MeshMarkerBuffer, cut_uv_SR[i], cut_tangents_SR[i], ref CreatedMainObj, false, true, out CreatedMarkerObj); - if (bHasMats) - { - SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, tRoad, "SCutRMarker" + i.ToString()); - } - else - { - //Destroy if no marker materials: - Object.DestroyImmediate(CreatedMarkerObj); - Object.DestroyImmediate(MeshMarkerBuffer); - } - } - } - - int lCount = cut_ShoulderL_Vectors.Count; - for (int i = 0; i < lCount; i++) - { - bool bHasMats = false; - CreatedMainObj = null; - MeshMainBuffer = tMesh_SLCuts_world[i]; - if (MeshMainBuffer != null) - { - MeshSetup2_Helper_CutsShoulder(i, ref MeshMainBuffer, cut_uv_SL_world[i], cut_tangents_SL_world[i], ref tRoad.MeshShoL, true, false, out CreatedMainObj); - SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, tRoad, "SCutL" + i.ToString()); - } - - - CreatedMarkerObj = null; - MeshMarkerBuffer = tMesh_SLCuts[i]; - if (MeshMarkerBuffer != null) - { - bHasMats = MeshSetup2_Helper_CutsShoulder(i, ref MeshMarkerBuffer, cut_uv_SL[i], cut_tangents_SL[i], ref CreatedMainObj, true, true, out CreatedMarkerObj); - if (bHasMats) - { - SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, tRoad, "SCutLMarker" + i.ToString()); - } - else - { - //Destroy if no marker materials: - Object.DestroyImmediate(CreatedMarkerObj); - Object.DestroyImmediate(MeshMarkerBuffer); - } - } - } - - if (tRoad.opt_bUseMeshColliders) - { - // MeshSetup2_Intersections_FixNormals(); - } - - //Remove main mesh stuff if necessary: - if (tMesh_SR != null) - { - Object.DestroyImmediate(tMesh_SR); - } - if (tMesh_SL != null) - { - Object.DestroyImmediate(tMesh_SL); - } - - if (tRoad.MeshShoR != null) - { - MeshCollider tMC = tRoad.MeshShoR.GetComponent(); - MeshRenderer tMR = tRoad.MeshShoR.GetComponent(); - if (tMC != null) { Object.DestroyImmediate(tMC); } - if (tMR != null) { Object.DestroyImmediate(tMR); } - } - if (tRoad.MeshShoL != null) - { - MeshCollider tMC = tRoad.MeshShoL.GetComponent(); - MeshRenderer tMR = tRoad.MeshShoL.GetComponent(); - if (tMC != null) { Object.DestroyImmediate(tMC); } - if (tMR != null) { Object.DestroyImmediate(tMR); } - } - } - } - else - { - //Remove main mesh stuff if necessary: - if (tMesh_SR != null) - { - Object.DestroyImmediate(tMesh_SR); - } - if (tMesh_SL != null) - { - Object.DestroyImmediate(tMesh_SL); - } - - if (tRoad.MeshShoR != null) - { - MeshCollider tMC = tRoad.MeshShoR.GetComponent(); - MeshRenderer tMR = tRoad.MeshShoR.GetComponent(); - if (tMC != null) { Object.DestroyImmediate(tMC); } - if (tMR != null) { Object.DestroyImmediate(tMR); } - } - if (tRoad.MeshShoL != null) - { - MeshCollider tMC = tRoad.MeshShoL.GetComponent(); - MeshRenderer tMR = tRoad.MeshShoL.GetComponent(); - if (tMC != null) { Object.DestroyImmediate(tMC); } - if (tMR != null) { Object.DestroyImmediate(tMR); } - } - - Mesh tBuffer = null; - int xCount = tMesh_SRCuts_world.Count; - for (int i = 0; i < xCount; i++) - { - tBuffer = tMesh_SRCuts_world[i]; - Object.DestroyImmediate(tBuffer); - tMesh_SRCuts_world[i] = null; - } - xCount = tMesh_SRCuts.Count; - for (int i = 0; i < xCount; i++) - { - tBuffer = tMesh_SRCuts[i]; - Object.DestroyImmediate(tBuffer); - tMesh_SRCuts[i] = null; - } - xCount = tMesh_SLCuts_world.Count; - for (int i = 0; i < xCount; i++) - { - tBuffer = tMesh_SLCuts_world[i]; - Object.DestroyImmediate(tBuffer); - tMesh_SLCuts_world[i] = null; - } - xCount = tMesh_SLCuts.Count; - for (int i = 0; i < xCount; i++) - { - tBuffer = tMesh_SLCuts[i]; - Object.DestroyImmediate(tBuffer); - tMesh_SLCuts[i] = null; - } - - if (tRoad.MeshShoR != null) - { - Object.DestroyImmediate(tRoad.MeshShoR); - } - - if (tRoad.MeshShoL != null) - { - Object.DestroyImmediate(tRoad.MeshShoL); - } - } - - - for (int i = 0; i < RoadConnections_tangents.Count; i++) - { - tMesh_RoadConnections[i].tangents = RoadConnections_tangents[i]; - GameObject tObj = new GameObject("RoadConnectionMarker"); - MeshFilter MF = tObj.AddComponent(); - MeshRenderer MR = tObj.AddComponent(); - float fDist = Vector3.Distance(RoadConnections_verts[i][2], RoadConnections_verts[i][3]); - fDist = Mathf.Round(fDist); - if (tRoad.opt_Lanes == 2) - { - if (fDist == Mathf.Round(tRoad.RoadWidth() * 2f)) - { - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-4L.mat", MR); - } - else if (fDist == Mathf.Round(tRoad.RoadWidth() * 3f)) - { - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-6L-2L.mat", MR); - } - } - else if (tRoad.opt_Lanes == 4) - { - if (fDist == Mathf.Round(tRoad.RoadWidth() * 1.5f)) - { - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-6L-4L.mat", MR); - } - } - MF.sharedMesh = tMesh_RoadConnections[i]; - tObj.transform.parent = tRoad.MeshRoad.transform; - - Mesh vMesh = new Mesh(); - vMesh.vertices = RoadConnections_verts[i]; - vMesh.triangles = RoadConnections_tris[i]; - vMesh.normals = RoadConnections_normals[i]; - Vector2[] vUV = new Vector2[4]; - vUV[0] = new Vector2(RoadConnections_verts[i][0].x / 5f, RoadConnections_verts[i][0].z / 5f); - vUV[1] = new Vector2(RoadConnections_verts[i][1].x / 5f, RoadConnections_verts[i][1].z / 5f); - vUV[2] = new Vector2(RoadConnections_verts[i][2].x / 5f, RoadConnections_verts[i][2].z / 5f); - vUV[3] = new Vector2(RoadConnections_verts[i][3].x / 5f, RoadConnections_verts[i][3].z / 5f); - vMesh.uv = vUV; - vMesh.RecalculateNormals(); - RoadConnections_normals[i] = vMesh.normals; - vMesh.tangents = GSDRootUtil.ProcessTangents(vMesh.triangles, vMesh.normals, vMesh.uv, vMesh.vertices); - - tObj = new GameObject("RoadConnectionBase"); - MF = tObj.AddComponent(); - MR = tObj.AddComponent(); - MeshCollider MC = tObj.AddComponent(); - MF.sharedMesh = vMesh; - MC.sharedMesh = MF.sharedMesh; - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", MR); - tObj.transform.parent = tRoad.MeshRoad.transform; - - SaveMesh(SaveMeshTypeEnum.RoadConn, vMesh, tRoad, "RoadConn" + i.ToString()); - } - } - - if (bInterseOn) - { - MeshSetup2_Intersections(); - } - - if (tRoad.MeshiLanes != null) { Object.DestroyImmediate(tRoad.MeshiLanes); } - if (tRoad.MeshiLanes0 != null) { Object.DestroyImmediate(tRoad.MeshiLanes0); } - if (tRoad.MeshiLanes1 != null) { Object.DestroyImmediate(tRoad.MeshiLanes1); } - if (tRoad.MeshiLanes2 != null) { Object.DestroyImmediate(tRoad.MeshiLanes2); } - if (tRoad.MeshiLanes3 != null) { Object.DestroyImmediate(tRoad.MeshiLanes3); } - if (tRoad.MeshiMainPlates != null) { Object.DestroyImmediate(tRoad.MeshiMainPlates); } - if (tRoad.MeshiMarkerPlates != null) { Object.DestroyImmediate(tRoad.MeshiMarkerPlates); } - - //Updates the road and shoulder cut materials if necessary. Note: Cycling through all nodes in case the road cuts and shoulder cut numbers don't match. - if (tRoad.opt_bRoadCuts || tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) - { - int mCount = tRoad.GSDSpline.GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - tRoad.GSDSpline.mNodes[i].UpdateCuts(); - } - } - } - - #region "MeshSetup2 - Intersections" - // private void MeshSetup2_Intersections_FixNormals(){ - // int mCount = tRoad.GSDSpline.GetNodeCount(); - // GSDSplineN tNode = null; - // GSDRoadIntersection GSDRI = null; - // float MaxDist = 0f; - // float[] tDists = new float[2]; - // Collider[] tColliders = null; - // List tCuts = null; - // - // for(int h=0;h(); - // foreach(Collider tCollider in tColliders){ - // if(tCollider.transform.name.Contains("cut")){ - // tCuts.Add(tCollider.transform.gameObject); - // } - // } - // - // - // - // foreach(GameObject tObj in tCuts){ - // MeshFilter MF1 = tCuts[0].GetComponent(); - // if(MF1 == null){ continue; } - // Mesh zMesh1 = MF1.sharedMesh; - // Vector3[] tVerts1 = zMesh1.vertices; - // Vector3[] tNormals1 = zMesh1.normals; - // int MVL1 = tVerts1.Length; - // for(int i=0;i> tCombineDict_Lane0 = new Dictionary>(); - Dictionary> tCombineDict_Lane1 = new Dictionary>(); - Dictionary> tCombineDict_Lane2 = new Dictionary>(); - Dictionary> tCombineDict_Lane3 = new Dictionary>(); - Dictionary> tCombineDict_MainPlate = new Dictionary>(); - Dictionary> tCombineDict_MainPlateM = new Dictionary>(); - HashSet UniqueGSDRI = new HashSet(); - - Dictionary> tCombineDict_Lane1_Disabled = new Dictionary>(); - Dictionary> tCombineDict_Lane2_Disabled = new Dictionary>(); - Dictionary> tCombineDict_Lane2_DisabledActive = new Dictionary>(); - Dictionary> tCombineDict_Lane2_DisabledActiveR = new Dictionary>(); - Dictionary> tCombineDict_Lane3_Disabled = new Dictionary>(); - Dictionary> tCombineDict_Lane1_DisabledActive = new Dictionary>(); - - vCount = iBLane0s.Count; - for (int i = 0; i < vCount; i++) - { - tUV = iBLane0s_uv[i]; - tTangents = iBLane0s_tangents[i]; - xMesh = tMesh_iBLanes0[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes0, "Lane0B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR.mat"); - if (!tCombineDict_Lane0.ContainsKey(iBLane0s_tID[i])) - { - tCombineDict_Lane0.Add(iBLane0s_tID[i], new List()); - } - tCombineDict_Lane0[iBLane0s_tID[i]].Add(MF); - } - vCount = iBLane1s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iBLane1s_tID[i].Node1 == iBLane1s_nID[i]); - if (!bPrimaryNode && iBLane1s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane || iBLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane1s_tID[i].bNode2B_LeftTurnLane) - { - tUV = iBLane1s_uv[i]; - tTangents = iBLane1s_tangents[i]; - xMesh = tMesh_iBLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneD1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - if (!tCombineDict_Lane1_Disabled.ContainsKey(iBLane1s_tID[i])) - { - tCombineDict_Lane1_Disabled.Add(iBLane1s_tID[i], new List()); - } - tCombineDict_Lane1_Disabled[iBLane1s_tID[i]].Add(MF); - } - else if (bPrimaryNode && iBLane1s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tUV = iBLane1s_uv[i]; - tTangents = iBLane1s_tangents[i]; - xMesh = tMesh_iBLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneDA1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); - if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iBLane1s_tID[i])) - { - tCombineDict_Lane1_DisabledActive.Add(iBLane1s_tID[i], new List()); - } - tCombineDict_Lane1_DisabledActive[iBLane1s_tID[i]].Add(MF); - } - else - { - tUV = iBLane1s_uv[i]; - tTangents = iBLane1s_tangents[i]; - xMesh = tMesh_iBLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "Lane1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); - if (!tCombineDict_Lane1.ContainsKey(iBLane1s_tID[i])) - { - tCombineDict_Lane1.Add(iBLane1s_tID[i], new List()); - } - tCombineDict_Lane1[iBLane1s_tID[i]].Add(MF); - } - } - vCount = iBLane2s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iBLane2s_tID[i].Node1 == iBLane2s_nID[i]); - if (!bPrimaryNode && iBLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane || iBLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane2s_tID[i].bNode2B_LeftTurnLane) - { - tUV = iBLane2s_uv[i]; - tTangents = iBLane2s_tangents[i]; - xMesh = tMesh_iBLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); - if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iBLane2s_tID[i])) - { - tCombineDict_Lane2_DisabledActive.Add(iBLane2s_tID[i], new List()); - } - tCombineDict_Lane2_DisabledActive[iBLane2s_tID[i]].Add(MF); - } - else if (!bPrimaryNode && iBLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane2s_tID[i].bNode2B_RightTurnLane) - { - tUV = iBLane2s_uv[i]; - tTangents = iBLane2s_tangents[i]; - xMesh = tMesh_iBLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); - if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iBLane2s_tID[i])) - { - tCombineDict_Lane2_DisabledActiveR.Add(iBLane2s_tID[i], new List()); - } - tCombineDict_Lane2_DisabledActiveR[iBLane2s_tID[i]].Add(MF); - } - else if (bPrimaryNode && iBLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tUV = iBLane2s_uv[i]; - tTangents = iBLane2s_tangents[i]; - xMesh = tMesh_iBLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneD2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - if (!tCombineDict_Lane2_Disabled.ContainsKey(iBLane2s_tID[i])) - { - tCombineDict_Lane2_Disabled.Add(iBLane2s_tID[i], new List()); - } - tCombineDict_Lane2_Disabled[iBLane2s_tID[i]].Add(MF); - } - else - { - tUV = iBLane2s_uv[i]; - tTangents = iBLane2s_tangents[i]; - xMesh = tMesh_iBLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "Lane2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - if (!tCombineDict_Lane2.ContainsKey(iBLane2s_tID[i])) - { - tCombineDict_Lane2.Add(iBLane2s_tID[i], new List()); - } - tCombineDict_Lane2[iBLane2s_tID[i]].Add(MF); - } - } - vCount = iBLane3s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iBLane3s_tID[i].Node1 == iBLane3s_nID[i]); - if (!bPrimaryNode && iBLane3s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane3s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane3s_tID[i].bNode2B_RightTurnLane) - { - tUV = iBLane3s_uv[i]; - tTangents = iBLane3s_tangents[i]; - xMesh = tMesh_iBLanes3[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "LaneD3B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - if (!tCombineDict_Lane3_Disabled.ContainsKey(iBLane3s_tID[i])) - { - tCombineDict_Lane3_Disabled.Add(iBLane3s_tID[i], new List()); - } - tCombineDict_Lane3_Disabled[iBLane3s_tID[i]].Add(MF); - } - else - { - tUV = iBLane3s_uv[i]; - tTangents = iBLane3s_tangents[i]; - xMesh = tMesh_iBLanes3[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "Lane3B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - if (!tCombineDict_Lane3.ContainsKey(iBLane3s_tID[i])) - { - tCombineDict_Lane3.Add(iBLane3s_tID[i], new List()); - } - tCombineDict_Lane3[iBLane3s_tID[i]].Add(MF); - } - } - - //Front lanes: - vCount = iFLane0s.Count; - for (int i = 0; i < vCount; i++) - { - tUV = iFLane0s_uv[i]; - tTangents = iFLane0s_tangents[i]; - xMesh = tMesh_iFLanes0[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes0, "Lane0F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR.mat"); - if (!tCombineDict_Lane0.ContainsKey(iFLane0s_tID[i])) - { - tCombineDict_Lane0.Add(iFLane0s_tID[i], new List()); - } - tCombineDict_Lane0[iFLane0s_tID[i]].Add(MF); - } - vCount = iFLane1s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iFLane1s_tID[i].Node1 == iFLane1s_nID[i]); - if (!bPrimaryNode && iFLane1s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) && !iFLane1s_tID[i].bNode2F_LeftTurnLane) - { - tUV = iFLane1s_uv[i]; - tTangents = iFLane1s_tangents[i]; - xMesh = tMesh_iFLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneD1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - if (!tCombineDict_Lane1_Disabled.ContainsKey(iFLane1s_tID[i])) - { - tCombineDict_Lane1_Disabled.Add(iFLane1s_tID[i], new List()); - } - tCombineDict_Lane1_Disabled[iFLane1s_tID[i]].Add(MF); - } - else if (bPrimaryNode && iFLane1s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane1s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tUV = iFLane1s_uv[i]; - tTangents = iFLane1s_tangents[i]; - xMesh = tMesh_iFLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneDAR1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); - if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iFLane1s_tID[i])) - { - tCombineDict_Lane1_DisabledActive.Add(iFLane1s_tID[i], new List()); - } - tCombineDict_Lane1_DisabledActive[iFLane1s_tID[i]].Add(MF); - } - else - { - tUV = iFLane1s_uv[i]; - tTangents = iFLane1s_tangents[i]; - xMesh = tMesh_iFLanes1[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "Lane1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); - if (!tCombineDict_Lane1.ContainsKey(iFLane1s_tID[i])) - { - tCombineDict_Lane1.Add(iFLane1s_tID[i], new List()); - } - tCombineDict_Lane1[iFLane1s_tID[i]].Add(MF); - } - } - vCount = iFLane2s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iFLane2s_tID[i].Node1 == iFLane2s_nID[i]); - if (!bPrimaryNode && iFLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) && !iFLane2s_tID[i].bNode2F_LeftTurnLane) - { - tUV = iFLane2s_uv[i]; - tTangents = iFLane2s_tangents[i]; - xMesh = tMesh_iFLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); - if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iFLane2s_tID[i])) - { - tCombineDict_Lane2_DisabledActive.Add(iFLane2s_tID[i], new List()); - } - tCombineDict_Lane2_DisabledActive[iFLane2s_tID[i]].Add(MF); - } - else if (!bPrimaryNode && iFLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane2s_tID[i].bNode2F_RightTurnLane) - { - tUV = iFLane2s_uv[i]; - tTangents = iFLane2s_tangents[i]; - xMesh = tMesh_iFLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDAR2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); - if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iFLane2s_tID[i])) - { - tCombineDict_Lane2_DisabledActiveR.Add(iFLane2s_tID[i], new List()); - } - tCombineDict_Lane2_DisabledActiveR[iFLane2s_tID[i]].Add(MF); - } - else if (bPrimaryNode && iFLane2s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tUV = iFLane2s_uv[i]; - tTangents = iFLane2s_tangents[i]; - xMesh = tMesh_iFLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneD2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); - if (!tCombineDict_Lane2_Disabled.ContainsKey(iFLane2s_tID[i])) - { - tCombineDict_Lane2_Disabled.Add(iFLane2s_tID[i], new List()); - } - tCombineDict_Lane2_Disabled[iFLane2s_tID[i]].Add(MF); - } - else - { - tUV = iFLane2s_uv[i]; - tTangents = iFLane2s_tangents[i]; - xMesh = tMesh_iFLanes2[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "Lane2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - if (!tCombineDict_Lane2.ContainsKey(iFLane2s_tID[i])) - { - tCombineDict_Lane2.Add(iFLane2s_tID[i], new List()); - } - tCombineDict_Lane2[iFLane2s_tID[i]].Add(MF); - } - } - vCount = iFLane3s.Count; - for (int i = 0; i < vCount; i++) - { - bool bPrimaryNode = (iFLane3s_tID[i].Node1 == iFLane3s_nID[i]); - if (!bPrimaryNode && iFLane3s_tID[i].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane3s_tID[i].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane3s_tID[i].bNode2F_RightTurnLane) - { - tUV = iFLane3s_uv[i]; - tTangents = iFLane3s_tangents[i]; - xMesh = tMesh_iFLanes3[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "LaneD3F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - if (!tCombineDict_Lane3_Disabled.ContainsKey(iFLane3s_tID[i])) - { - tCombineDict_Lane3_Disabled.Add(iFLane3s_tID[i], new List()); - } - tCombineDict_Lane3_Disabled[iFLane3s_tID[i]].Add(MF); - } - else - { - tUV = iFLane3s_uv[i]; - tTangents = iFLane3s_tangents[i]; - xMesh = tMesh_iFLanes3[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "Lane3F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); - if (!tCombineDict_Lane3.ContainsKey(iFLane3s_tID[i])) - { - tCombineDict_Lane3.Add(iFLane3s_tID[i], new List()); - } - tCombineDict_Lane3[iFLane3s_tID[i]].Add(MF); - } - } - - //Main plates: - vCount = iBMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - tUV = iBMainPlates_uv[i]; - tTangents = iBMainPlates_tangents[i]; - xMesh = tMesh_iBMainPlates[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateB", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", false); - if (!tCombineDict_MainPlate.ContainsKey(iBMainPlates_tID[i])) - { - tCombineDict_MainPlate.Add(iBMainPlates_tID[i], new List()); - } - tCombineDict_MainPlate[iBMainPlates_tID[i]].Add(MF); - - Mesh fMesh = new Mesh(); - fMesh.vertices = iBMainPlates[i]; - fMesh.triangles = iBMainPlates_tris[i]; - fMesh.normals = iBMainPlates_normals[i]; - tUV = iBMainPlates_uv2[i]; - tTangents = iBMainPlates_tangents2[i]; - MF = MeshSetup2_Intersection_Helper(ref fMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateBM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterMainPlate1.mat"); - if (!tCombineDict_MainPlateM.ContainsKey(iBMainPlates_tID[i])) - { - tCombineDict_MainPlateM.Add(iBMainPlates_tID[i], new List()); - } - tCombineDict_MainPlateM[iBMainPlates_tID[i]].Add(MF); - } - vCount = iFMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - tUV = iFMainPlates_uv[i]; - tTangents = iFMainPlates_tangents[i]; - xMesh = tMesh_iFMainPlates[i]; - MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateFM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", false); - - if (!tCombineDict_MainPlate.ContainsKey(iFMainPlates_tID[i])) - { - tCombineDict_MainPlate.Add(iFMainPlates_tID[i], new List()); - } - tCombineDict_MainPlate[iFMainPlates_tID[i]].Add(MF); - - Mesh tMesh = new Mesh(); - tMesh.vertices = iFMainPlates[i]; - tMesh.triangles = iFMainPlates_tris[i]; - tMesh.normals = iFMainPlates_normals[i]; - tUV = iFMainPlates_uv2[i]; - tTangents = iFMainPlates_tangents2[i]; - MF = MeshSetup2_Intersection_Helper(ref tMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateFM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterMainPlate1.mat"); - if (!tCombineDict_MainPlateM.ContainsKey(iFMainPlates_tID[i])) - { - tCombineDict_MainPlateM.Add(iFMainPlates_tID[i], new List()); - } - tCombineDict_MainPlateM[iFMainPlates_tID[i]].Add(MF); - } - - vCount = tRoad.GSDSpline.GetNodeCount(); - GSDSplineN tNode = null; - for (int i = 0; i < vCount; i++) - { - tNode = tRoad.GSDSpline.mNodes[i]; - if (tNode.bIsIntersection && tNode.GSDRI != null && tNode.GSDRI.Node1 == tNode) - { - //Create center plate - Vector3[] xVerts = new Vector3[4]; - xVerts[0] = tNode.GSDRI.CornerLR; - xVerts[1] = tNode.GSDRI.CornerRR; - xVerts[2] = tNode.GSDRI.CornerLL; - xVerts[3] = tNode.GSDRI.CornerRL; - - - int[] xTris = new int[6]; - xTris[0] = 0; - xTris[1] = 2; - xTris[2] = 1; - xTris[3] = 2; - xTris[4] = 3; - xTris[5] = 1; - - Vector2[] xUV = new Vector2[4]; - xUV[0] = new Vector2(xVerts[0].x / 5f, xVerts[0].z / 5f); - xUV[1] = new Vector2(xVerts[1].x / 5f, xVerts[1].z / 5f); - xUV[2] = new Vector2(xVerts[2].x / 5f, xVerts[2].z / 5f); - xUV[3] = new Vector2(xVerts[3].x / 5f, xVerts[3].z / 5f); - - Vector2[] xUV2 = new Vector2[4]; - xUV2[0] = new Vector2(0f, 0f); - xUV2[1] = new Vector2(1f, 0f); - xUV2[2] = new Vector2(0f, 1f); - xUV2[3] = new Vector2(1f, 1f); - - Mesh vMesh = new Mesh(); - vMesh.vertices = xVerts; - vMesh.triangles = xTris; - vMesh.normals = new Vector3[4]; - vMesh.uv = xUV; - vMesh.RecalculateBounds(); - vMesh.RecalculateNormals(); - vMesh.tangents = GSDRootUtil.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); - if (tRoad.opt_bIsLightmapped) - { - //UnityEditor.Unwrapping.GenerateSecondaryUVSet(vMesh); - } - - int cCount = tNode.GSDRI.transform.childCount; - List GOToDelete = new List(); - for (int j = 0; j < cCount; j++) - { - if (tNode.GSDRI.transform.GetChild(j).name.ToLower() == "tcenter") - { - GOToDelete.Add(tNode.GSDRI.transform.GetChild(j).gameObject); - } - if (tNode.GSDRI.transform.GetChild(j).name.ToLower() == "markcenter") - { - GOToDelete.Add(tNode.GSDRI.transform.GetChild(j).gameObject); - } - } - for (int j = GOToDelete.Count - 1; j >= 0; j--) - { - Object.DestroyImmediate(GOToDelete[j]); - } - - GameObject tCenter = new GameObject("tCenter"); - MF = tCenter.AddComponent(); - MF.sharedMesh = vMesh; - tCenter.transform.parent = tNode.GSDRI.transform; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(tCenter, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - tCenter.isStatic = true; - } - - - - Mesh mMesh = new Mesh(); - Vector3[] bVerts = new Vector3[4]; - mMesh.vertices = xVerts; - mMesh.triangles = xTris; - mMesh.normals = new Vector3[4]; - mMesh.uv = xUV2; - mMesh.RecalculateBounds(); - mMesh.RecalculateNormals(); - mMesh.tangents = GSDRootUtil.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); - - - GameObject tMarker = new GameObject("CenterMarkers"); - //tMarker.transform.localPosition = default(Vector3); - MF = tMarker.AddComponent(); - MF.sharedMesh = mMesh; - MeshRenderer MR = tMarker.AddComponent(); - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - // if(tNode.GSDRI.MarkerCenter != null){ - //// MR.material = tNode.GSDRI.MarkerCenter; - // } - tMarker.transform.parent = tNode.GSDRI.transform; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(tMarker, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - tMarker.isStatic = true; - } - - bVerts = MF.sharedMesh.vertices; - for (int j = 0; j < 4; j++) - { - bVerts[j].y = tNode.GSDRI.SignHeight; - } - - - int zCount = bVerts.Length; - for (int z = 0; z < zCount; z++) - { - bVerts[z] -= tNode.transform.position; - } - - MF.sharedMesh.vertices = bVerts; - - - - MR.transform.position = tNode.GSDRI.transform.position; - - mMesh.RecalculateBounds(); - if (tRoad.opt_bIsLightmapped) - { - //UnityEditor.Unwrapping.GenerateSecondaryUVSet(mMesh); - } - SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, tRoad, tNode.GSDRI.transform.name + "-" + "CenterMarkers"); - } - } - - // List MeshToDelete = new List(); - - foreach (KeyValuePair> KVP in tCombineDict_Lane0) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane0"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane1) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane1"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane2) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane2"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane3) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane3"); - } - foreach (KeyValuePair> KVP in tCombineDict_MainPlate) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "TiledExt", true); - } - foreach (KeyValuePair> KVP in tCombineDict_MainPlateM) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "StretchExt"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane1_Disabled) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD1"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane3_Disabled) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD3"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActive) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA2"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActiveR) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDAR2"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane2_Disabled) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD2"); - } - foreach (KeyValuePair> KVP in tCombineDict_Lane1_DisabledActive) - { - if (!UniqueGSDRI.Contains(KVP.Key)) { UniqueGSDRI.Add(KVP.Key); } - MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA1"); - } - - foreach (GSDRoadIntersection GSDRI in UniqueGSDRI) - { - GSDRI.UpdateMaterials(); - } - - } - - private void MeshSetup2_CombineIntersections(KeyValuePair> KVP, string tName, bool bMainPlates = false) - { - int vCount = KVP.Value.Count; - if (vCount < 1) { return; } - tName = tRoad.name + "-" + tName; - GameObject tCenter = null; - int cCount = KVP.Key.transform.childCount; - List GOToDelete = new List(); - for (int i = 0; i < cCount; i++) - { - if (KVP.Key.transform.GetChild(i).name.ToLower() == tName.ToLower()) - { - GOToDelete.Add(KVP.Key.transform.GetChild(i).gameObject); - } - if (bMainPlates && KVP.Key.transform.GetChild(i).name.ToLower() == "tcenter") - { - tCenter = KVP.Key.transform.GetChild(i).gameObject; - } - } - for (int i = GOToDelete.Count - 1; i >= 0; i--) - { - Object.DestroyImmediate(GOToDelete[i]); - } - - int CombineCount = vCount; - if (tCenter != null) { CombineCount += 1; } - CombineInstance[] combine = new CombineInstance[CombineCount]; - for (int i = 0; i < vCount; i++) - { - combine[i].mesh = KVP.Value[i].sharedMesh; - combine[i].transform = KVP.Value[i].transform.localToWorldMatrix; - } - - int SpecialVertCount = 0; - if (tCenter != null) - { - for (int i = 0; i < (CombineCount - 1); i++) - { - SpecialVertCount += combine[i].mesh.vertexCount; - } - MeshFilter tMF = tCenter.GetComponent(); - Vector3[] xVerts = tMF.sharedMesh.vertices; - float xHeight = combine[0].mesh.vertices[combine[0].mesh.vertexCount - 1].y; - for (int i = 0; i < xVerts.Length; i++) - { - xVerts[i].y = xHeight; - } - tMF.sharedMesh.vertices = xVerts; - combine[CombineCount - 1].mesh = tMF.sharedMesh; - combine[CombineCount - 1].transform = tMF.transform.localToWorldMatrix; - } - - GameObject tObj = new GameObject(tName); - MeshFilter MF = tObj.AddComponent(); - Mesh tMesh = new Mesh(); - tMesh.CombineMeshes(combine); - MF.sharedMesh = tMesh; - MeshRenderer MR = tObj.AddComponent(); - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - tObj.transform.parent = KVP.Key.transform; - Vector3[] tVerts = MF.sharedMesh.vertices; - Vector3 tVect = tObj.transform.localPosition; - // float tHeight = 0f; - for (int i = 0; i < tVerts.Length; i++) - { - tVerts[i] += tVect; - if (tName.ToLower().EndsWith("-stretchext")) - tVerts[i] += new Vector3(0f, 0.01f); - } - MF.sharedMesh.vertices = tVerts; - tObj.transform.localPosition = new Vector3(0f, 0f, 0f); - MF.sharedMesh.RecalculateBounds(); - MF.sharedMesh.RecalculateNormals(); - MF.sharedMesh.tangents = GSDRootUtil.ProcessTangents(MF.sharedMesh.triangles, MF.sharedMesh.normals, MF.sharedMesh.uv, MF.sharedMesh.vertices); - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.Unwrapping.GenerateSecondaryUVSet(MF.sharedMesh); - } - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - tObj.isStatic = true; - } - - - if (bMainPlates) - { - MeshCollider MC = tObj.AddComponent(); - MC.sharedMesh = MF.sharedMesh; - MC.material = tRoad.RoadPhysicMaterial; - } - - if (bMainPlates && tCenter != null) - { - Object.DestroyImmediate(tCenter); - } - - SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, tRoad, tName); - } - - private MeshFilter MeshSetup2_Intersection_Helper(ref Mesh xMesh, ref Vector2[] uv, ref Vector4[] tangents, ref GameObject MasterObj, string tName, string tMat, bool bCollider = false) - { - if (xMesh == null) { return null; } - xMesh.uv = uv; - xMesh.tangents = tangents; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.Unwrapping.GenerateSecondaryUVSet(xMesh); - } - - GameObject tObj = new GameObject(tName); - tObj.transform.parent = MasterObj.transform; - MeshFilter MF = tObj.AddComponent(); - MF.sharedMesh = xMesh; - if (bCollider) - { - MeshCollider MC = tObj.AddComponent(); - MC.sharedMesh = MF.sharedMesh; - } - if (tMat.Length < 1) { return null; } - MeshRenderer MR = tObj.AddComponent(); - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(tMat, MR); - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - tObj.isStatic = true; - } - - return MF; - } - #endregion - - private Mesh MeshSetup2_Helper(ref Mesh xMesh, Vector2[] uv, Vector4[] tangents, ref GameObject tObj, bool bMarker, bool bShoulder = false, bool bBridge = false) - { - xMesh.uv = uv; - xMesh.tangents = tangents; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.Unwrapping.GenerateSecondaryUVSet(xMesh); - } - MeshFilter MF = tObj.AddComponent(); - MF.sharedMesh = xMesh; - MeshCollider MC = null; - if (tRoad.opt_bUseMeshColliders) - { - MC = tObj.AddComponent(); - MC.sharedMesh = MF.sharedMesh; - } - MeshRenderer MR = tObj.AddComponent(); - - if (bShoulder) - { - int mCounter = 0; - if (tRoad.ShoulderMaterial1 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial2 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial3 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial4 != null) - { - mCounter += 1; - } - } - } - } - - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.ShoulderMaterial1 != null) - { - tMats[0] = tRoad.ShoulderMaterial1; - if (tRoad.ShoulderMaterial2 != null) - { - tMats[1] = tRoad.ShoulderMaterial2; - if (tRoad.ShoulderMaterial3 != null) - { - tMats[2] = tRoad.ShoulderMaterial3; - if (tRoad.ShoulderMaterial4 != null) - { - tMats[3] = tRoad.ShoulderMaterial4; - } - } - } - } - MR.materials = tMats; - } - } - else - { - if (bMarker) - { - int mCounter = 0; - if (tRoad.RoadMaterialMarker1 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker2 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker3 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker4 != null) - { - mCounter += 1; - } - } - } - } - - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.RoadMaterialMarker1 != null) - { - tMats[0] = tRoad.RoadMaterialMarker1; - if (tRoad.RoadMaterialMarker2 != null) - { - tMats[1] = tRoad.RoadMaterialMarker2; - if (tRoad.RoadMaterialMarker3 != null) - { - tMats[2] = tRoad.RoadMaterialMarker3; - if (tRoad.RoadMaterialMarker4 != null) - { - tMats[3] = tRoad.RoadMaterialMarker4; - } - } - } - } - MR.materials = tMats; - } - } - else - { - int mCounter = 0; - if (tRoad.RoadMaterial1 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial2 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial3 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.RoadMaterial1 != null) - { - tMats[0] = tRoad.RoadMaterial1; - if (tRoad.RoadMaterial2 != null) - { - tMats[1] = tRoad.RoadMaterial2; - if (tRoad.RoadMaterial3 != null) - { - tMats[2] = tRoad.RoadMaterial3; - if (tRoad.RoadMaterial4 != null) - { - tMats[3] = tRoad.RoadMaterial4; - } - } - } - } - MR.materials = tMats; - } - - if (MC) { MC.sharedMaterial = tRoad.RoadPhysicMaterial; } - } - } - - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - tObj.isStatic = true; - } - - return xMesh; - } - - private bool MeshSetup2_Helper_RoadCuts(int i, ref Mesh zMesh, Vector2[] uv, Vector4[] tangents, ref GameObject MasterObj, bool bIsMarkers, out GameObject CreatedObj) - { - string tName = "RoadCut" + i.ToString(); - if (bIsMarkers) - { - tName = "Markers" + i.ToString(); - } - CreatedObj = new GameObject(tName); - - if (!bIsMarkers) - { - RoadCutNodes[i].RoadCut_world = CreatedObj; - } - else - { - RoadCutNodes[i].RoadCut_marker = CreatedObj; - } - - CreatedObj.transform.position = cut_RoadVectorsHome[i]; - zMesh.uv = uv; - zMesh.tangents = tangents; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.Unwrapping.GenerateSecondaryUVSet(zMesh); - } - MeshFilter MF = CreatedObj.AddComponent(); - MF.sharedMesh = zMesh; - - MeshCollider MC = null; - if (tRoad.opt_bUseMeshColliders && !bIsMarkers) - { - MC = CreatedObj.AddComponent(); - if (MC.sharedMesh == null) - { - MC.sharedMesh = MF.sharedMesh; - } - } - MeshRenderer MR = CreatedObj.AddComponent(); - - //Disable shadows for road cuts and markers: - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - int mCounter = 0; - bool bHasMats = false; - - if (bIsMarkers) - { - - - //Get the mat count: - if (tRoad.RoadMaterialMarker1 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker2 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker3 != null) - { - mCounter += 1; - if (tRoad.RoadMaterialMarker4 != null) - { - mCounter += 1; - } - } - } - } - //Apply mats: - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.RoadMaterialMarker1 != null) - { - tMats[0] = tRoad.RoadMaterialMarker1; - if (tRoad.RoadMaterialMarker2 != null) - { - tMats[1] = tRoad.RoadMaterialMarker2; - if (tRoad.RoadMaterialMarker3 != null) - { - tMats[2] = tRoad.RoadMaterialMarker3; - if (tRoad.RoadMaterialMarker4 != null) - { - tMats[3] = tRoad.RoadMaterialMarker4; - } - } - } - } - MR.materials = tMats; - bHasMats = true; - } - } - else - { - //Get the mat count: - if (tRoad.RoadMaterial1 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial2 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial3 != null) - { - mCounter += 1; - if (tRoad.RoadMaterial4 != null) - { - mCounter += 1; - } - } - } - } - //Apply mats: - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.RoadMaterial1 != null) - { - tMats[0] = tRoad.RoadMaterial1; - if (tRoad.RoadMaterial2 != null) - { - tMats[1] = tRoad.RoadMaterial2; - if (tRoad.RoadMaterial3 != null) - { - tMats[2] = tRoad.RoadMaterial3; - if (tRoad.RoadMaterial4 != null) - { - tMats[3] = tRoad.RoadMaterial4; - } - } - } - } - MR.materials = tMats; - bHasMats = true; - } - } - - CreatedObj.transform.parent = MasterObj.transform; - if (!bIsMarkers && MC != null) { MC.sharedMaterial = tRoad.RoadPhysicMaterial; } - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(CreatedObj, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - CreatedObj.isStatic = true; - } - - return bHasMats; - } - - private bool MeshSetup2_Helper_CutsShoulder(int i, ref Mesh zMesh, Vector2[] uv, Vector4[] tangents, ref GameObject MasterObj, bool bIsLeft, bool bIsMarkers, out GameObject CreatedObj) - { - - string tName = ""; - if (bIsMarkers) - { - if (bIsLeft) - { - tName = "Markers" + i.ToString(); - } - else - { - tName = "Markers" + i.ToString(); - } - } - else - { - if (bIsLeft) - { - tName = "SCutL" + i.ToString(); - } - else - { - tName = "SCutR" + i.ToString(); - } - } - - CreatedObj = new GameObject(tName); - if (bIsLeft) - { - CreatedObj.transform.position = cut_ShoulderL_VectorsHome[i]; - if (!bIsMarkers) - { - ShoulderCutsLNodes[i].ShoulderCutL_world = CreatedObj; - } - else - { - ShoulderCutsLNodes[i].ShoulderCutL_marker = CreatedObj; - } - - } - else - { - CreatedObj.transform.position = cut_ShoulderR_VectorsHome[i]; - if (!bIsMarkers) - { - ShoulderCutsRNodes[i].ShoulderCutR_world = CreatedObj; - } - else - { - ShoulderCutsRNodes[i].ShoulderCutR_marker = CreatedObj; - } - } - - MeshCollider MC = null; - if (tRoad.opt_bUseMeshColliders) - { - MC = CreatedObj.AddComponent(); - } - - zMesh.uv = uv; - zMesh.tangents = tangents; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.Unwrapping.GenerateSecondaryUVSet(zMesh); - } - MeshFilter MF = CreatedObj.AddComponent(); - MF.sharedMesh = zMesh; - - if (tRoad.opt_bUseMeshColliders) - { - if (MC.sharedMesh == null) - { - MC.sharedMesh = MF.sharedMesh; - } - } - int mCounter = 0; - bool bHasMats = false; - - //Disable shadows for road cuts and markers: - MeshRenderer MR = CreatedObj.AddComponent(); - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - - if (bIsMarkers) - { - if (tRoad.ShoulderMaterialMarker1 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterialMarker2 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterialMarker3 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterialMarker4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.ShoulderMaterialMarker1 != null) - { - tMats[0] = tRoad.ShoulderMaterialMarker1; - if (tRoad.ShoulderMaterialMarker2 != null) - { - tMats[1] = tRoad.ShoulderMaterialMarker2; - if (tRoad.ShoulderMaterialMarker3 != null) - { - tMats[2] = tRoad.ShoulderMaterialMarker3; - if (tRoad.ShoulderMaterialMarker4 != null) - { - tMats[3] = tRoad.ShoulderMaterialMarker4; - } - } - } - } - - MR.materials = tMats; - bHasMats = true; - } - } - else - { - if (tRoad.ShoulderMaterial1 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial2 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial3 != null) - { - mCounter += 1; - if (tRoad.ShoulderMaterial4 != null) - { - mCounter += 1; - } - } - } - } - if (mCounter > 0) - { - Material[] tMats = new Material[mCounter]; - if (tRoad.ShoulderMaterial1 != null) - { - tMats[0] = tRoad.ShoulderMaterial1; - if (tRoad.ShoulderMaterial2 != null) - { - tMats[1] = tRoad.ShoulderMaterial2; - if (tRoad.ShoulderMaterial3 != null) - { - tMats[2] = tRoad.ShoulderMaterial3; - if (tRoad.ShoulderMaterial4 != null) - { - tMats[3] = tRoad.ShoulderMaterial4; - } - } - } - } - MR.materials = tMats; - MR = null; - bHasMats = true; - } - } - - if (!bIsMarkers && MC != null) { MC.sharedMaterial = tRoad.ShoulderPhysicMaterial; } - CreatedObj.transform.parent = MasterObj.transform; - if (tRoad.opt_bIsLightmapped) - { - UnityEditor.GameObjectUtility.SetStaticEditorFlags(CreatedObj, UnityEditor.StaticEditorFlags.LightmapStatic); - } - if (tRoad.opt_bIsStatic) - { - CreatedObj.isStatic = true; - } - - MF = null; - MC = null; - - return bHasMats; - } - #endregion - - private static void SaveMesh(SaveMeshTypeEnum SaveType, Mesh tMesh, GSDRoad tRoad, string tName) - { - if (!tRoad.GSDRS.opt_bSaveMeshes) { return; } - - //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); - string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; - tSceneName = tSceneName.Replace("/", ""); - tSceneName = tSceneName.Replace(".", ""); - string tFolderName = ""; - if (SaveType == SaveMeshTypeEnum.Road) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Roads/"; - } - else if (SaveType == SaveMeshTypeEnum.Shoulder) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Shoulders/"; - } - else if (SaveType == SaveMeshTypeEnum.Intersection) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Intersections/"; - } - else if (SaveType == SaveMeshTypeEnum.Railing) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Railings/"; - } - else if (SaveType == SaveMeshTypeEnum.Center) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/CenterDividers/"; - } - else if (SaveType == SaveMeshTypeEnum.RoadCut) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Roads/Cuts/"; - } - else if (SaveType == SaveMeshTypeEnum.SCut) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Shoulders/Cuts/"; - } - else if (SaveType == SaveMeshTypeEnum.RoadConn) - { - tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/RoadConn/"; - } - - string xPath = Application.dataPath.Replace("/Assets", "/" + tFolderName); - if (!System.IO.Directory.Exists(xPath)) - { - System.IO.Directory.CreateDirectory(xPath); - } - - string tRoadName = tRoad.transform.name; - string FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + ".asset"; - if (SaveType == SaveMeshTypeEnum.Intersection) - { - FinalName = tFolderName + tSceneName + "-" + tName + ".asset"; - } - - UnityEditor.AssetDatabase.CreateAsset(tMesh, FinalName); - } - } - - public static class GSDGeneralEditor - { - #region "Terrain history serialization" - //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; - } - } - - public static void TerrainHistory_Save(List tObj, GSDRoad tRoad) - { - string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); - if (string.IsNullOrEmpty(tPath) || tPath.Length < 2) { return; } - Stream stream = File.Open(tPath, FileMode.Create); - BinaryFormatter bformatter = new BinaryFormatter(); - bformatter.Binder = new VersionDeserializationBinder(); - bformatter.Serialize(stream, tObj); - tRoad.TerrainHistoryByteSize = (stream.Length * 0.001f).ToString("n0") + " kb"; - stream.Close(); - } - - public static void TerrainHistory_Delete(GSDRoad tRoad) - { - string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); - if (System.IO.File.Exists(tPath)) - { - System.IO.File.Delete(tPath); - } - } - - public static List TerrainHistory_Load(GSDRoad tRoad) - { - string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); - if (string.IsNullOrEmpty(tPath) || tPath.Length < 2) { return null; } - if (!File.Exists(tPath)) { return null; } - List result; - Stream stream = File.Open(tPath, FileMode.Open); - BinaryFormatter bFormatter = new BinaryFormatter(); - bFormatter.Binder = new VersionDeserializationBinder(); - // try{ - result = (List)bFormatter.Deserialize(stream) as List; - // }catch{ - // result = null; - // } - stream.Close(); - return result; - } - - private static string GetRoadTHFilename(ref GSDRoad tRoad) - { - //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); - string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; - tSceneName = tSceneName.Replace("/", ""); - tSceneName = tSceneName.Replace(".", ""); - string tRoadName = tRoad.GSDRS.transform.name.Replace("RoadArchitectSystem", "RAS") + "-" + tRoad.transform.name; - return tSceneName + "-" + tRoadName + "-TH.gsd"; - } - - public static string CheckNonAssetDir() - { - string tPath = GSDRootUtil.Dir_GetBase(); - if (!System.IO.Directory.Exists(tPath)) - { - System.IO.Directory.CreateDirectory(tPath); - } - if (System.IO.Directory.Exists(tPath)) - { - return tPath + "/"; - } - else - { - return ""; - } - } - - public static string CheckNonAssetDirTH() - { - CheckNonAssetDir(); - string xPath = GSDRootUtil.Dir_GetTH(); - if (!System.IO.Directory.Exists(xPath)) - { - System.IO.Directory.CreateDirectory(xPath); - } - if (System.IO.Directory.Exists(xPath)) - { - return xPath; - } - else - { - return ""; - } - } - - public static string CheckNonAssetDirLibrary() - { - CheckNonAssetDir(); - string xPath = GSDRootUtil.Dir_GetLibrary(); - if (!System.IO.Directory.Exists(xPath)) - { - System.IO.Directory.CreateDirectory(xPath); - } - if (System.IO.Directory.Exists(xPath)) - { - return xPath; - } - else - { - return ""; - } - } - - public static void CheckNonAssetDirs() - { - CheckNonAssetDir(); - CheckNonAssetDirTH(); - CheckNonAssetDirLibrary(); - } - #endregion - } - - public static class GSDRoadUtil - { - private const string FileSepString = "\n!!!! MICROGSD !!!!\n"; - private const string FileSepStringCRLF = "\r\n!!!! MICROGSD !!!!\r\n"; - - public static Terrain GetTerrain(Vector3 tVect) - { - return GetTerrain_Do(ref tVect); - } - private static Terrain GetTerrain_Do(ref Vector3 tVect) - { - //Sphere cast 5m first. Then raycast down 1000m, then up 1000m. - Collider[] tColliders = Physics.OverlapSphere(tVect, 10f); - if (tColliders != null) - { - int tCollidersLength = tColliders.Length; - for (int i = 0; i < tCollidersLength; i++) - { - Terrain tTerrain = tColliders[i].transform.GetComponent(); - if (tTerrain) - { - tColliders = null; - return tTerrain; - } - } - tColliders = null; - } - - RaycastHit[] tHits; - tHits = Physics.RaycastAll(tVect, Vector3.down, 1000f); - int tHitsLength = 0; - if (tHits != null) - { - tHitsLength = tHits.Length; - for (int i = 0; i < tHitsLength; i++) - { - Terrain tTerrain = tHits[i].collider.transform.GetComponent(); - if (tTerrain) - { - tHits = null; - return tTerrain; - } - } - tHits = null; - } - - tHits = Physics.RaycastAll(tVect, Vector3.up, 1000f); - if (tHits != null) - { - tHitsLength = tHits.Length; - for (int i = 0; i < tHitsLength; i++) - { - Terrain tTerrain = tHits[i].collider.transform.GetComponent(); - if (tTerrain) - { - tHits = null; - return tTerrain; - } - } - tHits = null; - } - return null; - } - - #region "Terrain history" - public static void ConstructRoad_StoreTerrainHistory(ref GSDRoad tRoad) - { - ConstructRoad_DoStoreTerrainHistory(ref tRoad); - } - private static void ConstructRoad_DoStoreTerrainHistory(ref GSDRoad tRoad) - { - Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); - - HashSet tTIDS = new HashSet(); - foreach (GSDTerrain TID in TIDs) - { - tTIDS.Add(TID.GSDID); - } - - if (tRoad.TerrainHistory != null && tRoad.TerrainHistory.Count > 0) - { - //Delete unnecessary terrain histories: - foreach (GSDTerrainHistoryMaker THf in tRoad.TerrainHistory) - { - if (!tTIDS.Contains(THf.TID)) - { - THf.Nullify(); - THf.bDestroyMe = true; - } - } - - int hCount = tRoad.TerrainHistory.Count; - for (int i = hCount - 1; i >= 0; i--) - { - if (tRoad.TerrainHistory[i].bDestroyMe) - { - GSDTerrainHistoryMaker THf = tRoad.TerrainHistory[i]; - tRoad.TerrainHistory.RemoveAt(i); - if (THf != null) { THf = null; } - } - } - } - - if (tRoad.TerrainHistory == null) { tRoad.TerrainHistory = new List(); } - foreach (GSDTerraforming.TempTerrainData TTD in tRoad.EditorTTDList) - { - GSDTerrainHistoryMaker TH = null; - GSDTerrain TID = null; - //Get TID: - foreach (GSDTerrain _TID in TIDs) - { - if (_TID.GSDID == TTD.GSDID) - { - TID = _TID; - } - } - - if (tRoad.TerrainHistory == null) { tRoad.TerrainHistory = new List(); } - if (TID == null) { continue; } - - int THCount = tRoad.TerrainHistory.Count; - bool bContainsTID = false; - for (int i = 0; i < THCount; i++) - { - if (tRoad.TerrainHistory[i].TID == TID.GSDID) - { - bContainsTID = true; - break; - } - } - - if (!bContainsTID) - { - GSDTerrainHistoryMaker THx = new GSDTerrainHistoryMaker(); - THx.TID = TID.GSDID; - tRoad.TerrainHistory.Add(THx); - } - - TH = null; - for (int i = 0; i < THCount; i++) - { - if (tRoad.TerrainHistory[i].TID == TID.GSDID) - { - TH = tRoad.TerrainHistory[i]; - break; - } - } - if (TH == null) { continue; } - - //Heights: - if (tRoad.opt_HeightModEnabled) - { - if (TTD.cX != null && TTD.cY != null) - { - TH.x1 = new int[TTD.cI]; - System.Array.Copy(TTD.cX, 0, TH.x1, 0, TTD.cI); - TH.y1 = new int[TTD.cI]; - System.Array.Copy(TTD.cY, 0, TH.y1, 0, TTD.cI); - TH.h = new float[TTD.cI]; - System.Array.Copy(TTD.oldH, 0, TH.h, 0, TTD.cI); - TH.cI = TTD.cI; - } - } - else - { - TH.x1 = null; - TH.y1 = null; - TH.h = null; - TH.cI = 0; - } - //Details: - if (tRoad.opt_DetailModEnabled) - { - int TotalSize = 0; - for (int i = 0; i < TTD.DetailLayersCount; i++) - { - TotalSize += TTD.DetailsI[i]; - } - - // float tHalf = (float)TotalSize / 2f; - // int IntHalf = Mathf.CeilToInt(tHalf); - - TH.DetailsX = new int[TotalSize]; - TH.DetailsY = new int[TotalSize]; - TH.DetailsOldValue = new int[TotalSize]; - - int RunningIndex = 0; - int cLength = 0; - for (int i = 0; i < TTD.DetailLayersCount; i++) - { - cLength = TTD.DetailsI[i]; - if (cLength < 1) { continue; } - System.Array.Copy(TTD.DetailsX[i].ToArray(), 0, TH.DetailsX, RunningIndex, cLength); - System.Array.Copy(TTD.DetailsY[i].ToArray(), 0, TH.DetailsY, RunningIndex, cLength); - System.Array.Copy(TTD.OldDetailsValue[i].ToArray(), 0, TH.DetailsOldValue, RunningIndex, cLength); - RunningIndex += TTD.DetailsI[i]; - } - - // TH.DetailsX = TTD.DetailsX; - // TH.DetailsY = TTD.DetailsY; - // TH.DetailsOldValue = TTD.OldDetailsValue; - TH.DetailsI = TTD.DetailsI; - TH.DetailLayersCount = TTD.DetailLayersCount; - } - else - { - TH.DetailsX = null; - TH.DetailsY = null; - TH.DetailsOldValue = null; - TH.DetailsI = null; - TH.DetailLayersCount = 0; - } - //Trees: - if (tRoad.opt_TreeModEnabled) - { - if (TTD.TreesOld != null) - { - TH.MakeGSDTrees(ref TTD.TreesOld); - TTD.TreesOld.Clear(); - TTD.TreesOld = null; - TH.TreesI = TTD.TreesI; - } - } - else - { - TH.TreesOld = null; - TH.TreesI = 0; - } - } - - // //TerrainHistoryRaw - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("TerrainHistorySerialize"); } - // TerrainHistorySerialize(ref tRoad); - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } - } - - // static void TerrainHistorySerialize(ref GSDRoad tRoad) { - // MemoryStream ms = new MemoryStream(); - // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); - // formatter.Serialize(ms,tRoad.TerrainHistory); - // ms.Close(); - // tRoad.TerrainHistoryRaw = ms.ToArray(); - // ms = null; - // } - // - // static void TerrainHistoryDeserialize(ref GSDRoad tRoad) { - // MemoryStream ms = new MemoryStream(tRoad.TerrainHistoryRaw); - // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); - // tRoad.TerrainHistory = (List)formatter.Deserialize(ms); - // ms.Close(); - // ms = null; - // } - - public static void ConstructRoad_ResetTerrainHistory(ref GSDRoad tRoad) - { - ConstructRoad_DoResetTerrainHistory(ref tRoad); - } - - private static void ConstructRoad_DoResetTerrainHistory(ref GSDRoad tRoad) - { - if (tRoad.TerrainHistory != null) - { - tRoad.TerrainHistory.Clear(); - tRoad.TerrainHistory = null; - } - } - #endregion - - [System.Serializable] - public class Construction3DTri - { - public Vector3 P1, P2, P3; - const float NearDist = 0.15f; - const float NearDistSQ = 0.0225f; - Vector2[] poly2D; - Vector3[] poly3D; - public float MaxDistance = 200f; - public float MaxDistanceSq = 200f; - public Vector3 normal = default(Vector3); - public Vector3 pMiddle = default(Vector3); - public float MinI = 0f; - public float MaxI = 1f; - - public Construction3DTri(Vector3 _P1, Vector3 _P2, Vector3 _P3, float _MinI, float _MaxI) - { - MinI = _MinI; - MaxI = _MaxI; - P1 = _P1; - P2 = _P2; - P3 = _P3; - - poly2D = new Vector2[3]; - poly2D[0] = new Vector2(P1.x, P1.z); - poly2D[1] = new Vector2(P2.x, P2.z); - poly2D[2] = new Vector2(P3.x, P3.z); - - poly3D = new Vector3[3]; - poly3D[0] = P1; - poly3D[1] = P2; - poly3D[2] = P3; - - float[] tMaxes = new float[3]; - tMaxes[0] = Vector3.Distance(P1, P2); - tMaxes[1] = Vector3.Distance(P1, P3); - tMaxes[2] = Vector3.Distance(P2, P3); - MaxDistance = Mathf.Max(tMaxes) * 1.5f; - - float[] tMaxesSQ = new float[3]; - tMaxesSQ[0] = Vector3.SqrMagnitude(P1 - P2); - tMaxesSQ[1] = Vector3.SqrMagnitude(P1 - P3); - tMaxesSQ[2] = Vector3.SqrMagnitude(P2 - P3); - MaxDistanceSq = Mathf.Max(tMaxesSQ) * 1.5f; - - PlaneFrom3Points(out normal, out pMiddle, P1, P2, P3); - - normal = Vector3.Cross((P3 - P1), (P2 - P1)); - - //// //This creates middle point: - // Vector3 tMiddle1 = ((P3-P1)*0.5f)+P1; - // Vector3 tMiddle2 = ((P2-P1)*0.5f)+P1; - // pMiddle = ((tMiddle2-tMiddle1)*0.5f)+tMiddle1; - } - - //Get the intersection between a line and a plane. - //If the line and plane are not parallel, the function outputs true, otherwise false. - public Vector3 LinePlaneIntersection(ref Vector3 F1) - { - F1.y = 0f; - - //calculate the distance between the linePoint and the line-plane intersection point - float dotNumerator = Vector3.Dot((pMiddle - F1), normal); - float dotDenominator = Vector3.Dot(Vector3.up.normalized, normal); - - //line and plane are not parallel - if (!IsApproximately(0f, dotDenominator, 0.001f)) - { - //get the coordinates of the line-plane intersection point - return (F1 + (Vector3.up.normalized * (dotNumerator / dotDenominator))); - } - else - { - //output not valid - return default(Vector3); - } - } - - static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - - //Convert a plane defined by 3 points to a plane defined by a vector and a point. - //The plane point is the middle of the triangle defined by the 3 points. - public static void PlaneFrom3Points(out Vector3 planeNormal, out Vector3 planePoint, Vector3 pointA, Vector3 pointB, Vector3 pointC) - { - planeNormal = Vector3.zero; - planePoint = Vector3.zero; - - //Make two vectors from the 3 input points, originating from point A - Vector3 AB = pointB - pointA; - Vector3 AC = pointC - pointA; - - //Calculate the normal - planeNormal = Vector3.Normalize(Vector3.Cross(AB, AC)); - - //Get the points in the middle AB and AC - Vector3 middleAB = pointA + (AB / 2.0f); - Vector3 middleAC = pointA + (AC / 2.0f); - - //Get vectors from the middle of AB and AC to the point which is not on that line. - Vector3 middleABtoC = pointC - middleAB; - Vector3 middleACtoB = pointB - middleAC; - - //Calculate the intersection between the two lines. This will be the center - //of the triangle defined by the 3 points. - //We could use LineLineIntersection instead of ClosestPointsOnTwoLines but due to rounding errors - //this sometimes doesn't work. - Vector3 temp; - ClosestPointsOnTwoLines(out planePoint, out temp, middleAB, middleABtoC, middleAC, middleACtoB); - } - - //Two non-parallel lines which may or may not touch each other have a point on each line which are closest - //to each other. This function finds those two points. If the lines are not parallel, the function - //outputs true, otherwise false. - public static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2) - { - - closestPointLine1 = Vector3.zero; - closestPointLine2 = Vector3.zero; - - float a = Vector3.Dot(lineVec1, lineVec1); - float b = Vector3.Dot(lineVec1, lineVec2); - float e = Vector3.Dot(lineVec2, lineVec2); - - float d = a * e - b * b; - - //lines are not parallel - if (d != 0.0f) - { - - Vector3 r = linePoint1 - linePoint2; - float c = Vector3.Dot(lineVec1, r); - float f = Vector3.Dot(lineVec2, r); - - float s = (b * f - c * e) / d; - float t = (a * f - c * b) / d; - - closestPointLine1 = linePoint1 + lineVec1 * s; - closestPointLine2 = linePoint2 + lineVec2 * t; - - return true; - } - - else - { - return false; - } - } - - //create a vector of direction "vector" with length "size" - public static Vector3 SetVectorLength(Vector3 vector, float size) - { - - //normalize the vector - Vector3 vectorNormalized = Vector3.Normalize(vector); - - //scale the vector - return vectorNormalized *= size; - } - - // public bool Contains2D(ref Vector2 p){ - // return Contains2D_Do(ref p); - // } - public bool Contains2D(ref Vector2 p) - { - if (Vector2.SqrMagnitude(p - poly2D[0]) > MaxDistanceSq) - { - return false; - } - // if(Vector2.Distance(p,P1) > MaxDistance){ return false; } - // if(poly2D.Length != 3){ return false; } - - Vector2 x1 = default(Vector2); - Vector2 x2 = default(Vector2); - Vector2 oldPoint = default(Vector2); - Vector2 newPoint = default(Vector2); - bool inside = false; - - inside = false; - oldPoint = new Vector2(poly2D[3 - 1].x, poly2D[3 - 1].y); - for (int i = 0; i < 3; i++) - { - newPoint = new Vector2(poly2D[i].x, poly2D[i].y); - if (newPoint.x > oldPoint.x) - { - x1 = oldPoint; - x2 = newPoint; - } - else - { - x1 = newPoint; - x2 = oldPoint; - } - if ((newPoint.x < p.x) == (p.x <= oldPoint.x) && (p.y - x1.y) * (x2.x - x1.x) < (x2.y - x1.y) * (p.x - x1.x)) - { - inside = !inside; - } - oldPoint = newPoint; - } - return inside; - } - - - public bool Contains2D(ref Vector3 p) - { - Vector2 tVect = new Vector2(p.x, p.z); - return Contains2D(ref tVect); - } - - public bool Near(ref Vector3 tVect, out Vector3 TheNearVect) - { - if (Vector3.SqrMagnitude(tVect - P1) > MaxDistanceSq) - { - // if(Vector3.Distance(tVect,P1) > MaxDistance){ - TheNearVect = default(Vector3); - return false; - } - - // if(Vector3.Distance(tVect,P1) < NearDist){ - if (Vector3.SqrMagnitude(tVect - P1) < NearDistSQ) - { - TheNearVect = P1; - return true; - } - // if(Vector3.Distance(tVect,P2) < NearDist){ - if (Vector3.SqrMagnitude(tVect - P2) < NearDistSQ) - { - TheNearVect = P2; - return true; - } - // if(Vector3.Distance(tVect,P3) < NearDist){ - if (Vector3.SqrMagnitude(tVect - P3) < NearDistSQ) - { - TheNearVect = P3; - return true; - } - TheNearVect = default(Vector3); - return false; - } - - public string ToStringGSD() - { - return ("P1:" + P1.ToString() + " P2:" + P2.ToString() + " P3:" + P3.ToString()); - } - } - - public class Construction2DRect - { - public Vector2 P1, P2, P3, P4; - const float NearDist = 0.15f; - const float NearDistSQ = 0.0225f; - Vector2[] poly; - public float MaxDistance = 200f; - public float MaxDistanceSQ = 200f; - public float Height = 0f; - public float MinI = 0f; - public float MaxI = 0f; - - static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - - public Construction2DRect(Vector2 _P1, Vector2 _P2, Vector2 _P3, Vector2 _P4, float tHeight = 0f) - { - Construction2DRect_Do(ref _P1, ref _P2, ref _P3, ref _P4, ref tHeight); - } - private void Construction2DRect_Do(ref Vector2 _P1, ref Vector2 _P2, ref Vector2 _P3, ref Vector2 _P4, ref float tHeight) - { - P1 = _P1; - P2 = _P2; - P3 = _P3; - P4 = _P4; - Height = tHeight; - - if (IsApproximately(P1.x, P2.x, 0.0001f)) - { - P2.x += 0.0002f; - } - if (IsApproximately(P1.x, P3.x, 0.0001f)) - { - P3.x += 0.0002f; - } - if (IsApproximately(P1.x, P4.x, 0.0001f)) - { - P4.x += 0.0002f; - } - if (IsApproximately(P2.x, P3.x, 0.0001f)) - { - P3.x += 0.0002f; - } - if (IsApproximately(P2.x, P4.x, 0.0001f)) - { - P4.x += 0.0002f; - } - if (IsApproximately(P3.x, P4.x, 0.0001f)) - { - P4.x += 0.0002f; - } - - if (IsApproximately(P1.y, P2.y, 0.0001f)) - { - P2.y += 0.0002f; - } - if (IsApproximately(P1.y, P3.y, 0.0001f)) - { - P3.y += 0.0002f; - } - if (IsApproximately(P1.y, P4.y, 0.0001f)) - { - P4.y += 0.0002f; - } - if (IsApproximately(P2.y, P3.y, 0.0001f)) - { - P3.y += 0.0002f; - } - if (IsApproximately(P2.y, P4.y, 0.0001f)) - { - P4.y += 0.0002f; - } - if (IsApproximately(P3.y, P4.y, 0.0001f)) - { - P4.y += 0.0002f; - } - - //Find two with smallest x, etc - float[] tX = new float[4]; - float[] tY = new float[4]; - - tX[0] = P1.x; - tX[1] = P2.x; - tX[2] = P3.x; - tX[3] = P4.x; - - tY[0] = P1.y; - tY[1] = P2.y; - tY[2] = P3.y; - tY[3] = P4.y; - - float MinX1, MinX2; - bool bIgnoreP1, bIgnoreP2, bIgnoreP3, bIgnoreP4; - bIgnoreP1 = bIgnoreP2 = bIgnoreP3 = bIgnoreP4 = false; - - //Get top two minimum X - MinX1 = Mathf.Min(tX); - tX = new float[3]; - int tCounter = 0; - if (!IsApproximately(MinX1, P1.x, 0.0001f)) - { - tX[tCounter] = P1.x; tCounter += 1; - } - if (!IsApproximately(MinX1, P2.x, 0.0001f)) - { - tX[tCounter] = P2.x; tCounter += 1; - } - if (!IsApproximately(MinX1, P3.x, 0.0001f)) - { - tX[tCounter] = P3.x; tCounter += 1; - } - if (!IsApproximately(MinX1, P4.x, 0.0001f)) - { - tX[tCounter] = P4.x; tCounter += 1; - } - MinX2 = Mathf.Min(tX); - - Vector2 xMin1 = default(Vector2); - Vector2 xMin2 = default(Vector2); - if (IsApproximately(MinX1, P1.x, 0.0001f)) - { - xMin1 = P1; - bIgnoreP1 = true; - } - else if (IsApproximately(MinX1, P2.x, 0.0001f)) - { - xMin1 = P2; - bIgnoreP2 = true; - } - else if (IsApproximately(MinX1, P3.x, 0.0001f)) - { - xMin1 = P3; - bIgnoreP3 = true; - } - else if (IsApproximately(MinX1, P4.x, 0.0001f)) - { - xMin1 = P4; - bIgnoreP4 = true; - } - - if (IsApproximately(MinX2, P1.x, 0.0001f)) - { - xMin2 = P1; - bIgnoreP1 = true; - } - else if (IsApproximately(MinX2, P2.x, 0.0001f)) - { - xMin2 = P2; - bIgnoreP2 = true; - } - else if (IsApproximately(MinX2, P3.x, 0.0001f)) - { - xMin2 = P3; - bIgnoreP3 = true; - } - else if (IsApproximately(MinX2, P4.x, 0.0001f)) - { - xMin2 = P4; - bIgnoreP4 = true; - } - - Vector2 TopLeft = default(Vector2); - Vector2 BottomLeft = default(Vector2); - if (xMin1.y > xMin2.y) - { - TopLeft = xMin1; - BottomLeft = xMin2; - } - else - { - TopLeft = xMin2; - BottomLeft = xMin1; - } - - Vector2 xMax1 = default(Vector2); - Vector2 xMax2 = default(Vector2); - bool bXmax1 = false; - if (!bIgnoreP1) - { - xMax1 = P1; - bXmax1 = true; - } - if (!bIgnoreP2) - { - if (bXmax1) - { - xMax2 = P2; - } - else - { - xMax1 = P2; - bXmax1 = true; - } - } - if (!bIgnoreP3) - { - if (bXmax1) - { - xMax2 = P3; - } - else - { - xMax1 = P3; - bXmax1 = true; - } - } - if (!bIgnoreP4) - { - if (bXmax1) - { - xMax2 = P4; - } - else - { - xMax1 = P4; - bXmax1 = true; - } - } - - Vector2 TopRight = default(Vector2); - Vector2 BottomRight = default(Vector2); - if (xMax1.y > xMax2.y) - { - TopRight = xMax1; - BottomRight = xMax2; - } - else - { - TopRight = xMax2; - BottomRight = xMax1; - } - - P1 = BottomLeft; - P2 = BottomRight; - P3 = TopRight; - P4 = TopLeft; - - poly = new Vector2[4]; - poly[0] = P1; - poly[1] = P2; - poly[2] = P3; - poly[3] = P4; - - float[] tMaxes = new float[6]; - tMaxes[0] = Vector2.Distance(P1, P2); - tMaxes[1] = Vector2.Distance(P1, P3); - tMaxes[2] = Vector2.Distance(P1, P4); - tMaxes[3] = Vector2.Distance(P2, P3); - tMaxes[4] = Vector2.Distance(P2, P4); - tMaxes[5] = Vector2.Distance(P3, P4); - MaxDistance = Mathf.Max(tMaxes) * 1.5f; - - float[] tMaxesSQ = new float[6]; - tMaxesSQ[0] = Vector2.SqrMagnitude(P1 - P2); - tMaxesSQ[1] = Vector2.SqrMagnitude(P1 - P3); - tMaxesSQ[2] = Vector2.SqrMagnitude(P1 - P4); - tMaxesSQ[3] = Vector2.SqrMagnitude(P2 - P3); - tMaxesSQ[4] = Vector2.SqrMagnitude(P2 - P4); - tMaxesSQ[5] = Vector2.SqrMagnitude(P3 - P4); - MaxDistanceSQ = Mathf.Max(tMaxesSQ) * 1.5f; - } - - - - Vector2 x1 = default(Vector2); - Vector2 x2 = default(Vector2); - Vector2 oldPoint = default(Vector2); - Vector2 newPoint = default(Vector2); - bool inside = false; - - // public bool Contains(ref Vector2 p){ - // return Contains_Do(ref p); - // } - public bool Contains(ref Vector2 p) - { - // if(Vector2.Distance(p,P1) > MaxDistance){ return false; } - if (Vector2.SqrMagnitude(p - P1) > MaxDistanceSQ) { return false; } - // if(poly.Length != 4){ return false; } - - inside = false; - oldPoint = new Vector2(poly[4 - 1].x, poly[4 - 1].y); - for (int i = 0; i < 4; i++) - { - newPoint = new Vector2(poly[i].x, poly[i].y); - if (newPoint.x > oldPoint.x) - { - x1 = oldPoint; - x2 = newPoint; - } - else - { - x1 = newPoint; - x2 = oldPoint; - } - if ((newPoint.x < p.x) == (p.x <= oldPoint.x) && (p.y - x1.y) * (x2.x - x1.x) < (x2.y - x1.y) * (p.x - x1.x)) - { - inside = !inside; - } - oldPoint = newPoint; - } - return inside; - } - - public bool Near(ref Vector2 tVect, out Vector2 TheNearVect) - { - if (Vector2.SqrMagnitude(tVect - P1) > MaxDistanceSQ) - { - // if(Vector2.Distance(tVect,P1) > MaxDistance){ - TheNearVect = default(Vector2); - return false; - } - - if (Vector2.SqrMagnitude(tVect - P1) < NearDistSQ) - { - // if(Vector2.Distance(tVect,P1) < NearDist){ - TheNearVect = P1; - return true; - } - if (Vector2.SqrMagnitude(tVect - P2) < NearDistSQ) - { - // if(Vector2.Distance(tVect,P2) < NearDist){ - TheNearVect = P2; - return true; - } - if (Vector2.SqrMagnitude(tVect - P3) < NearDistSQ) - { - // if(Vector2.Distance(tVect,P3) < NearDist){ - TheNearVect = P3; - return true; - } - if (Vector2.SqrMagnitude(tVect - P4) < NearDistSQ) - { - // if(Vector2.Distance(tVect,P4) < NearDist){ - TheNearVect = P4; - return true; - } - TheNearVect = default(Vector2); - return false; - } - - public string ToStringGSD() - { - return ("P1:" + P1.ToString() + " P2:" + P2.ToString() + " P3:" + P3.ToString() + " P4:" + P4.ToString()); - } - } - - public static GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[] GetRoadTerrainInfos() - { - Object[] tTerrainsObj = GameObject.FindObjectsOfType(typeof(Terrain)); - GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo tInfo; - List tInfos = new List(); - foreach (Terrain tTerrain in tTerrainsObj) - { - tInfo = new GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo(); - tInfo.GSDID = tTerrain.transform.gameObject.GetComponent().GSDID; - tInfo.tBounds = new Rect(tTerrain.transform.position.x, tTerrain.transform.position.z, tTerrain.terrainData.size.x, tTerrain.terrainData.size.z); - tInfo.hmWidth = tTerrain.terrainData.heightmapWidth; - tInfo.hmHeight = tTerrain.terrainData.heightmapHeight; - tInfo.tPos = tTerrain.transform.position; - tInfo.tSize = tTerrain.terrainData.size; - tInfo.heights = tTerrain.terrainData.GetHeights(0, 0, tInfo.hmWidth, tInfo.hmHeight); - tInfos.Add(tInfo); - } - GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[] fInfos = new GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[tInfos.Count]; - int fInfosLength = fInfos.Length; - for (int i = 0; i < fInfosLength; i++) - { - fInfos[i] = tInfos[i]; - } - tInfos = null; - return fInfos; - } - - - // RenderQueue provides ID's for Unity render queues. These can be applied to sub-shader tags, - // but it's easier to just set material.renderQueue. Static class instead of enum because these - // are int's, so this way client code doesn't need to use typecasting. - // - // From the documentation: - // For special uses in-between queues can be used. Internally each queue is represented - // by integer index; Background is 1000, Geometry is 2000, Transparent is 3000 and - // Overlay is 4000. - // - // NOTE: Keep these in numerical order for ease of understanding. Use plurals for start of - // a group of layers. - public static class RenderQueue - { - public const int Background = 1000; - - // Mid-ground. - public const int ParallaxLayers = Background + 100; // +1, 2, 3, ... for additional layers - - // Lines on the ground. - public const int GroundLines = Background + 200; - - public const int Tracks = GroundLines + 0; - public const int Routes = GroundLines + 1; - public const int IndicatorRings = GroundLines + 2; - public const int Road = GroundLines + 3; - - public const int Geometry = 2000; - - - public const int Transparent = 3000; - - // Lines on the screen. (Over world, but under GUI.) - public const int ScreenLines = Transparent + 100; - - public const int Overlay = 4000; - } - - - public static void SaveNodeObjects(ref Splination.SplinatedMeshMaker[] tSplinatedObjects, ref EdgeObjects.EdgeObjectMaker[] tEdgeObjects, ref WizardObject WO) - { - SaveNodeObjects_DO(ref tSplinatedObjects, ref tEdgeObjects, ref WO); - } - private static void SaveNodeObjects_DO(ref Splination.SplinatedMeshMaker[] tSplinatedObjects, ref EdgeObjects.EdgeObjectMaker[] tEdgeObjects, ref WizardObject WO) - { - int sCount = tSplinatedObjects.Length; - int eCount = tEdgeObjects.Length; - //Splinated objects first: - Splination.SplinatedMeshMaker SMM = null; - GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); - string xPath = GSDRootUtil.Dir_GetLibrary(); - string tPath = xPath + "B/" + WO.FileName + ".gsd"; - if (WO.bIsDefault) - { - tPath = xPath + "B/W/" + WO.FileName + ".gsd"; - } - StringBuilder builder = new StringBuilder(32768); - - //Wizard object: - builder.Append(WO.ConvertToString()); - builder.Append(FileSepString); - - for (int i = 0; i < sCount; i++) - { - SMM = tSplinatedObjects[i]; - builder.Append(SMM.ConvertToString()); - builder.Append(FileSepString); - } - - EdgeObjects.EdgeObjectMaker EOM = null; - for (int i = 0; i < eCount; i++) - { - EOM = tEdgeObjects[i]; - builder.Append(EOM.ConvertToString()); - builder.Append(FileSepString); - } - -#if UNITY_WEBPLAYER - -#else - System.IO.File.WriteAllText(tPath, builder.ToString()); -#endif - } - - public static void LoadNodeObjects(string tFileName, GSDSplineN tNode, bool bIsDefault = false, bool bIsBridge = false) - { -#if UNITY_WEBPLAYER - return; -#else - - string tPath = ""; - GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); - string xPath = GSDRootUtil.Dir_GetLibrary(); - if (bIsDefault) - { - tPath = xPath + "B/W/" + tFileName + ".gsd"; - } - else - { - tPath = xPath + "B/" + tFileName + ".gsd"; - } - - string tData = System.IO.File.ReadAllText(tPath); - string[] tSep = new string[2]; - tSep[0] = FileSepString; - tSep[1] = FileSepStringCRLF; - string[] tSplit = tData.Split(tSep, System.StringSplitOptions.RemoveEmptyEntries); - - Splination.SplinatedMeshMaker SMM = null; - Splination.SplinatedMeshMaker.SplinatedMeshLibraryMaker SLM = null; - EdgeObjects.EdgeObjectMaker EOM = null; - EdgeObjects.EdgeObjectMaker.EdgeObjectLibraryMaker ELM = null; - int tSplitCount = tSplit.Length; - - for (int i = 0; i < tSplitCount; i++) - { - SLM = null; - SLM = Splination.SplinatedMeshMaker.SLMFromData(tSplit[i]); - if (SLM != null) - { - SMM = tNode.AddSplinatedObject(); - SMM.LoadFromLibraryBulk(ref SLM); - SMM.bToggle = false; - if (bIsBridge && tNode.bIsBridgeStart && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null) - { - SMM.StartTime = tNode.tTime; - SMM.EndTime = tNode.BridgeCounterpartNode.tTime; - SMM.StartPos = tNode.GSDSpline.GetSplineValue(SMM.StartTime); - SMM.EndPos = tNode.GSDSpline.GetSplineValue(SMM.EndTime); - } - continue; - } - - ELM = null; - ELM = EdgeObjects.EdgeObjectMaker.ELMFromData(tSplit[i]); - if (ELM != null) - { - EOM = tNode.AddEdgeObject(); - EOM.LoadFromLibraryBulk(ref ELM); - EOM.bToggle = false; - if (!EOM.bSingle && bIsBridge && tNode.bIsBridgeStart && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null) - { - EOM.StartTime = tNode.tTime; - EOM.EndTime = tNode.BridgeCounterpartNode.tTime; - EOM.StartPos = tNode.GSDSpline.GetSplineValue(EOM.StartTime); - EOM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.EndTime); - } - else if (EOM.bSingle && bIsBridge && tNode.BridgeCounterpartNode != null && tNode.bIsBridgeStart) - { - float tDist = (EOM.SingleOnlyBridgePercent * (tNode.BridgeCounterpartNode.tDist - tNode.tDist) + tNode.tDist); - EOM.SinglePosition = tNode.GSDSpline.TranslateDistBasedToParam(tDist); - EOM.StartPos = tNode.GSDSpline.GetSplineValue(EOM.SinglePosition); - EOM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.SinglePosition); - } - continue; - } - } - - tNode.SetupSplinatedMeshes(); - tNode.SetupEdgeObjects(); - -#endif - } - - #region "Splat maps" - public static byte[] MakeSplatMap(Terrain tTerrain, Color tBG, Color tFG, int tWidth, int tHeight, float SplatWidth, bool bSkipBridge, bool bSkipTunnel, string xRoadUID = "") - { - return MakeSplatMapDo(tTerrain, tBG, tFG, tWidth, tHeight, SplatWidth, bSkipBridge, bSkipTunnel, xRoadUID); - } - - private static byte[] MakeSplatMapDo(Terrain tTerrain, Color tBG, Color tFG, int tWidth, int tHeight, float SplatWidth, bool bSkipBridge, bool bSkipTunnel, string xRoadUID) - { - Texture2D tTexture = new Texture2D(tWidth, tHeight, TextureFormat.RGB24, false); - - //Set background color: - Color[] tColorsBG = new Color[tWidth * tHeight]; - int tBGCount = tColorsBG.Length; - for (int i = 0; i < tBGCount; i++) - { - tColorsBG[i] = tBG; - } - tTexture.SetPixels(0, 0, tWidth, tHeight, tColorsBG); - tColorsBG = null; - - Object[] tRoads = null; - if (xRoadUID != "") - { - tRoads = new Object[1]; - Object[] bRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); - foreach (GSDRoad fRoad in bRoads) - { - if (string.CompareOrdinal(fRoad.UID, xRoadUID) == 0) - { - tRoads[0] = fRoad; - break; - } - } - } - else - { - tRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); - } - Vector3 tPos = tTerrain.transform.position; - Vector3 tSize = tTerrain.terrainData.size; - foreach (GSDRoad tRoad in tRoads) - { - GSDSplineC tSpline = tRoad.GSDSpline; - int tCount = tSpline.RoadDefKeysArray.Length; - - Vector3 POS1 = default(Vector3); - Vector3 POS2 = default(Vector3); - - Vector3 tVect = default(Vector3); - Vector3 tVect2 = default(Vector3); - Vector3 lVect1 = default(Vector3); - Vector3 lVect2 = default(Vector3); - Vector3 rVect1 = default(Vector3); - Vector3 rVect2 = default(Vector3); - - int x1, y1; - int[] tX = new int[4]; - int[] tY = new int[4]; - int MinX = -1; - int MaxX = -1; - int MinY = -1; - int MaxY = -1; - int xDiff = -1; - int yDiff = -1; - float p1 = 0f; - float p2 = 0f; - bool bXBad = false; - bool bYBad = false; - for (int i = 0; i < (tCount - 1); i++) - { - bXBad = false; - bYBad = false; - p1 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[i]); - p2 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[i + 1]); - - //Skip bridges: - if (bSkipBridge) - { - if (tSpline.IsInBridgeTerrain(p1)) - { - continue; - } - } - - //Skip tunnels: - if (bSkipTunnel) - { - if (tSpline.IsInTunnelTerrain(p1)) - { - continue; - } - } - - tSpline.GetSplineValue_Both(p1, out tVect, out POS1); - tSpline.GetSplineValue_Both(p2, out tVect2, out POS2); - lVect1 = (tVect + new Vector3(SplatWidth * -POS1.normalized.z, 0, SplatWidth * POS1.normalized.x)); - rVect1 = (tVect + new Vector3(SplatWidth * POS1.normalized.z, 0, SplatWidth * -POS1.normalized.x)); - lVect2 = (tVect2 + new Vector3(SplatWidth * -POS2.normalized.z, 0, SplatWidth * POS2.normalized.x)); - rVect2 = (tVect2 + new Vector3(SplatWidth * POS2.normalized.z, 0, SplatWidth * -POS2.normalized.x)); - - TranslateWorldVectToCustom(tWidth, tHeight, lVect1, ref tPos, ref tSize, out x1, out y1); - tX[0] = x1; - tY[0] = y1; - TranslateWorldVectToCustom(tWidth, tHeight, rVect1, ref tPos, ref tSize, out x1, out y1); - tX[1] = x1; - tY[1] = y1; - TranslateWorldVectToCustom(tWidth, tHeight, lVect2, ref tPos, ref tSize, out x1, out y1); - tX[2] = x1; - tY[2] = y1; - TranslateWorldVectToCustom(tWidth, tHeight, rVect2, ref tPos, ref tSize, out x1, out y1); - tX[3] = x1; - tY[3] = y1; - - MinX = Mathf.Min(tX); - MaxX = Mathf.Max(tX); - MinY = Mathf.Min(tY); - MaxY = Mathf.Max(tY); - - - if (MinX < 0) { MinX = 0; bXBad = true; } - if (MaxX < 0) { MaxX = 0; bXBad = true; } - if (MinY < 0) { MinY = 0; bYBad = true; } - if (MaxY < 0) { MaxY = 0; bYBad = true; } - - if (MinX > (tWidth - 1)) { MinX = (tWidth - 1); bXBad = true; } - if (MaxX > (tWidth - 1)) { MaxX = (tWidth - 1); bXBad = true; } - if (MinY > (tHeight - 1)) { MinY = (tHeight - 1); bYBad = true; } - if (MaxY > (tHeight - 1)) { MaxY = (tHeight - 1); bYBad = true; } - - if (bXBad && bYBad) { continue; } - - xDiff = MaxX - MinX; - yDiff = MaxY - MinY; - - Color[] tColors = new Color[xDiff * yDiff]; - int cCount = tColors.Length; - for (int j = 0; j < cCount; j++) - { - tColors[j] = tFG; - } - - if (xDiff > 0 && yDiff > 0) - { - tTexture.SetPixels(MinX, MinY, xDiff, yDiff, tColors); - } - } - } - - tTexture.Apply(); - byte[] tBytes = tTexture.EncodeToPNG(); - Object.DestroyImmediate(tTexture); - return tBytes; - } - - - private static void TranslateWorldVectToCustom(int tWidth, int tHeight, Vector3 tVect, ref Vector3 tPos, ref Vector3 tSize, out int x1, out int y1) - { - //Get the normalized position of this game object relative to the terrain: - tVect -= tPos; - - tVect.x = tVect.x / tSize.x; - tVect.z = tVect.z / tSize.z; - - //Get the position of the terrain heightmap where this game object is: - x1 = (int)(tVect.x * tWidth); - y1 = (int)(tVect.z * tHeight); - } - #endregion - - #region "Wizard objects" - public class WizardObject - { - public Texture2D Thumb; - public string ThumbString; - public string DisplayName; - public string Desc; - public bool bIsDefault; - public bool bIsBridge; - public string FileName; - public string FullPath; - public int sortID = 0; - - public string ConvertToString() - { - WizardObjectLibrary WOL = new WizardObjectLibrary(); - WOL.LoadFrom(this); - return GSDRootUtil.GetString(WOL); - } - - public void LoadDataFromWOL(WizardObjectLibrary WOL) - { - ThumbString = WOL.ThumbString; - DisplayName = WOL.DisplayName; - Desc = WOL.Desc; - bIsDefault = WOL.bIsDefault; - FileName = WOL.FileName; - bIsBridge = WOL.bIsBridge; - } - - public static WizardObject LoadFromLibrary(string tPath) - { -#if UNITY_WEBPLAYER - return null; -#else - string tData = System.IO.File.ReadAllText(tPath); - string[] tSep = new string[2]; - tSep[0] = FileSepString; - tSep[1] = FileSepStringCRLF; - string[] tSplit = tData.Split(tSep, System.StringSplitOptions.RemoveEmptyEntries); - int tSplitCount = tSplit.Length; - WizardObjectLibrary WOL = null; - for (int i = 0; i < tSplitCount; i++) - { - WOL = WizardObject.WizardObjectLibrary.WOLFromData(tSplit[i]); - if (WOL != null) - { - WizardObject WO = new WizardObject(); - WO.LoadDataFromWOL(WOL); - return WO; - } - } - return null; -#endif - } - - [System.Serializable] - public class WizardObjectLibrary - { - public string ThumbString; - public string DisplayName; - public string Desc; - public bool bIsDefault; - public bool bIsBridge; - public string FileName; - - public void LoadFrom(WizardObject WO) - { - ThumbString = WO.ThumbString; - DisplayName = WO.DisplayName; - Desc = WO.Desc; - bIsDefault = WO.bIsDefault; - FileName = WO.FileName; - bIsBridge = WO.bIsBridge; - } - - public static WizardObjectLibrary WOLFromData(string tData) - { - try - { - WizardObjectLibrary WOL = (WizardObjectLibrary)GSDRootUtil.LoadData(ref tData); - return WOL; - } - catch - { - return null; - } - } - } - } - - - #endregion - } - - public static class GSDIntersectionObjects - { - static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - - public static void CleanupIntersectionObjects(GameObject MasterGameObj) - { - int mCount = MasterGameObj.transform.childCount; - if (mCount == 0) { return; } - List tObjtoDelete = new List(); - for (int i = 0; i < mCount; i++) - { - if (MasterGameObj.transform.GetChild(i).name.ToLower().Contains("stopsign")) - { - tObjtoDelete.Add(MasterGameObj.transform.GetChild(i).gameObject); - } - if (MasterGameObj.transform.GetChild(i).name.ToLower().Contains("trafficlight")) - { - tObjtoDelete.Add(MasterGameObj.transform.GetChild(i).gameObject); - } - } - for (int i = (tObjtoDelete.Count - 1); i >= 0; i--) - { - Object.DestroyImmediate(tObjtoDelete[i]); - } - } - - #region "Stop Sign All Way" - public static void CreateStopSignsAllWay(GameObject MasterGameObj, bool bIsRB = true) - { - CreateStopSignsAllWay_Do(ref MasterGameObj, bIsRB); - } - private static void T_FixSigns(GameObject tObj) - { - Rigidbody rigidbody = tObj.GetComponent(); - rigidbody.useGravity = false; - rigidbody.isKinematic = true; - } - private static void CreateStopSignsAllWay_Do(ref GameObject MasterGameObj, bool bIsRB) - { - Object prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab", typeof(GameObject)); - - GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); - GSDSplineC tSpline = GSDRI.Node1.GSDSpline; - - GameObject tObj = null; - // Vector3 xDir = default(Vector3); - Vector3 tDir = default(Vector3); - // float RoadWidth = tSpline.tRoad.RoadWidth(); - // float LaneWidth = tSpline.tRoad.opt_LaneWidth; - float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; - - //Cleanup: - CleanupIntersectionObjects(MasterGameObj); - - float Mass = 100f; - - //Get four points: - float DistFromCorner = (ShoulderWidth * 0.45f); - Vector3 tPosRR = default(Vector3); - Vector3 tPosRL = default(Vector3); - Vector3 tPosLR = default(Vector3); - Vector3 tPosLL = default(Vector3); - GetFourPoints(GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); - - //RR: - tSpline = GSDRI.Node1.GSDSpline; - tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; - // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; - tDir = StopSign_GetRot_RR(GSDRI, tSpline); - tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); - if (bIsRB) - { - Rigidbody RB = tObj.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = new Vector3(0f, -10f, 0f); - } - tObj.transform.parent = MasterGameObj.transform; - tObj.transform.position = tPosRR; - tObj.name = "StopSignRR"; - T_FixSigns(tObj); - if (GSDRI.IgnoreCorner == 0) { Object.DestroyImmediate(tObj); } - - //LL: - tSpline = GSDRI.Node1.GSDSpline; - tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; - // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; - tDir = StopSign_GetRot_LL(GSDRI, tSpline); - tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); - if (bIsRB) - { - Rigidbody RB = tObj.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = new Vector3(0f, -10f, 0f); - } - tObj.transform.parent = MasterGameObj.transform; - tObj.transform.position = tPosLL; - tObj.name = "StopSignLL"; - T_FixSigns(tObj); - if (GSDRI.IgnoreCorner == 2) { Object.DestroyImmediate(tObj); } - - //RL: - tSpline = GSDRI.Node2.GSDSpline; - tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; - // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; - tDir = StopSign_GetRot_RL(GSDRI, tSpline); - tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); - if (bIsRB) - { - Rigidbody RB = tObj.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = new Vector3(0f, -10f, 0f); - } - tObj.transform.parent = MasterGameObj.transform; - tObj.transform.position = tPosRL; - tObj.name = "StopSignRL"; - T_FixSigns(tObj); - if (GSDRI.IgnoreCorner == 1) { Object.DestroyImmediate(tObj); } - - //LR: - tSpline = GSDRI.Node2.GSDSpline; - tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; - // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; - tDir = StopSign_GetRot_LR(GSDRI, tSpline); - tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); - if (bIsRB) - { - Rigidbody RB = tObj.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = new Vector3(0f, -10f, 0f); - } - tObj.transform.parent = MasterGameObj.transform; - tObj.transform.position = tPosLR; - tObj.name = "StopSignLR"; - T_FixSigns(tObj); - if (GSDRI.IgnoreCorner == 3) { Object.DestroyImmediate(tObj); } - } - - private static Vector3 StopSign_GetRot_RR(GSDRoadIntersection GSDRI, GSDSplineC tSpline) - { - float tDist = ((Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRR))) / tSpline.distance; ; - float p = Mathf.Clamp(GSDRI.Node1.tTime - tDist, 0f, 1f); - Vector3 POS = tSpline.GetSplineValue(p, true); - return (POS * -1); - } - - private static Vector3 StopSign_GetRot_LL(GSDRoadIntersection GSDRI, GSDSplineC tSpline) - { - float tDist = ((Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRR))) / tSpline.distance; ; - float p = Mathf.Clamp(GSDRI.Node1.tTime + tDist, 0f, 1f); - Vector3 POS = tSpline.GetSplineValue(p, true); - return POS; - } - - private static Vector3 StopSign_GetRot_RL(GSDRoadIntersection GSDRI, GSDSplineC tSpline) - { - float tDist = ((Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRL) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRL))) / tSpline.distance; ; - float p = -1f; - if (GSDRI.bFlipped) - { - p = Mathf.Clamp(GSDRI.Node2.tTime - tDist, 0f, 1f); - } - else - { - p = Mathf.Clamp(GSDRI.Node2.tTime + tDist, 0f, 1f); - } - Vector3 POS = tSpline.GetSplineValue(p, true); - //POS = Vector3.Cross(POS,Vector3.up); - if (GSDRI.bFlipped) - { - return (POS * -1); - } - else - { - return POS; - } - } - - private static Vector3 StopSign_GetRot_LR(GSDRoadIntersection GSDRI, GSDSplineC tSpline) - { - float tDist = ((Vector3.Distance(GSDRI.CornerRR, GSDRI.CornerLR) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRL))) / tSpline.distance; ; - float p = -1f; - if (GSDRI.bFlipped) - { - p = Mathf.Clamp(GSDRI.Node2.tTime + tDist, 0f, 1f); - } - else - { - p = Mathf.Clamp(GSDRI.Node2.tTime - tDist, 0f, 1f); - } - Vector3 POS = tSpline.GetSplineValue(p, true); - //POS = Vector3.Cross(POS,Vector3.up); - if (GSDRI.bFlipped) - { - return POS; - } - else - { - return (POS * -1); - } - } - #endregion - - #region "Traffic light bases" - public static void CreateTrafficLightBases(GameObject MasterGameObj, bool bIsTrafficLight1 = true) - { - CreateTrafficLightBases_Do(ref MasterGameObj, bIsTrafficLight1); - } - private static void CreateTrafficLightBases_Do(ref GameObject MasterGameObj, bool bIsTrafficLight1) - { - GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); - GSDSplineC tSpline = GSDRI.Node1.GSDSpline; - bool bIsRB = true; - - // float RoadWidth = tSpline.tRoad.RoadWidth(); - float LaneWidth = tSpline.tRoad.opt_LaneWidth; - float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; - - int Lanes = tSpline.tRoad.opt_Lanes; - int LanesHalf = Lanes / 2; - float LanesForInter = -1; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - LanesForInter = LanesHalf + 1f; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - LanesForInter = LanesHalf + 1f; - } - else - { - LanesForInter = LanesHalf - 1 + 1f; - } - float DistFromCorner = (ShoulderWidth * 0.45f); - float TLDistance = (LanesForInter * LaneWidth) + DistFromCorner; - - GameObject tObjRR = null; - GameObject tObjRL = null; - GameObject tObjLL = null; - GameObject tObjLR = null; - // Vector3 xDir = default(Vector3); - Vector3 tDir = default(Vector3); - float Mass = 12500f; - Vector3 COM = new Vector3(0f, 0f, 4f); - Vector3 zeroVect = new Vector3(0f, 0f, 0f); - Vector3 StartVec = default(Vector3); - Vector3 EndVec = default(Vector3); - // bool bContains = false; - // MeshFilter MF = null; - // Vector3[] tVerts = null; - Rigidbody RB = null; - - //Get four points: - Vector3 tPosRR = default(Vector3); - Vector3 tPosRL = default(Vector3); - Vector3 tPosLR = default(Vector3); - Vector3 tPosLL = default(Vector3); - GetFourPoints(GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); - - //Cleanup: - CleanupIntersectionObjects(MasterGameObj); - - float[] tempDistances = new float[4]; - tempDistances[0] = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerLL); - tempDistances[1] = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR); - tempDistances[2] = Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL); - tempDistances[3] = Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRR); - float MaxDistanceStart = Mathf.Max(tempDistances); - bool OrigPoleAlignment = GSDRI.bRegularPoleAlignment; - - //Node1: - //RL: - tObjRL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjRL.transform.parent = MasterGameObj.transform; - StartVec = tPosRL; - EndVec = (tDir.normalized * TLDistance) + StartVec; - if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) - { //Convert to regular alignment if necessary - tObjRL.transform.parent = null; - tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner, true); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjRL.transform.parent = MasterGameObj.transform; - } - else - { - GSDRI.bRegularPoleAlignment = true; - if (tObjRL != null) { Object.DestroyImmediate(tObjRL); } - tObjRL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjRL.transform.parent = MasterGameObj.transform; - StartVec = tPosRL; - EndVec = (tDir.normalized * TLDistance) + StartVec; - GSDRI.bRegularPoleAlignment = OrigPoleAlignment; - } - if (bIsRB) - { - RB = tObjRL.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = COM; - tObjRL.AddComponent(); - } - tObjRL.transform.position = tPosRL; - tObjRL.transform.name = "TrafficLightRL"; - //LR: - tObjLR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjLR.transform.parent = MasterGameObj.transform; - StartVec = tPosLR; - EndVec = (tDir.normalized * TLDistance) + StartVec; - if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) - { //Convert to regular alignment if necessary - tObjLR.transform.parent = null; - tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner, true); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjLR.transform.parent = MasterGameObj.transform; - } - else - { - GSDRI.bRegularPoleAlignment = true; - if (tObjLR != null) { Object.DestroyImmediate(tObjLR); } - tObjLR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjLR.transform.parent = MasterGameObj.transform; - StartVec = tPosLR; - EndVec = (tDir.normalized * TLDistance) + StartVec; - GSDRI.bRegularPoleAlignment = OrigPoleAlignment; - } - if (bIsRB) - { - RB = tObjLR.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = COM; - tObjLR.AddComponent(); - } - tObjLR.transform.position = tPosLR; - tObjLR.transform.name = "TrafficLightLR"; - //Node2: - //RR: - tObjRR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjRR.transform.parent = MasterGameObj.transform; - StartVec = tPosRR; - EndVec = (tDir.normalized * TLDistance) + StartVec; - if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) - { //Convert to regular alignment if necessary - tObjRR.transform.parent = null; - tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner, true); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, 0f, 0f); - tObjRR.transform.parent = MasterGameObj.transform; - } - else - { - GSDRI.bRegularPoleAlignment = true; - if (tObjRR != null) { Object.DestroyImmediate(tObjRR); } - tObjRR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjRR.transform.parent = MasterGameObj.transform; - StartVec = tPosRR; - EndVec = (tDir.normalized * TLDistance) + StartVec; - GSDRI.bRegularPoleAlignment = OrigPoleAlignment; - } - if (bIsRB) - { - RB = tObjRR.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = COM; - tObjRR.AddComponent(); - } - tObjRR.transform.position = tPosRR; - tObjRR.transform.name = "TrafficLightRR"; - - //LL: - tObjLL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjLL.transform.parent = MasterGameObj.transform; - StartVec = tPosLL; - EndVec = (tDir.normalized * TLDistance) + StartVec; - if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) - { //Convert to regular alignment if necessary - tObjLL.transform.parent = null; - tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner, true); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, 0f, 0f); - tObjLL.transform.parent = MasterGameObj.transform; - } - else - { - GSDRI.bRegularPoleAlignment = true; - if (tObjLL != null) { Object.DestroyImmediate(tObjLL); } - tObjLL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); - // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; - tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner); - if (tDir == zeroVect) { tDir = new Vector3(0f, 0.0001f, 0f); } - tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); - tObjLL.transform.parent = MasterGameObj.transform; - StartVec = tPosLL; - EndVec = (tDir.normalized * TLDistance) + StartVec; - GSDRI.bRegularPoleAlignment = OrigPoleAlignment; - } - if (bIsRB) - { - RB = tObjLL.AddComponent(); - RB.mass = Mass; - RB.centerOfMass = COM; - tObjLL.AddComponent(); - } - tObjLL.transform.position = tPosLL; - tObjLL.transform.name = "TrafficLightLL"; - - //Create the actual lights: - CreateTrafficLightMains(MasterGameObj, tObjRR, tObjRL, tObjLL, tObjLR); - } - - private static bool CreateTrafficLightBase_IsInIntersection(GSDRoadIntersection GSDRI, ref Vector3 StartVec, ref Vector3 EndVec) - { - return GSDRI.ContainsLine(StartVec, EndVec); - } - - private static GameObject CreateTrafficLight(float tDistance, bool bIsTrafficLight1, bool bOptionalCollider, float xDistance, bool bLight, bool bSaveAsset) - { - GameObject tObj = null; - string tTrafficLightNumber = "1"; - if (!bIsTrafficLight1) - { - tTrafficLightNumber = "2"; - } - - bool bDoCustom = false; - xDistance = Mathf.Ceil(xDistance); //Round up to nearest whole F - tDistance = Mathf.Ceil(tDistance); //Round up to nearest whole F - // string assetName = "GSDInterTLB" + tTrafficLightNumber + "_" + tDistance.ToString("F0") + "_" + xDistance.ToString("F0") + ".prefab"; - string assetNameAsset = "GSDInterTLB" + tTrafficLightNumber + "_" + tDistance.ToString("F0") + "_" + xDistance.ToString("F0") + ".asset"; - string BackupFBX = "GSDInterTLB" + tTrafficLightNumber + ".FBX"; - float tMod = tDistance / 5f; - float hMod = (tDistance / 10f) * 0.7f; - float xMod = ((xDistance / 20f) + 2f) * 0.3334f; - xMod = Mathf.Clamp(xMod, 1f, 20f); - tMod = Mathf.Clamp(tMod, 1f, 20f); - hMod = Mathf.Clamp(hMod, 1f, 20f); - - bool bXMod = false; - if (!IsApproximately(xMod, 1f, 0.0001f)) { bXMod = true; } - - Mesh xMesh = (Mesh)UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + assetNameAsset, typeof(Mesh)); - if (xMesh == null) - { - xMesh = (Mesh)UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + BackupFBX, typeof(Mesh)); - bDoCustom = true; - } - - tObj = new GameObject("TempTrafficLight"); - MeshFilter MF = tObj.GetComponent(); if (MF == null) { MF = tObj.AddComponent(); } - MeshRenderer MR = tObj.GetComponent(); if (MR == null) { MR = tObj.AddComponent(); } - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB" + tTrafficLightNumber + ".mat", MR); - - if (!bDoCustom) - { - MF.sharedMesh = xMesh; - } - - float tempMaxHeight = 7.6f * hMod; - float xValue = tempMaxHeight - 7.6f; - if (bDoCustom) - { - Mesh tMesh = new Mesh(); - tMesh.vertices = xMesh.vertices; - tMesh.triangles = xMesh.triangles; - tMesh.uv = xMesh.uv; - tMesh.normals = xMesh.normals; - tMesh.tangents = xMesh.tangents; - MF.sharedMesh = tMesh; - Vector3[] tVerts = tMesh.vertices; - - xValue = (xMod * 6f) - 6f; - if ((xMod * 6f) > (tempMaxHeight - 1f)) - { - xValue = (tempMaxHeight - 1f) - 6f; - } - - // float tValue = 0f; - // float hValue = 0f; - bool bIgnoreMe = false; - - - int mCount = tVerts.Length; - Vector2[] uv = tMesh.uv; - // List tUVInts = new List(); - for (int i = 0; i < mCount; i++) - { - bIgnoreMe = false; - if (IsApproximately(tVerts[i].y, 5f, 0.01f)) - { - tVerts[i].y = tDistance; - if (uv[i].y > 3.5f) - { - uv[i].y *= tMod; - } - bIgnoreMe = true; - } - if (!bIgnoreMe && tVerts[i].z > 7.5f) - { - tVerts[i].z *= hMod; - if (uv[i].y > 3.8f) - { - uv[i].y *= hMod; - } - } - - if (bXMod && tVerts[i].z > 4.8f && tVerts[i].z < 6.2f) - { - tVerts[i].z += xValue; - } - } - tMesh.vertices = tVerts; - tMesh.uv = uv; - tMesh.RecalculateNormals(); - tMesh.RecalculateBounds(); - - //Save: - if (bSaveAsset) - { - UnityEditor.AssetDatabase.CreateAsset(tMesh, GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + assetNameAsset); - } - } - - BoxCollider BC = tObj.AddComponent(); - float MaxHeight = MF.sharedMesh.vertices[447].z; - BC.size = new Vector3(0.35f, 0.35f, MaxHeight); - BC.center = new Vector3(0f, 0f, (MaxHeight / 2f)); - - if (bOptionalCollider) - { - float MaxWidth = MF.sharedMesh.vertices[497].y; - GameObject tObjCollider = new GameObject("col2"); - BC = tObjCollider.AddComponent(); - BC.size = new Vector3(0.175f, MaxWidth, 0.175f); - BC.center = new Vector3(0f, MaxWidth / 2f, 5.808f); - tObjCollider.transform.parent = tObj.transform; - } - - if (bLight) - { - GameObject yObj = (GameObject)UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDStreetLight_TrafficLight.prefab", typeof(GameObject)); - GameObject kObj = (GameObject)GameObject.Instantiate(yObj); - kObj.transform.position = tObj.transform.position; - kObj.transform.position += new Vector3(0f, 0f, MaxHeight - 7.6f); - kObj.transform.parent = tObj.transform; - kObj.transform.rotation = Quaternion.identity; - // kObj.name = "StreetLight"; - } - - - //Bounds calcs: - MeshFilter[] tMeshes = tObj.GetComponents(); - for (int i = 0; i < tMeshes.Length; i++) { tMeshes[i].sharedMesh.RecalculateBounds(); } - - return tObj; - } - - private static Vector3 TrafficLightBase_GetRot_RL(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) - { - Vector3 POS = default(Vector3); - if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) - { - // float tDist = ((Vector3.Distance(GSDRI.CornerRR,GSDRI.CornerRL) / 2f) + DistFromCorner) / tSpline.distance;; - float p = Mathf.Clamp(GSDRI.Node1.tTime, 0f, 1f); - POS = tSpline.GetSplineValue(p, true); - POS = Vector3.Cross(POS, Vector3.up); - return POS; - } - else - { - POS = GSDRI.CornerRL - GSDRI.CornerLL; - return POS * -1; - } - } - - private static Vector3 TrafficLightBase_GetRot_LR(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) - { - Vector3 POS = default(Vector3); - if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) - { - // float tDist = ((Vector3.Distance(GSDRI.CornerLR,GSDRI.CornerLL) / 2f) + DistFromCorner) / tSpline.distance;; - float p = Mathf.Clamp(GSDRI.Node1.tTime, 0f, 1f); - POS = tSpline.GetSplineValue(p, true); - POS = Vector3.Cross(POS, Vector3.up); - return POS * -1; - } - else - { - POS = GSDRI.CornerRR - GSDRI.CornerLR; - return POS; - } - } - - private static Vector3 TrafficLightBase_GetRot_RR(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) - { - Vector3 POS = default(Vector3); - if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) - { - // float tDist = ((Vector3.Distance(GSDRI.CornerRR,GSDRI.CornerLR) / 2f) + DistFromCorner) / tSpline.distance;; - float p = Mathf.Clamp(GSDRI.Node2.tTime, 0f, 1f); - POS = tSpline.GetSplineValue(p, true); - POS = Vector3.Cross(POS, Vector3.up); if (GSDRI.bFlipped) { POS = POS * -1; } - } - else - { - POS = GSDRI.CornerLL - GSDRI.CornerLR; - } - return POS; - } - - private static Vector3 TrafficLightBase_GetRot_LL(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) - { - Vector3 POS = default(Vector3); - if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) - { - // float tDist = ((Vector3.Distance(GSDRI.CornerLL,GSDRI.CornerRL) / 2f) + DistFromCorner) / tSpline.distance;; - float p = Mathf.Clamp(GSDRI.Node2.tTime, 0f, 1f); - POS = tSpline.GetSplineValue(p, true); - POS = Vector3.Cross(POS, Vector3.up); if (GSDRI.bFlipped) { POS = POS * -1; } - } - else - { - POS = GSDRI.CornerRL - GSDRI.CornerRR; - } - return POS * -1; - } - #endregion - - #region "Traffic light mains" - private static void CreateTrafficLightMains(GameObject MasterGameObj, GameObject tRR, GameObject tRL, GameObject tLL, GameObject tLR) - { - GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); - GSDSplineC tSpline = GSDRI.Node1.GSDSpline; - - float tDist = (Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR) / 2f) / tSpline.distance; - Vector3 tan = tSpline.GetSplineValue(GSDRI.Node1.tTime + tDist, true); - ProcessPole(MasterGameObj, tRL, tan * -1, 1, Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR)); - tDist = (Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL) / 2f) / tSpline.distance; - tan = tSpline.GetSplineValue(GSDRI.Node1.tTime - tDist, true); - ProcessPole(MasterGameObj, tLR, tan, 3, Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL)); - - - float InterDist = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerLL); - tDist = (InterDist / 2f) / tSpline.distance; - tan = tSpline.GetSplineValue(GSDRI.Node1.tTime + tDist, true); - - float fTime1 = GSDRI.Node2.tTime + tDist; - float fTime2neg = GSDRI.Node2.tTime - tDist; - - tSpline = GSDRI.Node2.GSDSpline; - if (GSDRI.bFlipped) - { - tan = tSpline.GetSplineValue(fTime1, true); - ProcessPole(MasterGameObj, tRR, tan, 0, InterDist); - tan = tSpline.GetSplineValue(fTime2neg, true); - ProcessPole(MasterGameObj, tLL, tan * -1, 2, InterDist); - } - else - { - tan = tSpline.GetSplineValue(fTime2neg, true); - ProcessPole(MasterGameObj, tRR, tan * -1, 0, InterDist); - tan = tSpline.GetSplineValue(fTime1, true); - ProcessPole(MasterGameObj, tLL, tan, 2, InterDist); - } - - if (GSDRI.IgnoreCorner == 0) - { - if (tRR != null) { Object.DestroyImmediate(tRR); } - } - else if (GSDRI.IgnoreCorner == 1) - { - if (tRL != null) { Object.DestroyImmediate(tRL); } - } - else if (GSDRI.IgnoreCorner == 2) - { - if (tLL != null) { Object.DestroyImmediate(tLL); } - } - else if (GSDRI.IgnoreCorner == 3) - { - if (tLR != null) { Object.DestroyImmediate(tLR); } - } - } - private static void AdjustLightPrefab(GameObject tLight) - { - foreach (Light light in tLight.GetComponentsInChildren()) - { - if (light.type == LightType.Point) - { - light.flare = UnityEditor.AssetDatabase.LoadAssetAtPath(GSDRoadUtilityEditor.GetBasePath() + "/Flares/GSDSodiumBulb.flare"); - } - } - } - private static void ProcessPole(GameObject MasterGameObj, GameObject tObj, Vector3 tan, int tCorner, float InterDist) - { - GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); - GSDSplineC tSpline = GSDRI.Node1.GSDSpline; - // bool bIsRB = true; - - // float RoadWidth = tSpline.tRoad.RoadWidth(); - float LaneWidth = tSpline.tRoad.opt_LaneWidth; - float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; - - int Lanes = tSpline.tRoad.opt_Lanes; - int LanesHalf = Lanes / 2; - float LanesForInter = -1; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - LanesForInter = LanesHalf + 1f; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - LanesForInter = LanesHalf + 1f; - } - else - { - LanesForInter = LanesHalf; - } - float DistFromCorner = (ShoulderWidth * 0.35f); - float TLDistance = (LanesForInter * LaneWidth) + DistFromCorner; - - MeshFilter MF = tObj.GetComponent(); - Mesh tMesh = MF.sharedMesh; - Vector3[] tVerts = tMesh.vertices; - Vector3 StartVec = tVerts[520]; - Vector3 EndVec = tVerts[521]; - StartVec = (((EndVec - StartVec) * (DistFromCorner / TLDistance)) + StartVec); - Vector3 tempR_Start = tVerts[399]; - Vector3 tempR_End = tVerts[396]; - Vector3 tLanePosR = ((tempR_End - tempR_Start) * 0.95f) + tempR_Start; - tLanePosR.z -= 1f; - - float SmallerDist = Vector3.Distance(StartVec, EndVec); - - //StartVec = Corner - //2.5m = lane - //7.5m = lane - //12.5m = lane - Vector3[] tLanePos = new Vector3[LanesHalf]; - for (int i = 0; i < LanesHalf; i++) - { - tLanePos[i] = (((EndVec - StartVec) * (((LaneWidth * 0.5f) + (i * LaneWidth)) / SmallerDist)) + StartVec); - } - Vector3 tLanePosL = default(Vector3); - Vector3 tLanePosL_Sign = default(Vector3); - - if (GSDRI.bLeftTurnYieldOnGreen) - { - tLanePosL = ((EndVec - StartVec) * ((SmallerDist - 1.8f) / SmallerDist)) + StartVec; - tLanePosL_Sign = ((EndVec - StartVec) * ((SmallerDist - 3.2f) / SmallerDist)) + StartVec; - } - else - { - tLanePosL = ((EndVec - StartVec) * ((SmallerDist - 2.5f) / SmallerDist)) + StartVec; - } - - Vector3 tPos1 = default(Vector3); - if (tCorner == 0) - { //RR - tPos1 = GSDRI.CornerLR; - } - else if (tCorner == 1) - { //RL - tPos1 = GSDRI.CornerRR; - } - else if (tCorner == 2) - { //LL - tPos1 = GSDRI.CornerRL; - } - else if (tCorner == 3) - { //LR - tPos1 = GSDRI.CornerLL; - } - - int mCount = tLanePos.Length; - float mDistance = -50000f; - float tDistance = 0f; - for (int i = 0; i < mCount; i++) - { - tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePos[i]), tPos1); - if (tDistance > mDistance) { mDistance = tDistance; } - } - tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePosL), tPos1); - if (tDistance > mDistance) { mDistance = tDistance; } - tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePosR), tPos1); - if (tDistance > mDistance) { mDistance = tDistance; } - - float tScaleSense = ((200f - GSDRI.ScalingSense) / 200f) * 200f; - tScaleSense = Mathf.Clamp(tScaleSense * 0.1f, 0f, 20f); - float ScaleMod = ((mDistance / 17f) + tScaleSense) * (1f / (tScaleSense + 1f)); - if (IsApproximately(tScaleSense, 20f, 0.05f)) { ScaleMod = 1f; } - ScaleMod = Mathf.Clamp(ScaleMod, 1f, 1.5f); - Vector3 tScale = new Vector3(ScaleMod, ScaleMod, ScaleMod); - bool bScale = true; if (IsApproximately(ScaleMod, 1f, 0.001f)) { bScale = false; } - - //Debug.Log (mDistance + " " + ScaleMod + " " + tScaleSense); - - GameObject tRight = null; - GameObject tLeft = null; - GameObject tLeft_Sign = null; - Object prefab = null; - - MeshRenderer MR_Left = null; - MeshRenderer MR_Right = null; - MeshRenderer[] MR_Mains = new MeshRenderer[LanesHalf]; - int cCount = -1; - if (GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (GSDRI.bLeftTurnYieldOnGreen) - { - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightLeftYield.prefab", typeof(GameObject)); - } - else - { - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightLeft.prefab", typeof(GameObject)); - } - tLeft = (GameObject)GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); - AdjustLightPrefab(tLeft); - tLeft.transform.position = tObj.transform.TransformPoint(tLanePosL); - tLeft.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); - tLeft.transform.parent = tObj.transform; - tLeft.transform.name = "LightLeft"; - - cCount = tLeft.transform.childCount; - for (int i = 0; i < cCount; i++) - { - if (tLeft.transform.GetChild(i).name.ToLower() == "lights") - { - MR_Left = tLeft.transform.GetChild(i).GetComponent(); - } - } - - if (bScale) { tLeft.transform.localScale = tScale; } - - if (GSDRI.bLeftTurnYieldOnGreen) - { - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDSignYieldOnGreen.prefab", typeof(GameObject)); - tLeft_Sign = (GameObject)GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); - tLeft_Sign.transform.position = tObj.transform.TransformPoint(tLanePosL_Sign); - tLeft_Sign.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(-90f, 90f, 0f); - tLeft_Sign.transform.parent = tObj.transform; - tLeft_Sign.transform.name = "SignYieldOnGreen"; - if (bScale) { tLeft_Sign.transform.localScale = tScale; } - } - } - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightRight.prefab", typeof(GameObject)); - tRight = (GameObject)GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); - AdjustLightPrefab(tRight); - tRight.transform.position = tObj.transform.TransformPoint(tLanePosR); - tRight.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); - tRight.transform.parent = tObj.transform; - tRight.transform.name = "LightRight"; - if (bScale) { tRight.transform.localScale = tScale; } - - cCount = tRight.transform.childCount; - for (int i = 0; i < cCount; i++) - { - if (tRight.transform.GetChild(i).name.ToLower() == "lights") - { - MR_Right = tRight.transform.GetChild(i).GetComponent(); - } - } - } - GameObject[] tLanes = new GameObject[LanesHalf]; - for (int i = 0; i < LanesHalf; i++) - { - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightMain.prefab", typeof(GameObject)); - tLanes[i] = (GameObject)GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); - AdjustLightPrefab(tLanes[i]); - tLanes[i].transform.position = tObj.transform.TransformPoint(tLanePos[i]); - tLanes[i].transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); - tLanes[i].transform.parent = tObj.transform; - tLanes[i].transform.name = "Light" + i.ToString(); - if (bScale) { tLanes[i].transform.localScale = tScale; } - - cCount = tLanes[i].transform.childCount; - for (int j = 0; j < cCount; j++) - { - if (tLanes[i].transform.GetChild(j).name.ToLower() == "lights") - { - MR_Mains[i] = tLanes[i].transform.GetChild(j).GetComponent(); - } - } - } - - GSDTrafficLightController LM = new GSDTrafficLightController(ref tLeft, ref tRight, ref tLanes, ref MR_Left, ref MR_Right, ref MR_Mains); - if (tCorner == 0) - { - GSDRI.LightsRR = null; - GSDRI.LightsRR = LM; - } - else if (tCorner == 1) - { - GSDRI.LightsRL = null; - GSDRI.LightsRL = LM; - } - else if (tCorner == 2) - { - GSDRI.LightsLL = null; - GSDRI.LightsLL = LM; - } - else if (tCorner == 3) - { - GSDRI.LightsLR = null; - GSDRI.LightsLR = LM; - } - } - #endregion - - public static void GetFourPoints(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR, float DistFromCorner) - { - GetFourPoints_Do(ref GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); - } - private static void GetFourPoints_Do(ref GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR, float DistFromCorner) - { - //Get four points: - float tPos1 = 0f; - float tPos2 = 0f; - Vector3 tTan1 = default(Vector3); - Vector3 tTan2 = default(Vector3); - float Node1Width = -1f; - float Node2Width = -1f; - Vector3 tVectRR = GSDRI.CornerRR; - Vector3 tVectRL = GSDRI.CornerRL; - Vector3 tVectLR = GSDRI.CornerLR; - Vector3 tVectLL = GSDRI.CornerLL; - Vector3 tDir = default(Vector3); - float ShoulderWidth1 = GSDRI.Node1.GSDSpline.tRoad.opt_ShoulderWidth; - float ShoulderWidth2 = GSDRI.Node2.GSDSpline.tRoad.opt_ShoulderWidth; - - if (!GSDRI.bFlipped) - { - //RR: - Node1Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime - Node1Width; - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; - tPos2 = GSDRI.Node2.tTime + Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosRR = tVectRR + (tDir * DistFromCorner); - //RL: - Node1Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime + Node1Width; - if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) { tPos1 = GSDRI.Node1.tTime; } - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); - tPos2 = GSDRI.Node2.tTime + Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosRL = tVectRL + (tDir * DistFromCorner); - //LL: - Node1Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime + Node1Width; - if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) { tPos1 = GSDRI.Node1.tTime; } - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); - tPos2 = GSDRI.Node2.tTime - Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosLL = tVectLL + (tDir * DistFromCorner); - //LR: - Node1Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime - Node1Width; - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; - tPos2 = GSDRI.Node2.tTime - Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosLR = tVectLR + (tDir * DistFromCorner); - } - else - { - //RR: - Node1Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime - Node1Width; - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; - tPos2 = GSDRI.Node2.tTime - Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosRR = tVectRR + (tDir * DistFromCorner); - //RL: - Node1Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime + Node1Width; - if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) { tPos1 = GSDRI.Node1.tTime; } - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); - tPos2 = GSDRI.Node2.tTime - Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosRL = tVectRL + (tDir * DistFromCorner); - //LL: - Node1Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime + Node1Width; - if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) { tPos1 = GSDRI.Node1.tTime; } - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); - tPos2 = GSDRI.Node2.tTime + Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosLL = tVectLL + (tDir * DistFromCorner); - //LR: - Node1Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; - Node2Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; - tPos1 = GSDRI.Node1.tTime - Node1Width; - tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; - tPos2 = GSDRI.Node2.tTime + Node2Width; - tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); - tDir = (tTan1.normalized + tTan2.normalized).normalized; - tPosLR = tVectLR + (tDir * DistFromCorner); - } - tPosRR.y = GSDRI.SignHeight; - tPosRL.y = GSDRI.SignHeight; - tPosLL.y = GSDRI.SignHeight; - tPosLR.y = GSDRI.SignHeight; - - // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22_RR"; - // tObj.transform.position = tPosRR; - // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22_RL"; - // tObj.transform.position = tPosRL; - // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22_LL"; - // tObj.transform.position = tPosLL; - // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22_LR"; - // tObj.transform.position = tPosLR; - } - - - // - // public static void GetOrigFour(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR){ - // //Get four points: - // float tPos1 = 0f; - // float tPos2 = 0f; - // Vector3 tTan1 = default(Vector3); - // Vector3 tTan2 = default(Vector3); - // float Node1Width = -1f; - // float Node2Width = -1f; - // Vector3 tDirRR = default(Vector3); - // Vector3 tDirRL = default(Vector3); - // Vector3 tDirLL = default(Vector3); - // Vector3 tDirLR = default(Vector3); - // float tAngleRR = 85f; - // float tAngleRL = 85f; - // float tAngleLL = 85f; - // float tAngleLR = 85f; - // float ShoulderWidth1 = GSDRI.Node1.GSDSpline.tRoad.opt_ShoulderWidth; - // float ShoulderWidth2 = GSDRI.Node2.GSDSpline.tRoad.opt_ShoulderWidth; - // Vector3 xPos1 = default(Vector3); - // Vector3 xPos2 = default(Vector3); - // - // if(!GSDRI.bFlipped){ - // //RR: - // Node1Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime - Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; - // tPos2 = GSDRI.Node2.tTime + Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tDirRR = (tTan1.normalized + tTan2.normalized).normalized; - // //tAngleRR = Vector3.Angle(tTan1,tTan2); - // tAngleRR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //RL: - // Node1Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime + Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); - // tPos2 = GSDRI.Node2.tTime + Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tDirRL = (tTan1.normalized + tTan2.normalized).normalized; - // //tAngleRL = Vector3.Angle(tTan1,tTan2); - // tAngleRL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //LL: - // Node1Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime + Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); - // tPos2 = GSDRI.Node2.tTime - Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tDirLL = (tTan1.normalized + tTan2.normalized).normalized; - // //tAngleLL = Vector3.Angle(tTan1,tTan2); - // tAngleLL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //LR: - // Node1Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime - Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; - // tPos2 = GSDRI.Node2.tTime - Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tDirLR = (tTan1.normalized + tTan2.normalized).normalized; - // //tAngleLR = Vector3.Angle(tTan1,tTan2); - // tAngleLR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // }else{ - // //RR: - // Node1Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime - Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; - // tPos2 = GSDRI.Node2.tTime - Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; - // tDirRR = (tTan1.normalized + tTan2.normalized).normalized; - //// tAngleRR = Vector3.Angle(tTan1,tTan2); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tAngleRR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //RL: - // Node1Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime + Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); - // tPos2 = GSDRI.Node2.tTime - Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; - // tDirRL = (tTan1.normalized + tTan2.normalized).normalized; - //// tAngleRL = Vector3.Angle(tTan1,tTan2); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tAngleRL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //LL: - // Node1Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime + Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); - // tPos2 = GSDRI.Node2.tTime + Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); - // tDirLL = (tTan1.normalized + tTan2.normalized).normalized; - //// tAngleLL = Vector3.Angle(tTan1,tTan2); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tAngleLL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // //LR: - // Node1Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; - // Node2Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; - // tPos1 = GSDRI.Node1.tTime - Node1Width; - // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; - // tPos2 = GSDRI.Node2.tTime + Node2Width; - // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); - // tDirLR = (tTan1.normalized + tTan2.normalized).normalized; - // //tAngleLR = Vector3.Angle(tTan1,tTan2); - // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); - // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); - // tAngleLR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); - // } - // - // //D = B*cos(angle/2) - // float tWidth = GSDRI.Node1.GSDSpline.tRoad.opt_RoadWidth * 0.5f; - // float tAngleRR_Opp = 180f - tAngleRR; - // float tAngleRL_Opp = 180f - tAngleRL; - // float tAngleLL_Opp = 180f - tAngleLL; - // float tAngleLR_Opp = 180f - tAngleLR; - // - // float tOffSetRR = tWidth*(Mathf.Cos((tAngleRR*0.5f)*Mathf.Deg2Rad)); - // float tOffSetRL = tWidth*(Mathf.Cos((tAngleRL*0.5f)*Mathf.Deg2Rad)); - // float tOffSetLL = tWidth*(Mathf.Cos((tAngleLL*0.5f)*Mathf.Deg2Rad)); - // float tOffSetLR = tWidth*(Mathf.Cos((tAngleLR*0.5f)*Mathf.Deg2Rad)); - // - // float tOffSetRR_opp = tWidth*(Mathf.Cos((tAngleRR_Opp*0.5f)*Mathf.Deg2Rad)); - // float tOffSetRL_opp = tWidth*(Mathf.Cos((tAngleRL_Opp*0.5f)*Mathf.Deg2Rad)); - // float tOffSetLL_opp = tWidth*(Mathf.Cos((tAngleLL_Opp*0.5f)*Mathf.Deg2Rad)); - // float tOffSetLR_opp = tWidth*(Mathf.Cos((tAngleLR_Opp*0.5f)*Mathf.Deg2Rad)); - // - // Vector3 tPos = GSDRI.Node1.pos; - // - //// tOffSetRR *=2f; - //// tOffSetRL *=2f; - //// tOffSetLL *=2f; - //// tOffSetLR *=2f; - // - // tPosRR = tPos + (tDirRR * (tOffSetRR+tOffSetRR_opp)); - // tPosRL = tPos + (tDirRL * (tOffSetRL+tOffSetRL_opp)); - // tPosLL = tPos + (tDirLL * (tOffSetLL+tOffSetLL_opp)); - // tPosLR = tPos + (tDirLR * (tOffSetLR+tOffSetLR_opp)); - // - // GameObject tObj = GameObject.Find("temp22_RR"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_RL"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_LL"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_LR"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // - // GameObject tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosRR; - // tCubeRR.transform.name = "temp22_RR"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosRL; - // tCubeRR.transform.name = "temp22_RL"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosLL; - // tCubeRR.transform.name = "temp22_LL"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosLR; - // tCubeRR.transform.name = "temp22_LR"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // } - // - // public static void GetCornerVectors_Test(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR){ - // GSDSplineN tNode = null; - // GSDSplineC tSpline = null; - // - // tNode = GSDRI.Node1; - // tSpline = tNode.GSDSpline; - // float tOffset = tSpline.tRoad.opt_RoadWidth * 0.5f; - // float tPos1 = tNode.tTime - (tOffset/tSpline.distance); - // float tPos2 = tNode.tTime + (tOffset/tSpline.distance); - // Vector3 tVect1 = tSpline.GetSplineValue(tPos1); - // Vector3 POS1 = tSpline.GetSplineValue(tPos1,true); - // Vector3 tVect2 = tSpline.GetSplineValue(tPos2); - // Vector3 POS2 = tSpline.GetSplineValue(tPos2,true); - // tPosRR = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); - // tPosLR = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); - // tPosRL = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); - // tPosLL = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); - // - // tNode = GSDRI.Node2; - // tSpline = tNode.GSDSpline; - // tOffset = tSpline.tRoad.opt_RoadWidth * 0.5f; - // tPos1 = tNode.tTime - (tOffset/tSpline.distance); - // tPos2 = tNode.tTime + (tOffset/tSpline.distance); - // tVect1 = tSpline.GetSplineValue(tPos1); - // POS1 = tSpline.GetSplineValue(tPos1,true); - // tVect2 = tSpline.GetSplineValue(tPos2); - // POS2 = tSpline.GetSplineValue(tPos2,true); - // Vector3 tPosRR2 = default(Vector3); - // Vector3 tPosLR2 = default(Vector3); - // Vector3 tPosRL2 = default(Vector3); - // Vector3 tPosLL2 = default(Vector3); - // - // if(GSDRI.bFlipped){ - // tPosRL2 = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); - // tPosRR2 = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); - // tPosLL2 = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); - // tPosLR2 = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); - // }else{ - // tPosLR2 = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); - // tPosLL2 = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); - // tPosRR2 = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); - // tPosRL2 = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); - // } - // - // tPosRR = ((tPosRR-tPosRR2)*0.5f)+tPosRR; - // tPosLR = ((tPosLR-tPosLR2)*0.5f)+tPosLR; - // tPosRL = ((tPosRL-tPosRL2)*0.5f)+tPosRL; - // tPosLL = ((tPosLL-tPosLL2)*0.5f)+tPosLL; - // - // - // GameObject tObj = GameObject.Find("temp22_RR"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_RL"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_LL"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // tObj = GameObject.Find("temp22_LR"); if(tObj != null){ Object.DestroyImmediate(tObj); } - // - // GameObject tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosRR; - // tCubeRR.transform.name = "temp22_RR"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosRL; - // tCubeRR.transform.name = "temp22_RL"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosLL; - // tCubeRR.transform.name = "temp22_LL"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // - // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tCubeRR.transform.position = tPosLR; - // tCubeRR.transform.name = "temp22_LR"; - // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); - // } - // - } - - public static class GSDIntersections - { - public class iConstructionMaker - { - //Lanes: - public List iBLane0L, iBLane0R; - public List iBLane1L, iBLane1R; - public List iBLane2L, iBLane2R; - public List iBLane3L, iBLane3R; - public List iFLane0L, iFLane0R; - public List iFLane1L, iFLane1R; - public List iFLane2L, iFLane2R; - public List iFLane3L, iFLane3R; - //Main plate: - public List iBMainPlateL; public List iBMainPlateR; - public List iFMainPlateL; public List iFMainPlateR; - //Front marker plates: - public List iBMarkerPlateL; public List iBMarkerPlateR; - public List iFMarkerPlateL; public List iFMarkerPlateR; - - public float tempconstruction_InterStart; - public float tempconstruction_InterEnd; - public bool tempconstruction_HasProcessed_Inter1 = false; - public bool tempconstruction_HasProcessed_Inter2 = false; - - public List tempconstruction_R_RightTurn; - public List tempconstruction_L_RightTurn; - public List tempconstruction_R; - public List tempconstruction_L; - - public float tempconstruction_MinXR = 0f; - public float tempconstruction_MaxXR = 0f; - public float tempconstruction_MinXL = 0f; - public float tempconstruction_MaxXL = 0f; - - public float tempconstruction_MinYR = 0f; - public float tempconstruction_MaxYR = 0f; - public float tempconstruction_MinYL = 0f; - public float tempconstruction_MaxYL = 0f; - - public bool bBLane0Done = false; - public bool bBLane1Done = false; - public bool bBLane2Done = false; - public bool bBLane3Done = false; - public bool bFLane0Done = false; - public bool bFLane1Done = false; - public bool bFLane2Done = false; - public bool bFLane3Done = false; - - public bool bBLane0Done_Final = false; - public bool bBLane1Done_Final = false; - public bool bBLane2Done_Final = false; - public bool bBLane3Done_Final = false; - public bool bFLane0Done_Final = false; - public bool bFLane1Done_Final = false; - public bool bFLane2Done_Final = false; - public bool bFLane3Done_Final = false; - - public bool bBLane0Done_Final_ThisRound = false; - public bool bBLane1Done_Final_ThisRound = false; - public bool bBLane2Done_Final_ThisRound = false; - public bool bBLane3Done_Final_ThisRound = false; - public bool bFLane0Done_Final_ThisRound = false; - public bool bFLane1Done_Final_ThisRound = false; - public bool bFLane2Done_Final_ThisRound = false; - public bool bFLane3Done_Final_ThisRound = false; - - public bool bFDone = false; - public bool bBDone = false; - - public bool bIsFrontFirstRound = false; - public bool bIsFrontFirstRoundTriggered = false; - - public Vector3 f0LAttempt = default(Vector3); - public Vector3 f1LAttempt = default(Vector3); - public Vector3 f2LAttempt = default(Vector3); - public Vector3 f3LAttempt = default(Vector3); - public Vector3 f0RAttempt = default(Vector3); - public Vector3 f1RAttempt = default(Vector3); - public Vector3 f2RAttempt = default(Vector3); - public Vector3 f3RAttempt = default(Vector3); - - public bool bNode1RLTriggered = false; - - public bool bDepressDoneR = false; - public bool bDepressDoneL = false; - - public bool bBackRRpassed = false; - - public List iBLane0_Real; - - public Vector3 ShoulderBL_Start = default(Vector3); - public Vector3 ShoulderBR_Start = default(Vector3); - public Vector3 ShoulderFL_Start = default(Vector3); - public Vector3 ShoulderFR_Start = default(Vector3); - - public Vector3 ShoulderBL_End = default(Vector3); - public Vector3 ShoulderBR_End = default(Vector3); - public Vector3 ShoulderFL_End = default(Vector3); - public Vector3 ShoulderFR_End = default(Vector3); - - public int ShoulderBL_StartIndex = -1; - public int ShoulderBR_StartIndex = -1; - public int ShoulderFL_StartIndex = -1; - public int ShoulderFR_StartIndex = -1; - - public void Nullify() - { - - //Intersection construction: - if (iBLane0L != null) { iBLane0L.Clear(); iBLane0L = null; } - if (iBLane0R != null) { iBLane0R.Clear(); iBLane0R = null; } - if (iBLane1L != null) { iBLane1L.Clear(); iBLane1L = null; } - if (iBLane1R != null) { iBLane1R.Clear(); iBLane1R = null; } - if (iBLane2L != null) { iBLane2L.Clear(); iBLane2L = null; } - if (iBLane2R != null) { iBLane2R.Clear(); iBLane2R = null; } - if (iBLane3L != null) { iBLane3L.Clear(); iBLane3L = null; } - if (iBLane3R != null) { iBLane3R.Clear(); iBLane3R = null; } - if (iFLane0L != null) { iFLane0L.Clear(); iFLane0L = null; } - if (iFLane0R != null) { iFLane0R.Clear(); iFLane0R = null; } - if (iFLane1L != null) { iFLane1L.Clear(); iFLane1L = null; } - if (iFLane1R != null) { iFLane1R.Clear(); iFLane1R = null; } - if (iFLane2L != null) { iFLane2L.Clear(); iFLane2L = null; } - if (iFLane2R != null) { iFLane2R.Clear(); iFLane2R = null; } - if (iFLane3L != null) { iFLane3L.Clear(); iFLane3L = null; } - if (iFLane3R != null) { iFLane3R.Clear(); iFLane3R = null; } - if (iBMainPlateL != null) { iBMainPlateL.Clear(); iBMainPlateL = null; } - if (iBMainPlateR != null) { iBMainPlateR.Clear(); iBMainPlateR = null; } - if (iFMainPlateL != null) { iFMainPlateL.Clear(); iFMainPlateL = null; } - if (iFMainPlateR != null) { iFMainPlateR.Clear(); iFMainPlateR = null; } - - if (iBMarkerPlateL != null) { iBMarkerPlateL.Clear(); iBMarkerPlateL = null; } - if (iBMarkerPlateR != null) { iBMarkerPlateR.Clear(); iBMarkerPlateR = null; } - if (iFMarkerPlateL != null) { iFMarkerPlateL.Clear(); iFMarkerPlateL = null; } - if (iFMarkerPlateR != null) { iFMarkerPlateR.Clear(); iFMarkerPlateR = null; } - - if (tempconstruction_R != null) { tempconstruction_R = null; } - if (tempconstruction_L != null) { tempconstruction_L = null; } - } - - public iConstructionMaker() - { - Nullify(); - - iBLane0_Real = new List(); - - //Lanes: - iBLane0L = new List(); - iBLane0R = new List(); - iBLane1L = new List(); - iBLane1R = new List(); - iBLane2L = new List(); - iBLane2R = new List(); - iBLane3L = new List(); - iBLane3R = new List(); - iFLane0L = new List(); - iFLane0R = new List(); - iFLane1L = new List(); - iFLane1R = new List(); - iFLane2L = new List(); - iFLane2R = new List(); - iFLane3L = new List(); - iFLane3R = new List(); - //Main plate: - iBMainPlateL = new List(); - iBMainPlateR = new List(); - iFMainPlateL = new List(); - iFMainPlateR = new List(); - - iBMarkerPlateL = new List(); - iBMarkerPlateR = new List(); - iFMarkerPlateL = new List(); - iFMarkerPlateR = new List(); - - tempconstruction_HasProcessed_Inter1 = false; - tempconstruction_HasProcessed_Inter2 = false; - tempconstruction_MinXR = 20000000f; - tempconstruction_MaxXR = 0f; - tempconstruction_MinXL = 20000000f; - tempconstruction_MaxXL = 0f; - tempconstruction_MinYR = 20000000f; - tempconstruction_MaxYR = 0f; - tempconstruction_MinYL = 20000000f; - tempconstruction_MaxYL = 0f; - - bBLane0Done = false; - bBLane1Done = false; - bBLane2Done = false; - bBLane3Done = false; - bFLane0Done = false; - bFLane1Done = false; - bFLane2Done = false; - bFLane3Done = false; - } - } - - public static GameObject CreateIntersection(GSDSplineN tNode, GSDSplineN xNode) - { - return CreateIntersection_Do(tNode, xNode); - } - private static GameObject CreateIntersection_Do(GSDSplineN tNode, GSDSplineN xNode) - { - float RoadMod = 10f; - GameObject SystemObj = tNode.transform.parent.parent.parent.gameObject; - if (!SystemObj) { Debug.LogWarning("Could not find GSD road system master object."); return null; } - GameObject InterMaster = null; - int cCount = SystemObj.transform.childCount; - for (int i = 0; i < cCount; i++) - { - if (SystemObj.transform.GetChild(i).transform.name.ToLower() == "intersections") - { - InterMaster = SystemObj.transform.GetChild(i).gameObject; - } - } - if (!InterMaster) - { - InterMaster = new GameObject("Intersections"); - InterMaster.transform.parent = SystemObj.transform; - } - if (!InterMaster) - { - Debug.LogWarning("Could not find intersections master object for this road system."); - return null; - } - cCount = InterMaster.transform.childCount; - - GameObject tObj = new GameObject("Inter" + (cCount + 1).ToString()); - tObj.transform.parent = InterMaster.transform; - GSDRoadIntersection GSDRI = tObj.AddComponent(); - GSDRI.IgnoreSide = -1; - GSDRI.bFirstSpecial_First = false; - GSDRI.bFirstSpecial_Last = false; - GSDRI.bSecondSpecial_First = false; - GSDRI.bSecondSpecial_Last = false; - - GSDSplineN tNode1 = null; - GSDSplineN tNode2 = null; - if (tNode.GSDSpline == xNode.GSDSpline) - { - if (tNode.idOnSpline < xNode.idOnSpline) - { - tNode1 = tNode; - tNode2 = xNode; - } - else - { - tNode1 = xNode; - tNode2 = tNode; - } - } - else - { - tNode1 = tNode; - tNode2 = xNode; - } - - //If 3way, always add the single node as primary: - if (tNode.bIsEndPoint) - { - tNode1 = tNode; - tNode2 = xNode; - } - else if (xNode.bIsEndPoint) - { - tNode1 = xNode; - tNode2 = tNode; - } - - tNode1.Intersection_OtherNode = tNode2; - tNode2.Intersection_OtherNode = tNode1; - - if (tNode1.bIsEndPoint || tNode2.bIsEndPoint) - { - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - } - - GSDSplineN zNode = null; - if (tNode1.bIsEndPoint) - { - bool bFirstNode = false; - bool bAlreadyNode = false; - if (tNode1.idOnSpline == 1 || tNode1.idOnSpline == 0) - { - bFirstNode = true; - } - if (bFirstNode && tNode1.idOnSpline == 1 && tNode1.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) - { - bAlreadyNode = true; - } - else if (!bFirstNode && tNode1.idOnSpline == tNode1.GSDSpline.GetNodeCount() - 2 && tNode1.GSDSpline.mNodes[tNode1.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) - { - bAlreadyNode = true; - } - - Vector3 tPos = default(Vector3); - if (bFirstNode) - { - tPos = ((tNode1.tangent * -1f).normalized * (tNode1.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode1.pos; - } - else - { - tPos = (tNode1.GSDSpline.GetSplineValue(0.999f, true).normalized * (tNode1.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode1.pos; - } - - if (!bAlreadyNode) - { - if (bFirstNode) - { - zNode = GSD.Roads.GSDConstruction.InsertNode(tNode1.GSDSpline.tRoad, true, tPos, false, 0, true, true); - zNode.bSpecialEndNode_IsStart = true; - zNode.bSpecialIntersection = true; - zNode.tangent = tNode1.tangent; - } - else - { - zNode = GSD.Roads.GSDConstruction.CreateNode(tNode1.GSDSpline.tRoad, true, tPos, true); - zNode.bSpecialEndNode_IsEnd = true; - zNode.bSpecialIntersection = true; - zNode.tangent = tNode1.tangent; - } - } - else - { - if (bFirstNode) - { - tNode1.GSDSpline.mNodes[0].transform.position = tPos; - } - else - { - tNode1.GSDSpline.mNodes[tNode1.GSDSpline.GetNodeCount() - 1].transform.position = tPos; - } - } - if (bFirstNode) - { - tNode1.GSDSpline.bSpecialStartControlNode = true; - GSDRI.bFirstSpecial_First = true; - } - else - { - tNode1.GSDSpline.bSpecialEndControlNode = true; - GSDRI.bFirstSpecial_Last = true; - } - - } - else if (tNode2.bIsEndPoint) - { - bool bFirstNode = false; - bool bAlreadyNode = false; - if (tNode2.idOnSpline == 1 || tNode2.idOnSpline == 0) - { - bFirstNode = true; - } - if (bFirstNode && tNode2.idOnSpline == 1 && tNode2.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) - { - bAlreadyNode = true; - } - else if (!bFirstNode && tNode2.idOnSpline == tNode2.GSDSpline.GetNodeCount() - 2 && tNode2.GSDSpline.mNodes[tNode2.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) - { - bAlreadyNode = true; - } - - Vector3 tPos = default(Vector3); - if (bFirstNode) - { - tPos = ((tNode2.tangent * -1f).normalized * (tNode2.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode2.pos; - } - else - { - tPos = (tNode2.GSDSpline.GetSplineValue(0.999f, true).normalized * (tNode2.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode2.pos; - } - - if (!bAlreadyNode) - { - if (bFirstNode) - { - zNode = GSD.Roads.GSDConstruction.InsertNode(tNode2.GSDSpline.tRoad, true, tPos, false, 0, true, true); - zNode.bSpecialEndNode_IsStart = true; - zNode.bSpecialIntersection = true; - zNode.tangent = tNode2.tangent; - } - else - { - zNode = GSD.Roads.GSDConstruction.CreateNode(tNode2.GSDSpline.tRoad, true, tPos, true); - zNode.bSpecialEndNode_IsEnd = true; - zNode.bSpecialIntersection = true; - zNode.tangent = tNode2.tangent; - } - } - else - { - if (bFirstNode) - { - tNode2.GSDSpline.mNodes[0].transform.position = tPos; - } - else - { - tNode2.GSDSpline.mNodes[tNode2.GSDSpline.GetNodeCount() - 1].transform.position = tPos; - } - } - if (bFirstNode) - { - tNode2.GSDSpline.bSpecialStartControlNode = true; - GSDRI.bSecondSpecial_First = true; - } - else - { - tNode2.GSDSpline.bSpecialEndControlNode = true; - GSDRI.bSecondSpecial_Last = true; - } - } - - //Undo crap: - UnityEditor.Undo.RegisterCreatedObjectUndo(tObj, "Created intersection"); - - GSDRI.Setup(tNode1, tNode2); - tObj.transform.position = tNode.transform.position; - - GSDRI.ResetMaterials_All(); - - // if(GSDRI.bSameSpline){ - // GSDRI.Node1.GSDSpline.tRoad.UpdateRoad(); - // }else{ - // GSDRI.Node1.GSDSpline.tRoad.UpdateRoad(); - // GSDRI.Node2.GSDSpline.tRoad.UpdateRoad(); - // } - - tNode1.ToggleHideFlags(true); - tNode2.ToggleHideFlags(true); - - if (GSDRI != null && GSDRI.Node1 != null && GSDRI.Node2 != null) - { - if (!GSDRI.bSameSpline) - { - GSDRI.Node1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[4]; - GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[0] = GSDRI.Node2.GSDSpline; - - GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[1] = GSDRI.Node1.GSDSpline; - GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[2] = GSDRI.Node2.GSDSpline; - GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[3] = GSDRI.Node1.GSDSpline; - // GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[4] = GSDRI.Node2.GSDSpline; - } - GSDRI.Node1.GSDSpline.tRoad.EditorUpdateMe = true; - } - - return tObj; - } - - public static Vector3[] GetCornerVectors_Test(GSDRoadIntersection GSDRI) - { - Vector3[] tVects = new Vector3[4]; - GSDSplineN tNode; - tNode = GSDRI.Node1; - GSDSplineC tSpline = tNode.GSDSpline; - - //RR = Node1 - 5, Node2 + 5 - //RL = Node1 + 5, Node2 + 5 - //LL = Node1 + 5, Node2 - 5 - //LR = Node1 - 5, Node2 - 5 - - float tOffset = 5f; - float tPos1 = tNode.tTime - (tOffset / tSpline.distance); - float tPos2 = tNode.tTime + (tOffset / tSpline.distance); - Vector3 tVect1 = tSpline.GetSplineValue(tPos1); - Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); - Vector3 tVect2 = tSpline.GetSplineValue(tPos2); - Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); - - tVects[0] = (tVect1 + new Vector3(5f * POS1.normalized.z, 0, 5f * -POS1.normalized.x)); - tVects[1] = (tVect1 + new Vector3(5f * -POS1.normalized.z, 0, 5f * POS1.normalized.x)); - tVects[2] = (tVect2 + new Vector3(5f * POS2.normalized.z, 0, 5f * -POS2.normalized.x)); - tVects[3] = (tVect2 + new Vector3(5f * -POS2.normalized.z, 0, 5f * POS2.normalized.x)); - - return tVects; - } - - #region "Old intersection" - public static void CreateIntersection(GSDRoadIntersection GSDRI) - { - //1. Overlap sphere to find all road objects within intersection: - float iWidth = GSDRI.IntersectionWidth * 1.25f; - Collider[] tColliders = Physics.OverlapSphere(GSDRI.transform.position, iWidth); - if (tColliders == null || tColliders.Length < 1) { return; } - List tRoads = new List(); - foreach (Collider tCollider in tColliders) - { - if (tCollider.transform.parent) - { - GSDRoad tRoad = tCollider.transform.parent.GetComponent(); - if (tRoad) - { - if (!tRoads.Contains(tRoad)) - { - tRoads.Add(tRoad); - } - } - } - } - - //Flatten intersection area: - float tHeight = -1f; - FlattenIntersectionArea(ref tRoads, GSDRI, iWidth, out tHeight); - - //Create main intersection mesh: - string tName = GSDRI.transform.name; - Vector3[] tVects; - CreateIntersectionMesh_Main(GSDRI, tHeight, out tVects, ref tName); - - //Now create the 4 text overlays: - CreateIntersectionMesh_Outer(GSDRI, tVects, ref tName); - - //Update connected nodes: - GSDNavigation.UpdateConnectedNodes(); - - //Now initialize intersection objects: - InitializeIntersectionObjects(GSDRI); - } - - private static void FlattenIntersectionArea(ref List tRoads, GSDRoadIntersection GSDRI, float iWidth, out float tHeight) - { - //Cycle through each road and get all mesh vertices that are within range: - Vector3 tInterPos = GSDRI.transform.position; - float tInterPosY = tInterPos.y; - foreach (GSDRoad tRoad in tRoads) - { - MeshFilter MF_Road = tRoad.MeshRoad.GetComponent(); - MeshFilter MF_Road_SR = tRoad.MeshShoR.GetComponent(); - MeshFilter MF_Road_SL = tRoad.MeshShoL.GetComponent(); - - Mesh Road = MF_Road.sharedMesh; - Mesh Road_SR = MF_Road_SR.sharedMesh; - Mesh Road_SL = MF_Road_SL.sharedMesh; - - Vector3[] tVects = Road.vertices; - Vector3[] tVects_SR = Road_SR.vertices; - Vector3[] tVects_SL = Road_SL.vertices; - int VertCount = Road.vertices.Length; - bool bLeftToggle = true; - for (int i = 0; i < VertCount; i += 2) - { - if (Vector3.Distance(tVects[i], tInterPos) < iWidth) - { - tVects[i].y = tInterPosY; - tVects[i + 1].y = tInterPosY; - if (bLeftToggle) - { - //Left: - tVects_SL[i + 2].y = tInterPosY; - tVects_SL[i + 3].y = tInterPosY; - } - else - { - //Right: - tVects_SR[i - 2].y = tInterPosY; - tVects_SR[i - 1].y = tInterPosY; - } - } - bLeftToggle = !bLeftToggle; - } - //Main road: - Road.vertices = tVects; - Road.RecalculateNormals(); - MF_Road.sharedMesh = Road; - //Right shoulder: - Road_SR.vertices = tVects_SR; - Road_SR.RecalculateNormals(); - MF_Road_SR.sharedMesh = Road_SR; - //Left shoulder: - Road_SL.vertices = tVects_SL; - Road_SL.RecalculateNormals(); - MF_Road_SL.sharedMesh = Road_SL; - } - tHeight = tInterPosY; - } - - private static bool V3Equal(Vector3 a, Vector3 b) - { - return Vector3.SqrMagnitude(a - b) < 0.0001f; - } - - private static Vector3[] GetCornerVectors(GSDRoadIntersection GSDRI, bool bPrimary = true) - { - Vector3[] tVects = new Vector3[4]; - GSDSplineN tNode; - if (bPrimary) - { - tNode = GSDRI.Node1; - } - else - { - tNode = GSDRI.Node2; - } - GSDSplineC tSpline = tNode.GSDSpline; - - float tOffset = 7f; - float tPos1 = tNode.tTime - (tOffset / tSpline.distance); - float tPos2 = tNode.tTime + (tOffset / tSpline.distance); - Vector3 tVect1 = tSpline.GetSplineValue(tPos1); - Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); - Vector3 tVect2 = tSpline.GetSplineValue(tPos2); - Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); - - tVects[0] = (tVect1 + new Vector3(5f * POS1.normalized.z, 0, 5f * -POS1.normalized.x)); - tVects[1] = (tVect1 + new Vector3(5f * -POS1.normalized.z, 0, 5f * POS1.normalized.x)); - tVects[2] = (tVect2 + new Vector3(5f * POS2.normalized.z, 0, 5f * -POS2.normalized.x)); - tVects[3] = (tVect2 + new Vector3(5f * -POS2.normalized.z, 0, 5f * POS2.normalized.x)); - - return tVects; - } - - private static Vector3[] GetExtendedVectors(GSDRoadIntersection GSDRI, bool bPrimary = true) - { - Vector3[] tVects = new Vector3[4]; - GSDSplineN tNode; - if (bPrimary) - { - tNode = GSDRI.Node1; - } - else - { - tNode = GSDRI.Node2; - } - GSDSplineC tSpline = tNode.GSDSpline; - Vector3 NodePos = tNode.transform.position; - - float tOffset = tNode.GSDSpline.tRoad.RoadWidth(); - float tOffset2 = tOffset * 0.5f; - float tPos1 = tNode.tTime - (tOffset / tSpline.distance); - float tPos2 = tNode.tTime + (tOffset / tSpline.distance); - Vector3 tVect1 = tSpline.GetSplineValue(tPos1); - Vector3 tVect2 = tSpline.GetSplineValue(tPos2); - - //Enforce distance: - int SpamGuard = 0; - int SGMax = 50; - while (Vector3.Distance(tVect1, NodePos) < tOffset && SpamGuard < SGMax) - { - SpamGuard += 1; - tPos1 -= (1f / tSpline.distance); - tVect1 = tSpline.GetSplineValue(tPos1); - } - SpamGuard = 0; - while (Vector3.Distance(tVect1, NodePos) > (tOffset * 1.2f) && SpamGuard < SGMax) - { - SpamGuard += 1; - tPos1 += (0.25f / tSpline.distance); - tVect1 = tSpline.GetSplineValue(tPos1); - } - SpamGuard = 0; - while (Vector3.Distance(tVect2, NodePos) < tOffset && SpamGuard < SGMax) - { - SpamGuard += 1; - tPos2 += (1f / tSpline.distance); - tVect2 = tSpline.GetSplineValue(tPos2); - } - SpamGuard = 0; - while (Vector3.Distance(tVect1, NodePos) > (tOffset * 1.2f) && SpamGuard < SGMax) - { - SpamGuard += 1; - tPos2 -= (0.25f / tSpline.distance); - tVect2 = tSpline.GetSplineValue(tPos2); - } - - Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); - Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); - - tVects[0] = (tVect1 + new Vector3(tOffset2 * POS1.normalized.z, 0, tOffset2 * -POS1.normalized.x)); - tVects[1] = (tVect1 + new Vector3(tOffset2 * -POS1.normalized.z, 0, tOffset2 * POS1.normalized.x)); - tVects[2] = (tVect2 + new Vector3(tOffset2 * POS2.normalized.z, 0, tOffset2 * -POS2.normalized.x)); - tVects[3] = (tVect2 + new Vector3(tOffset2 * -POS2.normalized.z, 0, tOffset2 * POS2.normalized.x)); - - return tVects; - } - - //Two non-parallel lines which may or may not touch each other have a point on each line which are closest - //to each other. This function finds those two points. If the lines are not parallel, the function - //outputs true, otherwise false. - private static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2) - { - - closestPointLine1 = Vector3.zero; - closestPointLine2 = Vector3.zero; - - float a = Vector3.Dot(lineVec1, lineVec1); - float b = Vector3.Dot(lineVec1, lineVec2); - float e = Vector3.Dot(lineVec2, lineVec2); - - float d = a * e - b * b; - - //lines are not parallel - if (d != 0.0f) - { - - Vector3 r = linePoint1 - linePoint2; - float c = Vector3.Dot(lineVec1, r); - float f = Vector3.Dot(lineVec2, r); - - float s = (b * f - c * e) / d; - float t = (a * f - c * b) / d; - - closestPointLine1 = linePoint1 + lineVec1 * s; - closestPointLine2 = linePoint2 + lineVec2 * t; - - return true; - } - - else - { - return false; - } - } - - - private static void CreateIntersectionMesh_Main(GSDRoadIntersection GSDRI, float tHeight, out Vector3[] tVects, ref string tName) - { - //Get four points: - Vector3[] pVects = GetCornerVectors(GSDRI); - Vector3[] sVects = GetCornerVectors(GSDRI, false); - tVects = new Vector3[4]; - Vector3 oIntersection = new Vector3(0f, 0f, 0f); - Vector3 oIntersection2 = new Vector3(0f, 0f, 0f);//Unused - - // bool bIntersection; - ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[0], (pVects[2] - pVects[0]), sVects[0], (sVects[2] - sVects[0])); - tVects[0] = oIntersection; - tVects[0].y = tHeight; - - ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[0], (pVects[2] - pVects[0]), sVects[1], (sVects[3] - sVects[1])); - tVects[1] = oIntersection; - tVects[1].y = tHeight; - - ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[1], (pVects[3] - pVects[1]), sVects[0], (sVects[2] - sVects[0])); - tVects[2] = oIntersection; - tVects[2].y = tHeight; - - ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[1], (pVects[3] - pVects[1]), sVects[1], (sVects[3] - sVects[1])); - tVects[3] = oIntersection; - tVects[3].y = tHeight; - - CreateIntersectionMesh_MainInternal(tVects, GSDRI.transform.gameObject, ref tName); - } - - private static void CreateIntersectionMesh_MainInternal(Vector3[] tVerts, GameObject iObj, ref string tName) - { - Mesh tMesh = new Mesh(); - int MVL = 4; - int triCount = (int)(4f * 1.5f); - - // GameObject tObj; - // tObj = GameObject.Find("tInter1"); tObj.transform.position = tVerts[0]; - // tObj = GameObject.Find("tInter2"); tObj.transform.position = tVerts[1]; - // tObj = GameObject.Find("tInter3"); tObj.transform.position = tVerts[2]; - // tObj = GameObject.Find("tInter4"); tObj.transform.position = tVerts[3]; - - for (int i = 0; i < MVL; i++) - { - tVerts[i] -= iObj.transform.position; - } - tMesh.vertices = tVerts; - tMesh.RecalculateBounds(); - - int[] tri = new int[triCount]; - tri[0] = 0; - tri[1] = 2; - tri[2] = 1; - tri[3] = 2; - tri[4] = 3; - tri[5] = 1; - tMesh.triangles = tri; - - Vector3[] normals = new Vector3[MVL]; - for (int i = 0; i < MVL; i++) - { - normals[i] = -Vector3.forward; - } - tMesh.normals = normals; - tMesh.RecalculateNormals(); - - Vector2[] uv = new Vector2[MVL]; - uv[0] = new Vector2(0f, 0f); - uv[1] = new Vector2(1f, 0f); - uv[2] = new Vector2(0f, 1f); - uv[3] = new Vector2(1f, 1f); - tMesh.uv = uv; - - GSDRootUtil.ProcessTangents(ref tMesh); - - //Final processing: - MeshFilter MF = iObj.GetComponent(); - if (!MF) { MF = iObj.AddComponent(); } - MF.sharedMesh = tMesh; - // MeshToFile(MF,GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Intersections/" + tName +".obj"); - - MeshCollider MC = iObj.GetComponent(); - if (MC) { Object.DestroyImmediate(MC); } - //if(!MC){ MC = iObj.AddComponent(); } - //MC.sharedMesh = MF.sharedMesh; - - MeshRenderer MR = iObj.GetComponent(); - if (!MR) { MR = iObj.AddComponent(); } - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - MR.receiveShadows = true; - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoadIntersection.mat", MR); - } - - private static void CreateIntersectionMesh_Outer(GSDRoadIntersection GSDRI, Vector3[] tVects, ref string tName) - { - Vector3[] bVects1 = GetExtendedVectors(GSDRI); - Vector3[] bVects2 = GetExtendedVectors(GSDRI, false); - Vector3[] eVects = new Vector3[16]; - eVects[0] = tVects[1]; - eVects[1] = tVects[0]; - eVects[2] = bVects2[3]; - eVects[3] = bVects2[2]; - // - eVects[4] = tVects[3]; - eVects[5] = tVects[1]; - eVects[6] = bVects1[3]; - eVects[7] = bVects1[2]; - // - eVects[8] = tVects[2]; - eVects[9] = tVects[3]; - eVects[10] = bVects2[0]; - eVects[11] = bVects2[1]; - // - eVects[12] = tVects[0]; - eVects[13] = tVects[2]; - eVects[14] = bVects1[0]; - eVects[15] = bVects1[1]; - - int cCount = GSDRI.transform.childCount; - // bool bOuter = false; - GameObject tOuter = null; - for (int i = 0; i < cCount; i++) - { - if (GSDRI.transform.GetChild(i).transform.name == "outer") - { - tOuter = GSDRI.transform.GetChild(i).transform.gameObject; - } - } - if (!tOuter) - { - tOuter = new GameObject("outer"); - tOuter.transform.parent = GSDRI.transform; - } - tOuter.transform.position = GSDRI.transform.position; - - // GameObject tObj; - // tObj = GameObject.Find("tInter1"); tObj.transform.position = bVects2[0]; - // tObj = GameObject.Find("tInter2"); tObj.transform.position = bVects2[1]; - // tObj = GameObject.Find("tInter3"); tObj.transform.position = bVects2[2]; - // tObj = GameObject.Find("tInter4"); tObj.transform.position = bVects2[3]; - - CreateIntersectionMesh_OuterInternal(eVects, tOuter, GSDRI.transform.position, ref tName); - } - - private static void CreateIntersectionMesh_OuterInternal(Vector3[] tVerts, GameObject iObj, Vector3 vOffset, ref string tName) - { - Mesh tMesh = new Mesh(); - int MVL = 16; - int triCount = (int)(16f * 1.5f); - - for (int i = 0; i < MVL; i += 4) - { - // tVerts[i] += vOffset; - // tVerts[i+1] += vOffset; - tVerts[i + 2] -= vOffset; - tVerts[i + 3] -= vOffset; - } - tMesh.vertices = tVerts; - tMesh.RecalculateBounds(); - - int[] tri = new int[triCount]; - int cTri = 0; - for (int i = 0; i < triCount; i += 4) - { - if (i + 3 >= MVL) - { - break; - } - tri[cTri] = i; cTri += 1; - tri[cTri] = i + 2; cTri += 1; - tri[cTri] = i + 1; cTri += 1; - - tri[cTri] = i + 2; cTri += 1; - tri[cTri] = i + 3; cTri += 1; - tri[cTri] = i + 1; cTri += 1; - } - tMesh.triangles = tri; - - Vector3[] normals = new Vector3[MVL]; - for (int i = 0; i < 4; i++) - { - normals[i] = -Vector3.forward; - } - tMesh.normals = normals; - tMesh.RecalculateNormals(); - - Vector2[] uv = new Vector2[MVL]; - for (int i = 0; i < MVL; i += 4) - { - uv[i] = new Vector2(1f, 1f); - uv[i + 1] = new Vector2(0f, 1f); - uv[i + 2] = new Vector2(1f, 0f); - uv[i + 3] = new Vector2(0f, 0f); - } - tMesh.uv = uv; - - GSDRootUtil.ProcessTangents(ref tMesh); - - //Final processing: - MeshFilter MF = iObj.GetComponent(); - if (!MF) { MF = iObj.AddComponent(); } - MF.sharedMesh = tMesh; - - // MeshToFile(MF,GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Intersections/" + tName +"-overlay.obj"); - - MeshCollider MC = iObj.GetComponent(); - if (MC) { Object.DestroyImmediate(MC); } - // if(!MC){ MC = iObj.AddComponent(); } - // MC.sharedMesh = MF.sharedMesh; - - MeshRenderer MR = iObj.GetComponent(); - if (!MR) { MR = iObj.AddComponent(); } - MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - MR.receiveShadows = true; - GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterText.mat", MR); - } - - #region "Intersection creation" - private static void InitializeIntersectionObjects(GSDRoadIntersection tGSDRI) - { - if (tGSDRI != null) - { - InitializeIntersectionObjects_Internal(tGSDRI); - } - else - { - Object[] iObjects = GameObject.FindObjectsOfType(typeof(GSDRoadIntersection)); - //Add intersection components, if necessary: - foreach (GSDRoadIntersection GSDRI in iObjects) - { - InitializeIntersectionObjects_Internal(GSDRI); - } - } - } - - private static void InitializeIntersectionObjects_Internal(GSDRoadIntersection GSDRI) - { - //1. Determine 3-way or 4-way. # of corners for 3-way: 2. 4-way = 4. - if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) - { - GSDRI.CornerPoints = new GSDRoadIntersection.CornerPositionMaker[2]; - } - else - { - GSDRI.CornerPoints = new GSDRoadIntersection.CornerPositionMaker[4]; - } - - //Contains int IDs of connected nodes: - List tList = new List(); - //Get all connected nodes on intersection node1: - int cCount = GSDRI.Node1.id_connected.Count; - GSDSplineN tNode; - for (int i = 0; i < cCount; i++) - { - //tNode = GetNodeByID(GSDRI.Node1.id_connected[i]); - tNode = GSDRI.Node1.node_connected[i]; - if (!tList.Contains(tNode)) - { - tList.Add(tNode); - } - } - //Get all connected nodes on intersection node2: - cCount = GSDRI.Node2.id_connected.Count; - for (int i = 0; i < cCount; i++) - { - //tNode = GetNodeByID(GSDRI.Node2.id_connected[i]); - tNode = GSDRI.Node2.node_connected[i]; - if (!tList.Contains(tNode)) - { - tList.Add(tNode); - } - } - //Declare connected nodes: - GSDSplineN n1, n2, n3, n4; - n1 = tList[0]; - n2 = tList[1]; - n3 = tList[2]; - n4 = null; - if (tList.Count > 3) { n4 = tList[3]; } - - //Determine most relevant spline: - GSDSplineC n1Spline = n1.GSDSpline; - GSDSplineC n2Spline = n2.GSDSpline; - GSDSplineC n3Spline = n3.GSDSpline; - GSDSplineC n4Spline = null; - if (n4 != null) { n4Spline = n4.GSDSpline; } - - //Get the point: - Vector3 n1Point = GetFourCornerPoint(ref n1Spline, ref n1, GSDRI); - Vector3 n2Point = GetFourCornerPoint(ref n2Spline, ref n2, GSDRI); - Vector3 n3Point = GetFourCornerPoint(ref n3Spline, ref n3, GSDRI); - Vector3 n4Point = new Vector3(0f, 0f, 0f); - if (n4Spline != null) { n4Point = GetFourCornerPoint(ref n4Spline, ref n4, GSDRI); } - - //2. If 3 way, we know that 2 of the nodes have the same spline. - if (1 == 1 && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) - { - //Should be size 3: - if (tList.Count != 3) - { - Debug.LogError("InitializeIntersections hashset != 3 connected on three way intersection, real size: " + tList.Count + " on intersection: " + GSDRI.transform.name); - return; - } - - ProcessFourCorners(ref n1Point, ref n2Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n2Spline)); - ProcessFourCorners(ref n1Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n3Spline)); - ProcessFourCorners(ref n2Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n3Spline)); - - } - else if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay) - { - //Should be size 3: - if (tList.Count != 4) - { - Debug.LogError("InitializeIntersections hashset != 4 connected on four way intersection, real size: " + tList.Count + " on intersection: " + GSDRI.transform.name); - return; - } - - ProcessFourCorners(ref n1Point, ref n2Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n2Spline)); - ProcessFourCorners(ref n1Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n3Spline)); - ProcessFourCorners(ref n1Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n4Spline)); - ProcessFourCorners(ref n2Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n3Spline)); - ProcessFourCorners(ref n2Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n4Spline)); - ProcessFourCorners(ref n3Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n3Spline, n4Spline)); - } - } - #endregion - - #region "Intersection creation helpers" - private static float GetLongestSplineDistance(GSDSplineC s1, GSDSplineC s2) - { - if (s1.distance > s2.distance) - { - return s1.distance; - } - else - { - return s2.distance; - } - } - - private static GSDSplineN GetNodeByID(int i) - { - Object[] SplineNodeObjects = GameObject.FindObjectsOfType(typeof(GSDSplineN)); - foreach (GSDSplineN tNode in SplineNodeObjects) - { - if (tNode.id == i) - { - return tNode; - } - } - return null; - } - - static Vector3 GetFourCornerPoint(ref GSDSplineC tSpline, ref GSDSplineN tNode, GSDRoadIntersection GSDRI) - { - GSDSplineN iNode; - if (tNode.node_connected.Contains(GSDRI.Node1)) - { - iNode = GSDRI.Node1; - } - else - { - iNode = GSDRI.Node2; - } - - float Pos1 = tNode.tTime; - float iPos = iNode.tTime; - - float tFloat = 0; - float NewSplinePos = 0; - if (iPos >= Pos1) - { - tFloat = iPos - Pos1; - tFloat = tFloat / 8; - NewSplinePos = iPos - tFloat; - } - else - { - tFloat = Pos1 - iPos; - tFloat = tFloat / 8; - NewSplinePos = iPos + tFloat; - } - - Vector3 tVect = new Vector3(0, 0, 0); - - bool bDone = false; - int spamguard = 0; - float tDist = 0f; - while (!bDone && spamguard < 20000) - { - spamguard += 1; - tVect = tSpline.GetSplineValue(NewSplinePos); - tDist = Vector3.Distance(tVect, iNode.transform.position); - - if (tDist > 22f) - { - //Get closer to intersection: - if (iPos >= NewSplinePos) - { - NewSplinePos += 0.001f; - } - else - { - NewSplinePos -= 0.001f; - } - } - else if (tDist < 20f) - { - //Move away from intersection: - if (iPos >= NewSplinePos) - { - NewSplinePos -= 0.001f; - } - else - { - NewSplinePos += 0.001f; - } - } - else - { - bDone = true; - } - } - return tVect; - } - - static void ProcessFourCorners(ref Vector3 n1, ref Vector3 n2, GameObject tIntersectionObject, float SplineDistance) - { - float Side1, Side2, Side3; - Side1 = Vector3.Distance(n1, n2); - Side2 = Vector3.Distance(tIntersectionObject.transform.position, n1); - Side3 = Vector3.Distance(tIntersectionObject.transform.position, n2); - float tAngle = AngleOfTriangle(Side2, Side3, Side1); - if (tAngle > 20f && tAngle < 140f) - { - ProcessTwoCorners(ref tIntersectionObject, ref n1, ref n2, SplineDistance); - } - } - - static float AngleOfTriangle(float a, float b, float c) - { - float cAng = (a * a + b * b - c * c) / (2 * a * b); - float rad = Mathf.Acos(cAng); - float tFloat = Mathf.Rad2Deg * rad; - return tFloat; - } - - static void ProcessTwoCorners(ref GameObject tIntersectionObject, ref Vector3 n1, ref Vector3 n2, float SplineDistance) - { - GameObject tCorner = GameObject.CreatePrimitive(PrimitiveType.Cube); - tCorner.transform.localScale = new Vector3(0.5f, 20f, 0.5f); - tCorner.name = "CornerPosition"; - tCorner.transform.parent = tIntersectionObject.transform; - tCorner.layer = 0; - - //Calculate the angle: - Vector3 v3BA = n2 - tIntersectionObject.transform.position; - Vector3 v3BC = n1 - tIntersectionObject.transform.position; - Vector3 axis = Vector3.Cross(v3BA, v3BC); - float angle = Vector3.Angle(v3BA, v3BC); - Vector3 v3 = Quaternion.AngleAxis(angle / 2.0f, axis) * v3BA; - //Vector3 v3 = (((n2.transform.position + n1.transform.position)/2) - tIntersectionObject.transform.position); - - tCorner.transform.rotation = Quaternion.LookRotation(v3); - - float tStep = 1.25f / SplineDistance; - bool bSuccess = MoveCorner(tStep, 3f, ref tCorner, ref tIntersectionObject, v3); - if (!bSuccess) - { - Debug.Log("not success"); - Object.DestroyImmediate(tCorner); - } - } - - static bool MoveCorner(float tStep, float tDist, ref GameObject tCorner, ref GameObject tIntersectionObject, Vector3 v3) - { - float tStart = 0.05f; - bool bDone = false; - int spamguard = 0; - bool bHitRoad = false; - Collider[] tCollider; - while (!bDone) - { - spamguard += 1; - tCorner.transform.position = tIntersectionObject.transform.position + (v3 * tStart); - - if (Vector3.Distance(tCorner.transform.position, tIntersectionObject.transform.position) > 25f) - { - Debug.Log("too long"); - bDone = true; - return false; - } - if (spamguard > 80000) - { - Debug.Log("spamguard"); - bDone = true; - return false; - } - - //Cast sphere now - bHitRoad = false; - tCollider = Physics.OverlapSphere(tCorner.transform.position, tDist); - if (tCollider == null || tCollider.Length < 1) - { - tStart += tStep; - continue; - } - else - { - for (int k = 0; k < tCollider.Length; k++) - { - if (tCollider[k].transform.name.ToLower().Contains("road")) - { - bHitRoad = true; - break; - } - } - } - - if (bHitRoad) - { - tStart += tStep; - continue; - } - else - { - //Debug.Log ("Distance: " + Vector3.Distance(tCorner.transform.position,tIntersectionObject.transform.position)); - bDone = true; - break; - } - } - return true; - } - #endregion - - #endregion - } - - public static class GSDNavigation - { - public static void UpdateConnectedNodes() - { - Init_ResetNavigationData(); - - Object[] SplineObjects = GameObject.FindObjectsOfType(typeof(GSDSplineC)); - - //Store connected spline nodes on each other: - GSDSplineN xNode; - foreach (GSDSplineC tSpline in SplineObjects) - { - int mNodeCount = tSpline.mNodes.Count; - for (int i = 0; i < mNodeCount; i++) - { - xNode = tSpline.mNodes[i]; - //Add next node if not last node: - if ((i + 1) < mNodeCount) - { - xNode.id_connected.Add(tSpline.mNodes[i + 1].id); - xNode.node_connected.Add(tSpline.mNodes[i + 1]); - } - //Add prev node if not first node: - if (i > 0) - { - xNode.id_connected.Add(tSpline.mNodes[i - 1].id); - xNode.node_connected.Add(tSpline.mNodes[i - 1]); - } - } - } - } - - public static void Init_ResetNavigationData() - { - Object[] tSplines = GameObject.FindObjectsOfType(typeof(GSDSplineC)); - int SplineCount = 0; - int NodeCount = 0; - foreach (GSDSplineC tSpline in tSplines) - { - SplineCount += 1; - foreach (GSDSplineN tNode in tSpline.mNodes) - { - NodeCount += 1; - tNode.ResetNavigationData(); - } - tSpline.ResetNavigationData(); - } - } - } - -#endif -} +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +using System.Collections; +using System.IO; +using System.Text; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; +#endif + + +// TODO: Remove // comments with /**/ // FH 29.01.19 +namespace GSD.Roads +{ + //Generic http://www.fhwa.dot.gov/bridge/bridgerail/br053504.cfm + public enum RailingTypeEnum { None, Generic1, Generic2, K_Rail, WBeam }; + public enum RailingSubTypeEnum { Both, Left, Right }; + public enum SignPlacementSubTypeEnum { Center, Left, Right }; + public enum CenterDividerTypeEnum { None, K_Rail, KRail_Blinds, Wire, Markers }; + public enum EndCapTypeEnum { None, WBeam, Barrels3Static, Barrels3Rigid, Barrels7Static, Barrels7Rigid }; + public enum RoadUpdateTypeEnum { Full, Intersection, Railing, CenterDivider, Bridges }; + public enum AxisTypeEnum { X, Y, Z }; + +#if UNITY_EDITOR + public static class GSDConstruction + { + private static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + private static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + + + public static GSDSplineN CreateNode(GSDRoad RS, bool bSpecialEndNode = false, Vector3 vSpecialLoc = default(Vector3), bool bInterNode = false) + { + Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); + GameObject tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); + if (!bInterNode) + { + UnityEditor.Undo.RegisterCreatedObjectUndo(tNodeObj, "Created node"); + } + GSDSplineN tNode = tNodeObj.AddComponent(); + + if (bSpecialEndNode) + { + tNode.bSpecialEndNode = true; + tNodeObj.transform.position = vSpecialLoc; + } + else + { + tNodeObj.transform.position = RS.Editor_MousePos; + //This helps prevent double clicks: + int mCount = RS.GSDSpline.GetNodeCount(); + for (int index = 0; index < mCount; index++) + { + if (Vector3.Distance(RS.Editor_MousePos, RS.GSDSpline.mNodes[index].pos) < 5f) + { + Object.DestroyImmediate(tNodeObj); + return null; + } + } + //End double click prevention + } + Vector3 xVect = tNodeObj.transform.position; + if (xVect.y < 0.03f) + { + xVect.y = 0.03f; } + tNodeObj.transform.position = xVect; + + tNodeObj.transform.parent = RS.GSDSplineObj.transform; + tNode.idOnSpline = RS.GSDSpline.GetNodeCount() + 1; + tNode.GSDSpline = RS.GSDSpline; + + //Enforce max road grade: + if (RS.opt_bMaxGradeEnabled && !bSpecialEndNode) + { + tNode.EnsureGradeValidity(-1, true); + } + + if (!bInterNode && !bSpecialEndNode) + { + RS.UpdateRoad(); + } + return tNode; + } + //Insert + //Detect closest node (if end node, auto select other node) + //Determine which node is closest (up or down) on spline + //Place node, adjust all id on splines + //Setup spline + public static GSDSplineN InsertNode(GSDRoad RS, bool bForcedLoc = false, Vector3 ForcedLoc = default(Vector3), bool bIsPreNode = false, int InsertIndex = -1, bool bSpecialEndNode = false, bool bInterNode = false) + { + GameObject tNodeObj; + Object[] tWorldNodeCount = GameObject.FindObjectsOfType(typeof(GSDSplineN)); + if (!bForcedLoc) + { + tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); + } + else if (bForcedLoc && !bSpecialEndNode) + { + tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString() + "Ignore"); + } + else + { + tNodeObj = new GameObject("Node" + tWorldNodeCount.Length.ToString()); + } + if (!bInterNode) + { + UnityEditor.Undo.RegisterCreatedObjectUndo(tNodeObj, "Inserted node"); + } + + if (!bForcedLoc) + { + tNodeObj.transform.position = RS.Editor_MousePos; + + //This helps prevent double clicks: + int mCount = RS.GSDSpline.GetNodeCount(); + for (int index = 0; index < mCount; index++) + { + if (Vector3.Distance(RS.Editor_MousePos, RS.GSDSpline.mNodes[index].pos) < 15f) + { + Object.DestroyImmediate(tNodeObj); + return null; + } + } + //End double click prevention + } + else + { + tNodeObj.transform.position = ForcedLoc; + } + Vector3 xVect = tNodeObj.transform.position; + if (xVect.y < 0.03f) + { + xVect.y = 0.03f; + } + tNodeObj.transform.position = xVect; + tNodeObj.transform.parent = RS.GSDSplineObj.transform; + + int cCount = RS.GSDSpline.mNodes.Count; + // float mDistance = 50000f; + // float tDistance = 0f; + + float tParam; + if (!bForcedLoc) + { + tParam = RS.GSDSpline.GetClosestParam(RS.Editor_MousePos, false, true); + } + else + { + tParam = RS.GSDSpline.GetClosestParam(ForcedLoc, false, true); + } + bool bEndInsert = false; + bool bZeroInsert = false; + int iStart = 0; + if (GSDRootUtil.IsApproximately(tParam, 0f, 0.0001f)) + { + bZeroInsert = true; + iStart = 0; + } + else if (GSDRootUtil.IsApproximately(tParam, 1f, 0.0001f)) + { + bEndInsert = true; + } + + if (bForcedLoc) + { + iStart = InsertIndex; + } + else + { + for (int index = 0; index < cCount; index++) + { + GSDSplineN xNode = RS.GSDSpline.mNodes[index]; + if (!bZeroInsert && !bEndInsert) + { + if (tParam > xNode.tTime) + { + iStart = xNode.idOnSpline + 1; + } + } + } + } + + if (bEndInsert) + { + iStart = RS.GSDSpline.mNodes.Count; + } + else + { + for (int i = iStart; i < cCount; i++) + { + RS.GSDSpline.mNodes[i].idOnSpline += 1; + } + } + + GSDSplineN tNode = tNodeObj.AddComponent(); + if (bForcedLoc && !bSpecialEndNode) + { + tNode.bIsBridge = true; + tNode.bIgnore = true; + // tNode.bIsBridge_PreNode = bIsPreNode; + // tNode.bIsBridge_PostNode = !bIsPreNode; + } + tNode.GSDSpline = RS.GSDSpline; + tNode.idOnSpline = iStart; + tNode.bSpecialEndNode = bSpecialEndNode; + if (!bForcedLoc) + { + tNode.pos = RS.Editor_MousePos; + } + else + { + tNode.pos = ForcedLoc; + } + + RS.GSDSpline.mNodes.Insert(iStart, tNode); + + //Enforce maximum road grade: + if (!bForcedLoc && !bSpecialEndNode && RS.opt_bMaxGradeEnabled) + { + tNode.EnsureGradeValidity(iStart); + } + + if (!bInterNode && !bSpecialEndNode) + { + if (!bForcedLoc) + { + RS.UpdateRoad(); + } + } + + return tNode; + } + } + + + public static class GSDTerraforming + { + 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 cI = 0; + public int TerrainMaxIndex; + + //Details: + public int DetailLayersCount; + + public List MainDetailsX; + public List MainDetailsY; + + public List> DetailsX; + public List> DetailsY; + public List> OldDetailsValue; + // public Dictionary DetailValues; + public int[] DetailsI; + public float DetailToHeightRatio; + + + // public Dictionary DetailHasProcessed; + + public HashSet DetailHasProcessed; + + + + // public List> OldDetailsValue; + + public int DetailMaxIndex; + public HashSet DetailLayersSkip; + + //Trees + public List TreesCurrent; + public List TreesOld; + public int TreesI; + public int TreeSize; + + public Vector3 TerrainSize; + public Vector3 TerrainPos; + public int GSDID; + + + 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; + } + } + + + private static void CheckAllTerrains() + { + Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); + GSDTerrain TID; + GameObject tObj; + foreach (Terrain tTerrain in tTerrains) + { + tObj = tTerrain.transform.gameObject; + TID = tObj.GetComponent(); + if (TID == null) + { + TID = tObj.AddComponent(); + } + TID.CheckID(); + } + } + + + public static void CheckAllTerrainsHeight0() + { + CheckAllTerrains(); + Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); + foreach (Terrain tTerrain in tTerrains) + { + if (!GSDRootUtil.IsApproximately(tTerrain.transform.position.y, 0f, 0.0001f)) + { + Vector3 tVect = tTerrain.transform.position; + tVect.y = 0f; + tTerrain.transform.position = tVect; + } + } + } + + + public static void ProcessRoad_Terrain_Hook1(GSDSplineC tSpline, GSDRoad tRoad, bool bMultithreaded = true) + { + ProcessRoad_Terrain_Hook1_Do(ref tSpline, ref tRoad, bMultithreaded); + } + + + private static void ProcessRoad_Terrain_Hook1_Do(ref GSDSplineC tSpline, ref GSDRoad tRoad, bool bMultithreaded) + { + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_Terrain_Hook1_Do"); + } + //First lets make sure all terrains have GSD shit on them: + CheckAllTerrains(); + + //Reset the terrain: + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("TerrainsReset"); + } + GSDTerraforming.TerrainsReset(tRoad); + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + float heightDistance = tRoad.opt_MatchHeightsDistance; + // float treeDistance = tRoad.opt_ClearTreesDistance; + float detailDistance = tRoad.opt_ClearDetailsDistance; + + Dictionary TempTerrainDict = new Dictionary(); + //Populate dictionary: + Object[] tTerrains = GameObject.FindObjectsOfType(typeof(Terrain)); + GSDTerrain TID; + int aSize = 0; + int dSize = 0; + TempTerrainData TTD; + bool bContains = false; + GSDRoadUtil.Construction2DRect tRect = null; + // GSDRoadUtil.Construction2DRect rRect = null; + foreach (Terrain tTerrain in tTerrains) + { + if (tTerrain.terrainData == null) + continue; + tRect = GetTerrainBounds(tTerrain); + bContains = false; + //Debug.Log(tTerrain.transform.name + " bounds: " + tRect.ToStringGSD()); + //Debug.Log(" Road bounds: " + tSpline.RoadV0 + "," + tSpline.RoadV1 + "," + tSpline.RoadV2 + "," + tSpline.RoadV3); + + if (bContains != true && tRect.Contains(ref tSpline.RoadV0)) + { + bContains = true; + } + else if (bContains != true && tRect.Contains(ref tSpline.RoadV1)) + { + bContains = true; + } + else if (bContains != true && tRect.Contains(ref tSpline.RoadV2)) + { + bContains = true; + } + else if (bContains != true && tRect.Contains(ref tSpline.RoadV3)) + { + bContains = true; + } + else + { + int mCount3 = tRoad.GSDSpline.GetNodeCount(); + Vector2 tVect2D_321 = default(Vector2); + for (int index = 0; index < mCount3; index++) + { + tVect2D_321 = new Vector2(tRoad.GSDSpline.mNodes[index].pos.x, tRoad.GSDSpline.mNodes[index].pos.z); + if (tRect.Contains(ref tVect2D_321)) + { + bContains = true; + break; + } + } + + if (!bContains) + { + float tDef = 5f / tSpline.distance; + Vector2 x2D = default(Vector2); + Vector3 x3D = default(Vector3); + for (float index = 0f; index <= 1f; index += tDef) + { + x3D = tSpline.GetSplineValue(index); + x2D = new Vector2(x3D.x, x3D.z); + if (tRect.Contains(ref x2D)) + { + bContains = true; + break; + } + } + } + } + + // rRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(tSpline.RoadV0,tSpline.RoadV1,tSpline.RoadV2,tSpline.RoadV3); + + + if (bContains && !TempTerrainDict.ContainsKey(tTerrain)) + { + TTD = new TempTerrainData(); + TTD.HM = tTerrain.terrainData.heightmapResolution; + TTD.HMHeight = tTerrain.terrainData.heightmapHeight; + TTD.heights = tTerrain.terrainData.GetHeights(0, 0, tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight); + TTD.HMRatio = TTD.HM / tTerrain.terrainData.size.x; + TTD.MetersPerHM = tTerrain.terrainData.size.x / tTerrain.terrainData.heightmapResolution; + float DetailRatio = tTerrain.terrainData.detailResolution / tTerrain.terrainData.size.x; + + //Heights: + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("Heights"); + } + if (tRoad.opt_HeightModEnabled) + { + aSize = (int) tSpline.distance * ((int) (heightDistance * 1.65f * TTD.HMRatio) + 2); + if (aSize > (tTerrain.terrainData.heightmapResolution * tTerrain.terrainData.heightmapResolution)) + { + aSize = tTerrain.terrainData.heightmapResolution * tTerrain.terrainData.heightmapResolution; + } + TTD.cX = new ushort[aSize]; + TTD.cY = new ushort[aSize]; + TTD.oldH = new float[aSize]; + TTD.cH = new float[aSize]; + TTD.cI = 0; + TTD.TerrainMaxIndex = tTerrain.terrainData.heightmapResolution; + TTD.TerrainSize = tTerrain.terrainData.size; + TTD.TerrainPos = tTerrain.transform.position; + TTD.tHeights = new bool[tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight]; + TID = tTerrain.transform.gameObject.GetComponent(); + if (TID != null) + { + TTD.GSDID = TID.GSDID; + TempTerrainDict.Add(tTerrain, TTD); + } + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + //Details: + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("Details"); + } + if (tRoad.opt_DetailModEnabled) + { + // TTD.DetailValues = new Dictionary(); + TTD.DetailLayersCount = tTerrain.terrainData.detailPrototypes.Length; + // TTD.DetailHasProcessed = new Dictionary(); + TTD.DetailHasProcessed = new HashSet(); + TTD.MainDetailsX = new List(); + TTD.MainDetailsY = new List(); + TTD.DetailsI = new int[TTD.DetailLayersCount]; + TTD.DetailToHeightRatio = (float) ((float) tTerrain.terrainData.detailResolution) / ((float) tTerrain.terrainData.heightmapResolution); + TTD.DetailMaxIndex = tTerrain.terrainData.detailResolution; + TTD.DetailLayersSkip = new HashSet(); + + // Get all of layer zero. + // int[] mMinMaxDetailEntryCount = new int[TTD.DetailLayersCount]; + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("DetailValues"); } + // Vector3 bVect = default(Vector3); + // Vector2 bVect2D = default(Vector2); + // int DetailRes = tTerrain.terrainData.detailResolution; + // for(int i=0;i 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]); + // } + // } + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } + + + dSize = (int) tSpline.distance * ((int) (detailDistance * 3f * DetailRatio) + 2); + if (dSize > (tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution)) + { + dSize = tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution; + } + + // TTD.DetailsX = new List(); + // TTD.DetailsY = new List(); + // TTD.OldDetailsValue = new List(); + TTD.DetailsX = new List>(); + TTD.DetailsY = new List>(); + TTD.OldDetailsValue = new List>(); + // TTD.DetailHasProcessed = new List>(); + + 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()); + TTD.DetailsY.Add(new List()); + TTD.OldDetailsValue.Add(new List()); + } + + + // TTD.DetailsX = new ushort[TTD.DetailLayersCount,dSize]; + // TTD.DetailsY = new ushort[TTD.DetailLayersCount,dSize]; + // TTD.OldDetailsValue = new ushort[TTD.DetailLayersCount,dSize]; + + + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + //Trees: + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("Trees"); + } + if (tRoad.opt_TreeModEnabled) + { + // TTD.TreesCurrent = tTerrain.terrainData.treeInstances; + TTD.TreesCurrent = new List(tTerrain.terrainData.treeInstances); + TTD.TreeSize = TTD.TreesCurrent.Count; + TTD.TreesI = 0; + TTD.TreesOld = new List(); + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + } + } + + //Figure out relevant TTD to spline: + List EditorTTDList = new List(); + if (TempTerrainDict != null) + { + foreach (Terrain tTerrain in tTerrains) + { + if (TempTerrainDict.ContainsKey(tTerrain)) + { + EditorTTDList.Add(TempTerrainDict[tTerrain]); + } + } + } + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + //Start job now, for each relevant TTD: + tRoad.EditorTerrainCalcs(ref EditorTTDList); + if (bMultithreaded) + { + GSD.Threaded.TerrainCalcs tJob = new GSD.Threaded.TerrainCalcs(); + tJob.Setup(ref EditorTTDList, tSpline, tRoad); + tRoad.TerrainCalcsJob = tJob; + tJob.Start(); + } + else + { + GSD.Threaded.TerrainCalcs_Static.RunMe(ref EditorTTDList, tSpline, tRoad); + } + } + + + public static GSDRoadUtil.Construction2DRect GetTerrainBounds(Terrain tTerrain) + { + float terrainWidth = tTerrain.terrainData.size.x; + float terrainLength = tTerrain.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 = tTerrain.transform.TransformPoint(X0); + X1 = tTerrain.transform.TransformPoint(X1); + X2 = tTerrain.transform.TransformPoint(X2); + X3 = tTerrain.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 GSDRoadUtil.Construction2DRect(P0, P1, P2, P3, tTerrain.transform.position.y); + } + + + public static void ProcessRoad_Terrain_Hook2(GSDSplineC tSpline, ref List TTDList) + { + if (tSpline.tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_Terrain_Hook2"); + } + ProcessRoad_Terrain_Hook2_Do(ref tSpline, ref TTDList); + if (tSpline.tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + } + + + private static void ProcessRoad_Terrain_Hook2_Do(ref GSDSplineC tSpline, ref List TTDList) + { + if (!tSpline.tRoad.opt_TreeModEnabled && !tSpline.tRoad.opt_HeightModEnabled && !tSpline.tRoad.opt_DetailModEnabled) + { + //Exit if no mod taking place. + return; + } + Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); + Terrain tTerrain; + int[,] tDetails = null; + int IntBufferX = 0; + int IntBufferY = 0; + int tVal = 0; + // ushort Invalid = 16384; + foreach (TempTerrainData TTD in TTDList) + { + foreach (GSDTerrain TID in TIDs) + { + if (TID.GSDID == TTD.GSDID) + { + tTerrain = TID.transform.gameObject.GetComponent(); + if (tTerrain != null) + { + //Details: + if (tSpline.tRoad.opt_DetailModEnabled) + { + 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 = tTerrain.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.DetailsI[index] = TTD.DetailsX[index].Count; + + tTerrain.terrainData.SetDetailLayer(0, 0, index, tDetails); + tDetails = null; + TTD.DetailHasProcessed = null; + } + TTD.MainDetailsX = null; + TTD.MainDetailsY = null; + System.GC.Collect(); + } + //Trees: + if (tSpline.tRoad.opt_TreeModEnabled && TTD.TreesCurrent != null && TTD.TreesI > 0) + { + tTerrain.terrainData.treeInstances = TTD.TreesCurrent.ToArray(); + } + //Heights: + if (tSpline.tRoad.opt_HeightModEnabled && TTD.heights != null && TTD.cI > 0) + { + //Do heights last to trigger collisions and stuff properly: + tTerrain.terrainData.SetHeights(0, 0, TTD.heights); + } + } + } + } + } + } + + + public static void TerrainsReset(GSDRoad tRoad) + { + TerrainsReset_Do(ref tRoad); + } + + + private static void TerrainsReset_Do(ref GSDRoad tRoad) + { + if (tRoad.TerrainHistory == null) + { + return; + } + if (tRoad.TerrainHistory.Count < 1) + { + return; + } + + Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); + float[,] heights; + int[,] tDetails; + int ArrayCount; + foreach (GSDTerrainHistoryMaker TH in tRoad.TerrainHistory) + { + Terrain tTerrain = null; + foreach (GSDTerrain TID in TIDs) + { + if (TID.GSDID == TH.TID) + { + tTerrain = TID.tTerrain; + } + } + if (!tTerrain) + { + continue; + } + + //Heights: + if (TH.x1 != null) + { + heights = tTerrain.terrainData.GetHeights(0, 0, tTerrain.terrainData.heightmapWidth, tTerrain.terrainData.heightmapHeight); + ArrayCount = TH.cI; + for (int index = 0; index < ArrayCount; index++) + { + heights[TH.x1[index], TH.y1[index]] = TH.h[index]; + } + tTerrain.terrainData.SetHeights(0, 0, heights); + } + //Details: + if (TH.DetailsI != null && TH.DetailsX != null && TH.DetailsY != null && TH.DetailsOldValue != null) + { + int RealLayerCount = tTerrain.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 == null || TH.DetailsY == null || TH.DetailsI == null || TH.DetailsX.Length < 1) + { + continue; + } + + tDetails = tTerrain.terrainData.GetDetailLayer(0, 0, tTerrain.terrainData.detailWidth, tTerrain.terrainData.detailHeight, index); + ArrayCount = TH.DetailsI[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; + tTerrain.terrainData.SetDetailLayer(0, 0, index, tDetails); + tDetails = null; + } + } + //Trees: + TreeInstance[] xTress = TH.MakeTrees(); + if (xTress != null) + { + ArrayCount = xTress.Length; + if (ArrayCount > 0 && TH.TreesOld != null) + { + int TerrainTreeCount = tTerrain.terrainData.treeInstances.Length; + ; + TreeInstance[] tTrees = new TreeInstance[ArrayCount + TerrainTreeCount]; + System.Array.Copy(tTerrain.terrainData.treeInstances, 0, tTrees, 0, TerrainTreeCount); + System.Array.Copy(xTress, 0, tTrees, TerrainTreeCount, ArrayCount); + tTerrain.terrainData.treeInstances = tTrees; + } + xTress = null; + } + } + System.GC.Collect(); + } + } + + + [System.Serializable] + public class GSDTerrainHistoryMaker + { + public int TID; + //Heights: + public int[] x1; + public int[] y1; + public float[] h; + public int cI; + public bool bHeightHistoryEnabled; + //Details: + public int DetailLayersCount; + + public int[] DetailsX; + public int[] DetailsY; + public int[] DetailsOldValue; + public int[] DetailsI; + + public bool bDetailHistoryEnabled; + //Trees: + public GSDTreeInstance[] TreesOld; + public int TreesI; + public bool bTreeHistoryEnabled; + public bool bDestroyMe = false; + + + public void Nullify() + { + //Heights: + x1 = null; + y1 = null; + h = null; + DetailsX = null; + DetailsY = null; + DetailsOldValue = null; + DetailsI = null; + //Trees: + TreesOld = null; + } + + + [System.Serializable] + public class GSDTreeInstance + { + public float colorR;//4 + public float colorG;//8 + public float colorB;//12 + public float colorA;//16 + public float heightScale;//20 + public float lightmapColorR;//24 + public float lightmapColorG;//28 + public float lightmapColorB;//32 + public float lightmapColorA;//36 + public float positionX;//40 + public float positionY;//44 + public float positionZ;//48 + public int prototypeIndex;//52 + public float widthScale;//56 + } + + + public void MakeGSDTrees(ref List tTrees) + { + int tSize = tTrees.Count; + TreesOld = new GSDTreeInstance[tSize]; + GSDTreeInstance tTree = null; + TreeInstance xTree; + for (int index = 0; index < tSize; index++) + { + xTree = tTrees[index]; + tTree = new GSDTreeInstance(); + 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; + TreesOld[index] = tTree; + } + } + + + public TreeInstance[] MakeTrees() + { + if (TreesOld == null || TreesOld.Length < 1) + { + return null; + } + int tSize = TreesOld.Length; + TreeInstance[] tTrees = new TreeInstance[tSize]; + GSDTreeInstance tTree = null; + TreeInstance xTree; + for (int index = 0; index < tSize; index++) + { + tTree = TreesOld[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; + } + + + 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 (h != null) + { + tSize += (h.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 (DetailsI != null) + { + tSize += (DetailsI.Length * 4); + tSize += 20; + } + tSize += 1; + //Trees: + if (TreesOld != null) + { + tSize += (TreesOld.Length * 56); + tSize += 20; + } + tSize += 4; + tSize += 1; + tSize += 1; + + return tSize; + } + } + + + public class RoadConstructorBufferMaker + { + public GSDRoad tRoad; + + public List RoadVectors; + public List ShoulderR_Vectors; + public List ShoulderL_Vectors; + + public int[] tris; + public int[] tris_ShoulderR; + public int[] tris_ShoulderL; + + public Vector3[] normals; + public Vector3[] normals_ShoulderR; + public Vector3[] normals_ShoulderL; + public List normals_ShoulderR_averageStartIndexes; + public List normals_ShoulderL_averageStartIndexes; + + public Vector2[] uv; + public Vector2[] uv2; + public Vector2[] uv_SR; + public Vector2[] uv_SL; + + public Vector4[] tangents; + public Vector4[] tangents2; + public Vector4[] tangents_SR; + public Vector4[] tangents_SL; + + public List> cut_RoadVectors; + public List cut_RoadVectorsHome; + public List> cut_ShoulderR_Vectors; + public List> cut_ShoulderL_Vectors; + public List cut_ShoulderR_VectorsHome; + public List cut_ShoulderL_VectorsHome; + public List cut_tris; + public List cut_tris_ShoulderR; + public List cut_tris_ShoulderL; + public List cut_normals; + public List cut_normals_ShoulderR; + public List cut_normals_ShoulderL; + public List cut_uv; + public List cut_uv_SR; + public List cut_uv_SL; + public List cut_tangents; + public List cut_tangents_SR; + public List cut_tangents_SL; + + public List cut_uv_world; + public List cut_uv_SR_world; + public List cut_uv_SL_world; + public List cut_tangents_world; + public List cut_tangents_SR_world; + public List cut_tangents_SL_world; + + //Road connections: + public List RoadConnections_verts; + public List RoadConnections_tris; + public List RoadConnections_normals; + public List RoadConnections_uv; + public List RoadConnections_tangents; + + //Back lanes: + public List iBLane0s; + public List iBLane1s; + public List iBLane1s_IsMiddleLane; + public List iBLane2s; + public List iBLane3s; + //Front lanes: + public List iFLane0s; + public List iFLane1s; + public List iFLane1s_IsMiddleLane; + public List iFLane2s; + public List iFLane3s; + //Main plates: + public List iBMainPlates; + public List iFMainPlates; + //Marker plates: + public List iBMarkerPlates; + public List iFMarkerPlates; + + //Back lanes: + public List iBLane0s_tris; + public List iBLane1s_tris; + public List iBLane2s_tris; + public List iBLane3s_tris; + //Front lanes: + public List iFLane0s_tris; + public List iFLane1s_tris; + public List iFLane2s_tris; + public List iFLane3s_tris; + //Main plates: + public List iBMainPlates_tris; + public List iFMainPlates_tris; + //Marker plates: + public List iBMarkerPlates_tris; + public List iFMarkerPlates_tris; + + //Back lanes: + public List iBLane0s_normals; + public List iBLane1s_normals; + public List iBLane2s_normals; + public List iBLane3s_normals; + //Front lanes: + public List iFLane0s_normals; + public List iFLane1s_normals; + public List iFLane2s_normals; + public List iFLane3s_normals; + //Main plates: + public List iBMainPlates_normals; + public List iFMainPlates_normals; + //Marker plates: + public List iBMarkerPlates_normals; + public List iFMarkerPlates_normals; + + //Back lanes: + public List iBLane0s_tID; + public List iBLane1s_tID; + public List iBLane2s_tID; + public List iBLane3s_tID; + //Front lanes: + public List iFLane0s_tID; + public List iFLane1s_tID; + public List iFLane2s_tID; + public List iFLane3s_tID; + //Main plates: + public List iBMainPlates_tID; + public List iFMainPlates_tID; + //Marker plates: + public List iBMarkerPlates_tID; + public List iFMarkerPlates_tID; + + //Back lanes: + public List iBLane0s_nID; + public List iBLane1s_nID; + public List iBLane2s_nID; + public List iBLane3s_nID; + //Front lanes: + public List iFLane0s_nID; + public List iFLane1s_nID; + public List iFLane2s_nID; + public List iFLane3s_nID; + //Main plates: + public List iBMainPlates_nID; + public List iFMainPlates_nID; + //Marker plates: + public List iBMarkerPlates_nID; + public List iFMarkerPlates_nID; + + //Back lanes: + public List iBLane0s_uv; + public List iBLane1s_uv; + public List iBLane2s_uv; + public List iBLane3s_uv; + //Front lanes: + public List iFLane0s_uv; + public List iFLane1s_uv; + public List iFLane2s_uv; + public List iFLane3s_uv; + //Main plates: + public List iBMainPlates_uv; + public List iFMainPlates_uv; + public List iBMainPlates_uv2; + public List iFMainPlates_uv2; + //Marker plates: + public List iBMarkerPlates_uv; + public List iFMarkerPlates_uv; + + //Back lanes: + public List iBLane0s_tangents; + public List iBLane1s_tangents; + public List iBLane2s_tangents; + public List iBLane3s_tangents; + //Front lanes: + public List iFLane0s_tangents; + public List iFLane1s_tangents; + public List iFLane2s_tangents; + public List iFLane3s_tangents; + //Main plates: + public List iBMainPlates_tangents; + public List iFMainPlates_tangents; + public List iBMainPlates_tangents2; + public List iFMainPlates_tangents2; + //Marker plates: + public List iBMarkerPlates_tangents; + public List iFMarkerPlates_tangents; + + public Terrain tTerrain; + + public List tIntersectionBounds; + public HashSet ImmuneVects; + + public Mesh tMesh; + public Mesh tMesh_SR; + public Mesh tMesh_SL; + public bool tMeshSkip = false; + public bool tMesh_SRSkip = false; + public bool tMesh_SLSkip = false; + public List tMesh_RoadCuts; + public List tMesh_SRCuts; + public List tMesh_SLCuts; + public List tMesh_RoadCuts_world; + public List tMesh_SRCuts_world; + public List tMesh_SLCuts_world; + + public List tMesh_RoadConnections; + + public List tMesh_iBLanes0; + public List tMesh_iBLanes1; + public List tMesh_iBLanes2; + public List tMesh_iBLanes3; + public List tMesh_iFLanes0; + public List tMesh_iFLanes1; + public List tMesh_iFLanes2; + public List tMesh_iFLanes3; + public List tMesh_iBMainPlates; + public List tMesh_iFMainPlates; + public List tMesh_iBMarkerPlates; + public List tMesh_iFMarkerPlates; + + public RoadUpdateTypeEnum tUpdateType; + + public bool bRoadOn = true; + public bool bTerrainOn = true; + public bool bBridgesOn = true; + public bool bInterseOn = true; + + public List RoadCuts; + public List RoadCutNodes; + public List ShoulderCutsR; + public List ShoulderCutsRNodes; + public List ShoulderCutsL; + public List ShoulderCutsLNodes; + + public enum SaveMeshTypeEnum { Road, Shoulder, Intersection, Railing, Center, Bridge, RoadCut, SCut, BSCut, RoadConn }; + + + public RoadConstructorBufferMaker(GSDRoad _tRoad, RoadUpdateTypeEnum _tUpdateType) + { + tUpdateType = _tUpdateType; + bRoadOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); + bTerrainOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); + bBridgesOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Bridges); + bInterseOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection); + + tRoad = _tRoad; + Nullify(); + RoadVectors = new List(); + ShoulderR_Vectors = new List(); + ShoulderL_Vectors = new List(); + normals_ShoulderR_averageStartIndexes = new List(); + normals_ShoulderL_averageStartIndexes = new List(); + + cut_RoadVectors = new List>(); + cut_RoadVectorsHome = new List(); + cut_ShoulderR_Vectors = new List>(); + cut_ShoulderL_Vectors = new List>(); + cut_ShoulderR_VectorsHome = new List(); + cut_ShoulderL_VectorsHome = new List(); + cut_tris = new List(); + cut_tris_ShoulderR = new List(); + cut_tris_ShoulderL = new List(); + cut_normals = new List(); + cut_normals_ShoulderR = new List(); + cut_normals_ShoulderL = new List(); + cut_uv = new List(); + cut_uv_SR = new List(); + cut_uv_SL = new List(); + cut_tangents = new List(); + cut_tangents_SR = new List(); + cut_tangents_SL = new List(); + + cut_uv_world = new List(); + cut_uv_SR_world = new List(); + cut_uv_SL_world = new List(); + cut_tangents_world = new List(); + cut_tangents_SR_world = new List(); + cut_tangents_SL_world = new List(); + + RoadCutNodes = new List(); + ShoulderCutsRNodes = new List(); + ShoulderCutsLNodes = new List(); + + RoadConnections_verts = new List(); + RoadConnections_tris = new List(); + RoadConnections_normals = new List(); + RoadConnections_uv = new List(); + RoadConnections_tangents = new List(); + + RoadCuts = new List(); + ShoulderCutsR = new List(); + ShoulderCutsL = new List(); + + //if(bInterseOn){ + //Back lanes: + iBLane0s = new List(); + iBLane1s = new List(); + iBLane2s = new List(); + iBLane3s = new List(); + //Front lanes: + iFLane0s = new List(); + iFLane1s = new List(); + iFLane2s = new List(); + iFLane3s = new List(); + //Main plates: + iBMainPlates = new List(); + iFMainPlates = new List(); + //Marker plates: + iBMarkerPlates = new List(); + iFMarkerPlates = new List(); + + //Back lanes: + iBLane0s_tris = new List(); + iBLane1s_tris = new List(); + iBLane2s_tris = new List(); + iBLane3s_tris = new List(); + //Front lanes: + iFLane0s_tris = new List(); + iFLane1s_tris = new List(); + iFLane2s_tris = new List(); + iFLane3s_tris = new List(); + //Main plates: + iBMainPlates_tris = new List(); + iFMainPlates_tris = new List(); + //Marker plates: + iBMarkerPlates_tris = new List(); + iFMarkerPlates_tris = new List(); + + //Back lanes: + iBLane0s_normals = new List(); + iBLane1s_normals = new List(); + iBLane2s_normals = new List(); + iBLane3s_normals = new List(); + //Front lanes: + iFLane0s_normals = new List(); + iFLane1s_normals = new List(); + iFLane2s_normals = new List(); + iFLane3s_normals = new List(); + //Main plates: + iBMainPlates_normals = new List(); + iFMainPlates_normals = new List(); + //Marker plates: + iBMarkerPlates_normals = new List(); + iFMarkerPlates_normals = new List(); + + //Back lanes: + iBLane0s_uv = new List(); + iBLane1s_uv = new List(); + iBLane2s_uv = new List(); + iBLane3s_uv = new List(); + //Front lanes: + iFLane0s_uv = new List(); + iFLane1s_uv = new List(); + iFLane2s_uv = new List(); + iFLane3s_uv = new List(); + //Main plates: + iBMainPlates_uv = new List(); + iFMainPlates_uv = new List(); + iBMainPlates_uv2 = new List(); + iFMainPlates_uv2 = new List(); + //Marker plates: + iBMarkerPlates_uv = new List(); + iFMarkerPlates_uv = new List(); + + //Back lanes: + iBLane0s_tangents = new List(); + iBLane1s_tangents = new List(); + iBLane2s_tangents = new List(); + iBLane3s_tangents = new List(); + //Front lanes: + iFLane0s_tangents = new List(); + iFLane1s_tangents = new List(); + iFLane2s_tangents = new List(); + iFLane3s_tangents = new List(); + //Main plates: + iBMainPlates_tangents = new List(); + iFMainPlates_tangents = new List(); + iBMainPlates_tangents2 = new List(); + iFMainPlates_tangents2 = new List(); + //Marker plates: + iBMarkerPlates_tangents = new List(); + iFMarkerPlates_tangents = new List(); + + iFLane1s_IsMiddleLane = new List(); + iBLane1s_IsMiddleLane = new List(); + + //Back lanes: + iBLane0s_tID = new List(); + iBLane1s_tID = new List(); + iBLane2s_tID = new List(); + iBLane3s_tID = new List(); + //Front lanes: + iFLane0s_tID = new List(); + iFLane1s_tID = new List(); + iFLane2s_tID = new List(); + iFLane3s_tID = new List(); + //Main plates: + iBMainPlates_tID = new List(); + iFMainPlates_tID = new List(); + //Marker plates: + iBMarkerPlates_tID = new List(); + iFMarkerPlates_tID = new List(); + + iBLane0s_nID = new List(); + iBLane1s_nID = new List(); + iBLane2s_nID = new List(); + iBLane3s_nID = new List(); + //Front lanes: + iFLane0s_nID = new List(); + iFLane1s_nID = new List(); + iFLane2s_nID = new List(); + iFLane3s_nID = new List(); + //Main plates: + iBMainPlates_nID = new List(); + iFMainPlates_nID = new List(); + //Marker plates: + iBMarkerPlates_nID = new List(); + iFMarkerPlates_nID = new List(); + //} + + tTerrain = null; + + tMesh = new Mesh(); + tMesh_SR = new Mesh(); + tMesh_SL = new Mesh(); + tMesh_RoadCuts = new List(); + tMesh_SRCuts = new List(); + tMesh_SLCuts = new List(); + tMesh_RoadCuts_world = new List(); + tMesh_SRCuts_world = new List(); + tMesh_SLCuts_world = new List(); + + tMesh_RoadConnections = new List(); + + //if(bInterseOn){ + tMesh_iBLanes0 = new List(); + tMesh_iBLanes1 = new List(); + tMesh_iBLanes2 = new List(); + tMesh_iBLanes3 = new List(); + tMesh_iFLanes0 = new List(); + tMesh_iFLanes1 = new List(); + tMesh_iFLanes2 = new List(); + tMesh_iFLanes3 = new List(); + tMesh_iBMainPlates = new List(); + tMesh_iFMainPlates = new List(); + tMesh_iBMarkerPlates = new List(); + tMesh_iFMarkerPlates = new List(); + tIntersectionBounds = new List(); + ImmuneVects = new HashSet(); + //} + + InitGameObjects(); + } + + + #region "Init and nullify" + private void InitGameObjects() + { + //Destry past objects: + if (tRoad.MainMeshes != null) + { + MeshFilter[] MFArray = tRoad.MainMeshes.GetComponentsInChildren(); + MeshCollider[] MCArray = tRoad.MainMeshes.GetComponentsInChildren(); + + int MFArrayCount = MFArray.Length; + int MCArrayCount = MCArray.Length; + for (int index = (MFArrayCount - 1); index > -1; index--) + { + MFArray[index].sharedMesh = null; + } + for (int index = (MCArrayCount - 1); index > -1; index--) + { + MCArray[index].sharedMesh = null; + } + + Object.DestroyImmediate(tRoad.MainMeshes); + } + + //Main mesh object: + tRoad.MainMeshes = new GameObject("MainMeshes"); + tRoad.MainMeshes.transform.parent = tRoad.transform; + + //Road and shoulders: + tRoad.MeshRoad = new GameObject("RoadMesh"); + tRoad.MeshShoR = new GameObject("ShoulderR"); + tRoad.MeshShoL = new GameObject("ShoulderL"); + tRoad.MeshRoad.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshShoR.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshShoL.transform.parent = tRoad.MainMeshes.transform; + + //Intersections: + tRoad.MeshiLanes = new GameObject("MeshiLanes"); + tRoad.MeshiLanes0 = new GameObject("MeshiLanes0"); + tRoad.MeshiLanes1 = new GameObject("MeshiLanes1"); + tRoad.MeshiLanes2 = new GameObject("MeshiLanes2"); + tRoad.MeshiLanes3 = new GameObject("MeshiLanes3"); + tRoad.MeshiMainPlates = new GameObject("MeshiMainPlates"); + tRoad.MeshiMarkerPlates = new GameObject("MeshiMarkerPlates"); + tRoad.MeshiLanes.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiLanes0.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiLanes1.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiLanes2.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiLanes3.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiMainPlates.transform.parent = tRoad.MainMeshes.transform; + tRoad.MeshiMarkerPlates.transform.parent = tRoad.MainMeshes.transform; + } + + + public void Nullify() + { + RoadVectors = null; + ShoulderR_Vectors = null; + ShoulderL_Vectors = null; + tris = null; + normals = null; + uv = null; + uv_SR = null; + uv_SL = null; + tangents = null; + tangents_SR = null; + tangents_SL = null; + tTerrain = null; + tIntersectionBounds = null; + ImmuneVects = null; + iBLane0s = null; + iBLane1s = null; + iBLane2s = null; + iBLane3s = null; + iFLane0s = null; + iFLane1s = null; + iFLane2s = null; + iFLane3s = null; + iBMainPlates = null; + iFMainPlates = null; + iBMarkerPlates = null; + iFMarkerPlates = null; + tMesh = null; + tMesh_SR = null; + tMesh_SL = null; + if (tMesh_iBLanes0 != null) + { + tMesh_iBLanes0.Clear(); + tMesh_iBLanes0 = null; + } + if (tMesh_iBLanes1 != null) + { + tMesh_iBLanes1.Clear(); + tMesh_iBLanes1 = null; + } + if (tMesh_iBLanes2 != null) + { + tMesh_iBLanes2.Clear(); + tMesh_iBLanes2 = null; + } + if (tMesh_iBLanes3 != null) + { + tMesh_iBLanes3.Clear(); + tMesh_iBLanes3 = null; + } + if (tMesh_iFLanes0 != null) + { + tMesh_iFLanes0.Clear(); + tMesh_iFLanes0 = null; + } + if (tMesh_iFLanes1 != null) + { + tMesh_iFLanes1.Clear(); + tMesh_iFLanes1 = null; + } + if (tMesh_iFLanes2 != null) + { + tMesh_iFLanes2.Clear(); + tMesh_iFLanes2 = null; + } + if (tMesh_iFLanes3 != null) + { + tMesh_iFLanes3.Clear(); + tMesh_iFLanes3 = null; + } + if (tMesh_iBMainPlates != null) + { + tMesh_iBMainPlates.Clear(); + tMesh_iBMainPlates = null; + } + if (tMesh_iFMainPlates != null) + { + tMesh_iFMainPlates.Clear(); + tMesh_iFMainPlates = null; + } + if (tMesh_iBMarkerPlates != null) + { + tMesh_iBMarkerPlates.Clear(); + tMesh_iBMarkerPlates = null; + } + if (tMesh_iFMarkerPlates != null) + { + tMesh_iFMarkerPlates.Clear(); + tMesh_iFMarkerPlates = null; + } + tMesh_RoadConnections = null; + + iFLane1s_IsMiddleLane = null; + iBLane1s_IsMiddleLane = null; + + RoadConnections_verts = null; + RoadConnections_tris = null; + RoadConnections_normals = null; + RoadConnections_uv = null; + RoadConnections_tangents = null; + + if (cut_uv_world != null) + { + cut_uv_world.Clear(); + cut_uv_world = null; + } + if (cut_uv_SR_world != null) + { + cut_uv_SR_world.Clear(); + cut_uv_SR_world = null; + } + if (cut_uv_SL_world != null) + { + cut_uv_SL_world.Clear(); + cut_uv_SL_world = null; + } + if (cut_tangents_world != null) + { + cut_tangents_world.Clear(); + cut_tangents_world = null; + } + if (cut_tangents_SR_world != null) + { + cut_tangents_SR_world.Clear(); + cut_tangents_SR_world = null; + } + if (cut_tangents_SL_world != null) + { + cut_tangents_SL_world.Clear(); + cut_tangents_SL_world = null; + } + + + tMesh = null; + tMesh_SR = null; + tMesh_SL = null; + tMesh_SR = null; + tMesh_SL = null; + tMesh_RoadCuts = null; + tMesh_SRCuts = null; + tMesh_SLCuts = null; + tMesh_RoadCuts_world = null; + tMesh_SRCuts_world = null; + tMesh_SLCuts_world = null; + } + #endregion + + + #region "Mesh Setup1" + public void MeshSetup1() + { + MeshSetup1_Do(); + } + + + /// + /// Creates meshes and assigns vertices, triangles and normals. If multithreading enabled, this occurs inbetween threaded jobs since unity library can't be used in threads. + /// + private void MeshSetup1_Do() + { + Mesh MeshBuffer = null; + + if (bInterseOn) + { + MeshSetup1_IntersectionObjectsSetup(); + } + + if (bRoadOn) + { + //Main road: + if (RoadVectors.Count < 64000) + { + if (tMesh == null) + { + tMesh = new Mesh(); + } + tMesh = MeshSetup1_Helper(ref tMesh, RoadVectors.ToArray(), ref tris, ref normals); + tMeshSkip = false; + } + else + { + tMeshSkip = true; + } + + //Right shoulder: + if (ShoulderR_Vectors.Count < 64000) + { + if (tMesh_SR == null) + { + tMesh_SR = new Mesh(); + } + tMesh_SR = MeshSetup1_Helper(ref tMesh_SR, ShoulderR_Vectors.ToArray(), ref tris_ShoulderR, ref normals_ShoulderR); + tMesh_SRSkip = false; + } + else + { + tMesh_SRSkip = true; + } + + //Left shoulder: + if (ShoulderL_Vectors.Count < 64000) + { + if (tMesh_SL == null) + { + tMesh_SL = new Mesh(); + } + tMesh_SL = MeshSetup1_Helper(ref tMesh_SL, ShoulderL_Vectors.ToArray(), ref tris_ShoulderL, ref normals_ShoulderL); + tMesh_SLSkip = false; + } + else + { + tMesh_SLSkip = true; + } + + if (RoadConnections_verts.Count > 0) + { + Mesh qMesh = null; + for (int index = 0; index < RoadConnections_verts.Count; index++) + { + qMesh = new Mesh(); + qMesh.vertices = RoadConnections_verts[index]; + qMesh.triangles = RoadConnections_tris[index]; + qMesh.normals = RoadConnections_normals[index]; + qMesh.uv = RoadConnections_uv[index]; + qMesh.RecalculateNormals(); + RoadConnections_normals[index] = qMesh.normals; + tMesh_RoadConnections.Add(qMesh); + } + } + + + if ((tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts) && RoadCuts.Count > 0) + { + int[] tTris = null; + Vector3[] tNormals = null; + int cCount = cut_RoadVectors.Count; + for (int index = 0; index < cCount; index++) + { + tTris = cut_tris[index]; + tNormals = cut_normals[index]; + MeshBuffer = new Mesh(); + tMesh_RoadCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_RoadVectors[index].ToArray(), ref tTris, ref tNormals)); + MeshBuffer = new Mesh(); + tMesh_RoadCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_RoadVectors[index].ToArray(), ref tTris, ref tNormals)); + cut_normals[index] = tNormals; + tMeshSkip = true; + } + } + if (tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) + { + int[] tTris = null; + Vector3[] tNormals = null; + int rCount = cut_ShoulderR_Vectors.Count; + for (int index = 0; index < rCount; index++) + { + tTris = cut_tris_ShoulderR[index]; + tNormals = cut_normals_ShoulderR[index]; + MeshBuffer = new Mesh(); + tMesh_SRCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderR_Vectors[index].ToArray(), ref tTris, ref tNormals)); + MeshBuffer = new Mesh(); + tMesh_SRCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderR_Vectors[index].ToArray(), ref tTris, ref tNormals)); + cut_normals_ShoulderR[index] = tNormals; + tMesh_SRSkip = true; + } + if (rCount <= 0) + { + tMesh_SRSkip = false; + } + int lCount = cut_ShoulderL_Vectors.Count; + for (int index = 0; index < lCount; index++) + { + tTris = cut_tris_ShoulderL[index]; + tNormals = cut_normals_ShoulderL[index]; + MeshBuffer = new Mesh(); + tMesh_SLCuts.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderL_Vectors[index].ToArray(), ref tTris, ref tNormals)); + MeshBuffer = new Mesh(); + tMesh_SLCuts_world.Add(MeshSetup1_Helper(ref MeshBuffer, cut_ShoulderL_Vectors[index].ToArray(), ref tTris, ref tNormals)); + cut_normals_ShoulderL[index] = tNormals; + tMesh_SLSkip = true; + } + if (lCount <= 0) + { + tMesh_SLSkip = false; + } + } + } + + if (bInterseOn) + { + MeshSetup1_IntersectionParts(); + } + + MeshBuffer = null; + } + + + #region "Intersection for MeshSetup1" + private void MeshSetup1_IntersectionObjectsSetup() + { + int mCount = tRoad.GSDSpline.GetNodeCount(); + List tGSDRIs = new List(); + for (int index = 0; index < mCount; index++) + { + if (tRoad.GSDSpline.mNodes[index].bIsIntersection) + { + if (!tGSDRIs.Contains(tRoad.GSDSpline.mNodes[index].GSDRI)) + { + tGSDRIs.Add(tRoad.GSDSpline.mNodes[index].GSDRI); + } + } + } + + //Cleanups: + foreach (GSDRoadIntersection GSDRI in tGSDRIs) + { + GSDIntersectionObjects.CleanupIntersectionObjects(GSDRI.transform.gameObject); + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDIntersectionObjects.CreateStopSignsAllWay(GSDRI.transform.gameObject, true); + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1) + { + GSDIntersectionObjects.CreateTrafficLightBases(GSDRI.transform.gameObject, true); + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.None) + { + //Do nothing. + } + } + } + + + private void MeshSetup1_IntersectionParts() + { + int mCount = tRoad.GSDSpline.GetNodeCount(); + bool bHasInter = false; + for (int index = 0; index < mCount; index++) + { + if (tRoad.GSDSpline.mNodes[index].bIsIntersection) + { + bHasInter = true; + break; + } + } + if (!bHasInter) + { + return; + } + + int vCount = -1; + Mesh MeshBuffer = null; + Vector3[] tNormals = null; + int[] tTris = null; + //Back lanes: + vCount = iBLane0s.Count; + for (int i = 0; i < vCount; i++) + { + tNormals = iBLane0s_normals[i]; + tTris = iBLane0s_tris[i]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane0s[i], ref tTris, ref tNormals); + tMesh_iBLanes0.Add(MeshBuffer); + } + vCount = iBLane1s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iBLane1s_normals[index]; + tTris = iBLane1s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane1s[index], ref tTris, ref tNormals); + tMesh_iBLanes1.Add(MeshBuffer); + } + vCount = iBLane2s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iBLane2s_normals[index]; + tTris = iBLane2s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane2s[index], ref tTris, ref tNormals); + tMesh_iBLanes2.Add(MeshBuffer); + } + vCount = iBLane3s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iBLane3s_normals[index]; + tTris = iBLane3s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBLane3s[index], ref tTris, ref tNormals); + tMesh_iBLanes3.Add(MeshBuffer); + } + //Front lanes: + vCount = iFLane0s.Count; + for (int i = 0; i < vCount; i++) + { + tNormals = iFLane0s_normals[i]; + tTris = iFLane0s_tris[i]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane0s[i], ref tTris, ref tNormals); + tMesh_iFLanes0.Add(MeshBuffer); + } + vCount = iFLane1s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iFLane1s_normals[index]; + tTris = iFLane1s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane1s[index], ref tTris, ref tNormals); + tMesh_iFLanes1.Add(MeshBuffer); + } + vCount = iFLane2s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iFLane2s_normals[index]; + tTris = iFLane2s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane2s[index], ref tTris, ref tNormals); + tMesh_iFLanes2.Add(MeshBuffer); + } + vCount = iFLane3s.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iFLane3s_normals[index]; + tTris = iFLane3s_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFLane3s[index], ref tTris, ref tNormals); + tMesh_iFLanes3.Add(MeshBuffer); + } + //Main plates: + vCount = iBMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iBMainPlates_normals[index]; + tTris = iBMainPlates_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iBMainPlates[index], ref tTris, ref tNormals); + tMesh_iBMainPlates.Add(MeshBuffer); + } + vCount = iFMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + tNormals = iFMainPlates_normals[index]; + tTris = iFMainPlates_tris[index]; + MeshBuffer = new Mesh(); + MeshBuffer = MeshSetup1_Helper(ref MeshBuffer, iFMainPlates[index], ref tTris, ref tNormals); + tMesh_iFMainPlates.Add(MeshBuffer); + } + + MeshBuffer = null; + } + #endregion + + + private Mesh MeshSetup1_Helper(ref Mesh xMesh, Vector3[] verts, ref int[] tris, ref Vector3[] normals) + { + xMesh.vertices = verts; + xMesh.triangles = tris; + xMesh.normals = normals; + xMesh.RecalculateNormals(); + normals = xMesh.normals; + // xMesh.hideFlags = HideFlags.DontSave; + return xMesh; + } + #endregion + + + #region "Mesh Setup2" + public void MeshSetup2() + { + MeshSetup2_Do(); + } + + + /// + /// Assigns UV and tangents to meshes. If multithreading enabled, this occurs after the last threaded job since unity library can't be used in threads. + /// + private void MeshSetup2_Do() + { + Mesh MeshMainBuffer = null; + Mesh MeshMarkerBuffer = null; + + if (bRoadOn) + { + //If road cuts is off, full size UVs: + if ((!tRoad.opt_bRoadCuts && !tRoad.opt_bDynamicCuts) || (RoadCuts == null || RoadCuts.Count <= 0)) + { + if (tMesh != null) + { + tMesh = MeshSetup2_Helper(ref tMesh, uv, tangents, ref tRoad.MeshRoad, true); + SaveMesh(SaveMeshTypeEnum.Road, tMesh, tRoad, tRoad.MeshRoad.transform.name); + + Vector3[] ooVerts = new Vector3[tMesh.vertexCount]; + int[] ooTris = new int[tMesh.triangles.Length]; + Vector3[] ooNormals = new Vector3[tMesh.normals.Length]; + Vector2[] ooUV = new Vector2[uv2.Length]; + Vector4[] ooTangents = new Vector4[tangents2.Length]; + + System.Array.Copy(tMesh.vertices, ooVerts, ooVerts.Length); + System.Array.Copy(tMesh.triangles, ooTris, ooTris.Length); + System.Array.Copy(tMesh.normals, ooNormals, ooNormals.Length); + System.Array.Copy(uv2, ooUV, ooUV.Length); + System.Array.Copy(tangents2, ooTangents, ooTangents.Length); + + Mesh pMesh = new Mesh(); + pMesh.vertices = ooVerts; + pMesh.triangles = ooTris; + pMesh.normals = ooNormals; + pMesh.uv = ooUV; + pMesh.tangents = ooTangents; + + GameObject gObj = new GameObject("Pavement"); + pMesh = MeshSetup2_Helper(ref pMesh, uv2, tangents2, ref gObj, false); + gObj.transform.parent = tRoad.MeshRoad.transform; //Road markers stored on parent "MeshRoad" game object, with a "Pavement" child game object storing the asphalt. + SaveMesh(SaveMeshTypeEnum.Road, pMesh, tRoad, gObj.transform.name); + } + } + else + { + //If road cuts, change it to one material (pavement) with world mapping + int cCount = cut_RoadVectors.Count; + // Vector2[] tUV; + GameObject CreatedMainObj; + GameObject CreatedMarkerObj; + for (int i = 0; i < cCount; i++) + { + CreatedMainObj = null; + MeshMainBuffer = tMesh_RoadCuts_world[i]; + if (MeshMainBuffer != null) + { + MeshSetup2_Helper_RoadCuts(i, ref MeshMainBuffer, cut_uv_world[i], cut_tangents_world[i], ref tRoad.MeshRoad, false, out CreatedMainObj); + SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMainBuffer, tRoad, "RoadCut" + i.ToString()); + } + + CreatedMarkerObj = null; + MeshMarkerBuffer = tMesh_RoadCuts[i]; + bool bHasMats = false; + if (MeshMarkerBuffer != null) + { + bHasMats = MeshSetup2_Helper_RoadCuts(i, ref MeshMarkerBuffer, cut_uv[i], cut_tangents[i], ref CreatedMainObj, true, out CreatedMarkerObj); + if (bHasMats) + { + SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMarkerBuffer, tRoad, "RoadCutMarker" + i.ToString()); + } + else + { + //Destroy if no marker materials: + Object.DestroyImmediate(CreatedMarkerObj); + Object.DestroyImmediate(MeshMarkerBuffer); + } + } + } + + //Remove main mesh stuff if necessary: + if (tRoad.MeshRoad != null) + { + MeshCollider tMC = tRoad.MeshRoad.GetComponent(); + MeshRenderer tMR = tRoad.MeshRoad.GetComponent(); + if (tMC != null) + { + Object.DestroyImmediate(tMC); + } + if (tMR != null) + { + Object.DestroyImmediate(tMR); + } + } + if (tMesh != null) + { + Object.DestroyImmediate(tMesh); + } + } + + //Shoulders: + if (tRoad.opt_bShouldersEnabled) + { + if ((!tRoad.opt_bShoulderCuts && !tRoad.opt_bDynamicCuts) || (ShoulderCutsL == null || cut_ShoulderL_Vectors.Count <= 0)) + { + //Right road shoulder: + if (tMesh_SR != null) + { + tMesh_SR = MeshSetup2_Helper(ref tMesh_SR, uv_SR, tangents_SR, ref tRoad.MeshShoR, false, true); + SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SR, tRoad, tRoad.MeshShoR.transform.name); + } + + //Left road shoulder: + if (tMesh_SL != null) + { + tMesh_SL = MeshSetup2_Helper(ref tMesh_SL, uv_SL, tangents_SL, ref tRoad.MeshShoL, false, true); + SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SL, tRoad, tRoad.MeshShoL.transform.name); + } + } + else + { + GameObject CreatedMainObj; + GameObject CreatedMarkerObj; + int rCount = cut_ShoulderR_Vectors.Count; + for (int index = 0; index < rCount; index++) + { + bool bHasMats = false; + CreatedMainObj = null; + MeshMainBuffer = tMesh_SRCuts_world[index]; + if (MeshMainBuffer != null) + { + MeshSetup2_Helper_CutsShoulder(index, ref MeshMainBuffer, cut_uv_SR_world[index], cut_tangents_SR_world[index], ref tRoad.MeshShoR, false, false, out CreatedMainObj); + SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, tRoad, "SCutR" + index.ToString()); + } + + CreatedMarkerObj = null; + MeshMarkerBuffer = tMesh_SRCuts[index]; + if (MeshMarkerBuffer != null) + { + bHasMats = MeshSetup2_Helper_CutsShoulder(index, ref MeshMarkerBuffer, cut_uv_SR[index], cut_tangents_SR[index], ref CreatedMainObj, false, true, out CreatedMarkerObj); + if (bHasMats) + { + SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, tRoad, "SCutRMarker" + index.ToString()); + } + else + { + //Destroy if no marker materials: + Object.DestroyImmediate(CreatedMarkerObj); + Object.DestroyImmediate(MeshMarkerBuffer); + } + } + } + + int lCount = cut_ShoulderL_Vectors.Count; + for (int index = 0; index < lCount; index++) + { + bool bHasMats = false; + CreatedMainObj = null; + MeshMainBuffer = tMesh_SLCuts_world[index]; + if (MeshMainBuffer != null) + { + MeshSetup2_Helper_CutsShoulder(index, ref MeshMainBuffer, cut_uv_SL_world[index], cut_tangents_SL_world[index], ref tRoad.MeshShoL, true, false, out CreatedMainObj); + SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, tRoad, "SCutL" + index.ToString()); + } + + + CreatedMarkerObj = null; + MeshMarkerBuffer = tMesh_SLCuts[index]; + if (MeshMarkerBuffer != null) + { + bHasMats = MeshSetup2_Helper_CutsShoulder(index, ref MeshMarkerBuffer, cut_uv_SL[index], cut_tangents_SL[index], ref CreatedMainObj, true, true, out CreatedMarkerObj); + if (bHasMats) + { + SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, tRoad, "SCutLMarker" + index.ToString()); + } + else + { + //Destroy if no marker materials: + Object.DestroyImmediate(CreatedMarkerObj); + Object.DestroyImmediate(MeshMarkerBuffer); + } + } + } + + if (tRoad.opt_bUseMeshColliders) + { + // MeshSetup2_Intersections_FixNormals(); + } + + //Remove main mesh stuff if necessary: + if (tMesh_SR != null) + { + Object.DestroyImmediate(tMesh_SR); + } + if (tMesh_SL != null) + { + Object.DestroyImmediate(tMesh_SL); + } + + if (tRoad.MeshShoR != null) + { + MeshCollider tMC = tRoad.MeshShoR.GetComponent(); + MeshRenderer tMR = tRoad.MeshShoR.GetComponent(); + if (tMC != null) + { + Object.DestroyImmediate(tMC); + } + if (tMR != null) + { + Object.DestroyImmediate(tMR); + } + } + if (tRoad.MeshShoL != null) + { + MeshCollider tMC = tRoad.MeshShoL.GetComponent(); + MeshRenderer tMR = tRoad.MeshShoL.GetComponent(); + if (tMC != null) + { + Object.DestroyImmediate(tMC); + } + if (tMR != null) + { + Object.DestroyImmediate(tMR); + } + } + } + } + else + { + //Remove main mesh stuff if necessary: + if (tMesh_SR != null) + { + Object.DestroyImmediate(tMesh_SR); + } + if (tMesh_SL != null) + { + Object.DestroyImmediate(tMesh_SL); + } + + if (tRoad.MeshShoR != null) + { + MeshCollider tMC = tRoad.MeshShoR.GetComponent(); + MeshRenderer tMR = tRoad.MeshShoR.GetComponent(); + if (tMC != null) + { + Object.DestroyImmediate(tMC); + } + if (tMR != null) + { + Object.DestroyImmediate(tMR); + } + } + if (tRoad.MeshShoL != null) + { + MeshCollider tMC = tRoad.MeshShoL.GetComponent(); + MeshRenderer tMR = tRoad.MeshShoL.GetComponent(); + if (tMC != null) + { + Object.DestroyImmediate(tMC); + } + if (tMR != null) + { + Object.DestroyImmediate(tMR); + } + } + + Mesh tBuffer = null; + int xCount = tMesh_SRCuts_world.Count; + for (int index = 0; index < xCount; index++) + { + tBuffer = tMesh_SRCuts_world[index]; + Object.DestroyImmediate(tBuffer); + tMesh_SRCuts_world[index] = null; + } + xCount = tMesh_SRCuts.Count; + for (int index = 0; index < xCount; index++) + { + tBuffer = tMesh_SRCuts[index]; + Object.DestroyImmediate(tBuffer); + tMesh_SRCuts[index] = null; + } + xCount = tMesh_SLCuts_world.Count; + for (int index = 0; index < xCount; index++) + { + tBuffer = tMesh_SLCuts_world[index]; + Object.DestroyImmediate(tBuffer); + tMesh_SLCuts_world[index] = null; + } + xCount = tMesh_SLCuts.Count; + for (int index = 0; index < xCount; index++) + { + tBuffer = tMesh_SLCuts[index]; + Object.DestroyImmediate(tBuffer); + tMesh_SLCuts[index] = null; + } + + if (tRoad.MeshShoR != null) + { + Object.DestroyImmediate(tRoad.MeshShoR); + } + + if (tRoad.MeshShoL != null) + { + Object.DestroyImmediate(tRoad.MeshShoL); + } + } + + + for (int index = 0; index < RoadConnections_tangents.Count; index++) + { + tMesh_RoadConnections[index].tangents = RoadConnections_tangents[index]; + GameObject tObj = new GameObject("RoadConnectionMarker"); + MeshFilter MF = tObj.AddComponent(); + MeshRenderer MR = tObj.AddComponent(); + float fDist = Vector3.Distance(RoadConnections_verts[index][2], RoadConnections_verts[index][3]); + fDist = Mathf.Round(fDist); + if (tRoad.opt_Lanes == 2) + { + if (fDist == Mathf.Round(tRoad.RoadWidth() * 2f)) + { + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-4L.mat", MR); + } + else if (fDist == Mathf.Round(tRoad.RoadWidth() * 3f)) + { + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-6L-2L.mat", MR); + } + } + else if (tRoad.opt_Lanes == 4) + { + if (fDist == Mathf.Round(tRoad.RoadWidth() * 1.5f)) + { + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDRoadConn-6L-4L.mat", MR); + } + } + MF.sharedMesh = tMesh_RoadConnections[index]; + tObj.transform.parent = tRoad.MeshRoad.transform; + + Mesh vMesh = new Mesh(); + vMesh.vertices = RoadConnections_verts[index]; + vMesh.triangles = RoadConnections_tris[index]; + vMesh.normals = RoadConnections_normals[index]; + Vector2[] vUV = new Vector2[4]; + vUV[0] = new Vector2(RoadConnections_verts[index][0].x / 5f, RoadConnections_verts[index][0].z / 5f); + vUV[1] = new Vector2(RoadConnections_verts[index][1].x / 5f, RoadConnections_verts[index][1].z / 5f); + vUV[2] = new Vector2(RoadConnections_verts[index][2].x / 5f, RoadConnections_verts[index][2].z / 5f); + vUV[3] = new Vector2(RoadConnections_verts[index][3].x / 5f, RoadConnections_verts[index][3].z / 5f); + vMesh.uv = vUV; + vMesh.RecalculateNormals(); + RoadConnections_normals[index] = vMesh.normals; + vMesh.tangents = GSDRootUtil.ProcessTangents(vMesh.triangles, vMesh.normals, vMesh.uv, vMesh.vertices); + + tObj = new GameObject("RoadConnectionBase"); + MF = tObj.AddComponent(); + MR = tObj.AddComponent(); + MeshCollider MC = tObj.AddComponent(); + MF.sharedMesh = vMesh; + MC.sharedMesh = MF.sharedMesh; + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", MR); + tObj.transform.parent = tRoad.MeshRoad.transform; + + SaveMesh(SaveMeshTypeEnum.RoadConn, vMesh, tRoad, "RoadConn" + index.ToString()); + } + } + + if (bInterseOn) + { + MeshSetup2_Intersections(); + } + + if (tRoad.MeshiLanes != null) + { + Object.DestroyImmediate(tRoad.MeshiLanes); + } + if (tRoad.MeshiLanes0 != null) + { + Object.DestroyImmediate(tRoad.MeshiLanes0); + } + if (tRoad.MeshiLanes1 != null) + { + Object.DestroyImmediate(tRoad.MeshiLanes1); + } + if (tRoad.MeshiLanes2 != null) + { + Object.DestroyImmediate(tRoad.MeshiLanes2); + } + if (tRoad.MeshiLanes3 != null) + { + Object.DestroyImmediate(tRoad.MeshiLanes3); + } + if (tRoad.MeshiMainPlates != null) + { + Object.DestroyImmediate(tRoad.MeshiMainPlates); + } + if (tRoad.MeshiMarkerPlates != null) + { + Object.DestroyImmediate(tRoad.MeshiMarkerPlates); + } + + //Updates the road and shoulder cut materials if necessary. Note: Cycling through all nodes in case the road cuts and shoulder cut numbers don't match. + if (tRoad.opt_bRoadCuts || tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) + { + int mCount = tRoad.GSDSpline.GetNodeCount(); + for (int index = 0; index < mCount; index++) + { + tRoad.GSDSpline.mNodes[index].UpdateCuts(); + } + } + } + + + #region "MeshSetup2 - Intersections" + // private void MeshSetup2_Intersections_FixNormals(){ + // int mCount = tRoad.GSDSpline.GetNodeCount(); + // GSDSplineN tNode = null; + // GSDRoadIntersection GSDRI = null; + // float MaxDist = 0f; + // float[] tDists = new float[2]; + // Collider[] tColliders = null; + // List tCuts = null; + // + // for(int h=0;h(); + // foreach(Collider tCollider in tColliders){ + // if(tCollider.transform.name.Contains("cut")){ + // tCuts.Add(tCollider.transform.gameObject); + // } + // } + // + // + // + // foreach(GameObject tObj in tCuts){ + // MeshFilter MF1 = tCuts[0].GetComponent(); + // if(MF1 == null){ continue; } + // Mesh zMesh1 = MF1.sharedMesh; + // Vector3[] tVerts1 = zMesh1.vertices; + // Vector3[] tNormals1 = zMesh1.normals; + // int MVL1 = tVerts1.Length; + // for(int i=0;i> tCombineDict_Lane0 = new Dictionary>(); + Dictionary> tCombineDict_Lane1 = new Dictionary>(); + Dictionary> tCombineDict_Lane2 = new Dictionary>(); + Dictionary> tCombineDict_Lane3 = new Dictionary>(); + Dictionary> tCombineDict_MainPlate = new Dictionary>(); + Dictionary> tCombineDict_MainPlateM = new Dictionary>(); + HashSet UniqueGSDRI = new HashSet(); + + Dictionary> tCombineDict_Lane1_Disabled = new Dictionary>(); + Dictionary> tCombineDict_Lane2_Disabled = new Dictionary>(); + Dictionary> tCombineDict_Lane2_DisabledActive = new Dictionary>(); + Dictionary> tCombineDict_Lane2_DisabledActiveR = new Dictionary>(); + Dictionary> tCombineDict_Lane3_Disabled = new Dictionary>(); + Dictionary> tCombineDict_Lane1_DisabledActive = new Dictionary>(); + + vCount = iBLane0s.Count; + for (int index = 0; index < vCount; index++) + { + tUV = iBLane0s_uv[index]; + tTangents = iBLane0s_tangents[index]; + xMesh = tMesh_iBLanes0[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes0, "Lane0B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR.mat"); + if (!tCombineDict_Lane0.ContainsKey(iBLane0s_tID[index])) + { + tCombineDict_Lane0.Add(iBLane0s_tID[index], new List()); + } + tCombineDict_Lane0[iBLane0s_tID[index]].Add(MF); + } + vCount = iBLane1s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iBLane1s_tID[index].Node1 == iBLane1s_nID[index]); + if (!bPrimaryNode && iBLane1s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane || iBLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane1s_tID[index].bNode2B_LeftTurnLane) + { + tUV = iBLane1s_uv[index]; + tTangents = iBLane1s_tangents[index]; + xMesh = tMesh_iBLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneD1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + if (!tCombineDict_Lane1_Disabled.ContainsKey(iBLane1s_tID[index])) + { + tCombineDict_Lane1_Disabled.Add(iBLane1s_tID[index], new List()); + } + tCombineDict_Lane1_Disabled[iBLane1s_tID[index]].Add(MF); + } + else if (bPrimaryNode && iBLane1s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tUV = iBLane1s_uv[index]; + tTangents = iBLane1s_tangents[index]; + xMesh = tMesh_iBLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneDA1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); + if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iBLane1s_tID[index])) + { + tCombineDict_Lane1_DisabledActive.Add(iBLane1s_tID[index], new List()); + } + tCombineDict_Lane1_DisabledActive[iBLane1s_tID[index]].Add(MF); + } + else + { + tUV = iBLane1s_uv[index]; + tTangents = iBLane1s_tangents[index]; + xMesh = tMesh_iBLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "Lane1B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); + if (!tCombineDict_Lane1.ContainsKey(iBLane1s_tID[index])) + { + tCombineDict_Lane1.Add(iBLane1s_tID[index], new List()); + } + tCombineDict_Lane1[iBLane1s_tID[index]].Add(MF); + } + } + vCount = iBLane2s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iBLane2s_tID[index].Node1 == iBLane2s_nID[index]); + if (!bPrimaryNode && iBLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane || iBLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane2s_tID[index].bNode2B_LeftTurnLane) + { + tUV = iBLane2s_uv[index]; + tTangents = iBLane2s_tangents[index]; + xMesh = tMesh_iBLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); + if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iBLane2s_tID[index])) + { + tCombineDict_Lane2_DisabledActive.Add(iBLane2s_tID[index], new List()); + } + tCombineDict_Lane2_DisabledActive[iBLane2s_tID[index]].Add(MF); + } + else if (!bPrimaryNode && iBLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane2s_tID[index].bNode2B_RightTurnLane) + { + tUV = iBLane2s_uv[index]; + tTangents = iBLane2s_tangents[index]; + xMesh = tMesh_iBLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); + if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iBLane2s_tID[index])) + { + tCombineDict_Lane2_DisabledActiveR.Add(iBLane2s_tID[index], new List()); + } + tCombineDict_Lane2_DisabledActiveR[iBLane2s_tID[index]].Add(MF); + } + else if (bPrimaryNode && iBLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tUV = iBLane2s_uv[index]; + tTangents = iBLane2s_tangents[index]; + xMesh = tMesh_iBLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneD2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + if (!tCombineDict_Lane2_Disabled.ContainsKey(iBLane2s_tID[index])) + { + tCombineDict_Lane2_Disabled.Add(iBLane2s_tID[index], new List()); + } + tCombineDict_Lane2_Disabled[iBLane2s_tID[index]].Add(MF); + } + else + { + tUV = iBLane2s_uv[index]; + tTangents = iBLane2s_tangents[index]; + xMesh = tMesh_iBLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "Lane2B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + if (!tCombineDict_Lane2.ContainsKey(iBLane2s_tID[index])) + { + tCombineDict_Lane2.Add(iBLane2s_tID[index], new List()); + } + tCombineDict_Lane2[iBLane2s_tID[index]].Add(MF); + } + } + vCount = iBLane3s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iBLane3s_tID[index].Node1 == iBLane3s_nID[index]); + if (!bPrimaryNode && iBLane3s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane3s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane3s_tID[index].bNode2B_RightTurnLane) + { + tUV = iBLane3s_uv[index]; + tTangents = iBLane3s_tangents[index]; + xMesh = tMesh_iBLanes3[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "LaneD3B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + if (!tCombineDict_Lane3_Disabled.ContainsKey(iBLane3s_tID[index])) + { + tCombineDict_Lane3_Disabled.Add(iBLane3s_tID[index], new List()); + } + tCombineDict_Lane3_Disabled[iBLane3s_tID[index]].Add(MF); + } + else + { + tUV = iBLane3s_uv[index]; + tTangents = iBLane3s_tangents[index]; + xMesh = tMesh_iBLanes3[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "Lane3B", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + if (!tCombineDict_Lane3.ContainsKey(iBLane3s_tID[index])) + { + tCombineDict_Lane3.Add(iBLane3s_tID[index], new List()); + } + tCombineDict_Lane3[iBLane3s_tID[index]].Add(MF); + } + } + + //Front lanes: + vCount = iFLane0s.Count; + for (int index = 0; index < vCount; index++) + { + tUV = iFLane0s_uv[index]; + tTangents = iFLane0s_tangents[index]; + xMesh = tMesh_iFLanes0[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes0, "Lane0F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteLYellowR.mat"); + if (!tCombineDict_Lane0.ContainsKey(iFLane0s_tID[index])) + { + tCombineDict_Lane0.Add(iFLane0s_tID[index], new List()); + } + tCombineDict_Lane0[iFLane0s_tID[index]].Add(MF); + } + vCount = iFLane1s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iFLane1s_tID[index].Node1 == iFLane1s_nID[index]); + if (!bPrimaryNode && iFLane1s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) && !iFLane1s_tID[index].bNode2F_LeftTurnLane) + { + tUV = iFLane1s_uv[index]; + tTangents = iFLane1s_tangents[index]; + xMesh = tMesh_iFLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneD1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + if (!tCombineDict_Lane1_Disabled.ContainsKey(iFLane1s_tID[index])) + { + tCombineDict_Lane1_Disabled.Add(iFLane1s_tID[index], new List()); + } + tCombineDict_Lane1_Disabled[iFLane1s_tID[index]].Add(MF); + } + else if (bPrimaryNode && iFLane1s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane1s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tUV = iFLane1s_uv[index]; + tTangents = iFLane1s_tangents[index]; + xMesh = tMesh_iFLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "LaneDAR1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); + if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iFLane1s_tID[index])) + { + tCombineDict_Lane1_DisabledActive.Add(iFLane1s_tID[index], new List()); + } + tCombineDict_Lane1_DisabledActive[iFLane1s_tID[index]].Add(MF); + } + else + { + tUV = iFLane1s_uv[index]; + tTangents = iFLane1s_tangents[index]; + xMesh = tMesh_iFLanes1[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes1, "Lane1F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterYellowLWhiteR.mat"); + if (!tCombineDict_Lane1.ContainsKey(iFLane1s_tID[index])) + { + tCombineDict_Lane1.Add(iFLane1s_tID[index], new List()); + } + tCombineDict_Lane1[iFLane1s_tID[index]].Add(MF); + } + } + vCount = iFLane2s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iFLane2s_tID[index].Node1 == iFLane2s_nID[index]); + if (!bPrimaryNode && iFLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) && !iFLane2s_tID[index].bNode2F_LeftTurnLane) + { + tUV = iFLane2s_uv[index]; + tTangents = iFLane2s_tangents[index]; + xMesh = tMesh_iFLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDA2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuter.mat"); + if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iFLane2s_tID[index])) + { + tCombineDict_Lane2_DisabledActive.Add(iFLane2s_tID[index], new List()); + } + tCombineDict_Lane2_DisabledActive[iFLane2s_tID[index]].Add(MF); + } + else if (!bPrimaryNode && iFLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane2s_tID[index].bNode2F_RightTurnLane) + { + tUV = iFLane2s_uv[index]; + tTangents = iFLane2s_tangents[index]; + xMesh = tMesh_iFLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneDAR2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabledOuterR.mat"); + if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iFLane2s_tID[index])) + { + tCombineDict_Lane2_DisabledActiveR.Add(iFLane2s_tID[index], new List()); + } + tCombineDict_Lane2_DisabledActiveR[iFLane2s_tID[index]].Add(MF); + } + else if (bPrimaryNode && iFLane2s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tUV = iFLane2s_uv[index]; + tTangents = iFLane2s_tangents[index]; + xMesh = tMesh_iFLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "LaneD2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterLaneDisabled.mat"); + if (!tCombineDict_Lane2_Disabled.ContainsKey(iFLane2s_tID[index])) + { + tCombineDict_Lane2_Disabled.Add(iFLane2s_tID[index], new List()); + } + tCombineDict_Lane2_Disabled[iFLane2s_tID[index]].Add(MF); + } + else + { + tUV = iFLane2s_uv[index]; + tTangents = iFLane2s_tangents[index]; + xMesh = tMesh_iFLanes2[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes2, "Lane2F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + if (!tCombineDict_Lane2.ContainsKey(iFLane2s_tID[index])) + { + tCombineDict_Lane2.Add(iFLane2s_tID[index], new List()); + } + tCombineDict_Lane2[iFLane2s_tID[index]].Add(MF); + } + } + vCount = iFLane3s.Count; + for (int index = 0; index < vCount; index++) + { + bool bPrimaryNode = (iFLane3s_tID[index].Node1 == iFLane3s_nID[index]); + if (!bPrimaryNode && iFLane3s_tID[index].iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane3s_tID[index].rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane3s_tID[index].bNode2F_RightTurnLane) + { + tUV = iFLane3s_uv[index]; + tTangents = iFLane3s_tangents[index]; + xMesh = tMesh_iFLanes3[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "LaneD3F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + if (!tCombineDict_Lane3_Disabled.ContainsKey(iFLane3s_tID[index])) + { + tCombineDict_Lane3_Disabled.Add(iFLane3s_tID[index], new List()); + } + tCombineDict_Lane3_Disabled[iFLane3s_tID[index]].Add(MF); + } + else + { + tUV = iFLane3s_uv[index]; + tTangents = iFLane3s_tangents[index]; + xMesh = tMesh_iFLanes3[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiLanes3, "Lane3F", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Markers/GSDInterWhiteR.mat"); + if (!tCombineDict_Lane3.ContainsKey(iFLane3s_tID[index])) + { + tCombineDict_Lane3.Add(iFLane3s_tID[index], new List()); + } + tCombineDict_Lane3[iFLane3s_tID[index]].Add(MF); + } + } + + //Main plates: + vCount = iBMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + tUV = iBMainPlates_uv[index]; + tTangents = iBMainPlates_tangents[index]; + xMesh = tMesh_iBMainPlates[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateB", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", false); + if (!tCombineDict_MainPlate.ContainsKey(iBMainPlates_tID[index])) + { + tCombineDict_MainPlate.Add(iBMainPlates_tID[index], new List()); + } + tCombineDict_MainPlate[iBMainPlates_tID[index]].Add(MF); + + Mesh fMesh = new Mesh(); + fMesh.vertices = iBMainPlates[index]; + fMesh.triangles = iBMainPlates_tris[index]; + fMesh.normals = iBMainPlates_normals[index]; + tUV = iBMainPlates_uv2[index]; + tTangents = iBMainPlates_tangents2[index]; + MF = MeshSetup2_Intersection_Helper(ref fMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateBM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterMainPlate1.mat"); + if (!tCombineDict_MainPlateM.ContainsKey(iBMainPlates_tID[index])) + { + tCombineDict_MainPlateM.Add(iBMainPlates_tID[index], new List()); + } + tCombineDict_MainPlateM[iBMainPlates_tID[index]].Add(MF); + } + vCount = iFMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + tUV = iFMainPlates_uv[index]; + tTangents = iFMainPlates_tangents[index]; + xMesh = tMesh_iFMainPlates[index]; + MF = MeshSetup2_Intersection_Helper(ref xMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateFM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoad1.mat", false); + + if (!tCombineDict_MainPlate.ContainsKey(iFMainPlates_tID[index])) + { + tCombineDict_MainPlate.Add(iFMainPlates_tID[index], new List()); + } + tCombineDict_MainPlate[iFMainPlates_tID[index]].Add(MF); + + Mesh tMesh = new Mesh(); + tMesh.vertices = iFMainPlates[index]; + tMesh.triangles = iFMainPlates_tris[index]; + tMesh.normals = iFMainPlates_normals[index]; + tUV = iFMainPlates_uv2[index]; + tTangents = iFMainPlates_tangents2[index]; + MF = MeshSetup2_Intersection_Helper(ref tMesh, ref tUV, ref tTangents, ref tRoad.MeshiMainPlates, "MainPlateFM", GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterMainPlate1.mat"); + if (!tCombineDict_MainPlateM.ContainsKey(iFMainPlates_tID[index])) + { + tCombineDict_MainPlateM.Add(iFMainPlates_tID[index], new List()); + } + tCombineDict_MainPlateM[iFMainPlates_tID[index]].Add(MF); + } + + vCount = tRoad.GSDSpline.GetNodeCount(); + GSDSplineN tNode = null; + for (int index = 0; index < vCount; index++) + { + tNode = tRoad.GSDSpline.mNodes[index]; + if (tNode.bIsIntersection && tNode.GSDRI != null && tNode.GSDRI.Node1 == tNode) + { + //Create center plate + Vector3[] xVerts = new Vector3[4]; + xVerts[0] = tNode.GSDRI.CornerLR; + xVerts[1] = tNode.GSDRI.CornerRR; + xVerts[2] = tNode.GSDRI.CornerLL; + xVerts[3] = tNode.GSDRI.CornerRL; + + + int[] xTris = new int[6]; + xTris[0] = 0; + xTris[1] = 2; + xTris[2] = 1; + xTris[3] = 2; + xTris[4] = 3; + xTris[5] = 1; + + Vector2[] xUV = new Vector2[4]; + xUV[0] = new Vector2(xVerts[0].x / 5f, xVerts[0].z / 5f); + xUV[1] = new Vector2(xVerts[1].x / 5f, xVerts[1].z / 5f); + xUV[2] = new Vector2(xVerts[2].x / 5f, xVerts[2].z / 5f); + xUV[3] = new Vector2(xVerts[3].x / 5f, xVerts[3].z / 5f); + + Vector2[] xUV2 = new Vector2[4]; + xUV2[0] = new Vector2(0f, 0f); + xUV2[1] = new Vector2(1f, 0f); + xUV2[2] = new Vector2(0f, 1f); + xUV2[3] = new Vector2(1f, 1f); + + Mesh vMesh = new Mesh(); + vMesh.vertices = xVerts; + vMesh.triangles = xTris; + vMesh.normals = new Vector3[4]; + vMesh.uv = xUV; + vMesh.RecalculateBounds(); + vMesh.RecalculateNormals(); + vMesh.tangents = GSDRootUtil.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); + if (tRoad.opt_bIsLightmapped) + { + //UnityEditor.Unwrapping.GenerateSecondaryUVSet(vMesh); + } + + int cCount = tNode.GSDRI.transform.childCount; + List GOToDelete = new List(); + for (int j = 0; j < cCount; j++) + { + if (tNode.GSDRI.transform.GetChild(j).name.ToLower() == "tcenter") + { + GOToDelete.Add(tNode.GSDRI.transform.GetChild(j).gameObject); + } + if (tNode.GSDRI.transform.GetChild(j).name.ToLower() == "markcenter") + { + GOToDelete.Add(tNode.GSDRI.transform.GetChild(j).gameObject); + } + } + for (int j = GOToDelete.Count - 1; j >= 0; j--) + { + Object.DestroyImmediate(GOToDelete[j]); + } + + GameObject tCenter = new GameObject("tCenter"); + MF = tCenter.AddComponent(); + MF.sharedMesh = vMesh; + tCenter.transform.parent = tNode.GSDRI.transform; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(tCenter, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + tCenter.isStatic = true; + } + + + + Mesh mMesh = new Mesh(); + Vector3[] bVerts = new Vector3[4]; + mMesh.vertices = xVerts; + mMesh.triangles = xTris; + mMesh.normals = new Vector3[4]; + mMesh.uv = xUV2; + mMesh.RecalculateBounds(); + mMesh.RecalculateNormals(); + mMesh.tangents = GSDRootUtil.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); + + + GameObject tMarker = new GameObject("CenterMarkers"); + //tMarker.transform.localPosition = default(Vector3); + MF = tMarker.AddComponent(); + MF.sharedMesh = mMesh; + MeshRenderer MR = tMarker.AddComponent(); + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + // if(tNode.GSDRI.MarkerCenter != null){ + //// MR.material = tNode.GSDRI.MarkerCenter; + // } + tMarker.transform.parent = tNode.GSDRI.transform; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(tMarker, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + tMarker.isStatic = true; + } + + bVerts = MF.sharedMesh.vertices; + for (int j = 0; j < 4; j++) + { + bVerts[j].y = tNode.GSDRI.SignHeight; + } + + + int zCount = bVerts.Length; + for (int z = 0; z < zCount; z++) + { + bVerts[z] -= tNode.transform.position; + } + + MF.sharedMesh.vertices = bVerts; + + + + MR.transform.position = tNode.GSDRI.transform.position; + + mMesh.RecalculateBounds(); + if (tRoad.opt_bIsLightmapped) + { + //UnityEditor.Unwrapping.GenerateSecondaryUVSet(mMesh); + } + SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, tRoad, tNode.GSDRI.transform.name + "-" + "CenterMarkers"); + } + } + + // List MeshToDelete = new List(); + + foreach (KeyValuePair> KVP in tCombineDict_Lane0) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane0"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane1) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane1"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane2) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane2"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane3) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane3"); + } + foreach (KeyValuePair> KVP in tCombineDict_MainPlate) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "TiledExt", true); + } + foreach (KeyValuePair> KVP in tCombineDict_MainPlateM) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "StretchExt"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane1_Disabled) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD1"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane3_Disabled) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD3"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActive) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA2"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActiveR) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDAR2"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane2_Disabled) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD2"); + } + foreach (KeyValuePair> KVP in tCombineDict_Lane1_DisabledActive) + { + if (!UniqueGSDRI.Contains(KVP.Key)) + { + UniqueGSDRI.Add(KVP.Key); + } + MeshSetup2_CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA1"); + } + + foreach (GSDRoadIntersection GSDRI in UniqueGSDRI) + { + GSDRI.UpdateMaterials(); + } + + } + + + private void MeshSetup2_CombineIntersections(KeyValuePair> KVP, string tName, bool bMainPlates = false) + { + int vCount = KVP.Value.Count; + if (vCount < 1) + { + return; + } + tName = tRoad.name + "-" + tName; + GameObject tCenter = null; + int cCount = KVP.Key.transform.childCount; + List GOToDelete = new List(); + for (int index = 0; index < cCount; index++) + { + if (KVP.Key.transform.GetChild(index).name.ToLower() == tName.ToLower()) + { + GOToDelete.Add(KVP.Key.transform.GetChild(index).gameObject); + } + if (bMainPlates && KVP.Key.transform.GetChild(index).name.ToLower() == "tcenter") + { + tCenter = KVP.Key.transform.GetChild(index).gameObject; + } + } + for (int index = GOToDelete.Count - 1; index >= 0; index--) + { + Object.DestroyImmediate(GOToDelete[index]); + } + + int CombineCount = vCount; + if (tCenter != null) + { + CombineCount += 1; + } + CombineInstance[] combine = new CombineInstance[CombineCount]; + for (int index = 0; index < vCount; index++) + { + combine[index].mesh = KVP.Value[index].sharedMesh; + combine[index].transform = KVP.Value[index].transform.localToWorldMatrix; + } + + int SpecialVertCount = 0; + if (tCenter != null) + { + for (int index = 0; index < (CombineCount - 1); index++) + { + SpecialVertCount += combine[index].mesh.vertexCount; + } + MeshFilter tMF = tCenter.GetComponent(); + Vector3[] xVerts = tMF.sharedMesh.vertices; + float xHeight = combine[0].mesh.vertices[combine[0].mesh.vertexCount - 1].y; + for (int index = 0; index < xVerts.Length; index++) + { + xVerts[index].y = xHeight; + } + tMF.sharedMesh.vertices = xVerts; + combine[CombineCount - 1].mesh = tMF.sharedMesh; + combine[CombineCount - 1].transform = tMF.transform.localToWorldMatrix; + } + + GameObject tObj = new GameObject(tName); + MeshFilter MF = tObj.AddComponent(); + Mesh tMesh = new Mesh(); + tMesh.CombineMeshes(combine); + MF.sharedMesh = tMesh; + MeshRenderer MR = tObj.AddComponent(); + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + tObj.transform.parent = KVP.Key.transform; + Vector3[] tVerts = MF.sharedMesh.vertices; + Vector3 tVect = tObj.transform.localPosition; + // float tHeight = 0f; + for (int index = 0; index < tVerts.Length; index++) + { + tVerts[index] += tVect; + if (tName.ToLower().EndsWith("-stretchext")) + tVerts[index] += new Vector3(0f, 0.01f); + } + MF.sharedMesh.vertices = tVerts; + tObj.transform.localPosition = new Vector3(0f, 0f, 0f); + MF.sharedMesh.RecalculateBounds(); + MF.sharedMesh.RecalculateNormals(); + MF.sharedMesh.tangents = GSDRootUtil.ProcessTangents(MF.sharedMesh.triangles, MF.sharedMesh.normals, MF.sharedMesh.uv, MF.sharedMesh.vertices); + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.Unwrapping.GenerateSecondaryUVSet(MF.sharedMesh); + } + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + tObj.isStatic = true; + } + + + if (bMainPlates) + { + MeshCollider MC = tObj.AddComponent(); + MC.sharedMesh = MF.sharedMesh; + MC.material = tRoad.RoadPhysicMaterial; + } + + if (bMainPlates && tCenter != null) + { + Object.DestroyImmediate(tCenter); + } + + SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, tRoad, tName); + } + + + private MeshFilter MeshSetup2_Intersection_Helper(ref Mesh xMesh, ref Vector2[] uv, ref Vector4[] tangents, ref GameObject MasterObj, string tName, string tMat, bool bCollider = false) + { + if (xMesh == null) + { + return null; + } + xMesh.uv = uv; + xMesh.tangents = tangents; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.Unwrapping.GenerateSecondaryUVSet(xMesh); + } + + GameObject tObj = new GameObject(tName); + tObj.transform.parent = MasterObj.transform; + MeshFilter MF = tObj.AddComponent(); + MF.sharedMesh = xMesh; + if (bCollider) + { + MeshCollider MC = tObj.AddComponent(); + MC.sharedMesh = MF.sharedMesh; + } + if (tMat.Length < 1) + { + return null; + } + MeshRenderer MR = tObj.AddComponent(); + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(tMat, MR); + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + tObj.isStatic = true; + } + + return MF; + } + #endregion + + + private Mesh MeshSetup2_Helper(ref Mesh xMesh, Vector2[] uv, Vector4[] tangents, ref GameObject tObj, bool bMarker, bool bShoulder = false, bool bBridge = false) + { + xMesh.uv = uv; + xMesh.tangents = tangents; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.Unwrapping.GenerateSecondaryUVSet(xMesh); + } + MeshFilter MF = tObj.AddComponent(); + MF.sharedMesh = xMesh; + MeshCollider MC = null; + if (tRoad.opt_bUseMeshColliders) + { + MC = tObj.AddComponent(); + MC.sharedMesh = MF.sharedMesh; + } + MeshRenderer MR = tObj.AddComponent(); + + if (bShoulder) + { + int mCounter = 0; + if (tRoad.ShoulderMaterial1 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial2 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial3 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial4 != null) + { + mCounter += 1; + } + } + } + } + + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.ShoulderMaterial1 != null) + { + tMats[0] = tRoad.ShoulderMaterial1; + if (tRoad.ShoulderMaterial2 != null) + { + tMats[1] = tRoad.ShoulderMaterial2; + if (tRoad.ShoulderMaterial3 != null) + { + tMats[2] = tRoad.ShoulderMaterial3; + if (tRoad.ShoulderMaterial4 != null) + { + tMats[3] = tRoad.ShoulderMaterial4; + } + } + } + } + MR.materials = tMats; + } + } + else + { + if (bMarker) + { + int mCounter = 0; + if (tRoad.RoadMaterialMarker1 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker2 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker3 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker4 != null) + { + mCounter += 1; + } + } + } + } + + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.RoadMaterialMarker1 != null) + { + tMats[0] = tRoad.RoadMaterialMarker1; + if (tRoad.RoadMaterialMarker2 != null) + { + tMats[1] = tRoad.RoadMaterialMarker2; + if (tRoad.RoadMaterialMarker3 != null) + { + tMats[2] = tRoad.RoadMaterialMarker3; + if (tRoad.RoadMaterialMarker4 != null) + { + tMats[3] = tRoad.RoadMaterialMarker4; + } + } + } + } + MR.materials = tMats; + } + } + else + { + int mCounter = 0; + if (tRoad.RoadMaterial1 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial2 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial3 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.RoadMaterial1 != null) + { + tMats[0] = tRoad.RoadMaterial1; + if (tRoad.RoadMaterial2 != null) + { + tMats[1] = tRoad.RoadMaterial2; + if (tRoad.RoadMaterial3 != null) + { + tMats[2] = tRoad.RoadMaterial3; + if (tRoad.RoadMaterial4 != null) + { + tMats[3] = tRoad.RoadMaterial4; + } + } + } + } + MR.materials = tMats; + } + + if (MC) + { + MC.sharedMaterial = tRoad.RoadPhysicMaterial; + } + } + } + + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(tObj, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + tObj.isStatic = true; + } + + return xMesh; + } + + + private bool MeshSetup2_Helper_RoadCuts(int i, ref Mesh zMesh, Vector2[] uv, Vector4[] tangents, ref GameObject MasterObj, bool bIsMarkers, out GameObject CreatedObj) + { + string tName = "RoadCut" + i.ToString(); + if (bIsMarkers) + { + tName = "Markers" + i.ToString(); + } + CreatedObj = new GameObject(tName); + + if (!bIsMarkers) + { + RoadCutNodes[i].RoadCut_world = CreatedObj; + } + else + { + RoadCutNodes[i].RoadCut_marker = CreatedObj; + } + + CreatedObj.transform.position = cut_RoadVectorsHome[i]; + zMesh.uv = uv; + zMesh.tangents = tangents; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.Unwrapping.GenerateSecondaryUVSet(zMesh); + } + MeshFilter MF = CreatedObj.AddComponent(); + MF.sharedMesh = zMesh; + + MeshCollider MC = null; + if (tRoad.opt_bUseMeshColliders && !bIsMarkers) + { + MC = CreatedObj.AddComponent(); + if (MC.sharedMesh == null) + { + MC.sharedMesh = MF.sharedMesh; + } + } + MeshRenderer MR = CreatedObj.AddComponent(); + + //Disable shadows for road cuts and markers: + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + int mCounter = 0; + bool bHasMats = false; + + if (bIsMarkers) + { + + + //Get the mat count: + if (tRoad.RoadMaterialMarker1 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker2 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker3 != null) + { + mCounter += 1; + if (tRoad.RoadMaterialMarker4 != null) + { + mCounter += 1; + } + } + } + } + //Apply mats: + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.RoadMaterialMarker1 != null) + { + tMats[0] = tRoad.RoadMaterialMarker1; + if (tRoad.RoadMaterialMarker2 != null) + { + tMats[1] = tRoad.RoadMaterialMarker2; + if (tRoad.RoadMaterialMarker3 != null) + { + tMats[2] = tRoad.RoadMaterialMarker3; + if (tRoad.RoadMaterialMarker4 != null) + { + tMats[3] = tRoad.RoadMaterialMarker4; + } + } + } + } + MR.materials = tMats; + bHasMats = true; + } + } + else + { + //Get the mat count: + if (tRoad.RoadMaterial1 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial2 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial3 != null) + { + mCounter += 1; + if (tRoad.RoadMaterial4 != null) + { + mCounter += 1; + } + } + } + } + //Apply mats: + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.RoadMaterial1 != null) + { + tMats[0] = tRoad.RoadMaterial1; + if (tRoad.RoadMaterial2 != null) + { + tMats[1] = tRoad.RoadMaterial2; + if (tRoad.RoadMaterial3 != null) + { + tMats[2] = tRoad.RoadMaterial3; + if (tRoad.RoadMaterial4 != null) + { + tMats[3] = tRoad.RoadMaterial4; + } + } + } + } + MR.materials = tMats; + bHasMats = true; + } + } + + CreatedObj.transform.parent = MasterObj.transform; + if (!bIsMarkers && MC != null) + { + MC.sharedMaterial = tRoad.RoadPhysicMaterial; + } + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(CreatedObj, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + CreatedObj.isStatic = true; + } + + return bHasMats; + } + + + private bool MeshSetup2_Helper_CutsShoulder(int i, ref Mesh zMesh, Vector2[] uv, Vector4[] tangents, ref GameObject MasterObj, bool bIsLeft, bool bIsMarkers, out GameObject CreatedObj) + { + + string tName = ""; + if (bIsMarkers) + { + if (bIsLeft) + { + tName = "Markers" + i.ToString(); + } + else + { + tName = "Markers" + i.ToString(); + } + } + else + { + if (bIsLeft) + { + tName = "SCutL" + i.ToString(); + } + else + { + tName = "SCutR" + i.ToString(); + } + } + + CreatedObj = new GameObject(tName); + if (bIsLeft) + { + CreatedObj.transform.position = cut_ShoulderL_VectorsHome[i]; + if (!bIsMarkers) + { + ShoulderCutsLNodes[i].ShoulderCutL_world = CreatedObj; + } + else + { + ShoulderCutsLNodes[i].ShoulderCutL_marker = CreatedObj; + } + + } + else + { + CreatedObj.transform.position = cut_ShoulderR_VectorsHome[i]; + if (!bIsMarkers) + { + ShoulderCutsRNodes[i].ShoulderCutR_world = CreatedObj; + } + else + { + ShoulderCutsRNodes[i].ShoulderCutR_marker = CreatedObj; + } + } + + MeshCollider MC = null; + if (tRoad.opt_bUseMeshColliders) + { + MC = CreatedObj.AddComponent(); + } + + zMesh.uv = uv; + zMesh.tangents = tangents; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.Unwrapping.GenerateSecondaryUVSet(zMesh); + } + MeshFilter MF = CreatedObj.AddComponent(); + MF.sharedMesh = zMesh; + + if (tRoad.opt_bUseMeshColliders) + { + if (MC.sharedMesh == null) + { + MC.sharedMesh = MF.sharedMesh; + } + } + int mCounter = 0; + bool bHasMats = false; + + //Disable shadows for road cuts and markers: + MeshRenderer MR = CreatedObj.AddComponent(); + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + + if (bIsMarkers) + { + if (tRoad.ShoulderMaterialMarker1 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterialMarker2 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterialMarker3 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterialMarker4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.ShoulderMaterialMarker1 != null) + { + tMats[0] = tRoad.ShoulderMaterialMarker1; + if (tRoad.ShoulderMaterialMarker2 != null) + { + tMats[1] = tRoad.ShoulderMaterialMarker2; + if (tRoad.ShoulderMaterialMarker3 != null) + { + tMats[2] = tRoad.ShoulderMaterialMarker3; + if (tRoad.ShoulderMaterialMarker4 != null) + { + tMats[3] = tRoad.ShoulderMaterialMarker4; + } + } + } + } + + MR.materials = tMats; + bHasMats = true; + } + } + else + { + if (tRoad.ShoulderMaterial1 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial2 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial3 != null) + { + mCounter += 1; + if (tRoad.ShoulderMaterial4 != null) + { + mCounter += 1; + } + } + } + } + if (mCounter > 0) + { + Material[] tMats = new Material[mCounter]; + if (tRoad.ShoulderMaterial1 != null) + { + tMats[0] = tRoad.ShoulderMaterial1; + if (tRoad.ShoulderMaterial2 != null) + { + tMats[1] = tRoad.ShoulderMaterial2; + if (tRoad.ShoulderMaterial3 != null) + { + tMats[2] = tRoad.ShoulderMaterial3; + if (tRoad.ShoulderMaterial4 != null) + { + tMats[3] = tRoad.ShoulderMaterial4; + } + } + } + } + MR.materials = tMats; + MR = null; + bHasMats = true; + } + } + + if (!bIsMarkers && MC != null) + { + MC.sharedMaterial = tRoad.ShoulderPhysicMaterial; + } + CreatedObj.transform.parent = MasterObj.transform; + if (tRoad.opt_bIsLightmapped) + { + UnityEditor.GameObjectUtility.SetStaticEditorFlags(CreatedObj, UnityEditor.StaticEditorFlags.LightmapStatic); + } + if (tRoad.opt_bIsStatic) + { + CreatedObj.isStatic = true; + } + + MF = null; + MC = null; + + return bHasMats; + } + #endregion + + + private static void SaveMesh(SaveMeshTypeEnum SaveType, Mesh tMesh, GSDRoad tRoad, string tName) + { + if (!tRoad.GSDRS.opt_bSaveMeshes) + { + return; + } + + //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); + string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; + tSceneName = tSceneName.Replace("/", ""); + tSceneName = tSceneName.Replace(".", ""); + string tFolderName = ""; + if (SaveType == SaveMeshTypeEnum.Road) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Roads/"; + } + else if (SaveType == SaveMeshTypeEnum.Shoulder) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Shoulders/"; + } + else if (SaveType == SaveMeshTypeEnum.Intersection) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Intersections/"; + } + else if (SaveType == SaveMeshTypeEnum.Railing) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Railings/"; + } + else if (SaveType == SaveMeshTypeEnum.Center) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/CenterDividers/"; + } + else if (SaveType == SaveMeshTypeEnum.RoadCut) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Roads/Cuts/"; + } + else if (SaveType == SaveMeshTypeEnum.SCut) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/Shoulders/Cuts/"; + } + else if (SaveType == SaveMeshTypeEnum.RoadConn) + { + tFolderName = GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Generated/RoadConn/"; + } + + string xPath = Application.dataPath.Replace("/Assets", "/" + tFolderName); + if (!System.IO.Directory.Exists(xPath)) + { + System.IO.Directory.CreateDirectory(xPath); + } + + string tRoadName = tRoad.transform.name; + string FinalName = tFolderName + tSceneName + "-" + tRoadName + "-" + tName + ".asset"; + if (SaveType == SaveMeshTypeEnum.Intersection) + { + FinalName = tFolderName + tSceneName + "-" + tName + ".asset"; + } + + UnityEditor.AssetDatabase.CreateAsset(tMesh, FinalName); + } + } + + + public static class GSDGeneralEditor + { + #region "Terrain history serialization" + //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; + } + } + + + public static void TerrainHistory_Save(List tObj, GSDRoad tRoad) + { + string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); + if (string.IsNullOrEmpty(tPath) || tPath.Length < 2) + { + return; + } + Stream stream = File.Open(tPath, FileMode.Create); + BinaryFormatter bformatter = new BinaryFormatter(); + bformatter.Binder = new VersionDeserializationBinder(); + bformatter.Serialize(stream, tObj); + tRoad.TerrainHistoryByteSize = (stream.Length * 0.001f).ToString("n0") + " kb"; + stream.Close(); + } + + + public static void TerrainHistory_Delete(GSDRoad tRoad) + { + string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); + if (System.IO.File.Exists(tPath)) + { + System.IO.File.Delete(tPath); + } + } + + + public static List TerrainHistory_Load(GSDRoad tRoad) + { + string tPath = CheckNonAssetDirTH() + GetRoadTHFilename(ref tRoad); + if (string.IsNullOrEmpty(tPath) || tPath.Length < 2) + { + return null; + } + if (!File.Exists(tPath)) + { + return null; + } + List result; + Stream stream = File.Open(tPath, FileMode.Open); + BinaryFormatter bFormatter = new BinaryFormatter(); + bFormatter.Binder = new VersionDeserializationBinder(); + // try{ + result = (List) bFormatter.Deserialize(stream) as List; + // }catch{ + // result = null; + // } + stream.Close(); + return result; + } + + + private static string GetRoadTHFilename(ref GSDRoad tRoad) + { + //string tSceneName = System.IO.Path.GetFileName(UnityEditor.EditorApplication.currentScene).ToLower().Replace(".unity",""); + string tSceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; + tSceneName = tSceneName.Replace("/", ""); + tSceneName = tSceneName.Replace(".", ""); + string tRoadName = tRoad.GSDRS.transform.name.Replace("RoadArchitectSystem", "RAS") + "-" + tRoad.transform.name; + return tSceneName + "-" + tRoadName + "-TH.gsd"; + } + + + public static string CheckNonAssetDir() + { + string tPath = GSDRootUtil.Dir_GetBase(); + if (!System.IO.Directory.Exists(tPath)) + { + System.IO.Directory.CreateDirectory(tPath); + } + if (System.IO.Directory.Exists(tPath)) + { + return tPath + "/"; + } + else + { + return ""; + } + } + + + public static string CheckNonAssetDirTH() + { + CheckNonAssetDir(); + string xPath = GSDRootUtil.Dir_GetTH(); + if (!System.IO.Directory.Exists(xPath)) + { + System.IO.Directory.CreateDirectory(xPath); + } + if (System.IO.Directory.Exists(xPath)) + { + return xPath; + } + else + { + return ""; + } + } + + + public static string CheckNonAssetDirLibrary() + { + CheckNonAssetDir(); + string xPath = GSDRootUtil.Dir_GetLibrary(); + if (!System.IO.Directory.Exists(xPath)) + { + System.IO.Directory.CreateDirectory(xPath); + } + if (System.IO.Directory.Exists(xPath)) + { + return xPath; + } + else + { + return ""; + } + } + + + public static void CheckNonAssetDirs() + { + CheckNonAssetDir(); + CheckNonAssetDirTH(); + CheckNonAssetDirLibrary(); + } + #endregion + } + + + public static class GSDRoadUtil + { + private const string FileSepString = "\n!!!! MICROGSD !!!!\n"; + private const string FileSepStringCRLF = "\r\n!!!! MICROGSD !!!!\r\n"; + + + public static Terrain GetTerrain(Vector3 tVect) + { + return GetTerrain_Do(ref tVect); + } + + + private static Terrain GetTerrain_Do(ref Vector3 tVect) + { + //Sphere cast 5m first. Then raycast down 1000m, then up 1000m. + Collider[] tColliders = Physics.OverlapSphere(tVect, 10f); + if (tColliders != null) + { + int tCollidersLength = tColliders.Length; + for (int index = 0; index < tCollidersLength; index++) + { + Terrain tTerrain = tColliders[index].transform.GetComponent(); + if (tTerrain) + { + tColliders = null; + return tTerrain; + } + } + tColliders = null; + } + + RaycastHit[] tHits; + tHits = Physics.RaycastAll(tVect, Vector3.down, 1000f); + int tHitsLength = 0; + if (tHits != null) + { + tHitsLength = tHits.Length; + for (int index = 0; index < tHitsLength; index++) + { + Terrain tTerrain = tHits[index].collider.transform.GetComponent(); + if (tTerrain) + { + tHits = null; + return tTerrain; + } + } + tHits = null; + } + + tHits = Physics.RaycastAll(tVect, Vector3.up, 1000f); + if (tHits != null) + { + tHitsLength = tHits.Length; + for (int i = 0; i < tHitsLength; i++) + { + Terrain tTerrain = tHits[i].collider.transform.GetComponent(); + if (tTerrain) + { + tHits = null; + return tTerrain; + } + } + tHits = null; + } + return null; + } + + + #region "Terrain history" + public static void ConstructRoad_StoreTerrainHistory(ref GSDRoad tRoad) + { + ConstructRoad_DoStoreTerrainHistory(ref tRoad); + } + + + private static void ConstructRoad_DoStoreTerrainHistory(ref GSDRoad tRoad) + { + Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); + + HashSet tTIDS = new HashSet(); + foreach (GSDTerrain TID in TIDs) + { + tTIDS.Add(TID.GSDID); + } + + if (tRoad.TerrainHistory != null && tRoad.TerrainHistory.Count > 0) + { + //Delete unnecessary terrain histories: + foreach (GSDTerrainHistoryMaker THf in tRoad.TerrainHistory) + { + if (!tTIDS.Contains(THf.TID)) + { + THf.Nullify(); + THf.bDestroyMe = true; + } + } + + int hCount = tRoad.TerrainHistory.Count; + for (int index = hCount - 1; index >= 0; index--) + { + if (tRoad.TerrainHistory[index].bDestroyMe) + { + GSDTerrainHistoryMaker THf = tRoad.TerrainHistory[index]; + tRoad.TerrainHistory.RemoveAt(index); + if (THf != null) + { + THf = null; + } + } + } + } + + if (tRoad.TerrainHistory == null) + { + tRoad.TerrainHistory = new List(); + } + foreach (GSDTerraforming.TempTerrainData TTD in tRoad.EditorTTDList) + { + GSDTerrainHistoryMaker TH = null; + GSDTerrain TID = null; + //Get TID: + foreach (GSDTerrain _TID in TIDs) + { + if (_TID.GSDID == TTD.GSDID) + { + TID = _TID; + } + } + + if (tRoad.TerrainHistory == null) + { + tRoad.TerrainHistory = new List(); + } + if (TID == null) + { + continue; + } + + int THCount = tRoad.TerrainHistory.Count; + bool bContainsTID = false; + for (int index = 0; index < THCount; index++) + { + if (tRoad.TerrainHistory[index].TID == TID.GSDID) + { + bContainsTID = true; + break; + } + } + + if (!bContainsTID) + { + GSDTerrainHistoryMaker THx = new GSDTerrainHistoryMaker(); + THx.TID = TID.GSDID; + tRoad.TerrainHistory.Add(THx); + } + + TH = null; + for (int index = 0; index < THCount; index++) + { + if (tRoad.TerrainHistory[index].TID == TID.GSDID) + { + TH = tRoad.TerrainHistory[index]; + break; + } + } + if (TH == null) + { + continue; + } + + //Heights: + if (tRoad.opt_HeightModEnabled) + { + if (TTD.cX != null && TTD.cY != null) + { + TH.x1 = new int[TTD.cI]; + System.Array.Copy(TTD.cX, 0, TH.x1, 0, TTD.cI); + TH.y1 = new int[TTD.cI]; + System.Array.Copy(TTD.cY, 0, TH.y1, 0, TTD.cI); + TH.h = new float[TTD.cI]; + System.Array.Copy(TTD.oldH, 0, TH.h, 0, TTD.cI); + TH.cI = TTD.cI; + } + } + else + { + TH.x1 = null; + TH.y1 = null; + TH.h = null; + TH.cI = 0; + } + //Details: + if (tRoad.opt_DetailModEnabled) + { + int TotalSize = 0; + for (int i = 0; i < TTD.DetailLayersCount; i++) + { + TotalSize += TTD.DetailsI[i]; + } + + // float tHalf = (float)TotalSize / 2f; + // int IntHalf = Mathf.CeilToInt(tHalf); + + TH.DetailsX = new int[TotalSize]; + TH.DetailsY = new int[TotalSize]; + TH.DetailsOldValue = new int[TotalSize]; + + int RunningIndex = 0; + int cLength = 0; + for (int index = 0; index < TTD.DetailLayersCount; index++) + { + cLength = TTD.DetailsI[index]; + if (cLength < 1) + { + continue; + } + System.Array.Copy(TTD.DetailsX[index].ToArray(), 0, TH.DetailsX, RunningIndex, cLength); + System.Array.Copy(TTD.DetailsY[index].ToArray(), 0, TH.DetailsY, RunningIndex, cLength); + System.Array.Copy(TTD.OldDetailsValue[index].ToArray(), 0, TH.DetailsOldValue, RunningIndex, cLength); + RunningIndex += TTD.DetailsI[index]; + } + + // TH.DetailsX = TTD.DetailsX; + // TH.DetailsY = TTD.DetailsY; + // TH.DetailsOldValue = TTD.OldDetailsValue; + TH.DetailsI = TTD.DetailsI; + TH.DetailLayersCount = TTD.DetailLayersCount; + } + else + { + TH.DetailsX = null; + TH.DetailsY = null; + TH.DetailsOldValue = null; + TH.DetailsI = null; + TH.DetailLayersCount = 0; + } + //Trees: + if (tRoad.opt_TreeModEnabled) + { + if (TTD.TreesOld != null) + { + TH.MakeGSDTrees(ref TTD.TreesOld); + TTD.TreesOld.Clear(); + TTD.TreesOld = null; + TH.TreesI = TTD.TreesI; + } + } + else + { + TH.TreesOld = null; + TH.TreesI = 0; + } + } + + // //TerrainHistoryRaw + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("TerrainHistorySerialize"); } + // TerrainHistorySerialize(ref tRoad); + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } + } + + + // static void TerrainHistorySerialize(ref GSDRoad tRoad) { + // MemoryStream ms = new MemoryStream(); + // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + // formatter.Serialize(ms,tRoad.TerrainHistory); + // ms.Close(); + // tRoad.TerrainHistoryRaw = ms.ToArray(); + // ms = null; + // } + // + // static void TerrainHistoryDeserialize(ref GSDRoad tRoad) { + // MemoryStream ms = new MemoryStream(tRoad.TerrainHistoryRaw); + // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + // tRoad.TerrainHistory = (List)formatter.Deserialize(ms); + // ms.Close(); + // ms = null; + // } + + + public static void ConstructRoad_ResetTerrainHistory(ref GSDRoad tRoad) + { + ConstructRoad_DoResetTerrainHistory(ref tRoad); + } + + + private static void ConstructRoad_DoResetTerrainHistory(ref GSDRoad tRoad) + { + if (tRoad.TerrainHistory != null) + { + tRoad.TerrainHistory.Clear(); + tRoad.TerrainHistory = null; + } + } + #endregion + + + [System.Serializable] + public class Construction3DTri + { + public Vector3 P1, P2, P3; + const float NearDist = 0.15f; + const float NearDistSQ = 0.0225f; + Vector2[] poly2D; + Vector3[] poly3D; + public float MaxDistance = 200f; + public float MaxDistanceSq = 200f; + public Vector3 normal = default(Vector3); + public Vector3 pMiddle = default(Vector3); + public float MinI = 0f; + public float MaxI = 1f; + + + public Construction3DTri(Vector3 _P1, Vector3 _P2, Vector3 _P3, float _MinI, float _MaxI) + { + MinI = _MinI; + MaxI = _MaxI; + P1 = _P1; + P2 = _P2; + P3 = _P3; + + poly2D = new Vector2[3]; + poly2D[0] = new Vector2(P1.x, P1.z); + poly2D[1] = new Vector2(P2.x, P2.z); + poly2D[2] = new Vector2(P3.x, P3.z); + + poly3D = new Vector3[3]; + poly3D[0] = P1; + poly3D[1] = P2; + poly3D[2] = P3; + + float[] tMaxes = new float[3]; + tMaxes[0] = Vector3.Distance(P1, P2); + tMaxes[1] = Vector3.Distance(P1, P3); + tMaxes[2] = Vector3.Distance(P2, P3); + MaxDistance = Mathf.Max(tMaxes) * 1.5f; + + float[] tMaxesSQ = new float[3]; + tMaxesSQ[0] = Vector3.SqrMagnitude(P1 - P2); + tMaxesSQ[1] = Vector3.SqrMagnitude(P1 - P3); + tMaxesSQ[2] = Vector3.SqrMagnitude(P2 - P3); + MaxDistanceSq = Mathf.Max(tMaxesSQ) * 1.5f; + + PlaneFrom3Points(out normal, out pMiddle, P1, P2, P3); + + normal = Vector3.Cross((P3 - P1), (P2 - P1)); + + //// //This creates middle point: + // Vector3 tMiddle1 = ((P3-P1)*0.5f)+P1; + // Vector3 tMiddle2 = ((P2-P1)*0.5f)+P1; + // pMiddle = ((tMiddle2-tMiddle1)*0.5f)+tMiddle1; + } + + + //Get the intersection between a line and a plane. + //If the line and plane are not parallel, the function outputs true, otherwise false. + public Vector3 LinePlaneIntersection(ref Vector3 F1) + { + F1.y = 0f; + + //calculate the distance between the linePoint and the line-plane intersection point + float dotNumerator = Vector3.Dot((pMiddle - F1), normal); + float dotDenominator = Vector3.Dot(Vector3.up.normalized, normal); + + //line and plane are not parallel + if (!IsApproximately(0f, dotDenominator, 0.001f)) + { + //get the coordinates of the line-plane intersection point + return (F1 + (Vector3.up.normalized * (dotNumerator / dotDenominator))); + } + else + { + //output not valid + return default(Vector3); + } + } + + + static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + + + //Convert a plane defined by 3 points to a plane defined by a vector and a point. + //The plane point is the middle of the triangle defined by the 3 points. + public static void PlaneFrom3Points(out Vector3 planeNormal, out Vector3 planePoint, Vector3 pointA, Vector3 pointB, Vector3 pointC) + { + planeNormal = Vector3.zero; + planePoint = Vector3.zero; + + //Make two vectors from the 3 input points, originating from point A + Vector3 AB = pointB - pointA; + Vector3 AC = pointC - pointA; + + //Calculate the normal + planeNormal = Vector3.Normalize(Vector3.Cross(AB, AC)); + + //Get the points in the middle AB and AC + Vector3 middleAB = pointA + (AB / 2.0f); + Vector3 middleAC = pointA + (AC / 2.0f); + + //Get vectors from the middle of AB and AC to the point which is not on that line. + Vector3 middleABtoC = pointC - middleAB; + Vector3 middleACtoB = pointB - middleAC; + + //Calculate the intersection between the two lines. This will be the center + //of the triangle defined by the 3 points. + //We could use LineLineIntersection instead of ClosestPointsOnTwoLines but due to rounding errors + //this sometimes doesn't work. + Vector3 temp; + ClosestPointsOnTwoLines(out planePoint, out temp, middleAB, middleABtoC, middleAC, middleACtoB); + } + + + //Two non-parallel lines which may or may not touch each other have a point on each line which are closest + //to each other. This function finds those two points. If the lines are not parallel, the function + //outputs true, otherwise false. + public static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2) + { + + closestPointLine1 = Vector3.zero; + closestPointLine2 = Vector3.zero; + + float a = Vector3.Dot(lineVec1, lineVec1); + float b = Vector3.Dot(lineVec1, lineVec2); + float e = Vector3.Dot(lineVec2, lineVec2); + + float d = a * e - b * b; + + //lines are not parallel + if (d != 0.0f) + { + + Vector3 r = linePoint1 - linePoint2; + float c = Vector3.Dot(lineVec1, r); + float f = Vector3.Dot(lineVec2, r); + + float s = (b * f - c * e) / d; + float t = (a * f - c * b) / d; + + closestPointLine1 = linePoint1 + lineVec1 * s; + closestPointLine2 = linePoint2 + lineVec2 * t; + + return true; + } + + else + { + return false; + } + } + + + //create a vector of direction "vector" with length "size" + public static Vector3 SetVectorLength(Vector3 vector, float size) + { + + //normalize the vector + Vector3 vectorNormalized = Vector3.Normalize(vector); + + //scale the vector + return vectorNormalized *= size; + } + + + // public bool Contains2D(ref Vector2 p){ + // return Contains2D_Do(ref p); + // } + public bool Contains2D(ref Vector2 p) + { + if (Vector2.SqrMagnitude(p - poly2D[0]) > MaxDistanceSq) + { + return false; + } + // if(Vector2.Distance(p,P1) > MaxDistance){ return false; } + // if(poly2D.Length != 3){ return false; } + + Vector2 x1 = default(Vector2); + Vector2 x2 = default(Vector2); + Vector2 oldPoint = default(Vector2); + Vector2 newPoint = default(Vector2); + bool inside = false; + + inside = false; + oldPoint = new Vector2(poly2D[3 - 1].x, poly2D[3 - 1].y); + for (int index = 0; index < 3; index++) + { + newPoint = new Vector2(poly2D[index].x, poly2D[index].y); + if (newPoint.x > oldPoint.x) + { + x1 = oldPoint; + x2 = newPoint; + } + else + { + x1 = newPoint; + x2 = oldPoint; + } + if ((newPoint.x < p.x) == (p.x <= oldPoint.x) && (p.y - x1.y) * (x2.x - x1.x) < (x2.y - x1.y) * (p.x - x1.x)) + { + inside = !inside; + } + oldPoint = newPoint; + } + return inside; + } + + + public bool Contains2D(ref Vector3 p) + { + Vector2 tVect = new Vector2(p.x, p.z); + return Contains2D(ref tVect); + } + + + public bool Near(ref Vector3 tVect, out Vector3 TheNearVect) + { + if (Vector3.SqrMagnitude(tVect - P1) > MaxDistanceSq) + { + // if(Vector3.Distance(tVect,P1) > MaxDistance){ + TheNearVect = default(Vector3); + return false; + } + + // if(Vector3.Distance(tVect,P1) < NearDist){ + if (Vector3.SqrMagnitude(tVect - P1) < NearDistSQ) + { + TheNearVect = P1; + return true; + } + // if(Vector3.Distance(tVect,P2) < NearDist){ + if (Vector3.SqrMagnitude(tVect - P2) < NearDistSQ) + { + TheNearVect = P2; + return true; + } + // if(Vector3.Distance(tVect,P3) < NearDist){ + if (Vector3.SqrMagnitude(tVect - P3) < NearDistSQ) + { + TheNearVect = P3; + return true; + } + TheNearVect = default(Vector3); + return false; + } + + + public string ToStringGSD() + { + return ("P1:" + P1.ToString() + " P2:" + P2.ToString() + " P3:" + P3.ToString()); + } + } + + + public class Construction2DRect + { + public Vector2 P1, P2, P3, P4; + const float NearDist = 0.15f; + const float NearDistSQ = 0.0225f; + Vector2[] poly; + public float MaxDistance = 200f; + public float MaxDistanceSQ = 200f; + public float Height = 0f; + public float MinI = 0f; + public float MaxI = 0f; + + + static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + + + public Construction2DRect(Vector2 _P1, Vector2 _P2, Vector2 _P3, Vector2 _P4, float tHeight = 0f) + { + Construction2DRect_Do(ref _P1, ref _P2, ref _P3, ref _P4, ref tHeight); + } + + + private void Construction2DRect_Do(ref Vector2 _P1, ref Vector2 _P2, ref Vector2 _P3, ref Vector2 _P4, ref float tHeight) + { + P1 = _P1; + P2 = _P2; + P3 = _P3; + P4 = _P4; + Height = tHeight; + + if (IsApproximately(P1.x, P2.x, 0.0001f)) + { + P2.x += 0.0002f; + } + if (IsApproximately(P1.x, P3.x, 0.0001f)) + { + P3.x += 0.0002f; + } + if (IsApproximately(P1.x, P4.x, 0.0001f)) + { + P4.x += 0.0002f; + } + if (IsApproximately(P2.x, P3.x, 0.0001f)) + { + P3.x += 0.0002f; + } + if (IsApproximately(P2.x, P4.x, 0.0001f)) + { + P4.x += 0.0002f; + } + if (IsApproximately(P3.x, P4.x, 0.0001f)) + { + P4.x += 0.0002f; + } + + if (IsApproximately(P1.y, P2.y, 0.0001f)) + { + P2.y += 0.0002f; + } + if (IsApproximately(P1.y, P3.y, 0.0001f)) + { + P3.y += 0.0002f; + } + if (IsApproximately(P1.y, P4.y, 0.0001f)) + { + P4.y += 0.0002f; + } + if (IsApproximately(P2.y, P3.y, 0.0001f)) + { + P3.y += 0.0002f; + } + if (IsApproximately(P2.y, P4.y, 0.0001f)) + { + P4.y += 0.0002f; + } + if (IsApproximately(P3.y, P4.y, 0.0001f)) + { + P4.y += 0.0002f; + } + + //Find two with smallest x, etc + float[] tX = new float[4]; + float[] tY = new float[4]; + + tX[0] = P1.x; + tX[1] = P2.x; + tX[2] = P3.x; + tX[3] = P4.x; + + tY[0] = P1.y; + tY[1] = P2.y; + tY[2] = P3.y; + tY[3] = P4.y; + + float MinX1, MinX2; + bool bIgnoreP1, bIgnoreP2, bIgnoreP3, bIgnoreP4; + bIgnoreP1 = bIgnoreP2 = bIgnoreP3 = bIgnoreP4 = false; + + //Get top two minimum X + MinX1 = Mathf.Min(tX); + tX = new float[3]; + int tCounter = 0; + if (!IsApproximately(MinX1, P1.x, 0.0001f)) + { + tX[tCounter] = P1.x; + tCounter += 1; + } + if (!IsApproximately(MinX1, P2.x, 0.0001f)) + { + tX[tCounter] = P2.x; + tCounter += 1; + } + if (!IsApproximately(MinX1, P3.x, 0.0001f)) + { + tX[tCounter] = P3.x; + tCounter += 1; + } + if (!IsApproximately(MinX1, P4.x, 0.0001f)) + { + tX[tCounter] = P4.x; + tCounter += 1; + } + MinX2 = Mathf.Min(tX); + + Vector2 xMin1 = default(Vector2); + Vector2 xMin2 = default(Vector2); + if (IsApproximately(MinX1, P1.x, 0.0001f)) + { + xMin1 = P1; + bIgnoreP1 = true; + } + else if (IsApproximately(MinX1, P2.x, 0.0001f)) + { + xMin1 = P2; + bIgnoreP2 = true; + } + else if (IsApproximately(MinX1, P3.x, 0.0001f)) + { + xMin1 = P3; + bIgnoreP3 = true; + } + else if (IsApproximately(MinX1, P4.x, 0.0001f)) + { + xMin1 = P4; + bIgnoreP4 = true; + } + + if (IsApproximately(MinX2, P1.x, 0.0001f)) + { + xMin2 = P1; + bIgnoreP1 = true; + } + else if (IsApproximately(MinX2, P2.x, 0.0001f)) + { + xMin2 = P2; + bIgnoreP2 = true; + } + else if (IsApproximately(MinX2, P3.x, 0.0001f)) + { + xMin2 = P3; + bIgnoreP3 = true; + } + else if (IsApproximately(MinX2, P4.x, 0.0001f)) + { + xMin2 = P4; + bIgnoreP4 = true; + } + + Vector2 TopLeft = default(Vector2); + Vector2 BottomLeft = default(Vector2); + if (xMin1.y > xMin2.y) + { + TopLeft = xMin1; + BottomLeft = xMin2; + } + else + { + TopLeft = xMin2; + BottomLeft = xMin1; + } + + Vector2 xMax1 = default(Vector2); + Vector2 xMax2 = default(Vector2); + bool bXmax1 = false; + if (!bIgnoreP1) + { + xMax1 = P1; + bXmax1 = true; + } + if (!bIgnoreP2) + { + if (bXmax1) + { + xMax2 = P2; + } + else + { + xMax1 = P2; + bXmax1 = true; + } + } + if (!bIgnoreP3) + { + if (bXmax1) + { + xMax2 = P3; + } + else + { + xMax1 = P3; + bXmax1 = true; + } + } + if (!bIgnoreP4) + { + if (bXmax1) + { + xMax2 = P4; + } + else + { + xMax1 = P4; + bXmax1 = true; + } + } + + Vector2 TopRight = default(Vector2); + Vector2 BottomRight = default(Vector2); + if (xMax1.y > xMax2.y) + { + TopRight = xMax1; + BottomRight = xMax2; + } + else + { + TopRight = xMax2; + BottomRight = xMax1; + } + + P1 = BottomLeft; + P2 = BottomRight; + P3 = TopRight; + P4 = TopLeft; + + poly = new Vector2[4]; + poly[0] = P1; + poly[1] = P2; + poly[2] = P3; + poly[3] = P4; + + float[] tMaxes = new float[6]; + tMaxes[0] = Vector2.Distance(P1, P2); + tMaxes[1] = Vector2.Distance(P1, P3); + tMaxes[2] = Vector2.Distance(P1, P4); + tMaxes[3] = Vector2.Distance(P2, P3); + tMaxes[4] = Vector2.Distance(P2, P4); + tMaxes[5] = Vector2.Distance(P3, P4); + MaxDistance = Mathf.Max(tMaxes) * 1.5f; + + float[] tMaxesSQ = new float[6]; + tMaxesSQ[0] = Vector2.SqrMagnitude(P1 - P2); + tMaxesSQ[1] = Vector2.SqrMagnitude(P1 - P3); + tMaxesSQ[2] = Vector2.SqrMagnitude(P1 - P4); + tMaxesSQ[3] = Vector2.SqrMagnitude(P2 - P3); + tMaxesSQ[4] = Vector2.SqrMagnitude(P2 - P4); + tMaxesSQ[5] = Vector2.SqrMagnitude(P3 - P4); + MaxDistanceSQ = Mathf.Max(tMaxesSQ) * 1.5f; + } + + + + Vector2 x1 = default(Vector2); + Vector2 x2 = default(Vector2); + Vector2 oldPoint = default(Vector2); + Vector2 newPoint = default(Vector2); + bool inside = false; + + // public bool Contains(ref Vector2 p){ + // return Contains_Do(ref p); + // } + public bool Contains(ref Vector2 p) + { + // if(Vector2.Distance(p,P1) > MaxDistance){ return false; } + if (Vector2.SqrMagnitude(p - P1) > MaxDistanceSQ) + { + return false; + } + // if(poly.Length != 4){ return false; } + + inside = false; + oldPoint = new Vector2(poly[4 - 1].x, poly[4 - 1].y); + for (int index = 0; index < 4; index++) + { + newPoint = new Vector2(poly[index].x, poly[index].y); + if (newPoint.x > oldPoint.x) + { + x1 = oldPoint; + x2 = newPoint; + } + else + { + x1 = newPoint; + x2 = oldPoint; + } + if ((newPoint.x < p.x) == (p.x <= oldPoint.x) && (p.y - x1.y) * (x2.x - x1.x) < (x2.y - x1.y) * (p.x - x1.x)) + { + inside = !inside; + } + oldPoint = newPoint; + } + return inside; + } + + + public bool Near(ref Vector2 tVect, out Vector2 TheNearVect) + { + if (Vector2.SqrMagnitude(tVect - P1) > MaxDistanceSQ) + { + // if(Vector2.Distance(tVect,P1) > MaxDistance){ + TheNearVect = default(Vector2); + return false; + } + + if (Vector2.SqrMagnitude(tVect - P1) < NearDistSQ) + { + // if(Vector2.Distance(tVect,P1) < NearDist){ + TheNearVect = P1; + return true; + } + if (Vector2.SqrMagnitude(tVect - P2) < NearDistSQ) + { + // if(Vector2.Distance(tVect,P2) < NearDist){ + TheNearVect = P2; + return true; + } + if (Vector2.SqrMagnitude(tVect - P3) < NearDistSQ) + { + // if(Vector2.Distance(tVect,P3) < NearDist){ + TheNearVect = P3; + return true; + } + if (Vector2.SqrMagnitude(tVect - P4) < NearDistSQ) + { + // if(Vector2.Distance(tVect,P4) < NearDist){ + TheNearVect = P4; + return true; + } + TheNearVect = default(Vector2); + return false; + } + + + public string ToStringGSD() + { + return ("P1:" + P1.ToString() + " P2:" + P2.ToString() + " P3:" + P3.ToString() + " P4:" + P4.ToString()); + } + } + + + public static GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[] GetRoadTerrainInfos() + { + Object[] tTerrainsObj = GameObject.FindObjectsOfType(typeof(Terrain)); + GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo tInfo; + List tInfos = new List(); + foreach (Terrain tTerrain in tTerrainsObj) + { + tInfo = new GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo(); + tInfo.GSDID = tTerrain.transform.gameObject.GetComponent().GSDID; + tInfo.tBounds = new Rect(tTerrain.transform.position.x, tTerrain.transform.position.z, tTerrain.terrainData.size.x, tTerrain.terrainData.size.z); + tInfo.hmWidth = tTerrain.terrainData.heightmapWidth; + tInfo.hmHeight = tTerrain.terrainData.heightmapHeight; + tInfo.tPos = tTerrain.transform.position; + tInfo.tSize = tTerrain.terrainData.size; + tInfo.heights = tTerrain.terrainData.GetHeights(0, 0, tInfo.hmWidth, tInfo.hmHeight); + tInfos.Add(tInfo); + } + GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[] fInfos = new GSD.Threaded.GSDRoadCreationT.RoadTerrainInfo[tInfos.Count]; + int fInfosLength = fInfos.Length; + for (int index = 0; index < fInfosLength; index++) + { + fInfos[index] = tInfos[index]; + } + tInfos = null; + return fInfos; + } + + + // RenderQueue provides ID's for Unity render queues. These can be applied to sub-shader tags, + // but it's easier to just set material.renderQueue. Static class instead of enum because these + // are int's, so this way client code doesn't need to use typecasting. + // + // From the documentation: + // For special uses in-between queues can be used. Internally each queue is represented + // by integer index; Background is 1000, Geometry is 2000, Transparent is 3000 and + // Overlay is 4000. + // + // NOTE: Keep these in numerical order for ease of understanding. Use plurals for start of + // a group of layers. + public static class RenderQueue + { + public const int Background = 1000; + + // Mid-ground. + public const int ParallaxLayers = Background + 100; // +1, 2, 3, ... for additional layers + + // Lines on the ground. + public const int GroundLines = Background + 200; + + public const int Tracks = GroundLines + 0; + public const int Routes = GroundLines + 1; + public const int IndicatorRings = GroundLines + 2; + public const int Road = GroundLines + 3; + + public const int Geometry = 2000; + + + public const int Transparent = 3000; + + // Lines on the screen. (Over world, but under GUI.) + public const int ScreenLines = Transparent + 100; + + public const int Overlay = 4000; + } + + + public static void SaveNodeObjects(ref Splination.SplinatedMeshMaker[] tSplinatedObjects, ref EdgeObjects.EdgeObjectMaker[] tEdgeObjects, ref WizardObject WO) + { + SaveNodeObjects_DO(ref tSplinatedObjects, ref tEdgeObjects, ref WO); + } + + + private static void SaveNodeObjects_DO(ref Splination.SplinatedMeshMaker[] tSplinatedObjects, ref EdgeObjects.EdgeObjectMaker[] tEdgeObjects, ref WizardObject WO) + { + int sCount = tSplinatedObjects.Length; + int eCount = tEdgeObjects.Length; + //Splinated objects first: + Splination.SplinatedMeshMaker SMM = null; + GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); + string xPath = GSDRootUtil.Dir_GetLibrary(); + string tPath = xPath + "B/" + WO.FileName + ".gsd"; + if (WO.bIsDefault) + { + tPath = xPath + "B/W/" + WO.FileName + ".gsd"; + } + StringBuilder builder = new StringBuilder(32768); + + //Wizard object: + builder.Append(WO.ConvertToString()); + builder.Append(FileSepString); + + for (int index = 0; index < sCount; index++) + { + SMM = tSplinatedObjects[index]; + builder.Append(SMM.ConvertToString()); + builder.Append(FileSepString); + } + + EdgeObjects.EdgeObjectMaker EOM = null; + for (int index = 0; index < eCount; index++) + { + EOM = tEdgeObjects[index]; + builder.Append(EOM.ConvertToString()); + builder.Append(FileSepString); + } + +#if UNITY_WEBPLAYER + +#else + System.IO.File.WriteAllText(tPath, builder.ToString()); +#endif + } + + + public static void LoadNodeObjects(string tFileName, GSDSplineN tNode, bool bIsDefault = false, bool bIsBridge = false) + { +#if UNITY_WEBPLAYER + return; +#else + + string tPath = ""; + GSDRootUtil.Dir_GetLibrary_CheckSpecialDirs(); + string xPath = GSDRootUtil.Dir_GetLibrary(); + if (bIsDefault) + { + tPath = xPath + "B/W/" + tFileName + ".gsd"; + } + else + { + tPath = xPath + "B/" + tFileName + ".gsd"; + } + + string tData = System.IO.File.ReadAllText(tPath); + string[] tSep = new string[2]; + tSep[0] = FileSepString; + tSep[1] = FileSepStringCRLF; + string[] tSplit = tData.Split(tSep, System.StringSplitOptions.RemoveEmptyEntries); + + Splination.SplinatedMeshMaker SMM = null; + Splination.SplinatedMeshMaker.SplinatedMeshLibraryMaker SLM = null; + EdgeObjects.EdgeObjectMaker EOM = null; + EdgeObjects.EdgeObjectMaker.EdgeObjectLibraryMaker ELM = null; + int tSplitCount = tSplit.Length; + + for (int index = 0; index < tSplitCount; index++) + { + SLM = null; + SLM = Splination.SplinatedMeshMaker.SLMFromData(tSplit[index]); + if (SLM != null) + { + SMM = tNode.AddSplinatedObject(); + SMM.LoadFromLibraryBulk(ref SLM); + SMM.bToggle = false; + if (bIsBridge && tNode.bIsBridgeStart && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null) + { + SMM.StartTime = tNode.tTime; + SMM.EndTime = tNode.BridgeCounterpartNode.tTime; + SMM.StartPos = tNode.GSDSpline.GetSplineValue(SMM.StartTime); + SMM.EndPos = tNode.GSDSpline.GetSplineValue(SMM.EndTime); + } + continue; + } + + ELM = null; + ELM = EdgeObjects.EdgeObjectMaker.ELMFromData(tSplit[index]); + if (ELM != null) + { + EOM = tNode.AddEdgeObject(); + EOM.LoadFromLibraryBulk(ref ELM); + EOM.bToggle = false; + if (!EOM.bSingle && bIsBridge && tNode.bIsBridgeStart && tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode != null) + { + EOM.StartTime = tNode.tTime; + EOM.EndTime = tNode.BridgeCounterpartNode.tTime; + EOM.StartPos = tNode.GSDSpline.GetSplineValue(EOM.StartTime); + EOM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.EndTime); + } + else if (EOM.bSingle && bIsBridge && tNode.BridgeCounterpartNode != null && tNode.bIsBridgeStart) + { + float tDist = (EOM.SingleOnlyBridgePercent * (tNode.BridgeCounterpartNode.tDist - tNode.tDist) + tNode.tDist); + EOM.SinglePosition = tNode.GSDSpline.TranslateDistBasedToParam(tDist); + EOM.StartPos = tNode.GSDSpline.GetSplineValue(EOM.SinglePosition); + EOM.EndPos = tNode.GSDSpline.GetSplineValue(EOM.SinglePosition); + } + continue; + } + } + + tNode.SetupSplinatedMeshes(); + tNode.SetupEdgeObjects(); + +#endif + } + + + #region "Splat maps" + public static byte[] MakeSplatMap(Terrain tTerrain, Color tBG, Color tFG, int tWidth, int tHeight, float SplatWidth, bool bSkipBridge, bool bSkipTunnel, string xRoadUID = "") + { + return MakeSplatMapDo(tTerrain, tBG, tFG, tWidth, tHeight, SplatWidth, bSkipBridge, bSkipTunnel, xRoadUID); + } + + + private static byte[] MakeSplatMapDo(Terrain tTerrain, Color tBG, Color tFG, int tWidth, int tHeight, float SplatWidth, bool bSkipBridge, bool bSkipTunnel, string xRoadUID) + { + Texture2D tTexture = new Texture2D(tWidth, tHeight, TextureFormat.RGB24, false); + + //Set background color: + Color[] tColorsBG = new Color[tWidth * tHeight]; + int tBGCount = tColorsBG.Length; + for (int i = 0; i < tBGCount; i++) + { + tColorsBG[i] = tBG; + } + tTexture.SetPixels(0, 0, tWidth, tHeight, tColorsBG); + tColorsBG = null; + + Object[] tRoads = null; + if (xRoadUID != "") + { + tRoads = new Object[1]; + Object[] bRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); + foreach (GSDRoad fRoad in bRoads) + { + if (string.CompareOrdinal(fRoad.UID, xRoadUID) == 0) + { + tRoads[0] = fRoad; + break; + } + } + } + else + { + tRoads = GameObject.FindObjectsOfType(typeof(GSDRoad)); + } + Vector3 tPos = tTerrain.transform.position; + Vector3 tSize = tTerrain.terrainData.size; + foreach (GSDRoad tRoad in tRoads) + { + GSDSplineC tSpline = tRoad.GSDSpline; + int tCount = tSpline.RoadDefKeysArray.Length; + + Vector3 POS1 = default(Vector3); + Vector3 POS2 = default(Vector3); + + Vector3 tVect = default(Vector3); + Vector3 tVect2 = default(Vector3); + Vector3 lVect1 = default(Vector3); + Vector3 lVect2 = default(Vector3); + Vector3 rVect1 = default(Vector3); + Vector3 rVect2 = default(Vector3); + + int x1, y1; + int[] tX = new int[4]; + int[] tY = new int[4]; + int MinX = -1; + int MaxX = -1; + int MinY = -1; + int MaxY = -1; + int xDiff = -1; + int yDiff = -1; + float p1 = 0f; + float p2 = 0f; + bool bXBad = false; + bool bYBad = false; + for (int i = 0; i < (tCount - 1); i++) + { + bXBad = false; + bYBad = false; + p1 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[i]); + p2 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[i + 1]); + + //Skip bridges: + if (bSkipBridge) + { + if (tSpline.IsInBridgeTerrain(p1)) + { + continue; + } + } + + //Skip tunnels: + if (bSkipTunnel) + { + if (tSpline.IsInTunnelTerrain(p1)) + { + continue; + } + } + + tSpline.GetSplineValue_Both(p1, out tVect, out POS1); + tSpline.GetSplineValue_Both(p2, out tVect2, out POS2); + lVect1 = (tVect + new Vector3(SplatWidth * -POS1.normalized.z, 0, SplatWidth * POS1.normalized.x)); + rVect1 = (tVect + new Vector3(SplatWidth * POS1.normalized.z, 0, SplatWidth * -POS1.normalized.x)); + lVect2 = (tVect2 + new Vector3(SplatWidth * -POS2.normalized.z, 0, SplatWidth * POS2.normalized.x)); + rVect2 = (tVect2 + new Vector3(SplatWidth * POS2.normalized.z, 0, SplatWidth * -POS2.normalized.x)); + + TranslateWorldVectToCustom(tWidth, tHeight, lVect1, ref tPos, ref tSize, out x1, out y1); + tX[0] = x1; + tY[0] = y1; + TranslateWorldVectToCustom(tWidth, tHeight, rVect1, ref tPos, ref tSize, out x1, out y1); + tX[1] = x1; + tY[1] = y1; + TranslateWorldVectToCustom(tWidth, tHeight, lVect2, ref tPos, ref tSize, out x1, out y1); + tX[2] = x1; + tY[2] = y1; + TranslateWorldVectToCustom(tWidth, tHeight, rVect2, ref tPos, ref tSize, out x1, out y1); + tX[3] = x1; + tY[3] = y1; + + MinX = Mathf.Min(tX); + MaxX = Mathf.Max(tX); + MinY = Mathf.Min(tY); + MaxY = Mathf.Max(tY); + + + if (MinX < 0) + { MinX = 0; bXBad = true; } + if (MaxX < 0) + { MaxX = 0; bXBad = true; } + if (MinY < 0) + { MinY = 0; bYBad = true; } + if (MaxY < 0) + { MaxY = 0; bYBad = true; } + + if (MinX > (tWidth - 1)) + { MinX = (tWidth - 1); bXBad = true; } + if (MaxX > (tWidth - 1)) + { MaxX = (tWidth - 1); bXBad = true; } + if (MinY > (tHeight - 1)) + { MinY = (tHeight - 1); bYBad = true; } + if (MaxY > (tHeight - 1)) + { MaxY = (tHeight - 1); bYBad = true; } + + if (bXBad && bYBad) + { continue; } + + xDiff = MaxX - MinX; + yDiff = MaxY - MinY; + + Color[] tColors = new Color[xDiff * yDiff]; + int cCount = tColors.Length; + for (int j = 0; j < cCount; j++) + { + tColors[j] = tFG; + } + + if (xDiff > 0 && yDiff > 0) + { + tTexture.SetPixels(MinX, MinY, xDiff, yDiff, tColors); + } + } + } + + tTexture.Apply(); + byte[] tBytes = tTexture.EncodeToPNG(); + Object.DestroyImmediate(tTexture); + return tBytes; + } + + + private static void TranslateWorldVectToCustom(int tWidth, int tHeight, Vector3 tVect, ref Vector3 tPos, ref Vector3 tSize, out int x1, out int y1) + { + //Get the normalized position of this game object relative to the terrain: + tVect -= tPos; + + tVect.x = tVect.x / tSize.x; + tVect.z = tVect.z / tSize.z; + + //Get the position of the terrain heightmap where this game object is: + x1 = (int) (tVect.x * tWidth); + y1 = (int) (tVect.z * tHeight); + } + #endregion + + + #region "Wizard objects" + public class WizardObject + { + public Texture2D Thumb; + public string ThumbString; + public string DisplayName; + public string Desc; + public bool bIsDefault; + public bool bIsBridge; + public string FileName; + public string FullPath; + public int sortID = 0; + + + public string ConvertToString() + { + WizardObjectLibrary WOL = new WizardObjectLibrary(); + WOL.LoadFrom(this); + return GSDRootUtil.GetString(WOL); + } + + + public void LoadDataFromWOL(WizardObjectLibrary WOL) + { + ThumbString = WOL.ThumbString; + DisplayName = WOL.DisplayName; + Desc = WOL.Desc; + bIsDefault = WOL.bIsDefault; + FileName = WOL.FileName; + bIsBridge = WOL.bIsBridge; + } + + + public static WizardObject LoadFromLibrary(string tPath) + { +#if UNITY_WEBPLAYER + return null; +#else + string tData = System.IO.File.ReadAllText(tPath); + string[] tSep = new string[2]; + tSep[0] = FileSepString; + tSep[1] = FileSepStringCRLF; + string[] tSplit = tData.Split(tSep, System.StringSplitOptions.RemoveEmptyEntries); + int tSplitCount = tSplit.Length; + WizardObjectLibrary WOL = null; + for (int i = 0; i < tSplitCount; i++) + { + WOL = WizardObject.WizardObjectLibrary.WOLFromData(tSplit[i]); + if (WOL != null) + { + WizardObject WO = new WizardObject(); + WO.LoadDataFromWOL(WOL); + return WO; + } + } + return null; +#endif + } + + + [System.Serializable] + public class WizardObjectLibrary + { + public string ThumbString; + public string DisplayName; + public string Desc; + public bool bIsDefault; + public bool bIsBridge; + public string FileName; + + + public void LoadFrom(WizardObject WO) + { + ThumbString = WO.ThumbString; + DisplayName = WO.DisplayName; + Desc = WO.Desc; + bIsDefault = WO.bIsDefault; + FileName = WO.FileName; + bIsBridge = WO.bIsBridge; + } + + + public static WizardObjectLibrary WOLFromData(string tData) + { + try + { + WizardObjectLibrary WOL = (WizardObjectLibrary) GSDRootUtil.LoadData(ref tData); + return WOL; + } + catch + { + return null; + } + } + } + } + #endregion + } + + + public static class GSDIntersectionObjects + { + static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + + + public static void CleanupIntersectionObjects(GameObject MasterGameObj) + { + int mCount = MasterGameObj.transform.childCount; + if (mCount == 0) + { + return; + } + List tObjtoDelete = new List(); + for (int index = 0; index < mCount; index++) + { + if (MasterGameObj.transform.GetChild(index).name.ToLower().Contains("stopsign")) + { + tObjtoDelete.Add(MasterGameObj.transform.GetChild(index).gameObject); + } + if (MasterGameObj.transform.GetChild(index).name.ToLower().Contains("trafficlight")) + { + tObjtoDelete.Add(MasterGameObj.transform.GetChild(index).gameObject); + } + } + for (int index = (tObjtoDelete.Count - 1); index >= 0; index--) + { + Object.DestroyImmediate(tObjtoDelete[index]); + } + } + + + #region "Stop Sign All Way" + public static void CreateStopSignsAllWay(GameObject MasterGameObj, bool bIsRB = true) + { + CreateStopSignsAllWay_Do(ref MasterGameObj, bIsRB); + } + + + private static void T_FixSigns(GameObject tObj) + { + Rigidbody rigidbody = tObj.GetComponent(); + rigidbody.useGravity = false; + rigidbody.isKinematic = true; + } + + + private static void CreateStopSignsAllWay_Do(ref GameObject MasterGameObj, bool bIsRB) + { + Object prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab", typeof(GameObject)); + + GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); + GSDSplineC tSpline = GSDRI.Node1.GSDSpline; + + GameObject tObj = null; + // Vector3 xDir = default(Vector3); + Vector3 tDir = default(Vector3); + // float RoadWidth = tSpline.tRoad.RoadWidth(); + // float LaneWidth = tSpline.tRoad.opt_LaneWidth; + float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; + + //Cleanup: + CleanupIntersectionObjects(MasterGameObj); + + float Mass = 100f; + + //Get four points: + float DistFromCorner = (ShoulderWidth * 0.45f); + Vector3 tPosRR = default(Vector3); + Vector3 tPosRL = default(Vector3); + Vector3 tPosLR = default(Vector3); + Vector3 tPosLL = default(Vector3); + GetFourPoints(GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); + + //RR: + tSpline = GSDRI.Node1.GSDSpline; + tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; + // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; + tDir = StopSign_GetRot_RR(GSDRI, tSpline); + tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); + if (bIsRB) + { + Rigidbody RB = tObj.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = new Vector3(0f, -10f, 0f); + } + tObj.transform.parent = MasterGameObj.transform; + tObj.transform.position = tPosRR; + tObj.name = "StopSignRR"; + T_FixSigns(tObj); + if (GSDRI.IgnoreCorner == 0) + { + Object.DestroyImmediate(tObj); + } + + //LL: + tSpline = GSDRI.Node1.GSDSpline; + tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; + // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; + tDir = StopSign_GetRot_LL(GSDRI, tSpline); + tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); + if (bIsRB) + { + Rigidbody RB = tObj.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = new Vector3(0f, -10f, 0f); + } + tObj.transform.parent = MasterGameObj.transform; + tObj.transform.position = tPosLL; + tObj.name = "StopSignLL"; + T_FixSigns(tObj); + if (GSDRI.IgnoreCorner == 2) + { + Object.DestroyImmediate(tObj); + } + + //RL: + tSpline = GSDRI.Node2.GSDSpline; + tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; + // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; + tDir = StopSign_GetRot_RL(GSDRI, tSpline); + tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); + if (bIsRB) + { + Rigidbody RB = tObj.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = new Vector3(0f, -10f, 0f); + } + tObj.transform.parent = MasterGameObj.transform; + tObj.transform.position = tPosRL; + tObj.name = "StopSignRL"; + T_FixSigns(tObj); + if (GSDRI.IgnoreCorner == 1) + { + Object.DestroyImmediate(tObj); + } + + //LR: + tSpline = GSDRI.Node2.GSDSpline; + tObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; + // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; + tDir = StopSign_GetRot_LR(GSDRI, tSpline); + tObj.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(0f, 180f, 0f); + if (bIsRB) + { + Rigidbody RB = tObj.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = new Vector3(0f, -10f, 0f); + } + tObj.transform.parent = MasterGameObj.transform; + tObj.transform.position = tPosLR; + tObj.name = "StopSignLR"; + T_FixSigns(tObj); + if (GSDRI.IgnoreCorner == 3) + { + Object.DestroyImmediate(tObj); + } + } + + + private static Vector3 StopSign_GetRot_RR(GSDRoadIntersection GSDRI, GSDSplineC tSpline) + { + float tDist = ((Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRR))) / tSpline.distance; + float p = Mathf.Clamp(GSDRI.Node1.tTime - tDist, 0f, 1f); + Vector3 POS = tSpline.GetSplineValue(p, true); + return (POS * -1); + } + + + private static Vector3 StopSign_GetRot_LL(GSDRoadIntersection GSDRI, GSDSplineC tSpline) + { + float tDist = ((Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRR))) / tSpline.distance; + float p = Mathf.Clamp(GSDRI.Node1.tTime + tDist, 0f, 1f); + Vector3 POS = tSpline.GetSplineValue(p, true); + return POS; + } + + + private static Vector3 StopSign_GetRot_RL(GSDRoadIntersection GSDRI, GSDSplineC tSpline) + { + float tDist = ((Vector3.Distance(GSDRI.CornerLL, GSDRI.CornerRL) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRL))) / tSpline.distance; + float p = -1f; + if (GSDRI.bFlipped) + { + p = Mathf.Clamp(GSDRI.Node2.tTime - tDist, 0f, 1f); + } + else + { + p = Mathf.Clamp(GSDRI.Node2.tTime + tDist, 0f, 1f); + } + Vector3 POS = tSpline.GetSplineValue(p, true); + //POS = Vector3.Cross(POS,Vector3.up); + if (GSDRI.bFlipped) + { + return (POS * -1); + } + else + { + return POS; + } + } + + + private static Vector3 StopSign_GetRot_LR(GSDRoadIntersection GSDRI, GSDSplineC tSpline) + { + float tDist = ((Vector3.Distance(GSDRI.CornerRR, GSDRI.CornerLR) / 2f) + (0.025f * Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRL))) / tSpline.distance; + float p = -1f; + if (GSDRI.bFlipped) + { + p = Mathf.Clamp(GSDRI.Node2.tTime + tDist, 0f, 1f); + } + else + { + p = Mathf.Clamp(GSDRI.Node2.tTime - tDist, 0f, 1f); + } + Vector3 POS = tSpline.GetSplineValue(p, true); + //POS = Vector3.Cross(POS,Vector3.up); + if (GSDRI.bFlipped) + { + return POS; + } + else + { + return (POS * -1); + } + } + #endregion + + + #region "Traffic light bases" + public static void CreateTrafficLightBases(GameObject MasterGameObj, bool bIsTrafficLight1 = true) + { + CreateTrafficLightBases_Do(ref MasterGameObj, bIsTrafficLight1); + } + + + private static void CreateTrafficLightBases_Do(ref GameObject MasterGameObj, bool bIsTrafficLight1) + { + GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); + GSDSplineC tSpline = GSDRI.Node1.GSDSpline; + bool bIsRB = true; + + // float RoadWidth = tSpline.tRoad.RoadWidth(); + float LaneWidth = tSpline.tRoad.opt_LaneWidth; + float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; + + int Lanes = tSpline.tRoad.opt_Lanes; + int LanesHalf = Lanes / 2; + float LanesForInter = -1; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + LanesForInter = LanesHalf + 1f; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + LanesForInter = LanesHalf + 1f; + } + else + { + LanesForInter = LanesHalf - 1 + 1f; + } + float DistFromCorner = (ShoulderWidth * 0.45f); + float TLDistance = (LanesForInter * LaneWidth) + DistFromCorner; + + GameObject tObjRR = null; + GameObject tObjRL = null; + GameObject tObjLL = null; + GameObject tObjLR = null; + // Vector3 xDir = default(Vector3); + Vector3 tDir = default(Vector3); + float Mass = 12500f; + Vector3 COM = new Vector3(0f, 0f, 4f); + Vector3 zeroVect = new Vector3(0f, 0f, 0f); + Vector3 StartVec = default(Vector3); + Vector3 EndVec = default(Vector3); + // bool bContains = false; + // MeshFilter MF = null; + // Vector3[] tVerts = null; + Rigidbody RB = null; + + //Get four points: + Vector3 tPosRR = default(Vector3); + Vector3 tPosRL = default(Vector3); + Vector3 tPosLR = default(Vector3); + Vector3 tPosLL = default(Vector3); + GetFourPoints(GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); + + //Cleanup: + CleanupIntersectionObjects(MasterGameObj); + + float[] tempDistances = new float[4]; + tempDistances[0] = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerLL); + tempDistances[1] = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR); + tempDistances[2] = Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL); + tempDistances[3] = Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerRR); + float MaxDistanceStart = Mathf.Max(tempDistances); + bool OrigPoleAlignment = GSDRI.bRegularPoleAlignment; + + //Node1: + //RL: + tObjRL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjRL.transform.parent = MasterGameObj.transform; + StartVec = tPosRL; + EndVec = (tDir.normalized * TLDistance) + StartVec; + if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) + { //Convert to regular alignment if necessary + tObjRL.transform.parent = null; + tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner, true); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjRL.transform.parent = MasterGameObj.transform; + } + else + { + GSDRI.bRegularPoleAlignment = true; + if (tObjRL != null) + { + Object.DestroyImmediate(tObjRL); + } + tObjRL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerRL - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_RL(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjRL.transform.parent = MasterGameObj.transform; + StartVec = tPosRL; + EndVec = (tDir.normalized * TLDistance) + StartVec; + GSDRI.bRegularPoleAlignment = OrigPoleAlignment; + } + if (bIsRB) + { + RB = tObjRL.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = COM; + tObjRL.AddComponent(); + } + tObjRL.transform.position = tPosRL; + tObjRL.transform.name = "TrafficLightRL"; + //LR: + tObjLR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjLR.transform.parent = MasterGameObj.transform; + StartVec = tPosLR; + EndVec = (tDir.normalized * TLDistance) + StartVec; + if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) + { //Convert to regular alignment if necessary + tObjLR.transform.parent = null; + tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner, true); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjLR.transform.parent = MasterGameObj.transform; + } + else + { + GSDRI.bRegularPoleAlignment = true; + if (tObjLR != null) + { + Object.DestroyImmediate(tObjLR); + } + tObjLR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerLR - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_LR(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjLR.transform.parent = MasterGameObj.transform; + StartVec = tPosLR; + EndVec = (tDir.normalized * TLDistance) + StartVec; + GSDRI.bRegularPoleAlignment = OrigPoleAlignment; + } + if (bIsRB) + { + RB = tObjLR.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = COM; + tObjLR.AddComponent(); + } + tObjLR.transform.position = tPosLR; + tObjLR.transform.name = "TrafficLightLR"; + //Node2: + //RR: + tObjRR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjRR.transform.parent = MasterGameObj.transform; + StartVec = tPosRR; + EndVec = (tDir.normalized * TLDistance) + StartVec; + if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) + { //Convert to regular alignment if necessary + tObjRR.transform.parent = null; + tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner, true); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, 0f, 0f); + tObjRR.transform.parent = MasterGameObj.transform; + } + else + { + GSDRI.bRegularPoleAlignment = true; + if (tObjRR != null) + { Object.DestroyImmediate(tObjRR); } + tObjRR = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerRR - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_RR(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjRR.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjRR.transform.parent = MasterGameObj.transform; + StartVec = tPosRR; + EndVec = (tDir.normalized * TLDistance) + StartVec; + GSDRI.bRegularPoleAlignment = OrigPoleAlignment; + } + if (bIsRB) + { + RB = tObjRR.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = COM; + tObjRR.AddComponent(); + } + tObjRR.transform.position = tPosRR; + tObjRR.transform.name = "TrafficLightRR"; + + //LL: + tObjLL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjLL.transform.parent = MasterGameObj.transform; + StartVec = tPosLL; + EndVec = (tDir.normalized * TLDistance) + StartVec; + if (!GSDRI.bRegularPoleAlignment && GSDRI.ContainsLine(StartVec, EndVec)) + { //Convert to regular alignment if necessary + tObjLL.transform.parent = null; + tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner, true); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, 0f, 0f); + tObjLL.transform.parent = MasterGameObj.transform; + } + else + { + GSDRI.bRegularPoleAlignment = true; + if (tObjLL != null) + { + Object.DestroyImmediate(tObjLL); + } + tObjLL = CreateTrafficLight(TLDistance, true, true, MaxDistanceStart, GSDRI.bTrafficPoleStreetLight, tSpline.tRoad.GSDRS.opt_bSaveMeshes); + // xDir = (GSDRI.CornerLL - GSDRI.transform.position).normalized; + tDir = TrafficLightBase_GetRot_LL(GSDRI, tSpline, DistFromCorner); + if (tDir == zeroVect) + { + tDir = new Vector3(0f, 0.0001f, 0f); + } + tObjLL.transform.rotation = Quaternion.LookRotation(tDir) * Quaternion.Euler(-90f, -180f, 0f); + tObjLL.transform.parent = MasterGameObj.transform; + StartVec = tPosLL; + EndVec = (tDir.normalized * TLDistance) + StartVec; + GSDRI.bRegularPoleAlignment = OrigPoleAlignment; + } + if (bIsRB) + { + RB = tObjLL.AddComponent(); + RB.mass = Mass; + RB.centerOfMass = COM; + tObjLL.AddComponent(); + } + tObjLL.transform.position = tPosLL; + tObjLL.transform.name = "TrafficLightLL"; + + //Create the actual lights: + CreateTrafficLightMains(MasterGameObj, tObjRR, tObjRL, tObjLL, tObjLR); + } + + + private static bool CreateTrafficLightBase_IsInIntersection(GSDRoadIntersection GSDRI, ref Vector3 StartVec, ref Vector3 EndVec) + { + return GSDRI.ContainsLine(StartVec, EndVec); + } + + + private static GameObject CreateTrafficLight(float tDistance, bool bIsTrafficLight1, bool bOptionalCollider, float xDistance, bool bLight, bool bSaveAsset) + { + GameObject tObj = null; + string tTrafficLightNumber = "1"; + if (!bIsTrafficLight1) + { + tTrafficLightNumber = "2"; + } + + bool bDoCustom = false; + xDistance = Mathf.Ceil(xDistance); //Round up to nearest whole F + tDistance = Mathf.Ceil(tDistance); //Round up to nearest whole F + // string assetName = "GSDInterTLB" + tTrafficLightNumber + "_" + tDistance.ToString("F0") + "_" + xDistance.ToString("F0") + ".prefab"; + string assetNameAsset = "GSDInterTLB" + tTrafficLightNumber + "_" + tDistance.ToString("F0") + "_" + xDistance.ToString("F0") + ".asset"; + string BackupFBX = "GSDInterTLB" + tTrafficLightNumber + ".FBX"; + float tMod = tDistance / 5f; + float hMod = (tDistance / 10f) * 0.7f; + float xMod = ((xDistance / 20f) + 2f) * 0.3334f; + xMod = Mathf.Clamp(xMod, 1f, 20f); + tMod = Mathf.Clamp(tMod, 1f, 20f); + hMod = Mathf.Clamp(hMod, 1f, 20f); + + bool bXMod = false; + if (!IsApproximately(xMod, 1f, 0.0001f)) + { + bXMod = true; + } + + Mesh xMesh = (Mesh) UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + assetNameAsset, typeof(Mesh)); + if (xMesh == null) + { + xMesh = (Mesh) UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + BackupFBX, typeof(Mesh)); + bDoCustom = true; + } + + tObj = new GameObject("TempTrafficLight"); + MeshFilter MF = tObj.GetComponent(); + if (MF == null) + { + MF = tObj.AddComponent(); + } + MeshRenderer MR = tObj.GetComponent(); + if (MR == null) + { + MR = tObj.AddComponent(); + } + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/Signs/GSDInterTLB" + tTrafficLightNumber + ".mat", MR); + + if (!bDoCustom) + { + MF.sharedMesh = xMesh; + } + + float tempMaxHeight = 7.6f * hMod; + float xValue = tempMaxHeight - 7.6f; + if (bDoCustom) + { + Mesh tMesh = new Mesh(); + tMesh.vertices = xMesh.vertices; + tMesh.triangles = xMesh.triangles; + tMesh.uv = xMesh.uv; + tMesh.normals = xMesh.normals; + tMesh.tangents = xMesh.tangents; + MF.sharedMesh = tMesh; + Vector3[] tVerts = tMesh.vertices; + + xValue = (xMod * 6f) - 6f; + if ((xMod * 6f) > (tempMaxHeight - 1f)) + { + xValue = (tempMaxHeight - 1f) - 6f; + } + + // float tValue = 0f; + // float hValue = 0f; + bool bIgnoreMe = false; + + + int mCount = tVerts.Length; + Vector2[] uv = tMesh.uv; + // List tUVInts = new List(); + for (int index = 0; index < mCount; index++) + { + bIgnoreMe = false; + if (IsApproximately(tVerts[index].y, 5f, 0.01f)) + { + tVerts[index].y = tDistance; + if (uv[index].y > 3.5f) + { + uv[index].y *= tMod; + } + bIgnoreMe = true; + } + if (!bIgnoreMe && tVerts[index].z > 7.5f) + { + tVerts[index].z *= hMod; + if (uv[index].y > 3.8f) + { + uv[index].y *= hMod; + } + } + + if (bXMod && tVerts[index].z > 4.8f && tVerts[index].z < 6.2f) + { + tVerts[index].z += xValue; + } + } + tMesh.vertices = tVerts; + tMesh.uv = uv; + tMesh.RecalculateNormals(); + tMesh.RecalculateBounds(); + + //Save: + if (bSaveAsset) + { + UnityEditor.AssetDatabase.CreateAsset(tMesh, GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/TrafficLightBases/" + assetNameAsset); + } + } + + BoxCollider BC = tObj.AddComponent(); + float MaxHeight = MF.sharedMesh.vertices[447].z; + BC.size = new Vector3(0.35f, 0.35f, MaxHeight); + BC.center = new Vector3(0f, 0f, (MaxHeight / 2f)); + + if (bOptionalCollider) + { + float MaxWidth = MF.sharedMesh.vertices[497].y; + GameObject tObjCollider = new GameObject("col2"); + BC = tObjCollider.AddComponent(); + BC.size = new Vector3(0.175f, MaxWidth, 0.175f); + BC.center = new Vector3(0f, MaxWidth / 2f, 5.808f); + tObjCollider.transform.parent = tObj.transform; + } + + if (bLight) + { + GameObject yObj = (GameObject) UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDStreetLight_TrafficLight.prefab", typeof(GameObject)); + GameObject kObj = (GameObject) GameObject.Instantiate(yObj); + kObj.transform.position = tObj.transform.position; + kObj.transform.position += new Vector3(0f, 0f, MaxHeight - 7.6f); + kObj.transform.parent = tObj.transform; + kObj.transform.rotation = Quaternion.identity; + // kObj.name = "StreetLight"; + } + + + //Bounds calcs: + MeshFilter[] tMeshes = tObj.GetComponents(); + for (int index = 0; index < tMeshes.Length; index++) + { + tMeshes[index].sharedMesh.RecalculateBounds(); + } + + return tObj; + } + + + private static Vector3 TrafficLightBase_GetRot_RL(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) + { + Vector3 POS = default(Vector3); + if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) + { + // float tDist = ((Vector3.Distance(GSDRI.CornerRR,GSDRI.CornerRL) / 2f) + DistFromCorner) / tSpline.distance;; + float p = Mathf.Clamp(GSDRI.Node1.tTime, 0f, 1f); + POS = tSpline.GetSplineValue(p, true); + POS = Vector3.Cross(POS, Vector3.up); + return POS; + } + else + { + POS = GSDRI.CornerRL - GSDRI.CornerLL; + return POS * -1; + } + } + + + private static Vector3 TrafficLightBase_GetRot_LR(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) + { + Vector3 POS = default(Vector3); + if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) + { + // float tDist = ((Vector3.Distance(GSDRI.CornerLR,GSDRI.CornerLL) / 2f) + DistFromCorner) / tSpline.distance;; + float p = Mathf.Clamp(GSDRI.Node1.tTime, 0f, 1f); + POS = tSpline.GetSplineValue(p, true); + POS = Vector3.Cross(POS, Vector3.up); + return POS * -1; + } + else + { + POS = GSDRI.CornerRR - GSDRI.CornerLR; + return POS; + } + } + + + private static Vector3 TrafficLightBase_GetRot_RR(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) + { + Vector3 POS = default(Vector3); + if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) + { + // float tDist = ((Vector3.Distance(GSDRI.CornerRR,GSDRI.CornerLR) / 2f) + DistFromCorner) / tSpline.distance;; + float p = Mathf.Clamp(GSDRI.Node2.tTime, 0f, 1f); + POS = tSpline.GetSplineValue(p, true); + POS = Vector3.Cross(POS, Vector3.up); + if (GSDRI.bFlipped) + { + POS = POS * -1; + } + } + else + { + POS = GSDRI.CornerLL - GSDRI.CornerLR; + } + return POS; + } + + + private static Vector3 TrafficLightBase_GetRot_LL(GSDRoadIntersection GSDRI, GSDSplineC tSpline, float DistFromCorner, bool bOverrideRegular = false) + { + Vector3 POS = default(Vector3); + if (!GSDRI.bRegularPoleAlignment && !bOverrideRegular) + { + // float tDist = ((Vector3.Distance(GSDRI.CornerLL,GSDRI.CornerRL) / 2f) + DistFromCorner) / tSpline.distance;; + float p = Mathf.Clamp(GSDRI.Node2.tTime, 0f, 1f); + POS = tSpline.GetSplineValue(p, true); + POS = Vector3.Cross(POS, Vector3.up); + if (GSDRI.bFlipped) + { + POS = POS * -1; + } + } + else + { + POS = GSDRI.CornerRL - GSDRI.CornerRR; + } + return POS * -1; + } + #endregion + + + #region "Traffic light mains" + private static void CreateTrafficLightMains(GameObject MasterGameObj, GameObject tRR, GameObject tRL, GameObject tLL, GameObject tLR) + { + GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); + GSDSplineC tSpline = GSDRI.Node1.GSDSpline; + + float tDist = (Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR) / 2f) / tSpline.distance; + Vector3 tan = tSpline.GetSplineValue(GSDRI.Node1.tTime + tDist, true); + ProcessPole(MasterGameObj, tRL, tan * -1, 1, Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerRR)); + tDist = (Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL) / 2f) / tSpline.distance; + tan = tSpline.GetSplineValue(GSDRI.Node1.tTime - tDist, true); + ProcessPole(MasterGameObj, tLR, tan, 3, Vector3.Distance(GSDRI.CornerLR, GSDRI.CornerLL)); + + + float InterDist = Vector3.Distance(GSDRI.CornerRL, GSDRI.CornerLL); + tDist = (InterDist / 2f) / tSpline.distance; + tan = tSpline.GetSplineValue(GSDRI.Node1.tTime + tDist, true); + + float fTime1 = GSDRI.Node2.tTime + tDist; + float fTime2neg = GSDRI.Node2.tTime - tDist; + + tSpline = GSDRI.Node2.GSDSpline; + if (GSDRI.bFlipped) + { + tan = tSpline.GetSplineValue(fTime1, true); + ProcessPole(MasterGameObj, tRR, tan, 0, InterDist); + tan = tSpline.GetSplineValue(fTime2neg, true); + ProcessPole(MasterGameObj, tLL, tan * -1, 2, InterDist); + } + else + { + tan = tSpline.GetSplineValue(fTime2neg, true); + ProcessPole(MasterGameObj, tRR, tan * -1, 0, InterDist); + tan = tSpline.GetSplineValue(fTime1, true); + ProcessPole(MasterGameObj, tLL, tan, 2, InterDist); + } + + if (GSDRI.IgnoreCorner == 0) + { + if (tRR != null) + { + Object.DestroyImmediate(tRR); + } + } + else if (GSDRI.IgnoreCorner == 1) + { + if (tRL != null) + { + Object.DestroyImmediate(tRL); + } + } + else if (GSDRI.IgnoreCorner == 2) + { + if (tLL != null) + { + Object.DestroyImmediate(tLL); + } + } + else if (GSDRI.IgnoreCorner == 3) + { + if (tLR != null) + { + Object.DestroyImmediate(tLR); + } + } + } + + + private static void AdjustLightPrefab(GameObject tLight) + { + foreach (Light light in tLight.GetComponentsInChildren()) + { + if (light.type == LightType.Point) + { + light.flare = UnityEditor.AssetDatabase.LoadAssetAtPath(GSDRoadUtilityEditor.GetBasePath() + "/Flares/GSDSodiumBulb.flare"); + } + } + } + + + private static void ProcessPole(GameObject MasterGameObj, GameObject tObj, Vector3 tan, int tCorner, float InterDist) + { + GSDRoadIntersection GSDRI = MasterGameObj.GetComponent(); + GSDSplineC tSpline = GSDRI.Node1.GSDSpline; + // bool bIsRB = true; + + // float RoadWidth = tSpline.tRoad.RoadWidth(); + float LaneWidth = tSpline.tRoad.opt_LaneWidth; + float ShoulderWidth = tSpline.tRoad.opt_ShoulderWidth; + + int Lanes = tSpline.tRoad.opt_Lanes; + int LanesHalf = Lanes / 2; + float LanesForInter = -1; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + LanesForInter = LanesHalf + 1f; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + LanesForInter = LanesHalf + 1f; + } + else + { + LanesForInter = LanesHalf; + } + float DistFromCorner = (ShoulderWidth * 0.35f); + float TLDistance = (LanesForInter * LaneWidth) + DistFromCorner; + + MeshFilter MF = tObj.GetComponent(); + Mesh tMesh = MF.sharedMesh; + Vector3[] tVerts = tMesh.vertices; + Vector3 StartVec = tVerts[520]; + Vector3 EndVec = tVerts[521]; + StartVec = (((EndVec - StartVec) * (DistFromCorner / TLDistance)) + StartVec); + Vector3 tempR_Start = tVerts[399]; + Vector3 tempR_End = tVerts[396]; + Vector3 tLanePosR = ((tempR_End - tempR_Start) * 0.95f) + tempR_Start; + tLanePosR.z -= 1f; + + float SmallerDist = Vector3.Distance(StartVec, EndVec); + + //StartVec = Corner + //2.5m = lane + //7.5m = lane + //12.5m = lane + Vector3[] tLanePos = new Vector3[LanesHalf]; + for (int index = 0; index < LanesHalf; index++) + { + tLanePos[index] = (((EndVec - StartVec) * (((LaneWidth * 0.5f) + (index * LaneWidth)) / SmallerDist)) + StartVec); + } + Vector3 tLanePosL = default(Vector3); + Vector3 tLanePosL_Sign = default(Vector3); + + if (GSDRI.bLeftTurnYieldOnGreen) + { + tLanePosL = ((EndVec - StartVec) * ((SmallerDist - 1.8f) / SmallerDist)) + StartVec; + tLanePosL_Sign = ((EndVec - StartVec) * ((SmallerDist - 3.2f) / SmallerDist)) + StartVec; + } + else + { + tLanePosL = ((EndVec - StartVec) * ((SmallerDist - 2.5f) / SmallerDist)) + StartVec; + } + + Vector3 tPos1 = default(Vector3); + if (tCorner == 0) + { //RR + tPos1 = GSDRI.CornerLR; + } + else if (tCorner == 1) + { //RL + tPos1 = GSDRI.CornerRR; + } + else if (tCorner == 2) + { //LL + tPos1 = GSDRI.CornerRL; + } + else if (tCorner == 3) + { //LR + tPos1 = GSDRI.CornerLL; + } + + int mCount = tLanePos.Length; + float mDistance = -50000f; + float tDistance = 0f; + for (int index = 0; index < mCount; index++) + { + tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePos[index]), tPos1); + if (tDistance > mDistance) + { + mDistance = tDistance; + } + } + tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePosL), tPos1); + if (tDistance > mDistance) + { + mDistance = tDistance; + } + tDistance = Vector3.Distance(tObj.transform.TransformPoint(tLanePosR), tPos1); + if (tDistance > mDistance) + { + mDistance = tDistance; + } + + float tScaleSense = ((200f - GSDRI.ScalingSense) / 200f) * 200f; + tScaleSense = Mathf.Clamp(tScaleSense * 0.1f, 0f, 20f); + float ScaleMod = ((mDistance / 17f) + tScaleSense) * (1f / (tScaleSense + 1f)); + if (IsApproximately(tScaleSense, 20f, 0.05f)) + { + ScaleMod = 1f; + } + ScaleMod = Mathf.Clamp(ScaleMod, 1f, 1.5f); + Vector3 tScale = new Vector3(ScaleMod, ScaleMod, ScaleMod); + bool bScale = true; + if (IsApproximately(ScaleMod, 1f, 0.001f)) + { + bScale = false; + } + + //Debug.Log (mDistance + " " + ScaleMod + " " + tScaleSense); + + GameObject tRight = null; + GameObject tLeft = null; + GameObject tLeft_Sign = null; + Object prefab = null; + + MeshRenderer MR_Left = null; + MeshRenderer MR_Right = null; + MeshRenderer[] MR_Mains = new MeshRenderer[LanesHalf]; + int cCount = -1; + if (GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (GSDRI.bLeftTurnYieldOnGreen) + { + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightLeftYield.prefab", typeof(GameObject)); + } + else + { + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightLeft.prefab", typeof(GameObject)); + } + tLeft = (GameObject) GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); + AdjustLightPrefab(tLeft); + tLeft.transform.position = tObj.transform.TransformPoint(tLanePosL); + tLeft.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); + tLeft.transform.parent = tObj.transform; + tLeft.transform.name = "LightLeft"; + + cCount = tLeft.transform.childCount; + for (int index = 0; index < cCount; index++) + { + if (tLeft.transform.GetChild(index).name.ToLower() == "lights") + { + MR_Left = tLeft.transform.GetChild(index).GetComponent(); + } + } + + if (bScale) + { tLeft.transform.localScale = tScale; } + + if (GSDRI.bLeftTurnYieldOnGreen) + { + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDSignYieldOnGreen.prefab", typeof(GameObject)); + tLeft_Sign = (GameObject) GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); + tLeft_Sign.transform.position = tObj.transform.TransformPoint(tLanePosL_Sign); + tLeft_Sign.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(-90f, 90f, 0f); + tLeft_Sign.transform.parent = tObj.transform; + tLeft_Sign.transform.name = "SignYieldOnGreen"; + if (bScale) + { tLeft_Sign.transform.localScale = tScale; } + } + } + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightRight.prefab", typeof(GameObject)); + tRight = (GameObject) GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); + AdjustLightPrefab(tRight); + tRight.transform.position = tObj.transform.TransformPoint(tLanePosR); + tRight.transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); + tRight.transform.parent = tObj.transform; + tRight.transform.name = "LightRight"; + if (bScale) + { tRight.transform.localScale = tScale; } + + cCount = tRight.transform.childCount; + for (int index = 0; index < cCount; index++) + { + if (tRight.transform.GetChild(index).name.ToLower() == "lights") + { + MR_Right = tRight.transform.GetChild(index).GetComponent(); + } + } + } + GameObject[] tLanes = new GameObject[LanesHalf]; + for (int index = 0; index < LanesHalf; index++) + { + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/RoadObj/Signs/GSDTrafficLightMain.prefab", typeof(GameObject)); + tLanes[index] = (GameObject) GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); + AdjustLightPrefab(tLanes[index]); + tLanes[index].transform.position = tObj.transform.TransformPoint(tLanePos[index]); + tLanes[index].transform.rotation = Quaternion.LookRotation(tan) * Quaternion.Euler(0f, 90f, 0f); + tLanes[index].transform.parent = tObj.transform; + tLanes[index].transform.name = "Light" + index.ToString(); + if (bScale) + { + tLanes[index].transform.localScale = tScale; + } + + cCount = tLanes[index].transform.childCount; + for (int j = 0; j < cCount; j++) + { + if (tLanes[index].transform.GetChild(j).name.ToLower() == "lights") + { + MR_Mains[index] = tLanes[index].transform.GetChild(j).GetComponent(); + } + } + } + + GSDTrafficLightController LM = new GSDTrafficLightController(ref tLeft, ref tRight, ref tLanes, ref MR_Left, ref MR_Right, ref MR_Mains); + if (tCorner == 0) + { + GSDRI.LightsRR = null; + GSDRI.LightsRR = LM; + } + else if (tCorner == 1) + { + GSDRI.LightsRL = null; + GSDRI.LightsRL = LM; + } + else if (tCorner == 2) + { + GSDRI.LightsLL = null; + GSDRI.LightsLL = LM; + } + else if (tCorner == 3) + { + GSDRI.LightsLR = null; + GSDRI.LightsLR = LM; + } + } + #endregion + + + public static void GetFourPoints(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR, float DistFromCorner) + { + GetFourPoints_Do(ref GSDRI, out tPosRR, out tPosRL, out tPosLL, out tPosLR, DistFromCorner); + } + + + private static void GetFourPoints_Do(ref GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR, float DistFromCorner) + { + //Get four points: + float tPos1 = 0f; + float tPos2 = 0f; + Vector3 tTan1 = default(Vector3); + Vector3 tTan2 = default(Vector3); + float Node1Width = -1f; + float Node2Width = -1f; + Vector3 tVectRR = GSDRI.CornerRR; + Vector3 tVectRL = GSDRI.CornerRL; + Vector3 tVectLR = GSDRI.CornerLR; + Vector3 tVectLL = GSDRI.CornerLL; + Vector3 tDir = default(Vector3); + float ShoulderWidth1 = GSDRI.Node1.GSDSpline.tRoad.opt_ShoulderWidth; + float ShoulderWidth2 = GSDRI.Node2.GSDSpline.tRoad.opt_ShoulderWidth; + + if (!GSDRI.bFlipped) + { + //RR: + Node1Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime - Node1Width; + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; + tPos2 = GSDRI.Node2.tTime + Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosRR = tVectRR + (tDir * DistFromCorner); + //RL: + Node1Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime + Node1Width; + if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + tPos1 = GSDRI.Node1.tTime; + } + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); + tPos2 = GSDRI.Node2.tTime + Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosRL = tVectRL + (tDir * DistFromCorner); + //LL: + Node1Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime + Node1Width; + if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + tPos1 = GSDRI.Node1.tTime; + } + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); + tPos2 = GSDRI.Node2.tTime - Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosLL = tVectLL + (tDir * DistFromCorner); + //LR: + Node1Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime - Node1Width; + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; + tPos2 = GSDRI.Node2.tTime - Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosLR = tVectLR + (tDir * DistFromCorner); + } + else + { + //RR: + Node1Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerRR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime - Node1Width; + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; + tPos2 = GSDRI.Node2.tTime - Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosRR = tVectRR + (tDir * DistFromCorner); + //RL: + Node1Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerRL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime + Node1Width; + if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + tPos1 = GSDRI.Node1.tTime; + } + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); + tPos2 = GSDRI.Node2.tTime - Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true) * -1f; + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosRL = tVectRL + (tDir * DistFromCorner); + //LL: + Node1Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerLL, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime + Node1Width; + if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + tPos1 = GSDRI.Node1.tTime; + } + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true); + tPos2 = GSDRI.Node2.tTime + Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosLL = tVectLL + (tDir * DistFromCorner); + //LR: + Node1Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node1.pos) + ShoulderWidth1) / GSDRI.Node1.GSDSpline.distance; + Node2Width = (Vector3.Distance(GSDRI.CornerLR, GSDRI.Node2.pos) + ShoulderWidth2) / GSDRI.Node2.GSDSpline.distance; + tPos1 = GSDRI.Node1.tTime - Node1Width; + tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1, true) * -1f; + tPos2 = GSDRI.Node2.tTime + Node2Width; + tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2, true); + tDir = (tTan1.normalized + tTan2.normalized).normalized; + tPosLR = tVectLR + (tDir * DistFromCorner); + } + tPosRR.y = GSDRI.SignHeight; + tPosRL.y = GSDRI.SignHeight; + tPosLL.y = GSDRI.SignHeight; + tPosLR.y = GSDRI.SignHeight; + + // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22_RR"; + // tObj.transform.position = tPosRR; + // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22_RL"; + // tObj.transform.position = tPosRL; + // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22_LL"; + // tObj.transform.position = tPosLL; + // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22_LR"; + // tObj.transform.position = tPosLR; + } + + + // + // public static void GetOrigFour(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR){ + // //Get four points: + // float tPos1 = 0f; + // float tPos2 = 0f; + // Vector3 tTan1 = default(Vector3); + // Vector3 tTan2 = default(Vector3); + // float Node1Width = -1f; + // float Node2Width = -1f; + // Vector3 tDirRR = default(Vector3); + // Vector3 tDirRL = default(Vector3); + // Vector3 tDirLL = default(Vector3); + // Vector3 tDirLR = default(Vector3); + // float tAngleRR = 85f; + // float tAngleRL = 85f; + // float tAngleLL = 85f; + // float tAngleLR = 85f; + // float ShoulderWidth1 = GSDRI.Node1.GSDSpline.tRoad.opt_ShoulderWidth; + // float ShoulderWidth2 = GSDRI.Node2.GSDSpline.tRoad.opt_ShoulderWidth; + // Vector3 xPos1 = default(Vector3); + // Vector3 xPos2 = default(Vector3); + // + // if(!GSDRI.bFlipped){ + // //RR: + // Node1Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime - Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; + // tPos2 = GSDRI.Node2.tTime + Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tDirRR = (tTan1.normalized + tTan2.normalized).normalized; + // //tAngleRR = Vector3.Angle(tTan1,tTan2); + // tAngleRR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //RL: + // Node1Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime + Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); + // tPos2 = GSDRI.Node2.tTime + Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tDirRL = (tTan1.normalized + tTan2.normalized).normalized; + // //tAngleRL = Vector3.Angle(tTan1,tTan2); + // tAngleRL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //LL: + // Node1Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime + Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); + // tPos2 = GSDRI.Node2.tTime - Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tDirLL = (tTan1.normalized + tTan2.normalized).normalized; + // //tAngleLL = Vector3.Angle(tTan1,tTan2); + // tAngleLL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //LR: + // Node1Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime - Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; + // tPos2 = GSDRI.Node2.tTime - Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tDirLR = (tTan1.normalized + tTan2.normalized).normalized; + // //tAngleLR = Vector3.Angle(tTan1,tTan2); + // tAngleLR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // }else{ + // //RR: + // Node1Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerRR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime - Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; + // tPos2 = GSDRI.Node2.tTime - Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; + // tDirRR = (tTan1.normalized + tTan2.normalized).normalized; + //// tAngleRR = Vector3.Angle(tTan1,tTan2); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tAngleRR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //RL: + // Node1Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerRL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime + Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); + // tPos2 = GSDRI.Node2.tTime - Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true) * -1f; + // tDirRL = (tTan1.normalized + tTan2.normalized).normalized; + //// tAngleRL = Vector3.Angle(tTan1,tTan2); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tAngleRL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //LL: + // Node1Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerLL,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime + Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true); + // tPos2 = GSDRI.Node2.tTime + Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); + // tDirLL = (tTan1.normalized + tTan2.normalized).normalized; + //// tAngleLL = Vector3.Angle(tTan1,tTan2); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tAngleLL = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // //LR: + // Node1Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node1.pos) + ShoulderWidth1)/GSDRI.Node1.GSDSpline.distance; + // Node2Width = (Vector3.Distance(GSDRI.CornerLR,GSDRI.Node2.pos) + ShoulderWidth2)/GSDRI.Node2.GSDSpline.distance; + // tPos1 = GSDRI.Node1.tTime - Node1Width; + // tTan1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1,true) * -1f; + // tPos2 = GSDRI.Node2.tTime + Node2Width; + // tTan2 = GSDRI.Node2.GSDSpline.GetSplineValue(tPos2,true); + // tDirLR = (tTan1.normalized + tTan2.normalized).normalized; + // //tAngleLR = Vector3.Angle(tTan1,tTan2); + // xPos1 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos1); + // xPos2 = GSDRI.Node1.GSDSpline.GetSplineValue(tPos2); + // tAngleLR = Vector3.Angle(xPos1 - GSDRI.Node1.pos,xPos2 - GSDRI.Node1.pos); + // } + // + // //D = B*cos(angle/2) + // float tWidth = GSDRI.Node1.GSDSpline.tRoad.opt_RoadWidth * 0.5f; + // float tAngleRR_Opp = 180f - tAngleRR; + // float tAngleRL_Opp = 180f - tAngleRL; + // float tAngleLL_Opp = 180f - tAngleLL; + // float tAngleLR_Opp = 180f - tAngleLR; + // + // float tOffSetRR = tWidth*(Mathf.Cos((tAngleRR*0.5f)*Mathf.Deg2Rad)); + // float tOffSetRL = tWidth*(Mathf.Cos((tAngleRL*0.5f)*Mathf.Deg2Rad)); + // float tOffSetLL = tWidth*(Mathf.Cos((tAngleLL*0.5f)*Mathf.Deg2Rad)); + // float tOffSetLR = tWidth*(Mathf.Cos((tAngleLR*0.5f)*Mathf.Deg2Rad)); + // + // float tOffSetRR_opp = tWidth*(Mathf.Cos((tAngleRR_Opp*0.5f)*Mathf.Deg2Rad)); + // float tOffSetRL_opp = tWidth*(Mathf.Cos((tAngleRL_Opp*0.5f)*Mathf.Deg2Rad)); + // float tOffSetLL_opp = tWidth*(Mathf.Cos((tAngleLL_Opp*0.5f)*Mathf.Deg2Rad)); + // float tOffSetLR_opp = tWidth*(Mathf.Cos((tAngleLR_Opp*0.5f)*Mathf.Deg2Rad)); + // + // Vector3 tPos = GSDRI.Node1.pos; + // + //// tOffSetRR *=2f; + //// tOffSetRL *=2f; + //// tOffSetLL *=2f; + //// tOffSetLR *=2f; + // + // tPosRR = tPos + (tDirRR * (tOffSetRR+tOffSetRR_opp)); + // tPosRL = tPos + (tDirRL * (tOffSetRL+tOffSetRL_opp)); + // tPosLL = tPos + (tDirLL * (tOffSetLL+tOffSetLL_opp)); + // tPosLR = tPos + (tDirLR * (tOffSetLR+tOffSetLR_opp)); + // + // GameObject tObj = GameObject.Find("temp22_RR"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_RL"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_LL"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_LR"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // + // GameObject tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosRR; + // tCubeRR.transform.name = "temp22_RR"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosRL; + // tCubeRR.transform.name = "temp22_RL"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosLL; + // tCubeRR.transform.name = "temp22_LL"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosLR; + // tCubeRR.transform.name = "temp22_LR"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // } + // + // public static void GetCornerVectors_Test(GSDRoadIntersection GSDRI, out Vector3 tPosRR, out Vector3 tPosRL, out Vector3 tPosLL, out Vector3 tPosLR){ + // GSDSplineN tNode = null; + // GSDSplineC tSpline = null; + // + // tNode = GSDRI.Node1; + // tSpline = tNode.GSDSpline; + // float tOffset = tSpline.tRoad.opt_RoadWidth * 0.5f; + // float tPos1 = tNode.tTime - (tOffset/tSpline.distance); + // float tPos2 = tNode.tTime + (tOffset/tSpline.distance); + // Vector3 tVect1 = tSpline.GetSplineValue(tPos1); + // Vector3 POS1 = tSpline.GetSplineValue(tPos1,true); + // Vector3 tVect2 = tSpline.GetSplineValue(tPos2); + // Vector3 POS2 = tSpline.GetSplineValue(tPos2,true); + // tPosRR = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); + // tPosLR = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); + // tPosRL = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); + // tPosLL = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); + // + // tNode = GSDRI.Node2; + // tSpline = tNode.GSDSpline; + // tOffset = tSpline.tRoad.opt_RoadWidth * 0.5f; + // tPos1 = tNode.tTime - (tOffset/tSpline.distance); + // tPos2 = tNode.tTime + (tOffset/tSpline.distance); + // tVect1 = tSpline.GetSplineValue(tPos1); + // POS1 = tSpline.GetSplineValue(tPos1,true); + // tVect2 = tSpline.GetSplineValue(tPos2); + // POS2 = tSpline.GetSplineValue(tPos2,true); + // Vector3 tPosRR2 = default(Vector3); + // Vector3 tPosLR2 = default(Vector3); + // Vector3 tPosRL2 = default(Vector3); + // Vector3 tPosLL2 = default(Vector3); + // + // if(GSDRI.bFlipped){ + // tPosRL2 = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); + // tPosRR2 = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); + // tPosLL2 = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); + // tPosLR2 = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); + // }else{ + // tPosLR2 = (tVect1 + new Vector3(5f*POS1.normalized.z,0,5f*-POS1.normalized.x)); + // tPosLL2 = (tVect1 + new Vector3(5f*-POS1.normalized.z,0,5f*POS1.normalized.x)); + // tPosRR2 = (tVect2 + new Vector3(5f*POS2.normalized.z,0,5f*-POS2.normalized.x)); + // tPosRL2 = (tVect2 + new Vector3(5f*-POS2.normalized.z,0,5f*POS2.normalized.x)); + // } + // + // tPosRR = ((tPosRR-tPosRR2)*0.5f)+tPosRR; + // tPosLR = ((tPosLR-tPosLR2)*0.5f)+tPosLR; + // tPosRL = ((tPosRL-tPosRL2)*0.5f)+tPosRL; + // tPosLL = ((tPosLL-tPosLL2)*0.5f)+tPosLL; + // + // + // GameObject tObj = GameObject.Find("temp22_RR"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_RL"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_LL"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // tObj = GameObject.Find("temp22_LR"); if(tObj != null){ Object.DestroyImmediate(tObj); } + // + // GameObject tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosRR; + // tCubeRR.transform.name = "temp22_RR"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosRL; + // tCubeRR.transform.name = "temp22_RL"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosLL; + // tCubeRR.transform.name = "temp22_LL"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // + // tCubeRR = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tCubeRR.transform.position = tPosLR; + // tCubeRR.transform.name = "temp22_LR"; + // tCubeRR.transform.localScale = new Vector3(0.2f,20f,0.2f); + // } + // + } + + + public static class GSDIntersections + { + public class iConstructionMaker + { + //Lanes: + public List iBLane0L, iBLane0R; + public List iBLane1L, iBLane1R; + public List iBLane2L, iBLane2R; + public List iBLane3L, iBLane3R; + public List iFLane0L, iFLane0R; + public List iFLane1L, iFLane1R; + public List iFLane2L, iFLane2R; + public List iFLane3L, iFLane3R; + //Main plate: + public List iBMainPlateL; public List iBMainPlateR; + public List iFMainPlateL; public List iFMainPlateR; + //Front marker plates: + public List iBMarkerPlateL; public List iBMarkerPlateR; + public List iFMarkerPlateL; public List iFMarkerPlateR; + + public float tempconstruction_InterStart; + public float tempconstruction_InterEnd; + public bool tempconstruction_HasProcessed_Inter1 = false; + public bool tempconstruction_HasProcessed_Inter2 = false; + + public List tempconstruction_R_RightTurn; + public List tempconstruction_L_RightTurn; + public List tempconstruction_R; + public List tempconstruction_L; + + public float tempconstruction_MinXR = 0f; + public float tempconstruction_MaxXR = 0f; + public float tempconstruction_MinXL = 0f; + public float tempconstruction_MaxXL = 0f; + + public float tempconstruction_MinYR = 0f; + public float tempconstruction_MaxYR = 0f; + public float tempconstruction_MinYL = 0f; + public float tempconstruction_MaxYL = 0f; + + public bool bBLane0Done = false; + public bool bBLane1Done = false; + public bool bBLane2Done = false; + public bool bBLane3Done = false; + public bool bFLane0Done = false; + public bool bFLane1Done = false; + public bool bFLane2Done = false; + public bool bFLane3Done = false; + + public bool bBLane0Done_Final = false; + public bool bBLane1Done_Final = false; + public bool bBLane2Done_Final = false; + public bool bBLane3Done_Final = false; + public bool bFLane0Done_Final = false; + public bool bFLane1Done_Final = false; + public bool bFLane2Done_Final = false; + public bool bFLane3Done_Final = false; + + public bool bBLane0Done_Final_ThisRound = false; + public bool bBLane1Done_Final_ThisRound = false; + public bool bBLane2Done_Final_ThisRound = false; + public bool bBLane3Done_Final_ThisRound = false; + public bool bFLane0Done_Final_ThisRound = false; + public bool bFLane1Done_Final_ThisRound = false; + public bool bFLane2Done_Final_ThisRound = false; + public bool bFLane3Done_Final_ThisRound = false; + + public bool bFDone = false; + public bool bBDone = false; + + public bool bIsFrontFirstRound = false; + public bool bIsFrontFirstRoundTriggered = false; + + public Vector3 f0LAttempt = default(Vector3); + public Vector3 f1LAttempt = default(Vector3); + public Vector3 f2LAttempt = default(Vector3); + public Vector3 f3LAttempt = default(Vector3); + public Vector3 f0RAttempt = default(Vector3); + public Vector3 f1RAttempt = default(Vector3); + public Vector3 f2RAttempt = default(Vector3); + public Vector3 f3RAttempt = default(Vector3); + + public bool bNode1RLTriggered = false; + + public bool bDepressDoneR = false; + public bool bDepressDoneL = false; + + public bool bBackRRpassed = false; + + public List iBLane0_Real; + + public Vector3 ShoulderBL_Start = default(Vector3); + public Vector3 ShoulderBR_Start = default(Vector3); + public Vector3 ShoulderFL_Start = default(Vector3); + public Vector3 ShoulderFR_Start = default(Vector3); + + public Vector3 ShoulderBL_End = default(Vector3); + public Vector3 ShoulderBR_End = default(Vector3); + public Vector3 ShoulderFL_End = default(Vector3); + public Vector3 ShoulderFR_End = default(Vector3); + + public int ShoulderBL_StartIndex = -1; + public int ShoulderBR_StartIndex = -1; + public int ShoulderFL_StartIndex = -1; + public int ShoulderFR_StartIndex = -1; + + + public void Nullify() + { + + //Intersection construction: + if (iBLane0L != null) + { + iBLane0L.Clear(); + iBLane0L = null; + } + if (iBLane0R != null) + { + iBLane0R.Clear(); + iBLane0R = null; + } + if (iBLane1L != null) + { + iBLane1L.Clear(); + iBLane1L = null; + } + if (iBLane1R != null) + { + iBLane1R.Clear(); + iBLane1R = null; + } + if (iBLane2L != null) + { + iBLane2L.Clear(); + iBLane2L = null; + } + if (iBLane2R != null) + { + iBLane2R.Clear(); + iBLane2R = null; + } + if (iBLane3L != null) + { + iBLane3L.Clear(); + iBLane3L = null; + } + if (iBLane3R != null) + { + iBLane3R.Clear(); + iBLane3R = null; + } + if (iFLane0L != null) + { + iFLane0L.Clear(); + iFLane0L = null; + } + if (iFLane0R != null) + { + iFLane0R.Clear(); + iFLane0R = null; + } + if (iFLane1L != null) + { + iFLane1L.Clear(); + iFLane1L = null; + } + if (iFLane1R != null) + { + iFLane1R.Clear(); + iFLane1R = null; + } + if (iFLane2L != null) + { + iFLane2L.Clear(); + iFLane2L = null; + } + if (iFLane2R != null) + { + iFLane2R.Clear(); + iFLane2R = null; + } + if (iFLane3L != null) + { + iFLane3L.Clear(); + iFLane3L = null; + } + if (iFLane3R != null) + { + iFLane3R.Clear(); + iFLane3R = null; + } + if (iBMainPlateL != null) + { + iBMainPlateL.Clear(); + iBMainPlateL = null; + } + if (iBMainPlateR != null) + { + iBMainPlateR.Clear(); + iBMainPlateR = null; + } + if (iFMainPlateL != null) + { + iFMainPlateL.Clear(); + iFMainPlateL = null; + } + if (iFMainPlateR != null) + { + iFMainPlateR.Clear(); + iFMainPlateR = null; + } + + if (iBMarkerPlateL != null) + { + iBMarkerPlateL.Clear(); + iBMarkerPlateL = null; + } + if (iBMarkerPlateR != null) + { + iBMarkerPlateR.Clear(); + iBMarkerPlateR = null; + } + if (iFMarkerPlateL != null) + { + iFMarkerPlateL.Clear(); + iFMarkerPlateL = null; + } + if (iFMarkerPlateR != null) + { + iFMarkerPlateR.Clear(); + iFMarkerPlateR = null; + } + + if (tempconstruction_R != null) + { + tempconstruction_R = null; + } + if (tempconstruction_L != null) + { + tempconstruction_L = null; + } + } + + + public iConstructionMaker() + { + Nullify(); + + iBLane0_Real = new List(); + + //Lanes: + iBLane0L = new List(); + iBLane0R = new List(); + iBLane1L = new List(); + iBLane1R = new List(); + iBLane2L = new List(); + iBLane2R = new List(); + iBLane3L = new List(); + iBLane3R = new List(); + iFLane0L = new List(); + iFLane0R = new List(); + iFLane1L = new List(); + iFLane1R = new List(); + iFLane2L = new List(); + iFLane2R = new List(); + iFLane3L = new List(); + iFLane3R = new List(); + //Main plate: + iBMainPlateL = new List(); + iBMainPlateR = new List(); + iFMainPlateL = new List(); + iFMainPlateR = new List(); + + iBMarkerPlateL = new List(); + iBMarkerPlateR = new List(); + iFMarkerPlateL = new List(); + iFMarkerPlateR = new List(); + + tempconstruction_HasProcessed_Inter1 = false; + tempconstruction_HasProcessed_Inter2 = false; + tempconstruction_MinXR = 20000000f; + tempconstruction_MaxXR = 0f; + tempconstruction_MinXL = 20000000f; + tempconstruction_MaxXL = 0f; + tempconstruction_MinYR = 20000000f; + tempconstruction_MaxYR = 0f; + tempconstruction_MinYL = 20000000f; + tempconstruction_MaxYL = 0f; + + bBLane0Done = false; + bBLane1Done = false; + bBLane2Done = false; + bBLane3Done = false; + bFLane0Done = false; + bFLane1Done = false; + bFLane2Done = false; + bFLane3Done = false; + } + } + + + public static GameObject CreateIntersection(GSDSplineN tNode, GSDSplineN xNode) + { + return CreateIntersection_Do(tNode, xNode); + } + + + private static GameObject CreateIntersection_Do(GSDSplineN tNode, GSDSplineN xNode) + { + float RoadMod = 10f; + GameObject SystemObj = tNode.transform.parent.parent.parent.gameObject; + if (!SystemObj) + { + Debug.LogWarning("Could not find GSD road system master object."); + return null; + } + GameObject InterMaster = null; + int cCount = SystemObj.transform.childCount; + for (int i = 0; i < cCount; i++) + { + if (SystemObj.transform.GetChild(i).transform.name.ToLower() == "intersections") + { + InterMaster = SystemObj.transform.GetChild(i).gameObject; + } + } + if (!InterMaster) + { + InterMaster = new GameObject("Intersections"); + InterMaster.transform.parent = SystemObj.transform; + } + if (!InterMaster) + { + Debug.LogWarning("Could not find intersections master object for this road system."); + return null; + } + cCount = InterMaster.transform.childCount; + + GameObject tObj = new GameObject("Inter" + (cCount + 1).ToString()); + tObj.transform.parent = InterMaster.transform; + GSDRoadIntersection GSDRI = tObj.AddComponent(); + GSDRI.IgnoreSide = -1; + GSDRI.bFirstSpecial_First = false; + GSDRI.bFirstSpecial_Last = false; + GSDRI.bSecondSpecial_First = false; + GSDRI.bSecondSpecial_Last = false; + + GSDSplineN tNode1 = null; + GSDSplineN tNode2 = null; + if (tNode.GSDSpline == xNode.GSDSpline) + { + if (tNode.idOnSpline < xNode.idOnSpline) + { + tNode1 = tNode; + tNode2 = xNode; + } + else + { + tNode1 = xNode; + tNode2 = tNode; + } + } + else + { + tNode1 = tNode; + tNode2 = xNode; + } + + //If 3way, always add the single node as primary: + if (tNode.bIsEndPoint) + { + tNode1 = tNode; + tNode2 = xNode; + } + else if (xNode.bIsEndPoint) + { + tNode1 = xNode; + tNode2 = tNode; + } + + tNode1.Intersection_OtherNode = tNode2; + tNode2.Intersection_OtherNode = tNode1; + + if (tNode1.bIsEndPoint || tNode2.bIsEndPoint) + { + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + } + + GSDSplineN zNode = null; + if (tNode1.bIsEndPoint) + { + bool bFirstNode = false; + bool bAlreadyNode = false; + if (tNode1.idOnSpline == 1 || tNode1.idOnSpline == 0) + { + bFirstNode = true; + } + if (bFirstNode && tNode1.idOnSpline == 1 && tNode1.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) + { + bAlreadyNode = true; + } + else if (!bFirstNode && tNode1.idOnSpline == tNode1.GSDSpline.GetNodeCount() - 2 && tNode1.GSDSpline.mNodes[tNode1.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) + { + bAlreadyNode = true; + } + + Vector3 tPos = default(Vector3); + if (bFirstNode) + { + tPos = ((tNode1.tangent * -1f).normalized * (tNode1.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode1.pos; + } + else + { + tPos = (tNode1.GSDSpline.GetSplineValue(0.999f, true).normalized * (tNode1.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode1.pos; + } + + if (!bAlreadyNode) + { + if (bFirstNode) + { + zNode = GSD.Roads.GSDConstruction.InsertNode(tNode1.GSDSpline.tRoad, true, tPos, false, 0, true, true); + zNode.bSpecialEndNode_IsStart = true; + zNode.bSpecialIntersection = true; + zNode.tangent = tNode1.tangent; + } + else + { + zNode = GSD.Roads.GSDConstruction.CreateNode(tNode1.GSDSpline.tRoad, true, tPos, true); + zNode.bSpecialEndNode_IsEnd = true; + zNode.bSpecialIntersection = true; + zNode.tangent = tNode1.tangent; + } + } + else + { + if (bFirstNode) + { + tNode1.GSDSpline.mNodes[0].transform.position = tPos; + } + else + { + tNode1.GSDSpline.mNodes[tNode1.GSDSpline.GetNodeCount() - 1].transform.position = tPos; + } + } + if (bFirstNode) + { + tNode1.GSDSpline.bSpecialStartControlNode = true; + GSDRI.bFirstSpecial_First = true; + } + else + { + tNode1.GSDSpline.bSpecialEndControlNode = true; + GSDRI.bFirstSpecial_Last = true; + } + + } + else if (tNode2.bIsEndPoint) + { + bool bFirstNode = false; + bool bAlreadyNode = false; + if (tNode2.idOnSpline == 1 || tNode2.idOnSpline == 0) + { + bFirstNode = true; + } + if (bFirstNode && tNode2.idOnSpline == 1 && tNode2.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) + { + bAlreadyNode = true; + } + else if (!bFirstNode && tNode2.idOnSpline == tNode2.GSDSpline.GetNodeCount() - 2 && tNode2.GSDSpline.mNodes[tNode2.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) + { + bAlreadyNode = true; + } + + Vector3 tPos = default(Vector3); + if (bFirstNode) + { + tPos = ((tNode2.tangent * -1f).normalized * (tNode2.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode2.pos; + } + else + { + tPos = (tNode2.GSDSpline.GetSplineValue(0.999f, true).normalized * (tNode2.GSDSpline.tRoad.RoadWidth() * RoadMod)) + tNode2.pos; + } + + if (!bAlreadyNode) + { + if (bFirstNode) + { + zNode = GSD.Roads.GSDConstruction.InsertNode(tNode2.GSDSpline.tRoad, true, tPos, false, 0, true, true); + zNode.bSpecialEndNode_IsStart = true; + zNode.bSpecialIntersection = true; + zNode.tangent = tNode2.tangent; + } + else + { + zNode = GSD.Roads.GSDConstruction.CreateNode(tNode2.GSDSpline.tRoad, true, tPos, true); + zNode.bSpecialEndNode_IsEnd = true; + zNode.bSpecialIntersection = true; + zNode.tangent = tNode2.tangent; + } + } + else + { + if (bFirstNode) + { + tNode2.GSDSpline.mNodes[0].transform.position = tPos; + } + else + { + tNode2.GSDSpline.mNodes[tNode2.GSDSpline.GetNodeCount() - 1].transform.position = tPos; + } + } + if (bFirstNode) + { + tNode2.GSDSpline.bSpecialStartControlNode = true; + GSDRI.bSecondSpecial_First = true; + } + else + { + tNode2.GSDSpline.bSpecialEndControlNode = true; + GSDRI.bSecondSpecial_Last = true; + } + } + + //Undo crap: + UnityEditor.Undo.RegisterCreatedObjectUndo(tObj, "Created intersection"); + + GSDRI.Setup(tNode1, tNode2); + tObj.transform.position = tNode.transform.position; + + GSDRI.ResetMaterials_All(); + + // if(GSDRI.bSameSpline){ + // GSDRI.Node1.GSDSpline.tRoad.UpdateRoad(); + // }else{ + // GSDRI.Node1.GSDSpline.tRoad.UpdateRoad(); + // GSDRI.Node2.GSDSpline.tRoad.UpdateRoad(); + // } + + tNode1.ToggleHideFlags(true); + tNode2.ToggleHideFlags(true); + + if (GSDRI != null && GSDRI.Node1 != null && GSDRI.Node2 != null) + { + if (!GSDRI.bSameSpline) + { + GSDRI.Node1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[4]; + GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[0] = GSDRI.Node2.GSDSpline; + + GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[1] = GSDRI.Node1.GSDSpline; + GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[2] = GSDRI.Node2.GSDSpline; + GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[3] = GSDRI.Node1.GSDSpline; + // GSDRI.Node1.GSDSpline.tRoad.PiggyBacks[4] = GSDRI.Node2.GSDSpline; + } + GSDRI.Node1.GSDSpline.tRoad.EditorUpdateMe = true; + } + + return tObj; + } + + + public static Vector3[] GetCornerVectors_Test(GSDRoadIntersection GSDRI) + { + Vector3[] tVects = new Vector3[4]; + GSDSplineN tNode; + tNode = GSDRI.Node1; + GSDSplineC tSpline = tNode.GSDSpline; + + //RR = Node1 - 5, Node2 + 5 + //RL = Node1 + 5, Node2 + 5 + //LL = Node1 + 5, Node2 - 5 + //LR = Node1 - 5, Node2 - 5 + + float tOffset = 5f; + float tPos1 = tNode.tTime - (tOffset / tSpline.distance); + float tPos2 = tNode.tTime + (tOffset / tSpline.distance); + Vector3 tVect1 = tSpline.GetSplineValue(tPos1); + Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); + Vector3 tVect2 = tSpline.GetSplineValue(tPos2); + Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); + + tVects[0] = (tVect1 + new Vector3(5f * POS1.normalized.z, 0, 5f * -POS1.normalized.x)); + tVects[1] = (tVect1 + new Vector3(5f * -POS1.normalized.z, 0, 5f * POS1.normalized.x)); + tVects[2] = (tVect2 + new Vector3(5f * POS2.normalized.z, 0, 5f * -POS2.normalized.x)); + tVects[3] = (tVect2 + new Vector3(5f * -POS2.normalized.z, 0, 5f * POS2.normalized.x)); + + return tVects; + } + + + #region "Old intersection" + public static void CreateIntersection(GSDRoadIntersection GSDRI) + { + //1. Overlap sphere to find all road objects within intersection: + float iWidth = GSDRI.IntersectionWidth * 1.25f; + Collider[] tColliders = Physics.OverlapSphere(GSDRI.transform.position, iWidth); + if (tColliders == null || tColliders.Length < 1) + { + return; + } + List tRoads = new List(); + foreach (Collider tCollider in tColliders) + { + if (tCollider.transform.parent) + { + GSDRoad tRoad = tCollider.transform.parent.GetComponent(); + if (tRoad) + { + if (!tRoads.Contains(tRoad)) + { + tRoads.Add(tRoad); + } + } + } + } + + //Flatten intersection area: + float tHeight = -1f; + FlattenIntersectionArea(ref tRoads, GSDRI, iWidth, out tHeight); + + //Create main intersection mesh: + string tName = GSDRI.transform.name; + Vector3[] tVects; + CreateIntersectionMesh_Main(GSDRI, tHeight, out tVects, ref tName); + + //Now create the 4 text overlays: + CreateIntersectionMesh_Outer(GSDRI, tVects, ref tName); + + //Update connected nodes: + GSDNavigation.UpdateConnectedNodes(); + + //Now initialize intersection objects: + InitializeIntersectionObjects(GSDRI); + } + + + private static void FlattenIntersectionArea(ref List tRoads, GSDRoadIntersection GSDRI, float iWidth, out float tHeight) + { + //Cycle through each road and get all mesh vertices that are within range: + Vector3 tInterPos = GSDRI.transform.position; + float tInterPosY = tInterPos.y; + foreach (GSDRoad tRoad in tRoads) + { + MeshFilter MF_Road = tRoad.MeshRoad.GetComponent(); + MeshFilter MF_Road_SR = tRoad.MeshShoR.GetComponent(); + MeshFilter MF_Road_SL = tRoad.MeshShoL.GetComponent(); + + Mesh Road = MF_Road.sharedMesh; + Mesh Road_SR = MF_Road_SR.sharedMesh; + Mesh Road_SL = MF_Road_SL.sharedMesh; + + Vector3[] tVects = Road.vertices; + Vector3[] tVects_SR = Road_SR.vertices; + Vector3[] tVects_SL = Road_SL.vertices; + int VertCount = Road.vertices.Length; + bool bLeftToggle = true; + for (int i = 0; i < VertCount; i += 2) + { + if (Vector3.Distance(tVects[i], tInterPos) < iWidth) + { + tVects[i].y = tInterPosY; + tVects[i + 1].y = tInterPosY; + if (bLeftToggle) + { + //Left: + tVects_SL[i + 2].y = tInterPosY; + tVects_SL[i + 3].y = tInterPosY; + } + else + { + //Right: + tVects_SR[i - 2].y = tInterPosY; + tVects_SR[i - 1].y = tInterPosY; + } + } + bLeftToggle = !bLeftToggle; + } + //Main road: + Road.vertices = tVects; + Road.RecalculateNormals(); + MF_Road.sharedMesh = Road; + //Right shoulder: + Road_SR.vertices = tVects_SR; + Road_SR.RecalculateNormals(); + MF_Road_SR.sharedMesh = Road_SR; + //Left shoulder: + Road_SL.vertices = tVects_SL; + Road_SL.RecalculateNormals(); + MF_Road_SL.sharedMesh = Road_SL; + } + tHeight = tInterPosY; + } + + + private static bool V3Equal(Vector3 a, Vector3 b) + { + return Vector3.SqrMagnitude(a - b) < 0.0001f; + } + + + private static Vector3[] GetCornerVectors(GSDRoadIntersection GSDRI, bool bPrimary = true) + { + Vector3[] tVects = new Vector3[4]; + GSDSplineN tNode; + if (bPrimary) + { + tNode = GSDRI.Node1; + } + else + { + tNode = GSDRI.Node2; + } + GSDSplineC tSpline = tNode.GSDSpline; + + float tOffset = 7f; + float tPos1 = tNode.tTime - (tOffset / tSpline.distance); + float tPos2 = tNode.tTime + (tOffset / tSpline.distance); + Vector3 tVect1 = tSpline.GetSplineValue(tPos1); + Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); + Vector3 tVect2 = tSpline.GetSplineValue(tPos2); + Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); + + tVects[0] = (tVect1 + new Vector3(5f * POS1.normalized.z, 0, 5f * -POS1.normalized.x)); + tVects[1] = (tVect1 + new Vector3(5f * -POS1.normalized.z, 0, 5f * POS1.normalized.x)); + tVects[2] = (tVect2 + new Vector3(5f * POS2.normalized.z, 0, 5f * -POS2.normalized.x)); + tVects[3] = (tVect2 + new Vector3(5f * -POS2.normalized.z, 0, 5f * POS2.normalized.x)); + + return tVects; + } + + + private static Vector3[] GetExtendedVectors(GSDRoadIntersection GSDRI, bool bPrimary = true) + { + Vector3[] tVects = new Vector3[4]; + GSDSplineN tNode; + if (bPrimary) + { + tNode = GSDRI.Node1; + } + else + { + tNode = GSDRI.Node2; + } + GSDSplineC tSpline = tNode.GSDSpline; + Vector3 NodePos = tNode.transform.position; + + float tOffset = tNode.GSDSpline.tRoad.RoadWidth(); + float tOffset2 = tOffset * 0.5f; + float tPos1 = tNode.tTime - (tOffset / tSpline.distance); + float tPos2 = tNode.tTime + (tOffset / tSpline.distance); + Vector3 tVect1 = tSpline.GetSplineValue(tPos1); + Vector3 tVect2 = tSpline.GetSplineValue(tPos2); + + //Enforce distance: + int SpamGuard = 0; + int SGMax = 50; + while (Vector3.Distance(tVect1, NodePos) < tOffset && SpamGuard < SGMax) + { + SpamGuard += 1; + tPos1 -= (1f / tSpline.distance); + tVect1 = tSpline.GetSplineValue(tPos1); + } + SpamGuard = 0; + while (Vector3.Distance(tVect1, NodePos) > (tOffset * 1.2f) && SpamGuard < SGMax) + { + SpamGuard += 1; + tPos1 += (0.25f / tSpline.distance); + tVect1 = tSpline.GetSplineValue(tPos1); + } + SpamGuard = 0; + while (Vector3.Distance(tVect2, NodePos) < tOffset && SpamGuard < SGMax) + { + SpamGuard += 1; + tPos2 += (1f / tSpline.distance); + tVect2 = tSpline.GetSplineValue(tPos2); + } + SpamGuard = 0; + while (Vector3.Distance(tVect1, NodePos) > (tOffset * 1.2f) && SpamGuard < SGMax) + { + SpamGuard += 1; + tPos2 -= (0.25f / tSpline.distance); + tVect2 = tSpline.GetSplineValue(tPos2); + } + + Vector3 POS1 = tSpline.GetSplineValue(tPos1, true); + Vector3 POS2 = tSpline.GetSplineValue(tPos2, true); + + tVects[0] = (tVect1 + new Vector3(tOffset2 * POS1.normalized.z, 0, tOffset2 * -POS1.normalized.x)); + tVects[1] = (tVect1 + new Vector3(tOffset2 * -POS1.normalized.z, 0, tOffset2 * POS1.normalized.x)); + tVects[2] = (tVect2 + new Vector3(tOffset2 * POS2.normalized.z, 0, tOffset2 * -POS2.normalized.x)); + tVects[3] = (tVect2 + new Vector3(tOffset2 * -POS2.normalized.z, 0, tOffset2 * POS2.normalized.x)); + + return tVects; + } + + + //Two non-parallel lines which may or may not touch each other have a point on each line which are closest + //to each other. This function finds those two points. If the lines are not parallel, the function + //outputs true, otherwise false. + private static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2) + { + + closestPointLine1 = Vector3.zero; + closestPointLine2 = Vector3.zero; + + float a = Vector3.Dot(lineVec1, lineVec1); + float b = Vector3.Dot(lineVec1, lineVec2); + float e = Vector3.Dot(lineVec2, lineVec2); + + float d = a * e - b * b; + + //lines are not parallel + if (d != 0.0f) + { + + Vector3 r = linePoint1 - linePoint2; + float c = Vector3.Dot(lineVec1, r); + float f = Vector3.Dot(lineVec2, r); + + float s = (b * f - c * e) / d; + float t = (a * f - c * b) / d; + + closestPointLine1 = linePoint1 + lineVec1 * s; + closestPointLine2 = linePoint2 + lineVec2 * t; + + return true; + } + + else + { + return false; + } + } + + + private static void CreateIntersectionMesh_Main(GSDRoadIntersection GSDRI, float tHeight, out Vector3[] tVects, ref string tName) + { + //Get four points: + Vector3[] pVects = GetCornerVectors(GSDRI); + Vector3[] sVects = GetCornerVectors(GSDRI, false); + tVects = new Vector3[4]; + Vector3 oIntersection = new Vector3(0f, 0f, 0f); + Vector3 oIntersection2 = new Vector3(0f, 0f, 0f);//Unused + + // bool bIntersection; + ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[0], (pVects[2] - pVects[0]), sVects[0], (sVects[2] - sVects[0])); + tVects[0] = oIntersection; + tVects[0].y = tHeight; + + ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[0], (pVects[2] - pVects[0]), sVects[1], (sVects[3] - sVects[1])); + tVects[1] = oIntersection; + tVects[1].y = tHeight; + + ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[1], (pVects[3] - pVects[1]), sVects[0], (sVects[2] - sVects[0])); + tVects[2] = oIntersection; + tVects[2].y = tHeight; + + ClosestPointsOnTwoLines(out oIntersection, out oIntersection2, pVects[1], (pVects[3] - pVects[1]), sVects[1], (sVects[3] - sVects[1])); + tVects[3] = oIntersection; + tVects[3].y = tHeight; + + CreateIntersectionMesh_MainInternal(tVects, GSDRI.transform.gameObject, ref tName); + } + + + private static void CreateIntersectionMesh_MainInternal(Vector3[] tVerts, GameObject iObj, ref string tName) + { + Mesh tMesh = new Mesh(); + int MVL = 4; + int triCount = (int) (4f * 1.5f); + + // GameObject tObj; + // tObj = GameObject.Find("tInter1"); tObj.transform.position = tVerts[0]; + // tObj = GameObject.Find("tInter2"); tObj.transform.position = tVerts[1]; + // tObj = GameObject.Find("tInter3"); tObj.transform.position = tVerts[2]; + // tObj = GameObject.Find("tInter4"); tObj.transform.position = tVerts[3]; + + for (int index = 0; index < MVL; index++) + { + tVerts[index] -= iObj.transform.position; + } + tMesh.vertices = tVerts; + tMesh.RecalculateBounds(); + + int[] tri = new int[triCount]; + tri[0] = 0; + tri[1] = 2; + tri[2] = 1; + tri[3] = 2; + tri[4] = 3; + tri[5] = 1; + tMesh.triangles = tri; + + Vector3[] normals = new Vector3[MVL]; + for (int i = 0; i < MVL; i++) + { + normals[i] = -Vector3.forward; + } + tMesh.normals = normals; + tMesh.RecalculateNormals(); + + Vector2[] uv = new Vector2[MVL]; + uv[0] = new Vector2(0f, 0f); + uv[1] = new Vector2(1f, 0f); + uv[2] = new Vector2(0f, 1f); + uv[3] = new Vector2(1f, 1f); + tMesh.uv = uv; + + GSDRootUtil.ProcessTangents(ref tMesh); + + //Final processing: + MeshFilter MF = iObj.GetComponent(); + if (!MF) + { + MF = iObj.AddComponent(); + } + MF.sharedMesh = tMesh; + // MeshToFile(MF,GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Intersections/" + tName +".obj"); + + MeshCollider MC = iObj.GetComponent(); + if (MC) + { + Object.DestroyImmediate(MC); + } + //if(!MC){ MC = iObj.AddComponent(); } + //MC.sharedMesh = MF.sharedMesh; + + MeshRenderer MR = iObj.GetComponent(); + if (!MR) + { + MR = iObj.AddComponent(); + } + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + MR.receiveShadows = true; + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDRoadIntersection.mat", MR); + } + + + private static void CreateIntersectionMesh_Outer(GSDRoadIntersection GSDRI, Vector3[] tVects, ref string tName) + { + Vector3[] bVects1 = GetExtendedVectors(GSDRI); + Vector3[] bVects2 = GetExtendedVectors(GSDRI, false); + Vector3[] eVects = new Vector3[16]; + eVects[0] = tVects[1]; + eVects[1] = tVects[0]; + eVects[2] = bVects2[3]; + eVects[3] = bVects2[2]; + // + eVects[4] = tVects[3]; + eVects[5] = tVects[1]; + eVects[6] = bVects1[3]; + eVects[7] = bVects1[2]; + // + eVects[8] = tVects[2]; + eVects[9] = tVects[3]; + eVects[10] = bVects2[0]; + eVects[11] = bVects2[1]; + // + eVects[12] = tVects[0]; + eVects[13] = tVects[2]; + eVects[14] = bVects1[0]; + eVects[15] = bVects1[1]; + + int cCount = GSDRI.transform.childCount; + // bool bOuter = false; + GameObject tOuter = null; + for (int index = 0; index < cCount; index++) + { + if (GSDRI.transform.GetChild(index).transform.name == "outer") + { + tOuter = GSDRI.transform.GetChild(index).transform.gameObject; + } + } + if (!tOuter) + { + tOuter = new GameObject("outer"); + tOuter.transform.parent = GSDRI.transform; + } + tOuter.transform.position = GSDRI.transform.position; + + // GameObject tObj; + // tObj = GameObject.Find("tInter1"); tObj.transform.position = bVects2[0]; + // tObj = GameObject.Find("tInter2"); tObj.transform.position = bVects2[1]; + // tObj = GameObject.Find("tInter3"); tObj.transform.position = bVects2[2]; + // tObj = GameObject.Find("tInter4"); tObj.transform.position = bVects2[3]; + + CreateIntersectionMesh_OuterInternal(eVects, tOuter, GSDRI.transform.position, ref tName); + } + + + private static void CreateIntersectionMesh_OuterInternal(Vector3[] tVerts, GameObject iObj, Vector3 vOffset, ref string tName) + { + Mesh tMesh = new Mesh(); + int MVL = 16; + int triCount = (int) (16f * 1.5f); + + for (int index = 0; index < MVL; index += 4) + { + // tVerts[index] += vOffset; + // tVerts[index+1] += vOffset; + tVerts[index + 2] -= vOffset; + tVerts[index + 3] -= vOffset; + } + tMesh.vertices = tVerts; + tMesh.RecalculateBounds(); + + int[] tri = new int[triCount]; + int cTri = 0; + for (int i = 0; i < triCount; i += 4) + { + if (i + 3 >= MVL) + { + break; + } + tri[cTri] = i; + cTri += 1; + tri[cTri] = i + 2; + cTri += 1; + tri[cTri] = i + 1; + cTri += 1; + + tri[cTri] = i + 2; + cTri += 1; + tri[cTri] = i + 3; + cTri += 1; + tri[cTri] = i + 1; + cTri += 1; + } + tMesh.triangles = tri; + + Vector3[] normals = new Vector3[MVL]; + for (int i = 0; i < 4; i++) + { + normals[i] = -Vector3.forward; + } + tMesh.normals = normals; + tMesh.RecalculateNormals(); + + Vector2[] uv = new Vector2[MVL]; + for (int i = 0; i < MVL; i += 4) + { + uv[i] = new Vector2(1f, 1f); + uv[i + 1] = new Vector2(0f, 1f); + uv[i + 2] = new Vector2(1f, 0f); + uv[i + 3] = new Vector2(0f, 0f); + } + tMesh.uv = uv; + + GSDRootUtil.ProcessTangents(ref tMesh); + + //Final processing: + MeshFilter MF = iObj.GetComponent(); + if (!MF) + { + MF = iObj.AddComponent(); + } + MF.sharedMesh = tMesh; + + // MeshToFile(MF,GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Mesh/Intersections/" + tName +"-overlay.obj"); + + MeshCollider MC = iObj.GetComponent(); + if (MC) + { + Object.DestroyImmediate(MC); + } + // if(!MC){ MC = iObj.AddComponent(); } + // MC.sharedMesh = MF.sharedMesh; + + MeshRenderer MR = iObj.GetComponent(); + if (!MR) + { + MR = iObj.AddComponent(); + } + MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + MR.receiveShadows = true; + GSD.Roads.GSDRoadUtilityEditor.SetRoadMaterial(GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Materials/GSDInterText.mat", MR); + } + + + #region "Intersection creation" + private static void InitializeIntersectionObjects(GSDRoadIntersection tGSDRI) + { + if (tGSDRI != null) + { + InitializeIntersectionObjects_Internal(tGSDRI); + } + else + { + Object[] iObjects = GameObject.FindObjectsOfType(typeof(GSDRoadIntersection)); + //Add intersection components, if necessary: + foreach (GSDRoadIntersection GSDRI in iObjects) + { + InitializeIntersectionObjects_Internal(GSDRI); + } + } + } + + + private static void InitializeIntersectionObjects_Internal(GSDRoadIntersection GSDRI) + { + //1. Determine 3-way or 4-way. # of corners for 3-way: 2. 4-way = 4. + if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + GSDRI.CornerPoints = new GSDRoadIntersection.CornerPositionMaker[2]; + } + else + { + GSDRI.CornerPoints = new GSDRoadIntersection.CornerPositionMaker[4]; + } + + //Contains int IDs of connected nodes: + List tList = new List(); + //Get all connected nodes on intersection node1: + int cCount = GSDRI.Node1.id_connected.Count; + GSDSplineN tNode; + for (int index = 0; index < cCount; index++) + { + //tNode = GetNodeByID(GSDRI.Node1.id_connected[i]); + tNode = GSDRI.Node1.node_connected[index]; + if (!tList.Contains(tNode)) + { + tList.Add(tNode); + } + } + //Get all connected nodes on intersection node2: + cCount = GSDRI.Node2.id_connected.Count; + for (int index = 0; index < cCount; index++) + { + //tNode = GetNodeByID(GSDRI.Node2.id_connected[i]); + tNode = GSDRI.Node2.node_connected[index]; + if (!tList.Contains(tNode)) + { + tList.Add(tNode); + } + } + //Declare connected nodes: + GSDSplineN n1, n2, n3, n4; + n1 = tList[0]; + n2 = tList[1]; + n3 = tList[2]; + n4 = null; + if (tList.Count > 3) + { + n4 = tList[3]; + } + + //Determine most relevant spline: + GSDSplineC n1Spline = n1.GSDSpline; + GSDSplineC n2Spline = n2.GSDSpline; + GSDSplineC n3Spline = n3.GSDSpline; + GSDSplineC n4Spline = null; + if (n4 != null) + { + n4Spline = n4.GSDSpline; + } + + //Get the point: + Vector3 n1Point = GetFourCornerPoint(ref n1Spline, ref n1, GSDRI); + Vector3 n2Point = GetFourCornerPoint(ref n2Spline, ref n2, GSDRI); + Vector3 n3Point = GetFourCornerPoint(ref n3Spline, ref n3, GSDRI); + Vector3 n4Point = new Vector3(0f, 0f, 0f); + if (n4Spline != null) + { + n4Point = GetFourCornerPoint(ref n4Spline, ref n4, GSDRI); + } + + //2. If 3 way, we know that 2 of the nodes have the same spline. + if (1 == 1 && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.ThreeWay) + { + //Should be size 3: + if (tList.Count != 3) + { + Debug.LogError("InitializeIntersections hashset != 3 connected on three way intersection, real size: " + tList.Count + " on intersection: " + GSDRI.transform.name); + return; + } + + ProcessFourCorners(ref n1Point, ref n2Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n2Spline)); + ProcessFourCorners(ref n1Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n3Spline)); + ProcessFourCorners(ref n2Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n3Spline)); + + } + else if (GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay) + { + //Should be size 3: + if (tList.Count != 4) + { + Debug.LogError("InitializeIntersections hashset != 4 connected on four way intersection, real size: " + tList.Count + " on intersection: " + GSDRI.transform.name); + return; + } + + ProcessFourCorners(ref n1Point, ref n2Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n2Spline)); + ProcessFourCorners(ref n1Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n3Spline)); + ProcessFourCorners(ref n1Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n1Spline, n4Spline)); + ProcessFourCorners(ref n2Point, ref n3Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n3Spline)); + ProcessFourCorners(ref n2Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n2Spline, n4Spline)); + ProcessFourCorners(ref n3Point, ref n4Point, GSDRI.transform.gameObject, GetLongestSplineDistance(n3Spline, n4Spline)); + } + } + #endregion + + + #region "Intersection creation helpers" + private static float GetLongestSplineDistance(GSDSplineC s1, GSDSplineC s2) + { + if (s1.distance > s2.distance) + { + return s1.distance; + } + else + { + return s2.distance; + } + } + + + private static GSDSplineN GetNodeByID(int _ID) + { + Object[] SplineNodeObjects = GameObject.FindObjectsOfType(typeof(GSDSplineN)); + foreach (GSDSplineN tNode in SplineNodeObjects) + { + if (tNode.id == _ID) + { + return tNode; + } + } + return null; + } + + + static Vector3 GetFourCornerPoint(ref GSDSplineC tSpline, ref GSDSplineN tNode, GSDRoadIntersection GSDRI) + { + GSDSplineN iNode; + if (tNode.node_connected.Contains(GSDRI.Node1)) + { + iNode = GSDRI.Node1; + } + else + { + iNode = GSDRI.Node2; + } + + float Pos1 = tNode.tTime; + float iPos = iNode.tTime; + + float tFloat = 0; + float NewSplinePos = 0; + if (iPos >= Pos1) + { + tFloat = iPos - Pos1; + tFloat = tFloat / 8; + NewSplinePos = iPos - tFloat; + } + else + { + tFloat = Pos1 - iPos; + tFloat = tFloat / 8; + NewSplinePos = iPos + tFloat; + } + + Vector3 tVect = new Vector3(0, 0, 0); + + bool bDone = false; + int spamguard = 0; + float tDist = 0f; + while (!bDone && spamguard < 20000) + { + spamguard += 1; + tVect = tSpline.GetSplineValue(NewSplinePos); + tDist = Vector3.Distance(tVect, iNode.transform.position); + + if (tDist > 22f) + { + //Get closer to intersection: + if (iPos >= NewSplinePos) + { + NewSplinePos += 0.001f; + } + else + { + NewSplinePos -= 0.001f; + } + } + else if (tDist < 20f) + { + //Move away from intersection: + if (iPos >= NewSplinePos) + { + NewSplinePos -= 0.001f; + } + else + { + NewSplinePos += 0.001f; + } + } + else + { + bDone = true; + } + } + return tVect; + } + + + static void ProcessFourCorners(ref Vector3 n1, ref Vector3 n2, GameObject tIntersectionObject, float SplineDistance) + { + float Side1, Side2, Side3; + Side1 = Vector3.Distance(n1, n2); + Side2 = Vector3.Distance(tIntersectionObject.transform.position, n1); + Side3 = Vector3.Distance(tIntersectionObject.transform.position, n2); + float tAngle = AngleOfTriangle(Side2, Side3, Side1); + if (tAngle > 20f && tAngle < 140f) + { + ProcessTwoCorners(ref tIntersectionObject, ref n1, ref n2, SplineDistance); + } + } + + + static float AngleOfTriangle(float a, float b, float c) + { + float cAng = (a * a + b * b - c * c) / (2 * a * b); + float rad = Mathf.Acos(cAng); + float tFloat = Mathf.Rad2Deg * rad; + return tFloat; + } + + + static void ProcessTwoCorners(ref GameObject tIntersectionObject, ref Vector3 n1, ref Vector3 n2, float SplineDistance) + { + GameObject tCorner = GameObject.CreatePrimitive(PrimitiveType.Cube); + tCorner.transform.localScale = new Vector3(0.5f, 20f, 0.5f); + tCorner.name = "CornerPosition"; + tCorner.transform.parent = tIntersectionObject.transform; + tCorner.layer = 0; + + //Calculate the angle: + Vector3 v3BA = n2 - tIntersectionObject.transform.position; + Vector3 v3BC = n1 - tIntersectionObject.transform.position; + Vector3 axis = Vector3.Cross(v3BA, v3BC); + float angle = Vector3.Angle(v3BA, v3BC); + Vector3 v3 = Quaternion.AngleAxis(angle / 2.0f, axis) * v3BA; + //Vector3 v3 = (((n2.transform.position + n1.transform.position)/2) - tIntersectionObject.transform.position); + + tCorner.transform.rotation = Quaternion.LookRotation(v3); + + float tStep = 1.25f / SplineDistance; + bool bSuccess = MoveCorner(tStep, 3f, ref tCorner, ref tIntersectionObject, v3); + if (!bSuccess) + { + Debug.Log("not success"); + Object.DestroyImmediate(tCorner); + } + } + + + static bool MoveCorner(float tStep, float tDist, ref GameObject tCorner, ref GameObject tIntersectionObject, Vector3 v3) + { + float tStart = 0.05f; + bool bDone = false; + int spamguard = 0; + bool bHitRoad = false; + Collider[] tCollider; + while (!bDone) + { + spamguard += 1; + tCorner.transform.position = tIntersectionObject.transform.position + (v3 * tStart); + + if (Vector3.Distance(tCorner.transform.position, tIntersectionObject.transform.position) > 25f) + { + Debug.Log("too long"); + bDone = true; + return false; + } + if (spamguard > 80000) + { + Debug.Log("spamguard"); + bDone = true; + return false; + } + + //Cast sphere now + bHitRoad = false; + tCollider = Physics.OverlapSphere(tCorner.transform.position, tDist); + if (tCollider == null || tCollider.Length < 1) + { + tStart += tStep; + continue; + } + else + { + for (int k = 0; k < tCollider.Length; k++) + { + if (tCollider[k].transform.name.ToLower().Contains("road")) + { + bHitRoad = true; + break; + } + } + } + + if (bHitRoad) + { + tStart += tStep; + continue; + } + else + { + //Debug.Log ("Distance: " + Vector3.Distance(tCorner.transform.position,tIntersectionObject.transform.position)); + bDone = true; + break; + } + } + return true; + } + #endregion + + #endregion + } + + + public static class GSDNavigation + { + public static void UpdateConnectedNodes() + { + Init_ResetNavigationData(); + + Object[] SplineObjects = GameObject.FindObjectsOfType(typeof(GSDSplineC)); + + //Store connected spline nodes on each other: + GSDSplineN xNode; + foreach (GSDSplineC tSpline in SplineObjects) + { + int mNodeCount = tSpline.mNodes.Count; + for (int i = 0; i < mNodeCount; i++) + { + xNode = tSpline.mNodes[i]; + //Add next node if not last node: + if ((i + 1) < mNodeCount) + { + xNode.id_connected.Add(tSpline.mNodes[i + 1].id); + xNode.node_connected.Add(tSpline.mNodes[i + 1]); + } + //Add prev node if not first node: + if (i > 0) + { + xNode.id_connected.Add(tSpline.mNodes[i - 1].id); + xNode.node_connected.Add(tSpline.mNodes[i - 1]); + } + } + } + } + + + public static void Init_ResetNavigationData() + { + Object[] tSplines = GameObject.FindObjectsOfType(typeof(GSDSplineC)); + int SplineCount = 0; + int NodeCount = 0; + foreach (GSDSplineC tSpline in tSplines) + { + SplineCount += 1; + foreach (GSDSplineN tNode in tSpline.mNodes) + { + NodeCount += 1; + tNode.ResetNavigationData(); + } + tSpline.ResetNavigationData(); + } + } + } + +#endif +} \ No newline at end of file diff --git a/GSDRoadUtilityEditor.cs b/GSDRoadUtilityEditor.cs index 2167dc5f..dd4d7dd1 100755 --- a/GSDRoadUtilityEditor.cs +++ b/GSDRoadUtilityEditor.cs @@ -1,66 +1,78 @@ -using UnityEngine; -using System.IO; -using System; -#if UNITY_EDITOR -using UnityEditor; -#endif -namespace GSD.Roads -{ - public static class GSDRoadUtilityEditor - { - private static readonly string[] validFolders = - { - "Assets/RoadArchitect", - "Assets/RoadArchitect-master", - "Assets/Resources/RoadArchitect", - "Assets/Resources/RoadArchitect-master" - }; - public static string GetBasePath() - { - // TODO this might break in future versions of Unity -#if UNITY_EDITOR - foreach (string folder in validFolders) - { - if (Directory.Exists(Environment.CurrentDirectory + "/" + folder)) - return folder; - } - throw new System.Exception("RoadArchitect must be placed in one of the valid folders, read the top of this script"); -#else - return ""; -#endif - } -#if UNITY_EDITOR - public static void SetRoadMaterial(string tPath, MeshRenderer MR, string tPath2 = "") - { - Material tMat2; - - Material[] tMats; - Material tMat = (Material)AssetDatabase.LoadAssetAtPath(tPath, typeof(Material)); - if (tPath2.Length > 0) - { - tMats = new Material[2]; - tMats[0] = tMat; - tMat2 = (Material)AssetDatabase.LoadAssetAtPath(tPath2, typeof(Material)); - tMats[1] = tMat2; - } - else - { - tMats = new Material[1]; - tMats[0] = tMat; - } - - MR.sharedMaterials = tMats; - } - - public static Material GiveMaterial(string tPath) - { - return (Material)AssetDatabase.LoadAssetAtPath(tPath, typeof(Material)); - } - - public static PhysicMaterial GivePhysicsMaterial(string tPath) - { - return (PhysicMaterial)AssetDatabase.LoadAssetAtPath(tPath, typeof(PhysicMaterial)); - } -#endif - } +#region "Imports" +using UnityEngine; +using System.IO; +using System; +#if UNITY_EDITOR +using UnityEditor; +#endif +#endregion + + +namespace GSD.Roads +{ + public static class GSDRoadUtilityEditor + { + private static readonly string[] validFolders = + { + "Assets/RoadArchitect", + "Assets/RoadArchitect-master", + "Assets/Resources/RoadArchitect", + "Assets/Resources/RoadArchitect-master" + }; + + + public static string GetBasePath() + { + // TODO this might break in future versions of Unity +#if UNITY_EDITOR + foreach (string folder in validFolders) + { + if (Directory.Exists(Environment.CurrentDirectory + "/" + folder)) + { + return folder; + } + } + throw new System.Exception("RoadArchitect must be placed in one of the valid folders, read the top of this script"); +#else + return ""; +#endif + } + + +#if UNITY_EDITOR + public static void SetRoadMaterial(string tPath, MeshRenderer MR, string tPath2 = "") + { + Material tMat2; + + Material[] tMats; + Material tMat = (Material) AssetDatabase.LoadAssetAtPath(tPath, typeof(Material)); + if (tPath2.Length > 0) + { + tMats = new Material[2]; + tMats[0] = tMat; + tMat2 = (Material) AssetDatabase.LoadAssetAtPath(tPath2, typeof(Material)); + tMats[1] = tMat2; + } + else + { + tMats = new Material[1]; + tMats[0] = tMat; + } + + MR.sharedMaterials = tMats; + } + + + public static Material GiveMaterial(string tPath) + { + return (Material) AssetDatabase.LoadAssetAtPath(tPath, typeof(Material)); + } + + + public static PhysicMaterial GivePhysicsMaterial(string tPath) + { + return (PhysicMaterial) AssetDatabase.LoadAssetAtPath(tPath, typeof(PhysicMaterial)); + } +#endif + } } \ No newline at end of file diff --git a/GSDRoadUtilityT.cs b/GSDRoadUtilityT.cs index ced52069..1fde3654 100755 --- a/GSDRoadUtilityT.cs +++ b/GSDRoadUtilityT.cs @@ -1,7841 +1,8681 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections; -using System.Collections.Generic; -using GSD; -#endif -namespace GSD.Threaded -{ -#if UNITY_EDITOR - - public static class GSDTerraformingT - { - public class TerrainBoundsMaker - { - public List triList; - public GSD.Roads.GSDRoadUtil.Construction2DRect tRect; - public float MinI = 0f; - public float MaxI = 1f; - } - - // static Vector3 ProcessLineHeights_PrevVect = new Vector3(0f,0f,0f); - // public static float ProcessLineHeights(GSDSplineC tSpline, ref Vector3 tVect, ref Vector3 POS, float tDistance, GSD.Roads.GSDTerraforming.TempTerrainData TTD, float PrevDesiredHeight){ - // Vector3 ShoulderR_rVect = new Vector3(0f,0f,0f); - // Vector3 ShoulderL_lVect = new Vector3(0f,0f,0f); - // - // float DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect,ref TTD, ref tSpline); - // float nResult = 0f; - // bool bIntersection = tSpline.IsNearIntersection(ref tVect,ref nResult); - // if(bIntersection){ - // if(nResult < tVect.y){ - // tVect.y = nResult; - // DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect,ref TTD, ref tSpline); - // } - // } - // - // int x1 = 0,y1 = 0; - // GetTempHeights_Coordinates(ref tVect,ref TTD,out x1,out y1); - // - // bool bOverride = false; - // int StepMod = (int)(1 / TTD.HMRatio); - // for(float i=tDistance;i>=1f;i-=StepMod){ - // ShoulderR_rVect = (tVect + new Vector3(i*POS.normalized.z,0,i*-POS.normalized.x)); - // GetTempHeights_Coordinates(ref ShoulderR_rVect,ref TTD,out x1,out y1); - // if(TTD.heights[x1,y1] > DesiredHeight){ - // bOverride = true; - // } - // if(bOverride || !TTD.tHeights[x1,y1]){ - // TTD.tHeights[x1,y1] = true; - // TTD.cX[TTD.cI] = x1; - // TTD.cY[TTD.cI] = y1; - // TTD.cH[TTD.cI] = DesiredHeight; - // TTD.oldH[TTD.cI] = TTD.heights[x1,y1]; - // TTD.cI += 1; - // } - // bOverride = false; - // - // ShoulderL_lVect = (tVect + new Vector3(i*-POS.normalized.z,0,i*POS.normalized.x)); - // GetTempHeights_Coordinates(ref ShoulderL_lVect,ref TTD,out x1,out y1); - // if(TTD.heights[x1,y1] > DesiredHeight){ - // bOverride = true; - // } - // if(bOverride || !TTD.tHeights[x1,y1]){ - // TTD.tHeights[x1,y1] = true; - // TTD.cX[TTD.cI] = x1; - // TTD.cY[TTD.cI] = y1; - // TTD.cH[TTD.cI] = DesiredHeight; - // TTD.oldH[TTD.cI] = TTD.heights[x1,y1]; - // TTD.cI += 1; - // } - // bOverride=false; - // } - // - // GetTempHeights_Coordinates(ref tVect,ref TTD,out x1,out y1); - // if(TTD.heights[x1,y1] > DesiredHeight || (tVect.y < ProcessLineHeights_PrevVect.y)){ - // bOverride = true; - // } - // if(bOverride || !TTD.tHeights[x1,y1]){ - // TTD.tHeights[x1,y1] = true; - // TTD.cX[TTD.cI] = x1; - // TTD.cY[TTD.cI] = y1; - // if(tDistance > 15f && TTD.HMRatio > 0.24f){ - // TTD.cH[TTD.cI] = DesiredHeight-0.0002f; - // }else{ - // TTD.cH[TTD.cI] = DesiredHeight; - // } - // TTD.oldH[TTD.cI] = TTD.heights[x1,y1]; - // TTD.cI += 1; - // } - // - // ProcessLineHeights_PrevVect = tVect; - // return DesiredHeight; - // } - // - // private static float ProcessLineHeights_GetDesiredHeight(Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref GSDSplineC tSpline){ - // return ((((tVect - TTD.TerrainPos).y)-tSpline.tRoad.opt_TerrainSubtract_Alt) / TTD.TerrainSize.y); - // } - - private static void GetTempHeights_Coordinates(ref Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, out int x, out int y) - { - //Get the normalized position of this game object relative to the terrain: - Vector3 tempCoord = (tVect - TTD.TerrainPos); - - Vector3 coord; - coord.x = tempCoord.x / TTD.TerrainSize.x; - coord.y = tempCoord.y / TTD.TerrainSize.y; - coord.z = tempCoord.z / TTD.TerrainSize.z; - - //Get the position of the terrain heightmap where this game object is: - y = (int)(coord.x * TTD.HM); - x = (int)(coord.z * TTD.HM); - } - - private static void GetTempDetails_Coordinates(ref Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, out int x, out int y) - { - //Get the normalized position of this game object relative to the terrain: - Vector3 tempCoord = (tVect - TTD.TerrainPos); - - Vector3 coord; - coord.x = tempCoord.x / TTD.TerrainSize.x; - coord.y = tempCoord.y / TTD.TerrainSize.y; - coord.z = tempCoord.z / TTD.TerrainSize.z; - - //Get the position of the terrain heightmap where this game object is: - y = (int)(coord.x * TTD.DetailMaxIndex); - x = (int)(coord.z * TTD.DetailMaxIndex); - } - - //Privatized for obfuscate: - public static void DoRects(GSDSplineC tSpline, GSD.Roads.GSDTerraforming.TempTerrainData TTD) - { - DoRectsDo(ref tSpline, ref TTD); - } - - private static void DoRectsDo(ref GSDSplineC tSpline, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD) - { - float Sep = tSpline.tRoad.RoadWidth() * 0.5f; - float HeightSep = Sep + (tSpline.tRoad.opt_MatchHeightsDistance * 0.5f); - List TBMList = new List(); - // List triList = new List(); - List TreerectList = new List(); - float tStep = tSpline.tRoad.opt_RoadDefinition / tSpline.distance; - // tStep *= 0.5f; - - //Start initializing the loop. Convuluted to handle special control nodes, so roads don't get rendered where they aren't supposed to, while still preserving the proper curvature. - float FinalMax = 1f; - float StartMin = 0f; - if (tSpline.bSpecialEndControlNode) - { //If control node, start after the control node: - FinalMax = tSpline.mNodes[tSpline.GetNodeCount() - 2].tTime; - } - if (tSpline.bSpecialStartControlNode) - { //If ends in control node, end construction before the control node: - StartMin = tSpline.mNodes[1].tTime; - } - // bool bFinalEnd = false; - // float RoadConnection_StartMin1 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. - // float RoadConnection_FinalMax1 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. - if (tSpline.bSpecialEndNode_IsStart_Delay) - { - StartMin += (tSpline.SpecialEndNodeDelay_Start / tSpline.distance); //If there's a start delay (in meters), delay the start of road construction: Due to special control nodes for road connections or 3 way intersections. - } - else if (tSpline.bSpecialEndNode_IsEnd_Delay) - { - FinalMax -= (tSpline.SpecialEndNodeDelay_End / tSpline.distance); //If there's a end delay (in meters), cut early the end of road construction: Due to special control nodes for road connections or 3 way intersections. - } - // float RoadConnection_StartMin2 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. - // float RoadConnection_FinalMax2 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. - - FinalMax = FinalMax + tStep; - - Vector3 tVect1 = default(Vector3); - Vector3 tVect2 = default(Vector3); - Vector3 POS1 = default(Vector3); - Vector3 POS2 = default(Vector3); - if (FinalMax > 1f) { FinalMax = 1f; } - - float tNext = 0f; - float fValue1, fValue2; - float fValueMod = tSpline.tRoad.opt_RoadDefinition / tSpline.distance; - bool bIsPastInter = false; - float tIntStrength = 0f; - float tIntStrength2 = 0f; - // bool bMaxIntersection = false; - // bool bFirstInterNode = false; - GSDSplineN xNode = null; - float tIntHeight = 0f; - float tIntHeight2 = 0f; - GSDRoadIntersection GSDRI = null; - float T1SUB = 0f; - float T2SUB = 0f; - bool bIntStr1_Full = false; - bool bIntStr1_FullPrev = false; - bool bIntStr1_FullNext = false; - bool bIntStr2_Full = false; - bool bIntStr2_FullPrev = false; - bool bIntStr2_FullNext = false; - Vector3 tVect3 = default(Vector3); - // bool bStarted = false; - // bool T3Added = false; - List tXYs = new List(); - float TreeClearDist = tSpline.tRoad.opt_ClearTreesDistance; - if (TreeClearDist < tSpline.tRoad.RoadWidth()) { TreeClearDist = tSpline.tRoad.RoadWidth(); } - GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; - float tGrade = 0f; - for (float i = StartMin; i < FinalMax; i += tStep) - { - if (tSpline.tRoad.opt_HeightModEnabled) - { - if (i > 1f) { break; } - tNext = i + tStep; - if (tNext > 1f) { break; } - - tSpline.GetSplineValue_Both(i, out tVect1, out POS1); - - if (tNext <= 1f) - { - tSpline.GetSplineValue_Both(tNext, out tVect2, out POS2); - } - else - { - tSpline.GetSplineValue_Both(1f, out tVect2, out POS2); - } - - //Determine if intersection: - bIsPastInter = false; //If past intersection - tIntStrength = tSpline.IntersectionStrength(ref tVect1, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - // if(IsApproximately(tIntStrength,1f,0.001f) || tIntStrength > 1f){ - // bMaxIntersection = true; - // }else{ - // bMaxIntersection = false; - // } - // bFirstInterNode = false; - - tIntStrength2 = tSpline.IntersectionStrength(ref tVect2, ref tIntHeight2, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - if (tIntStrength2 > 1f) { tIntStrength2 = 1f; } - - T1SUB = tVect1.y; - T2SUB = tVect2.y; - - if (tIntStrength > 1f) { tIntStrength = 1f; } - if (tIntStrength >= 0f) - {// || IsApproximately(tIntStrength,0f,0.01f)){ - if (IsApproximately(tIntStrength, 1f, 0.01f)) - { - T1SUB = tIntHeight; - bIntStr1_Full = true; - bIntStr1_FullNext = false; - } - else - { - bIntStr1_Full = false; - bIntStr1_FullNext = (tIntStrength2 >= 1f); - if (!IsApproximately(tIntStrength, 0f, 0.01f)) { T1SUB = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect1.y); } - // if(tIntStrength <= 0f){ T1SUB = (tIntStrength*tIntHeight) + ((1-tIntStrength)*tVect1.y); } - } - - if ((bIntStr1_Full && !bIntStr1_FullPrev) || (!bIntStr1_Full && bIntStr1_FullNext)) - { - tGrade = tSpline.GetCurrentNode(i).GradeToPrevValue; - if (tGrade < 0f) - { - T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); - } - else - { - T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); - } - - // if(tGrade < 0f){ - // T1SUB *= -1f; - // } - } - else if (bIntStr1_Full && !bIntStr1_FullNext) - { - tGrade = tSpline.GetCurrentNode(i).GradeToNextValue; - if (tGrade < 0f) - { - T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); - } - else - { - T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); - } - // if(tGrade < 0f){ - // T1SUB *= -1f; - // } - } - else - { - T1SUB -= 0.02f; - } - bIntStr1_FullPrev = bIntStr1_Full; - } - - if (tIntStrength2 >= 0f || IsApproximately(tIntStrength2, 0f, 0.01f)) - { - // if(!IsApproximately(tIntStrength,1f,0.01f)){ - if (IsApproximately(tIntStrength, 1f, 0.01f)) - { - bIntStr2_Full = true; - T2SUB = tIntHeight2; - } - else - { - bIntStr2_Full = false; - if (!IsApproximately(tIntStrength2, 0f, 0.01f)) { T2SUB = (tIntStrength2 * tIntHeight) + ((1 - tIntStrength2) * tVect2.y); } - // if(tIntStrength2 <= 0f){ T2SUB = (tIntStrength2*tIntHeight) + ((1-tIntStrength2)*tVect2.y); } - } - - if ((bIntStr2_Full && !bIntStr2_FullPrev)) - { - tGrade = tSpline.GetCurrentNode(i).GradeToPrevValue; - if (tGrade < 0f) - { - T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); - } - else - { - T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); - } - // T2SUB -= tIntHeight2 - tVect2.y; - } - else if (bIntStr2_Full && !bIntStr2_FullNext) - { - tGrade = tSpline.GetCurrentNode(i).GradeToNextValue; - if (tGrade < 0f) - { - T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); - } - else - { - T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); - } - // if(tGrade < 0f){ - // T2SUB *= -1f; - // } - // T2SUB -= tIntHeight2 - tVect2.y; - } - else if (!bIntStr2_Full) - { - if (tNext + tStep < 1f) - { - tVect3 = tSpline.GetSplineValue(tNext + tStep, false); - tIntStrength2 = tSpline.IntersectionStrength(ref tVect3, ref tIntHeight2, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - } - else - { - tIntStrength2 = 0f; - } - - if (tIntStrength2 >= 1f) - { - T2SUB -= 0.06f; - } - else - { - T2SUB -= 0.02f; - } - } - else - { - T2SUB -= 0.02f; - } - bIntStr2_FullPrev = bIntStr2_Full; - } - - fValue1 = i - fValueMod; - fValue2 = i + fValueMod; - if (fValue1 < 0) { fValue1 = 0; } - if (fValue2 > 1) { fValue2 = 1; } - - tXYs.Add(CreateTris(fValue1, fValue2, ref tVect1, ref POS1, ref tVect2, ref POS2, Sep, ref TBMList, ref T1SUB, ref T2SUB, ref TTD, HeightSep)); - - //Details and trees: - tRect = SetDetailCoords(i, ref tVect1, ref POS1, ref tVect2, ref POS2, tSpline.tRoad.opt_ClearDetailsDistance, TreeClearDist, ref TTD, ref tSpline); - if (tSpline.tRoad.opt_TreeModEnabled && tRect != null) - { - TreerectList.Add(tRect); - } - } - else - { - if (i > 1f) { break; } - tNext = i + tStep; - if (tNext > 1f) { break; } - - tSpline.GetSplineValue_Both(i, out tVect1, out POS1); - - if (tNext <= 1f) - { - tSpline.GetSplineValue_Both(tNext, out tVect2, out POS2); - } - else - { - tSpline.GetSplineValue_Both(1f, out tVect2, out POS2); - } - - //Details and trees: - tRect = SetDetailCoords(i, ref tVect1, ref POS1, ref tVect2, ref POS2, tSpline.tRoad.opt_ClearDetailsDistance, TreeClearDist, ref TTD, ref tSpline); - if (tSpline.tRoad.opt_TreeModEnabled && tRect != null) - { - TreerectList.Add(tRect); - } - } - } - - if (tSpline.tRoad.bProfiling) - { - UnityEngine.Profiling.Profiler.BeginSample("DoRectsTree"); - } - if (tSpline.tRoad.opt_TreeModEnabled && TreerectList != null && TreerectList.Count > 0) - { - int tCount = TTD.TreeSize; - int jCount = TreerectList.Count; - Vector3 tVect3D = default(Vector3); - Vector2 tVect2D = default(Vector2); - TreeInstance tTree; - for (int i = 0; i < tCount; i++) - { - tTree = TTD.TreesCurrent[i]; - - tVect3D = tTree.position; - tVect3D.x *= TTD.TerrainSize.z; - tVect3D.y *= TTD.TerrainSize.y; - tVect3D.z *= TTD.TerrainSize.x; - tVect3D += TTD.TerrainPos; - tVect2D.x = tVect3D.x; - tVect2D.y = tVect3D.z; - - for (int j = 0; j < jCount; j++) - { - if (TreerectList[j].Contains(ref tVect2D)) - { - TTD.TreesOld.Add(TTD.TreesCurrent[i]); - tTree = TTD.TreesCurrent[i]; - tTree.prototypeIndex = -2; - TTD.TreesCurrent[i] = tTree; - TTD.TreesI += 1; - break; - } - } - } - TTD.TreesCurrent.RemoveAll(item => item.prototypeIndex < -1); - } - if (tSpline.tRoad.bProfiling) - { - UnityEngine.Profiling.Profiler.EndSample(); - } - - if (!tSpline.tRoad.opt_HeightModEnabled) - { - return; - } - - // //Temp testing: - // tSpline.mNodes[22].tTriList = new List(); - // int tCount = triList.Count; - // for(int i=0;i(); - - - float tFloat = -1f; - Sep = tSpline.tRoad.RoadWidth() * 1.5f; - int k = 0; - int[] tXY = null; - int tXYsCount = tXYs.Count; - bool bIsBridge = false; - bool bIsTunnel = false; - for (float i = StartMin; i < FinalMax; i += tStep) - { - if (TBMList.Count > 0) - { - if (TBMList[0].MaxI < i) - { - CleanupTris(i, ref TBMList); - } - } - else - { - break; - } - - //If in bridg mode: - if (tSpline.IsInBridgeTerrain(i)) - { - bIsBridge = true; - } - else - { - bIsBridge = false; - } - //If in tunnel mode: - if (tSpline.IsInTunnelTerrain(i)) - { - bIsTunnel = true; - } - else - { - bIsTunnel = false; - } - - if (k < tXYsCount) - { - tXY = tXYs[k]; - tFloat = ProcessCoordinateGrabber(ref i, ref tSpline, ref TTD, ref TBMList, ref tXY, bIsBridge, bIsTunnel); - if (!IsApproximately(tFloat, 0f, 0.0001f)) - { - tSpline.HeightHistory.Add(new KeyValuePair(i, tFloat)); - } - } - else - { - break; - } - k += 1; - } - } - - private static void CleanupTris(float CurrentI, ref List tList) - { - int mCount = tList.Count; - int LastIndexToRemove = -1; - for (int i = 0; i < mCount; i++) - { - if (tList[i].MaxI < CurrentI) - { - LastIndexToRemove = i; - } - else - { - break; - } - } - if (LastIndexToRemove >= 0) - { - tList.RemoveRange(0, LastIndexToRemove); - } - // - // mCount = rectList.Count; - // LastIndexToRemove = -1; - // for(int i=0;i= 0){ - // rectList.RemoveRange(0,LastIndexToRemove); - // } - } - - private static int[] CreateTris(float i, float i2, ref Vector3 tVect1, ref Vector3 POS1, ref Vector3 tVect2, ref Vector3 POS2, float Sep, ref List tList, ref float T1SUB, ref float T2SUB, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, float HeightSep) - { - Vector3 lVect1 = (tVect1 + new Vector3(Sep * -POS1.normalized.z, 0, Sep * POS1.normalized.x)); - Vector3 rVect1 = (tVect1 + new Vector3(Sep * POS1.normalized.z, 0, Sep * -POS1.normalized.x)); - Vector3 lVect2 = (tVect2 + new Vector3(Sep * -POS2.normalized.z, 0, Sep * POS2.normalized.x)); - Vector3 rVect2 = (tVect2 + new Vector3(Sep * POS2.normalized.z, 0, Sep * -POS2.normalized.x)); - - lVect1.y = T1SUB; - rVect1.y = T1SUB; - lVect2.y = T2SUB; - rVect2.y = T2SUB; - - TerrainBoundsMaker TBM = new TerrainBoundsMaker(); - TBM.triList = new List(); - - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect1, rVect1, lVect2, i, i2)); - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect2, rVect1, rVect2, i, i2)); - - Vector3 lVect1far = (tVect1 + new Vector3(HeightSep * -POS1.normalized.z, 0, HeightSep * POS1.normalized.x)); - Vector3 rVect1far = (tVect1 + new Vector3(HeightSep * POS1.normalized.z, 0, HeightSep * -POS1.normalized.x)); - Vector3 lVect2far = (tVect2 + new Vector3(HeightSep * -POS2.normalized.z, 0, HeightSep * POS2.normalized.x)); - Vector3 rVect2far = (tVect2 + new Vector3(HeightSep * POS2.normalized.z, 0, HeightSep * -POS2.normalized.x)); - - lVect1far.y = lVect1.y; - lVect2far.y = lVect2.y; - rVect1far.y = rVect1.y; - rVect2far.y = rVect2.y; - - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect1far, lVect1, lVect2far, i, i2)); - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect2far, lVect1, lVect2, i, i2)); - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(rVect1, rVect1far, rVect2, i, i2)); - TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(rVect2, rVect1far, rVect2far, i, i2)); - - TBM.tRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f); - // tRect.MinI = i; - // tRect.MaxI = i2; - - TBM.MinI = i; - TBM.MaxI = i2; - - tList.Add(TBM); - - int[] Xs = new int[4]; - int[] Ys = new int[4]; - - int x1, y1; - GetTempHeights_Coordinates(ref lVect1far, ref TTD, out x1, out y1); - Xs[0] = x1; - Ys[0] = y1; - GetTempHeights_Coordinates(ref lVect2far, ref TTD, out x1, out y1); - Xs[1] = x1; - Ys[1] = y1; - GetTempHeights_Coordinates(ref rVect1far, ref TTD, out x1, out y1); - Xs[2] = x1; - Ys[2] = y1; - GetTempHeights_Coordinates(ref rVect2far, ref TTD, out x1, out y1); - Xs[3] = x1; - Ys[3] = y1; - - int Min = Mathf.Min(Xs); - int Max = Mathf.Max(Xs); - Xs[0] = Min - 2; - Xs[2] = Max + 2; - Min = Mathf.Min(Ys); - Max = Mathf.Max(Ys); - Xs[1] = Min - 2; - Xs[3] = Max + 2; - - return Xs; - } - - private static GSD.Roads.GSDRoadUtil.Construction2DRect SetDetailCoords(float param, ref Vector3 tVect1, ref Vector3 POS1, ref Vector3 tVect2, ref Vector3 POS2, float Sep, float TreeSep, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref GSDSplineC tSpline) - { - Vector3 lVect1far = default(Vector3); - Vector3 rVect1far = default(Vector3); - Vector3 lVect2far = default(Vector3); - Vector3 rVect2far = default(Vector3); - - bool bIsInBridge = tSpline.IsInBridgeTerrain(param); - bool bIsInTunnel = tSpline.IsInTunnelTerrain(param); - int x2, y2, x3, y3; - GetTempHeights_Coordinates(ref tVect1, ref TTD, out x2, out y2); - if (x2 >= TTD.HM) { x2 = -1; } - if (y2 >= TTD.HM) { y2 = -1; } - if (x2 < 0) { x2 = -1; } - if (y2 < 0) { y2 = -1; } - if (x2 == -1) { return null; } - if (y2 == -1) { return null; } - - float tDiff1 = ((TTD.heights[x2, y2] * (float)TTD.TerrainSize.y) - tVect1.y); - GetTempHeights_Coordinates(ref tVect2, ref TTD, out x3, out y3); - if (x3 >= TTD.HM) { x3 = -1; } - if (y3 >= TTD.HM) { y3 = -1; } - if (x3 < 0) { x3 = -1; } - if (y3 < 0) { y3 = -1; } - if (x3 == -1) { return null; } - if (y3 == -1) { return null; } - float tDiff2 = ((TTD.heights[x3, y3] * (float)TTD.TerrainSize.y) - tVect2.y); - - - - GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; - if (tSpline.tRoad.opt_TreeModEnabled) - { - bool bQuit = false; - if (x2 == -1) { bQuit = true; } - if (y2 == -1) { bQuit = true; } - - if (bIsInBridge && !bQuit) - { - if (tDiff1 < 0f) { tDiff1 *= -1f; } - if (tDiff2 < 0f) { tDiff2 *= -1f; } - if (tDiff1 > tSpline.tRoad.opt_ClearTreesDistanceHeight) - { - bQuit = true; - } - if (tDiff2 > tSpline.tRoad.opt_ClearTreesDistanceHeight) - { - bQuit = true; - } - } - if (bIsInTunnel && !bQuit) - { - if (tDiff1 < 0f) - { - if ((tDiff1 * -1f) > tSpline.tRoad.opt_ClearTreesDistanceHeight) - { - bQuit = true; - } - } - else - { - if (tDiff1 > (tSpline.tRoad.opt_ClearTreesDistanceHeight * 0.1f)) - { - bQuit = true; - } - } - if (tDiff2 < 0f) - { - if ((tDiff2 * -1f) > tSpline.tRoad.opt_ClearTreesDistanceHeight) - { - bQuit = true; - } - } - else - { - if (tDiff2 > (tSpline.tRoad.opt_ClearTreesDistanceHeight * 0.1f)) - { - bQuit = true; - } - } - } - - if (!bQuit) - { - TreeSep = TreeSep * 0.5f; - lVect1far = (tVect1 + new Vector3(TreeSep * -POS1.normalized.z, 0, TreeSep * POS1.normalized.x)); - rVect1far = (tVect1 + new Vector3(TreeSep * POS1.normalized.z, 0, TreeSep * -POS1.normalized.x)); - lVect2far = (tVect2 + new Vector3(TreeSep * -POS2.normalized.z, 0, TreeSep * POS2.normalized.x)); - rVect2far = (tVect2 + new Vector3(TreeSep * POS2.normalized.z, 0, TreeSep * -POS2.normalized.x)); - tRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f); - } - } - - if (tSpline.tRoad.opt_DetailModEnabled) - { - if (bIsInBridge || bIsInTunnel) - { - if (tDiff1 < 0f) { tDiff1 *= -1f; } - if (tDiff2 < 0f) { tDiff2 *= -1f; } - - bool bQuit = false; - if (x2 == -1) { bQuit = true; } - if (y2 == -1) { bQuit = true; } - - if (tDiff1 > tSpline.tRoad.opt_ClearDetailsDistanceHeight) - { - bQuit = true; - } - if (tDiff2 > tSpline.tRoad.opt_ClearDetailsDistanceHeight) - { - bQuit = true; - } - - if (bQuit) - { - return tRect; - } - } - - Sep = Sep * 0.5f; - - lVect1far = (tVect1 + new Vector3(Sep * -POS1.normalized.z, 0, Sep * POS1.normalized.x)); - rVect1far = (tVect1 + new Vector3(Sep * POS1.normalized.z, 0, Sep * -POS1.normalized.x)); - lVect2far = (tVect2 + new Vector3(Sep * -POS2.normalized.z, 0, Sep * POS2.normalized.x)); - rVect2far = (tVect2 + new Vector3(Sep * POS2.normalized.z, 0, Sep * -POS2.normalized.x)); - - int[] Xs = new int[4]; - int[] Ys = new int[4]; - - int x1, y1; - GetTempDetails_Coordinates(ref lVect1far, ref TTD, out x1, out y1); - Xs[0] = x1; - Ys[0] = y1; - GetTempDetails_Coordinates(ref lVect2far, ref TTD, out x1, out y1); - Xs[1] = x1; - Ys[1] = y1; - GetTempDetails_Coordinates(ref rVect1far, ref TTD, out x1, out y1); - Xs[2] = x1; - Ys[2] = y1; - GetTempDetails_Coordinates(ref rVect2far, ref TTD, out x1, out y1); - Xs[3] = x1; - Ys[3] = y1; - // - // if(TTD.DetailLayersCount == 1 && x1 > 0 && y1 > 0){ - // Debug.Log(Xs[0]+","+Ys[0] + " " + Xs[1]+","+Ys[1]); - // } - - int MinX = Mathf.Min(Xs); - int MinY = Mathf.Min(Ys); - int MaxX = Mathf.Max(Xs); - int MaxY = Mathf.Max(Ys); - - if (MinX >= TTD.DetailMaxIndex) { MinX = TTD.DetailMaxIndex - 1; } - if (MinY >= TTD.DetailMaxIndex) { MinY = TTD.DetailMaxIndex - 1; } - if (MaxX >= TTD.DetailMaxIndex) { MaxX = TTD.DetailMaxIndex - 1; } - if (MaxY >= TTD.DetailMaxIndex) { MaxY = TTD.DetailMaxIndex - 1; } - - if (MinX < 0) { MinX = 0; } - if (MinY < 0) { MinY = 0; } - if (MaxX < 0) { MaxX = 0; } - if (MaxY < 0) { MaxY = 0; } - - // int DetailI = 0; - if (tSpline.tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("Dorectsdetails"); } - int tInt = 0; - for (int i = MinX; i <= MaxX; i++) - { - for (int k = MinY; k <= MaxY; k++) - { - //Bitfield for identification: - tInt = k; - tInt = tInt << 16; - tInt = tInt | (ushort)i; - if (!TTD.DetailHasProcessed.Contains(tInt)) - { - // for(int h=0;h 0){ - - TTD.MainDetailsX.Add((ushort)i); - TTD.MainDetailsY.Add((ushort)k); - - // DetailI = TTD.DetailsI[h]; - - // TTD.DetailsX[h].Add((ushort)i); - // TTD.DetailsY[h].Add((ushort)k); - - // TTD.DetailsX[h][DetailI] = (ushort)i; - // TTD.DetailsY[h][DetailI] = (ushort)k; - // TTD.OldDetailsValue[h][DetailI] = (ushort)TTD.DetailValues[h][i,k]; - // TTD.DetailValues[h][i,k] = 0; - - // TTD.DetailsI[h]+=1; - - // } - TTD.DetailHasProcessed.Add(tInt); - } - } - } - if (tSpline.tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - } - - return tRect; - } - - private static float ProcessCoordinateGrabber(ref float param, ref GSDSplineC tSpline, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref List tList, ref int[] tXY, bool bIsBridge, bool bIsTunnel) - { - int MinX = tXY[0]; - int MinY = tXY[1]; - int MaxX = tXY[2]; - int MaxY = tXY[3]; - - if (MinX >= TTD.TerrainMaxIndex) { MinX = TTD.TerrainMaxIndex - 1; } - if (MinY >= TTD.TerrainMaxIndex) { MinY = TTD.TerrainMaxIndex - 1; } - if (MaxX >= TTD.TerrainMaxIndex) { MaxX = TTD.TerrainMaxIndex - 1; } - if (MaxY >= TTD.TerrainMaxIndex) { MaxY = TTD.TerrainMaxIndex - 1; } - - if (MinX < 0) { MinX = 0; } - if (MinY < 0) { MinY = 0; } - if (MaxX < 0) { MaxX = 0; } - if (MaxY < 0) { MaxY = 0; } - - Vector3 xVect = default(Vector3); - bool bAdjusted = false; - float tHeight = -1f; - float tReturnFloat = 0f; - // int dX = 0; - // int dY = 0; - // int tdX = 0; - // int tdY = 0; - // bool bOneHit = false; - - for (int i = MinX; i <= MaxX; i++) - { - for (int k = MinY; k <= MaxY; k++) - { - if (TTD.tHeights[i, k] != true) - { - if (TTD.cX.Length <= TTD.cI) { break; } - - xVect = ConvertTerrainCoordToWorldVect(i, k, TTD.heights[i, k], ref TTD); - AdjustedTerrainVect_Tri(ref param, out bAdjusted, out tHeight, ref xVect, ref tList, bIsBridge, bIsTunnel); - - if (bAdjusted) - { - tHeight -= tSpline.tRoad.opt_TerrainSubtract_Match; - if (tHeight < 0f) { tHeight = 0f; } - xVect.y = tHeight; - tHeight = ((tHeight) / TTD.TerrainSize.y); - - //Set height values: - TTD.tHeights[i, k] = true; - TTD.cX[TTD.cI] = (ushort)i; - TTD.cY[TTD.cI] = (ushort)k; - TTD.oldH[TTD.cI] = TTD.heights[i, k]; - TTD.heights[i, k] = tHeight; - TTD.cI += 1; - - tReturnFloat = xVect.y; - // bOneHit = true; - } - } - else - { - xVect = ConvertTerrainCoordToWorldVect(i, k, TTD.heights[i, k], ref TTD); - AdjustedTerrainVect_Tri(ref param, out bAdjusted, out tHeight, ref xVect, ref tList, bIsBridge, bIsTunnel); - - if (bAdjusted) - { - tHeight -= tSpline.tRoad.opt_TerrainSubtract_Match; - if (tHeight < 0f) { tHeight = 0f; } - tReturnFloat = tHeight; - // bOneHit = true; - } - } - } - } - - if (bIsBridge && IsApproximately(tReturnFloat, 0f, 0.0001f)) - { - tReturnFloat = tSpline.GetSplineValue(param, false).y; - } - - return tReturnFloat; - } - - private static Vector3 ConvertTerrainCoordToWorldVect(int x, int y, float tHeight, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD) - { - //Get the normalized position of this game object relative to the terrain: - float x1 = x / ((float)TTD.HM - 1f); - x1 = x1 * TTD.TerrainSize.x; - - float z1 = y / ((float)TTD.HM - 1f); - z1 = z1 * TTD.TerrainSize.z; - - float y1 = tHeight * TTD.TerrainSize.y; - - Vector3 xVect = new Vector3(z1, y1, x1); - xVect += TTD.TerrainPos; - - return xVect; - } - - private static void AdjustedTerrainVect_Tri(ref float param, out bool bAdjusted, out float tHeight, ref Vector3 xVect, ref List tList, bool bIsBridge, bool bIsTunnel) - { - float OrigHeight = xVect.y; - int mCount = tList.Count; - int tCount = 0; - GSD.Roads.GSDRoadUtil.Construction3DTri tTri; - TerrainBoundsMaker TBM; - bAdjusted = false; - tHeight = 0f; - Vector2 t2D = new Vector2(xVect.x, xVect.z); - for (int i = 0; i < mCount; i++) - { - TBM = tList[i]; - if (param < TBM.MinI) - { - return; - } - if (param > TBM.MaxI) - { - continue; - } - if (TBM.tRect.Contains(ref t2D)) - { - tCount = TBM.triList.Count; - for (int k = 0; k < tCount; k++) - { - tTri = TBM.triList[k]; - if (tTri.Contains2D(ref t2D)) - { - tHeight = tTri.LinePlaneIntersection(ref xVect).y; - if (bIsBridge) - { - if (OrigHeight > (tHeight - 0.03f)) - { - tHeight -= 0.03f; - bAdjusted = true; - return; - } - } - else if (bIsTunnel) - { - if (OrigHeight < (tHeight + 0.03f)) - { - tHeight += 0.03f; - bAdjusted = true; - return; - } - } - else - { - bAdjusted = true; - return; - } - } - } - } - } - } - - private static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - private static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - } - - public static class GSDRoadCreationT - { - #region "Road Prelim" - //Privatized for obfuscate: - public static void RoadJob_Prelim(ref GSDRoad tRoad) - { - RoadJob_DoPrelim(ref tRoad); - } - private static void RoadJob_DoPrelim(ref GSDRoad tRoad) - { - GSDSplineC tSpline = tRoad.GSDSpline; - //Road,shoulder,ramp and lane widths: - float RoadWidth = tRoad.RoadWidth(); - float ShoulderWidth = tRoad.opt_ShoulderWidth; - float RoadSeperation = RoadWidth / 2f; - float RoadSeperation_NoTurn = RoadWidth / 2f; - float ShoulderSeperation = RoadSeperation + ShoulderWidth; - float LaneWidth = tRoad.opt_LaneWidth; - float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); - float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); - float ShoulderSep1Lane = (ShoulderSeperation + (LaneWidth * 0.5f)); - float ShoulderSep2Lane = (ShoulderSeperation + (LaneWidth * 1.5f)); - - //Vector3 buffers used in construction: - Vector3 rVect = default(Vector3); - Vector3 lVect = default(Vector3); - Vector3 ShoulderR_rVect = default(Vector3); - Vector3 ShoulderR_lVect = default(Vector3); - Vector3 ShoulderL_rVect = default(Vector3); - Vector3 ShoulderL_lVect = default(Vector3); - Vector3 RampR_R = default(Vector3); - Vector3 RampR_L = default(Vector3); - Vector3 RampL_R = default(Vector3); - Vector3 RampL_L = default(Vector3); - float ShoulderR_OuterAngle = 0f; if (ShoulderR_OuterAngle < 0f) { } - float ShoulderL_OuterAngle = 0f; if (ShoulderL_OuterAngle < 0f) { } - // Vector3 ShoulderR_OuterDirection = default(Vector3); - // Vector3 ShoulderL_OuterDirection = default(Vector3); - - //Previous temp storage values: - Vector3 tVect_Prev = default(Vector3); if (tVect_Prev == default(Vector3)) { } //Prev step storage of road variable. - Vector3 rVect_Prev = default(Vector3); if (rVect_Prev == default(Vector3)) { }//Prev step storage of road variable. - Vector3 lVect_Prev = default(Vector3); if (lVect_Prev == default(Vector3)) { }//Prev step storage of road variable. - Vector3 ShoulderR_PrevLVect = default(Vector3); if (ShoulderR_PrevLVect == default(Vector3)) { }//Prev step storage of shoulder variable. - Vector3 ShoulderL_PrevRVect = default(Vector3); if (ShoulderL_PrevRVect == default(Vector3)) { }//Prev step storage of shoulder variable. - Vector3 ShoulderR_PrevRVect = default(Vector3); if (ShoulderR_PrevRVect == default(Vector3)) { }//Prev step storage of shoulder variable. - Vector3 ShoulderL_PrevLVect = default(Vector3); if (ShoulderL_PrevLVect == default(Vector3)) { }//Prev step storage of shoulder variable. - // Vector3 ShoulderR_PrevRVect2 = default(Vector3); //Prev storage of shoulder variable (2 step history). - // Vector3 ShoulderL_PrevLVect2 = default(Vector3); //Prev storage of shoulder variable (2 step history). - // Vector3 ShoulderR_PrevRVect3 = default(Vector3); //Prev storage of shoulder variable (3 step history). - // Vector3 ShoulderL_PrevLVect3 = default(Vector3); //Prev storage of shoulder variable (3 step history). - Vector3 RampR_PrevR = default(Vector3); if (RampR_PrevR == default(Vector3)) { }//Prev storage of ramp variables (outer shoulder). - Vector3 RampR_PrevL = default(Vector3); if (RampR_PrevL == default(Vector3)) { }//Prev storage of ramp variables (outer shoulder). - Vector3 RampL_PrevR = default(Vector3); if (RampL_PrevR == default(Vector3)) { }//Prev storage of ramp variables (outer shoulder). - Vector3 RampL_PrevL = default(Vector3); if (RampL_PrevL == default(Vector3)) { }//Prev storage of ramp variables (outer shoulder). - // Vector3 ShoulderR_OuterDirectionPrev = default(Vector3); //Prev storage of outer shoulder direction (euler). - // Vector3 ShoulderL_OuterDirectionPrev = default(Vector3); //Prev storage of outer shoulder direction (euler). - - //Height and angle variables, used to change certain parameters of road depending on past & future angle and height changes. - // float tAngle = 0f; - // float OrigStep = 0.06f; - float Step = tRoad.opt_RoadDefinition / tSpline.distance; - // float AngleStep = 5f; - Vector3 tHeight0 = new Vector3(0f, 0.1f, 0f); - // Vector3 tHeight2 = new Vector3(0f,0.15f,0f); - // Vector3 tHeight1 = new Vector3(0f,0.2f,0f); - float OuterShoulderWidthR = 0f; - float OuterShoulderWidthL = 0f; - float RampOuterWidthR = (OuterShoulderWidthR / 6f) + OuterShoulderWidthR; - float RampOuterWidthL = (OuterShoulderWidthL / 6f) + OuterShoulderWidthL; - Vector3 tVect = default(Vector3); - Vector3 POS = default(Vector3); - float TempY = 0f; - // bool bTempYWasNegative = false; - // Vector3 tY = new Vector3(0f,0f,0f); - float tHeightAdded = 0f; if (tHeightAdded < 0f) { } - // float[] HeightChecks = new float[5]; - Vector3 gHeight = default(Vector3); - - //Bridge variables: - bool bIsBridge = false; if (bIsBridge == false) { } - bool bTempbridge = false; if (bTempbridge == false) { } - bool bBridgeInitial = false; if (bBridgeInitial == false) { } - bool bBridgeLast = false; if (bBridgeLast == false) { } - float BridgeUpComing; - // int BridgeLIndex; - // int BridgeRIndex; - - //Tunnel variables: - bool bIsTunnel = false; if (bIsTunnel == false) { } - bool bTempTunnel = false; if (bTempTunnel == false) { } - bool bTunnelInitial = false; if (bTunnelInitial == false) { } - bool bTunnelLast = false; if (bTunnelLast == false) { } - float TunnelUpComing = 0f; if (TunnelUpComing < 0f) { } - // int TunnelLIndex; - // int TunnelRIndex; - - //Intersection variables and buffers: - float tIntHeight = 0f; if (tIntHeight < 0f) { } - float tIntStrength = 0f; if (tIntStrength < 0f) { } - float tIntStrength_temp = 0f; if (tIntStrength_temp < 0f) { } - // float tIntDistCheck = 75f; - GSDRoadIntersection GSDRI = null; - bool bIsPastInter = false; - bool bMaxIntersection = false; - bool bWasPrevMaxInter = false; - GSDSplineN xNode = null; - float tInterSubtract = 4f; - float tLastInterHeight = -4f; - bool bOverrideRampR = false; - bool bOverrideRampL = false; - Vector3 RampR_Override = default(Vector3); - Vector3 RampL_Override = default(Vector3); - bool bFirstInterNode = false; - bool bInter_PrevWasCorner = false; if (bInter_PrevWasCorner == false) { } - bool bInter_CurreIsCorner = false; - bool bInter_CurreIsCornerRR = false; - bool bInter_CurreIsCornerRL = false; - bool bInter_CurreIsCornerLL = false; - bool bInter_CurreIsCornerLR = false; - bool bInter_PrevWasCornerRR = false; - bool bInter_PrevWasCornerRL = false; - bool bInter_PrevWasCornerLL = false; - bool bInter_PrevWasCornerLR = false; - Vector3 iTemp_HeightVect = default(Vector3); - Vector3 rVect_iTemp = default(Vector3); - Vector3 lVect_iTemp = default(Vector3); - Vector3 ShoulderR_R_iTemp = default(Vector3); - Vector3 ShoulderL_L_iTemp = default(Vector3); - Vector3 RampR_R_iTemp = default(Vector3); - Vector3 RampR_L_iTemp = default(Vector3); - Vector3 RampL_R_iTemp = default(Vector3); - Vector3 RampL_L_iTemp = default(Vector3); - Vector3 tempIVect_Prev = default(Vector3); - Vector3 tempIVect = tVect; - bool b0LAdded = false; if (b0LAdded == false) { } - bool b1LAdded = false; if (b1LAdded == false) { } - bool b2LAdded = false; if (b2LAdded == false) { } - bool b3LAdded = false; if (b3LAdded == false) { } - bool f0LAdded = false; if (f0LAdded == false) { } - bool f1LAdded = false; if (f1LAdded == false) { } - bool f2LAdded = false; if (f2LAdded == false) { } - bool f3LAdded = false; if (f3LAdded == false) { } - bool b0RAdded = false; if (b0RAdded == false) { } - bool b1RAdded = false; if (b1RAdded == false) { } - bool b2RAdded = false; if (b2RAdded == false) { } - bool b3RAdded = false; if (b3RAdded == false) { } - bool f0RAdded = false; if (f0RAdded == false) { } - bool f1RAdded = false; if (f1RAdded == false) { } - bool f2RAdded = false; if (f2RAdded == false) { } - bool f3RAdded = false; if (f3RAdded == false) { } - bool bInterTestAddAfterR = false; if (bInterTestAddAfterR == false) { } - bool bInterTestAddAfterL = false; if (bInterTestAddAfterL == false) { } - // Vector3 InterTestVect1 = default(Vector3); - // Vector3 InterTestVect2 = default(Vector3); - // Vector3 InterTestVect3 = default(Vector3); - // Vector3 InterTestVect4 = default(Vector3); - bool bShoulderSkipR = false; - bool bShoulderSkipL = false; - bool bShrinkRoadB = false; - bool bShrinkRoadFNext = false; - bool bShrinkRoadF = false; - bool bIsNextInter = false; - GSDSplineN cNode = null; - int NodeID = -1; - int NodeIDPrev = -1; - int NodeCount = tSpline.GetNodeCount(); - bool bDynamicCut = false; - float CullDistanceSQ = (3f * RoadWidth) * (3f * RoadWidth); - float mCornerDist = 0f; - Vector2 CornerRR = default(Vector2); if (CornerRR == default(Vector2)) { } - Vector2 CornerRL = default(Vector2); if (CornerRL == default(Vector2)) { } - Vector2 CornerLR = default(Vector2); if (CornerLR == default(Vector2)) { } - Vector2 CornerLL = default(Vector2); if (CornerLL == default(Vector2)) { } - Vector2 rVect2D = default(Vector2); if (rVect2D == default(Vector2)) { } - Vector2 lVect2D = default(Vector2); if (lVect2D == default(Vector2)) { } - Vector3 tempIVect_prev = default(Vector3); if (tempIVect_prev == default(Vector3)) { } - Vector3 POS_Next = default(Vector3); if (POS_Next == default(Vector3)) { } - Vector3 tVect_Next = default(Vector3); if (tVect_Next == default(Vector3)) { } - Vector3 rVect_Next = default(Vector3); if (rVect_Next == default(Vector3)) { } - Vector3 lVect_Next = default(Vector3); if (lVect_Next == default(Vector3)) { } - Vector3 xHeight = default(Vector3); if (xHeight == default(Vector3)) { } - bool bLRtoRR = false; - bool bLLtoLR = false; - bool bLine = false; - bool bImmuneR = false; - bool bImmuneL = false; - bool bSpecAddedL = false; if (bSpecAddedL == false) { } - bool bSpecAddedR = false; if (bSpecAddedR == false) { } - bool bTriggerInterAddition = false; - bool bSpecialThreeWayIgnoreR = false; - bool bSpecialThreeWayIgnoreL = false; - // int eCount = -1; - // int eIndex = -1; - // int uCount = -1; - // int uIndex = -1; - float bMod1 = 1.75f; - float bMod2 = 1.25f; - float t2DDist = -1f; - List vList = null; - List eList = null; - float tParam2 = 0f; - float tParam1 = 0f; - bool bRecordShoulderForNormals = false; - bool bRecordShoulderLForNormals = false; - - //Unused for now, for later partial construction methods: - bool bInterseOn = tRoad.RCS.bInterseOn; - // bool bBridgesOn = tRoad.RCS.bBridgesOn; - // if(tRoad.RCS.bRoadOn){ - bInterseOn = true; - // } - - //Prelim intersection construction and profiling: - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_Inter"); } - if (bInterseOn) - { - RoadJob_Prelim_Inter(ref tRoad); - } - - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("RoadPrelimForLoop"); } - - //Road/shoulder cuts: Init necessary since a road cut is added for the last segment after this function: - if (tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts) - { - tRoad.RCS.RoadCutNodes.Add(tSpline.mNodes[0]); - } - if (tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) - { - tRoad.RCS.ShoulderCutsLNodes.Add(tSpline.mNodes[0]); - tRoad.RCS.ShoulderCutsRNodes.Add(tSpline.mNodes[0]); - } - - //Start initializing the loop. Convuluted to handle special control nodes, so roads don't get rendered where they aren't supposed to, while still preserving the proper curvature. - float FinalMax = 1f; - float StartMin = 0f; - if (tSpline.bSpecialEndControlNode) - { //If control node, start after the control node: - FinalMax = tSpline.mNodes[tSpline.GetNodeCount() - 2].tTime; - } - if (tSpline.bSpecialStartControlNode) - { //If ends in control node, end construction before the control node: - StartMin = tSpline.mNodes[1].tTime; - } - bool bFinalEnd = false; - float RoadConnection_StartMin1 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. - float RoadConnection_FinalMax1 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. - if (tSpline.bSpecialEndNode_IsStart_Delay) - { - StartMin += (tSpline.SpecialEndNodeDelay_Start / tSpline.distance); //If there's a start delay (in meters), delay the start of road construction: Due to special control nodes for road connections or 3 way intersections. - } - else if (tSpline.bSpecialEndNode_IsEnd_Delay) - { - FinalMax -= (tSpline.SpecialEndNodeDelay_End / tSpline.distance); //If there's a end delay (in meters), cut early the end of road construction: Due to special control nodes for road connections or 3 way intersections. - } - // float RoadConnection_StartMin2 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. - // float RoadConnection_FinalMax2 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. - float i = StartMin; - - // int StartIndex = tSpline.GetClosestRoadDefIndex(StartMin,true,false); - // int EndIndex = tSpline.GetClosestRoadDefIndex(FinalMax,false,true); - // float cDist = 0f; - bool kSkip = true; - bool kSkipFinal = false; - int kCount = 0; - int vCount = kCount; - int kFinalCount = tSpline.RoadDefKeysArray.Length; - int spamcheckmax1 = 18000; - int spamcheck1 = 0; - - if (IsApproximately(StartMin, 0f, 0.0001f)) - { - kSkip = false; - } - if (IsApproximately(FinalMax, 1f, 0.0001f)) - { - kSkipFinal = true; - } - - //If startmin > 0 then kcount needs to start at proper road def - // bool bStartMinEnabled = false; - int StartMinIndex1 = 0; - - if (StartMin > 0f) - { - kCount = tSpline.GetClosestRoadDefIndex(StartMin, true, false); - // bStartMinEnabled = true; - StartMinIndex1 = 1; - } - - while (!bFinalEnd && spamcheck1 < spamcheckmax1) - { - spamcheck1++; - - if (kSkip) - { - i = StartMin; - kSkip = false; - } - else - { - if (kCount >= kFinalCount) - { - i = FinalMax; - if (kSkipFinal) { break; } - } - else - { - i = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); - kCount += 1; - } - } - - if (i > 1f) - { - break; - } - if (i < 0f) - { - i = 0f; - } - - if (IsApproximately(i, FinalMax, 0.00001f)) - { - bFinalEnd = true; - } - else if (i > FinalMax) - { - if (tSpline.bSpecialEndControlNode) - { - i = FinalMax; - bFinalEnd = true; - } - else - { - bFinalEnd = true; - break; - } - } - cNode = tSpline.GetCurrentNode(i); //Set the current node. - NodeID = cNode.idOnSpline; //Set the current node ID. - if (NodeID != NodeIDPrev && (tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts)) - { //If different than the previous node id, time to make a cut, if necessary: - //Don't ever cut the first node, last node, intersection node, special control nodes, bridge nodes or bridge control nodes: - if (NodeID > StartMinIndex1 && NodeID < (NodeCount - 1) && !cNode.bIsIntersection && !cNode.bSpecialEndNode) - { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ - if (tRoad.opt_bDynamicCuts) - { - bDynamicCut = cNode.bRoadCut; - } - else - { - bDynamicCut = true; - } - - if (bDynamicCut) - { - tRoad.RCS.RoadCuts.Add(tRoad.RCS.RoadVectors.Count); //Add the vector index to cut later. - tRoad.RCS.RoadCutNodes.Add(cNode); //Store the node which was at the beginning of this cut. - } - if (tRoad.opt_bShoulderCuts && bDynamicCut) - { //If option shoulder cuts is on. - tRoad.RCS.ShoulderCutsL.Add(tRoad.RCS.ShoulderL_Vectors.Count); //Add the vector index to cut later. - tRoad.RCS.ShoulderCutsLNodes.Add(cNode); //Store the node which was at the beginning of this cut. - tRoad.RCS.ShoulderCutsR.Add(tRoad.RCS.ShoulderR_Vectors.Count); //Add the vector index to cut later. - tRoad.RCS.ShoulderCutsRNodes.Add(cNode); //Store the node which was at the beginning of this cut. - } - } - } - if (NodeID != NodeIDPrev) - { - if (tRoad.RCS.RoadVectors.Count > 0) - { - cNode.bInitialRoadHeight = tRoad.RCS.RoadVectors[tRoad.RCS.RoadVectors.Count - 1].y; - } - } - NodeIDPrev = NodeID; //Store the previous node ID for the next round. Done now with road cuts as far as this function is concerned. - - //Set all necessary intersection triggers to false: - bInter_CurreIsCorner = false; - bInter_CurreIsCornerRR = false; - bInter_CurreIsCornerRL = false; - bInter_CurreIsCornerLL = false; - bInter_CurreIsCornerLR = false; - b0LAdded = false; - b1LAdded = false; - b2LAdded = false; - b3LAdded = false; - f0LAdded = false; - f1LAdded = false; - f2LAdded = false; - f3LAdded = false; - b0RAdded = false; - b1RAdded = false; - b2RAdded = false; - b3RAdded = false; - f0RAdded = false; - f1RAdded = false; - f2RAdded = false; - f3RAdded = false; - bInterTestAddAfterR = false; - bInterTestAddAfterL = false; - bShoulderSkipR = false; - bShoulderSkipL = false; - bShrinkRoadB = false; - bShrinkRoadF = false; - bIsNextInter = false; - if (bShrinkRoadFNext) - { - bShrinkRoadFNext = false; - bShrinkRoadF = true; - } - bRecordShoulderForNormals = false; - bRecordShoulderLForNormals = false; - - //Bridges: Note: This is convoluted due to need for triggers: - bBridgeInitial = false; - bBridgeLast = false; - bTempbridge = tSpline.IsInBridge(i); - if (!bIsBridge && bTempbridge) - { - bIsBridge = true; - bBridgeInitial = true; - } - else if (bIsBridge && !bTempbridge) - { - bIsBridge = false; - } - //Check if this is the last bridge run for this bridge: - if (bIsBridge) - { - bTempbridge = tSpline.IsInBridge(i + Step); - if (!bTempbridge) - { - bBridgeLast = true; - } - } - - //Tunnels: Note: This is convoluted due to need for triggers: - bTunnelInitial = false; - bTunnelLast = false; - bTempTunnel = tSpline.IsInTunnel(i); - if (!bIsTunnel && bTempTunnel) - { - bIsTunnel = true; - bTunnelInitial = true; - } - else if (bIsTunnel && !bTempTunnel) - { - bIsTunnel = false; - } - //Check if this is the last Tunnel run for this Tunnel: - if (bIsTunnel) - { - bTempTunnel = tSpline.IsInTunnel(i + Step); - if (!bTempTunnel) - { - bTunnelLast = true; - } - } - - //Master Vector3 for the current road construction location: - tSpline.GetSplineValue_Both(i, out tVect, out POS); - - // Profiler.EndSample(); - // Profiler.BeginSample("Test2"); - - //Detect downward or upward slope: - TempY = POS.y; - // bTempYWasNegative = false; - if (TempY < 0f) - { - // bTempYWasNegative = true; - TempY *= -1f; - } - if (tVect.y < 0f) - { - tVect.y = 0f; - } - - //Determine if intersection: - if (bInterseOn) - { - bIsPastInter = false; //If past intersection - tIntStrength = tRoad.GSDSpline.IntersectionStrength(ref tVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - bMaxIntersection = (tIntStrength >= 1f); //1f strength = max intersection - bFirstInterNode = false; - } - - //Outer widths: - if (bMaxIntersection && bInterseOn) - { - GSDRI.SignHeight = tIntHeight; - xNode.iConstruction.bBLane0Done_Final_ThisRound = false; - xNode.iConstruction.bBLane1Done_Final_ThisRound = false; - xNode.iConstruction.bBLane2Done_Final_ThisRound = false; - xNode.iConstruction.bBLane3Done_Final_ThisRound = false; - xNode.iConstruction.bFLane0Done_Final_ThisRound = false; - xNode.iConstruction.bFLane1Done_Final_ThisRound = false; - xNode.iConstruction.bFLane2Done_Final_ThisRound = false; - xNode.iConstruction.bFLane3Done_Final_ThisRound = false; - xNode.iConstruction.bIsFrontFirstRound = false; - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - OuterShoulderWidthR = ShoulderSeperation; - OuterShoulderWidthL = ShoulderSeperation; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - OuterShoulderWidthR = ShoulderSep1Lane; - OuterShoulderWidthL = ShoulderSep1Lane; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bIsPastInter) - { - OuterShoulderWidthR = ShoulderSep1Lane; - OuterShoulderWidthL = ShoulderSep2Lane; - } - else - { - OuterShoulderWidthR = ShoulderSep2Lane; - OuterShoulderWidthL = ShoulderSep1Lane; - } - } - } - else - { - if (TempY < 0.5f || bIsBridge || bIsTunnel) - { - OuterShoulderWidthR = ShoulderSeperation; - OuterShoulderWidthL = ShoulderSeperation; - } - else - { - OuterShoulderWidthR = ShoulderSeperation + (TempY * 0.05f); - OuterShoulderWidthL = ShoulderSeperation + (TempY * 0.05f); - } - } - - if (bIsBridge) - { //No ramps for bridges: - RampOuterWidthR = OuterShoulderWidthR; - RampOuterWidthL = OuterShoulderWidthL; - } - else - { - RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; - RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; - } - - //The master outer road edges vector locations: - if (bMaxIntersection && bInterseOn) - { //If in maximum intersection, adjust road edge (also the shoulder inner edges): - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - rVect = (tVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bIsPastInter) - { - rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); ; - } - else - { - rVect = (tVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - } - else - { - rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); - } - } - else - { - //Typical road/shoulder inner edge location: - rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); - } - - //Shoulder right vectors: - ShoulderR_rVect = (tVect + new Vector3(OuterShoulderWidthR * POS.normalized.z, 0, OuterShoulderWidthR * -POS.normalized.x)); - ShoulderR_lVect = rVect; //Note that the shoulder inner edge is the same as the road edge vector. - //Shoulder left vectors: - ShoulderL_rVect = lVect; //Note that the shoulder inner edge is the same as the road edge vector. - ShoulderL_lVect = (tVect + new Vector3(OuterShoulderWidthL * -POS.normalized.z, 0, OuterShoulderWidthL * POS.normalized.x)); - - // Profiler.EndSample(); - // Profiler.BeginSample("Test3"); - - //Now to start the main lane construction for the intersection: - if (bMaxIntersection && bInterseOn) - { - // if(kCount >= tSpline.RoadDefKeysArray.Length){ - // vCount = tSpline.RoadDefKeysArray.Length-1; - // }else{ - // vCount = kCount-1; - // } - vCount = kCount; - - tParam2 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[vCount]); - float tInterStrNext = tRoad.GSDSpline.IntersectionStrength_Next(tSpline.GetSplineValue(tParam2, false)); - if (IsApproximately(tInterStrNext, 1f, 0.001f) || tInterStrNext > 1f) - { - bIsNextInter = true; - } - else - { - bIsNextInter = false; - } - - if (string.Compare(xNode.UID, GSDRI.Node1.UID) == 0) - { - bFirstInterNode = true; - } - else - { - bFirstInterNode = false; - } - - tempIVect = tVect; - if (bIsPastInter) - { - bool bLLtoRL = bFirstInterNode; - bool bRLtoRR = !bFirstInterNode; - if (xNode.iConstruction.iFLane0L.Count == 0) - { - xNode.iConstruction.bIsFrontFirstRound = true; - xNode.iConstruction.bIsFrontFirstRoundTriggered = true; - xNode.iConstruction.bFLane0Done_Final_ThisRound = true; - xNode.iConstruction.bFLane1Done_Final_ThisRound = true; - xNode.iConstruction.bFLane2Done_Final_ThisRound = true; - xNode.iConstruction.bFLane3Done_Final_ThisRound = true; - - if (GSDRI.bFlipped && !bFirstInterNode) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); - xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); - xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerLL_CornerLR[4], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - } - } - else - { - if (bLLtoRL) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[4], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); - } - } - else if (bRLtoRR) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[4], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); - } - } - } - - xNode.iConstruction.ShoulderFR_End = xNode.iConstruction.iFLane0L[0]; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane3R[0]; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane2R[0]; - } - else - { - xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane1R[0]; - } - xNode.iConstruction.ShoulderFL_StartIndex = tRoad.RCS.ShoulderL_Vectors.Count - 2; - xNode.iConstruction.ShoulderFR_StartIndex = tRoad.RCS.ShoulderR_Vectors.Count - 2; - } - - //Line 0: - xNode.iConstruction.f0LAttempt = rVect; - if (!xNode.iConstruction.bFLane0Done && !GSDRI.Contains(ref rVect)) - { - xNode.iConstruction.iFLane0L.Add(GVC(rVect, tIntHeight)); f0LAdded = true; - } - - //Line 1: - // if(f0LAdded){ - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - tempIVect = tVect; - if (!xNode.iConstruction.bFLane1Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) - { - if (f0LAdded) { xNode.iConstruction.iFLane0R.Add(GVC(tempIVect, tIntHeight)); f0RAdded = true; } - xNode.iConstruction.iFLane1L.Add(GVC(tempIVect, tIntHeight)); f1LAdded = true; - } - else - { - if (f0LAdded) { xNode.iConstruction.iFLane0L.RemoveAt(xNode.iConstruction.iFLane0L.Count - 1); f0LAdded = false; } - } - } - else - { - tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0f, (LaneWidth * 0.5f) * -POS.normalized.x)); - if (!xNode.iConstruction.bFLane1Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) - { - if (f0LAdded) { xNode.iConstruction.iFLane0R.Add(GVC(tempIVect, tIntHeight)); f0RAdded = true; } - xNode.iConstruction.iFLane1L.Add(GVC(tempIVect, tIntHeight)); f1LAdded = true; - } - else - { - if (f0LAdded) { xNode.iConstruction.iFLane0L.RemoveAt(xNode.iConstruction.iFLane0L.Count - 1); f0LAdded = false; } - } - } - //} - xNode.iConstruction.f0RAttempt = tempIVect; - xNode.iConstruction.f1LAttempt = tempIVect; - - //Line 2: - //if(f1LAdded){ - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - tempIVect = lVect; - if (!xNode.iConstruction.bFLane2Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) - { - if (f1LAdded) { xNode.iConstruction.iFLane1R.Add(GVC(tempIVect, tIntHeight)); f1RAdded = true; } - } - else - { - if (f1LAdded && xNode.iConstruction.iFLane1L.Count > 1) { xNode.iConstruction.iFLane1L.RemoveAt(xNode.iConstruction.iFLane1L.Count - 1); f1LAdded = false; } - } - } - else - { - tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0f, (LaneWidth * 0.5f) * POS.normalized.x)); - tempIVect_prev = tempIVect; - if (!xNode.iConstruction.bFLane2Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) - { - if (f1LAdded) { xNode.iConstruction.iFLane1R.Add(GVC(tempIVect, tIntHeight)); f1RAdded = true; } - xNode.iConstruction.iFLane2L.Add(GVC(tempIVect, tIntHeight)); f2LAdded = true; - } - else - { - if (f1LAdded) { xNode.iConstruction.iFLane1L.RemoveAt(xNode.iConstruction.iFLane1L.Count - 1); f1LAdded = false; f1RAdded = false; } - } - } - //} - xNode.iConstruction.f1RAttempt = tempIVect; - xNode.iConstruction.f2LAttempt = tempIVect; - - //Line 3 / 4: - //if(f2LAdded){ - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.x)); - if (!xNode.iConstruction.bFLane3Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(lVect, tempIVect)) - { - - xNode.iConstruction.iFLane3L.Add(GVC(tempIVect, tIntHeight)); f3LAdded = true; - xNode.iConstruction.iFLane3R.Add(GVC(lVect, tIntHeight)); f3RAdded = true; - // if(bIsNextInter && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay){ - if (f2LAdded) { xNode.iConstruction.iFLane2R.Add(GVC(tempIVect, tIntHeight)); f2RAdded = true; } - // } - } - else - { - if (f2LAdded) - { - xNode.iConstruction.iFLane2L.RemoveAt(xNode.iConstruction.iFLane2L.Count - 1); f2LAdded = false; - } - } - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.x)); - if (f2LAdded && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(rVect, tempIVect)) - { - xNode.iConstruction.iFLane2R.Add(GVC(tempIVect, tIntHeight)); f2RAdded = true; - } - else if (f2LAdded) - { - xNode.iConstruction.iFLane2L.RemoveAt(xNode.iConstruction.iFLane2L.Count - 1); f2LAdded = false; - } - } - - // } - xNode.iConstruction.f2RAttempt = tempIVect; - xNode.iConstruction.f3LAttempt = tempIVect; - xNode.iConstruction.f3RAttempt = lVect; - - if (!bIsNextInter && !xNode.iConstruction.bFDone) - { - // xNode.iConstruction.bFDone = true; - xNode.iConstruction.bFLane0Done = true; - xNode.iConstruction.bFLane1Done = true; - xNode.iConstruction.bFLane2Done = true; - xNode.iConstruction.bFLane3Done = true; - - POS_Next = default(Vector3); - tVect_Next = default(Vector3); - - tParam1 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); - tSpline.GetSplineValue_Both(tParam1, out tVect_Next, out POS_Next); - rVect_Next = (tVect_Next + new Vector3(RoadSeperation * POS_Next.normalized.z, 0, RoadSeperation * -POS_Next.normalized.x)); - lVect_Next = (tVect_Next + new Vector3(RoadSeperation * -POS_Next.normalized.z, 0, RoadSeperation * POS_Next.normalized.x)); - - xNode.iConstruction.iFLane0L.Add(GVC(rVect_Next, tIntHeight)); - xNode.iConstruction.iFLane0R.Add(GVC(tVect_Next, tIntHeight)); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); - if (tRoad.opt_Lanes == 2) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.475f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 4) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.488f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 6) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.492f) + lVect_Next, tIntHeight)); - } - - if (tRoad.opt_Lanes == 2) - { - xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.03f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 4) - { - xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.015f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 6) - { - xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.01f) + lVect_Next, tIntHeight)); - } - - xNode.iConstruction.iFLane3R.Add(GVC(lVect_Next, tIntHeight)); - // xNode.iConstruction.iFLane2L.Add(GVC(tVect_Next,tIntHeight)); - // xNode.iConstruction.iFLane2R.Add(GVC(lVect_Next,tIntHeight)); - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); - if (tRoad.opt_Lanes == 2) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.475f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 4) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.488f) + lVect_Next, tIntHeight)); - } - else if (tRoad.opt_Lanes == 6) - { - xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.492f) + lVect_Next, tIntHeight)); - } - xNode.iConstruction.iFLane2L.Add(GVC(tVect_Next, tIntHeight)); - xNode.iConstruction.iFLane2R.Add(GVC(lVect_Next, tIntHeight)); - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); - xNode.iConstruction.iFLane1R.Add(GVC(lVect_Next, tIntHeight)); - } - bShrinkRoadFNext = true; - // bShrinkRoadF = true; - } - - } - else - { - bLRtoRR = bFirstInterNode; - bLLtoLR = !bFirstInterNode; - //B: - //Line 0: - tempIVect = lVect; - bool bFirst123 = false; - if (xNode.iConstruction.iBLane0R.Count == 0) - { - xNode.iConstruction.iBLane0L.Add(lVect_Prev); - xNode.iConstruction.iBLane0R.Add(tVect_Prev); - bShrinkRoadB = true; - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iBLane1L.Add(tVect_Prev); - xNode.iConstruction.iBLane1R.Add((tVect_Prev + new Vector3((LaneWidth * 0.05f) * POS.normalized.z, 0, (LaneWidth * 0.05f) * -POS.normalized.x))); - xNode.iConstruction.iBLane3L.Add(((lVect_Prev - rVect_Prev) * 0.03f) + rVect_Prev); - xNode.iConstruction.iBLane3R.Add(rVect_Prev); - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iBLane1L.Add(tVect_Prev); - xNode.iConstruction.iBLane1R.Add((tVect_Prev + new Vector3((LaneWidth * 0.05f) * POS.normalized.z, 0, (LaneWidth * 0.05f) * -POS.normalized.x))); - xNode.iConstruction.iBLane2L.Add(xNode.iConstruction.iBLane1R[0]); - xNode.iConstruction.iBLane2R.Add(rVect_Prev); - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iBLane1L.Add(tVect_Prev); - xNode.iConstruction.iBLane1R.Add(rVect_Prev); - } - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; - xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane3R[0]; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; - xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane2R[0]; - } - else - { - xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; - xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane1R[0]; - } - - xNode.iConstruction.ShoulderBL_StartIndex = tRoad.RCS.ShoulderL_Vectors.Count - 2; - xNode.iConstruction.ShoulderBR_StartIndex = tRoad.RCS.ShoulderR_Vectors.Count - 2; - // bFirst123 = true; - // goto InterSkip; - } - - bLine = false; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x))); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x))); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - bLine = !GSDRI.ContainsLine(lVect, tVect); - } - if (!xNode.iConstruction.bBLane0Done && !GSDRI.Contains(ref tempIVect) && bLine) - { - xNode.iConstruction.iBLane0L.Add(GVC(tempIVect, tIntHeight)); b0LAdded = true; - } - else if (!xNode.iConstruction.bBLane0Done_Final) - { - //Finalize lane 0: - InterFinalizeiBLane0(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode); - } - - //Line 1: - if (xNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (xNode.iConstruction.iBLane0L.Count == 2) - { - tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x)); - xNode.iConstruction.iBLane0R.Add(GVC(tempIVect, tIntHeight)); b0RAdded = true; - } - } - tempIVect_Prev = tempIVect; - tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x)); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { tempIVect = tVect; } - bLine = false; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0, (LaneWidth * 0.5f) * -POS.normalized.x))); - } - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - bLine = !GSDRI.ContainsLine(tempIVect, rVect); - } - else - { - bLine = !GSDRI.ContainsLine(tempIVect, rVect); - } - tempIVect_Prev = tempIVect; - if (b0LAdded && !xNode.iConstruction.bBLane1Done && !GSDRI.Contains(ref tempIVect) && bLine) - { - if (b0LAdded && (xNode.iConstruction.iBLane0L.Count != 2 || GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane)) - { - xNode.iConstruction.iBLane0R.Add(GVC(tempIVect, tIntHeight)); b0RAdded = true; - } - xNode.iConstruction.iBLane1L.Add(GVC(tempIVect, tIntHeight)); b1LAdded = true; - } - else if (!xNode.iConstruction.bBLane1Done_Final) - { - //Finalize lane 1: - InterFinalizeiBLane1(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b0LAdded, ref b1RAdded); - } - - //Line 2: - if (xNode.iConstruction.iBLane1R.Count == 0 && xNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.iBLane1R.Add(GVC(tVect, tIntHeight)); b1RAdded = true; - xNode.iConstruction.iBLane2L.Add(GVC(tVect, tIntHeight)); b2LAdded = true; - b2LAdded = true; - } - else - { - tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0, (LaneWidth * 0.5f) * -POS.normalized.x)); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { tempIVect = rVect; } - if (b1LAdded) - { - bLine = !GSDRI.ContainsLine(tempIVect, tempIVect_Prev); - } - else - { - bLine = !GSDRI.ContainsLine(tempIVect, rVect); - } - if (!xNode.iConstruction.bBLane2Done && !GSDRI.Contains(ref tempIVect) && bLine) - { - if (b1LAdded) { xNode.iConstruction.iBLane1R.Add(GVC(tempIVect, tIntHeight)); b1RAdded = true; } - xNode.iConstruction.iBLane2L.Add(GVC(tempIVect, tIntHeight)); b2LAdded = true; - } - else if (!xNode.iConstruction.bBLane2Done_Final) - { - InterFinalizeiBLane2(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); - } - } - - //Line 3 / 4: - tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.x)); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { tempIVect = rVect; } - if (!xNode.iConstruction.bBLane3Done && !GSDRI.ContainsLine(rVect, tempIVect) && !GSDRI.ContainsLine(rVect, lVect)) - { - xNode.iConstruction.iBLane3L.Add(GVC(tempIVect, tIntHeight)); b3LAdded = true; - xNode.iConstruction.iBLane3R.Add(GVC(rVect, tIntHeight)); b3RAdded = true; - if (!bFirst123 && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay) - { - if (b2LAdded) { xNode.iConstruction.iBLane2R.Add(GVC(tempIVect, tIntHeight)); b2RAdded = true; } - } - } - else if (!xNode.iConstruction.bBLane3Done_Final) - { - InterFinalizeiBLane3(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); - } - - } - } - - // InterSkip: - - if (!bIsBridge) - { - BridgeUpComing = tRoad.GSDSpline.BridgeUpComing(i); - // if(TempY < 0.5f){ - // gHeight = tHeight0; - // }else if(TempY < 2f){ - // gHeight = tHeight2; - // }else{ - // if(bTempYWasNegative){ - // tY = new Vector3(0f,(TempY*0.035f),0f); - // } - // if(tY.y < tHeight1.y){ - // tY = tHeight1; - // } - // gHeight = tY; - // } - if (BridgeUpComing < 0.2f) - { - BridgeUpComing = 0.2f; - } - // gHeight.y = gHeight.y * BridgeUpComing; - - // if(tRoad.opt_MatchTerrain){ - gHeight.y = 0f; - // } - - lVect += gHeight; - rVect += gHeight; - ShoulderR_lVect += gHeight; - ShoulderL_rVect += gHeight; - ShoulderL_lVect += gHeight; - ShoulderR_rVect += gHeight; - tHeightAdded = gHeight.y; - } - - - if (tIntStrength >= 1f) - { - tVect.y -= tInterSubtract; - tLastInterHeight = tVect.y; - rVect.y -= tInterSubtract; - lVect.y -= tInterSubtract; - - ShoulderL_rVect.y = tIntHeight; - ShoulderR_lVect.y = tIntHeight; - ShoulderR_rVect.y = tIntHeight; - ShoulderL_lVect.y = tIntHeight; - - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_rVect.y); } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_lVect.y); } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_rVect.y); } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_lVect.y); } - } - else if (tIntStrength > 0f) - { - - rVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * rVect.y); - ShoulderR_lVect = rVect; - lVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * lVect.y); - ShoulderL_rVect = lVect; - ShoulderR_rVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * ShoulderR_rVect.y); - ShoulderL_lVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * ShoulderL_lVect.y); - - // if(!Mathf.Approximately(tIntStrength,0f)){ tVect.y = (tIntStrength*tIntHeight) + ((1-tIntStrength)*tVect.y); } - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*rVect.y); ShoulderR_lVect = rVect; } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*lVect.y); ShoulderL_rVect = lVect; } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_rVect.y); } - // - // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); - // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_lVect.y); } - } - - //Ramp: - RampR_L = ShoulderR_rVect; - RampL_R = ShoulderL_lVect; - if (bIsBridge) - { - RampR_R = RampR_L; - RampL_L = RampL_R; - } - else - { - RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)) + gHeight; - SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); - RampR_R.y -= 0.35f; - - RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)) + gHeight; - SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); - RampL_L.y -= 0.35f; - } - - //Merge points to intersection corners if necessary: - if (bMaxIntersection && !bIsBridge && !bIsTunnel && bInterseOn) - { - mCornerDist = tRoad.opt_RoadDefinition * 1.35f; - mCornerDist *= mCornerDist; - - CornerRR = new Vector2(GSDRI.CornerRR.x, GSDRI.CornerRR.z); - CornerRL = new Vector2(GSDRI.CornerRL.x, GSDRI.CornerRL.z); - CornerLR = new Vector2(GSDRI.CornerLR.x, GSDRI.CornerLR.z); - CornerLL = new Vector2(GSDRI.CornerLL.x, GSDRI.CornerLL.z); - rVect2D = new Vector2(rVect.x, rVect.z); - lVect2D = new Vector2(lVect.x, lVect.z); - bOverrideRampR = false; - bOverrideRampL = false; - bImmuneR = false; - bImmuneL = false; - bMod1 = 1.75f; - bMod2 = 1.25f; - t2DDist = -1f; - - //Find equatable lane vect and move it too - // eCount = -1; - // eIndex = -1; - // uCount = -1; - // uIndex = -1; - - xHeight = new Vector3(0f, -0.1f, 0f); - bSpecAddedL = false; - bSpecAddedR = false; - - if (bFirstInterNode) - { - bSpecAddedL = (b0LAdded || f0LAdded); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - bSpecAddedR = (b1RAdded || f1LAdded); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - bSpecAddedR = (b2RAdded || f2LAdded); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - bSpecAddedR = (b3RAdded || f3LAdded); - } - } - - float tempRoadDef = Mathf.Clamp(tRoad.opt_LaneWidth, 3f, 5f); - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - - } - - //RR: - if (GSDRI.EvenAngle > 90f) { mCornerDist = tempRoadDef * bMod1; } else { mCornerDist = tempRoadDef * bMod2; } - mCornerDist *= mCornerDist; - t2DDist = Vector2.SqrMagnitude(CornerRR - rVect2D); - if (t2DDist < mCornerDist) - { - bImmuneR = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerRR = true; - - if (bFirstInterNode) - { - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iBLane1R; - if (xNode.iConstruction.bBLane1Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iBLane2R; - if (xNode.iConstruction.bBLane2Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iBLane3R; - if (xNode.iConstruction.bBLane3Done_Final_ThisRound) { vList = null; } - } - - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x, 0.01f) && IsApproximately(vList[m].z, GSDRI.CornerRR.z, 0.01f))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - else - { - //2nd node can only come through RR as front with R - vList = null; - vList = xNode.iConstruction.iFLane0L; - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x, 0.01f) && IsApproximately(vList[m].z, GSDRI.CornerRR.z, 0.01f))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderR_lVect = new Vector3(CornerRR.x, tIntHeight, CornerRR.y); - ShoulderR_rVect = new Vector3(GSDRI.CornerRR_Outer.x, tIntHeight, GSDRI.CornerRR_Outer.z); - RampR_Override = new Vector3(GSDRI.CornerRR_RampOuter.x, tIntHeight, GSDRI.CornerRR_RampOuter.z); - bRecordShoulderForNormals = true; - } - else - { - t2DDist = Vector2.SqrMagnitude(CornerRR - lVect2D); - if (t2DDist < mCornerDist) - { - bImmuneL = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerRR = true; - - //2nd node can come in via left - if (!bFirstInterNode) - { - vList = null; - vList = xNode.iConstruction.iBLane0L; - if (xNode.iConstruction.bBLane0Done_Final_ThisRound) { vList = null; } - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x) && IsApproximately(vList[m].z, GSDRI.CornerRR.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderL_rVect = new Vector3(CornerRR.x, tIntHeight, CornerRR.y); - ShoulderL_lVect = new Vector3(GSDRI.CornerRR_Outer.x, tIntHeight, GSDRI.CornerRR_Outer.z); - RampL_Override = new Vector3(GSDRI.CornerRR_RampOuter.x, tIntHeight, GSDRI.CornerRR_RampOuter.z); - bRecordShoulderLForNormals = true; - } - } - //RL: - if (GSDRI.OddAngle > 90f) { mCornerDist = tempRoadDef * bMod1; } else { mCornerDist = tempRoadDef * bMod2; } - mCornerDist *= mCornerDist; - t2DDist = Vector2.SqrMagnitude(CornerRL - rVect2D); - if (t2DDist < mCornerDist) - { - bImmuneR = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerRL = true; - - if (bFirstInterNode) - { - vList = null; - vList = xNode.iConstruction.iFLane0L; - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - else - { - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iBLane1R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iBLane2R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iBLane3R; - } - - //Hitting RL from backside with second node: - if (!bFirstInterNode) - { - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) - { - eList.Add(m); - if (m == vList.Count - 1) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - b1RAdded = false; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - b2RAdded = false; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - b3RAdded = false; - } - } - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - } - eList = null; - } - - ShoulderR_lVect = new Vector3(CornerRL.x, tIntHeight, CornerRL.y); - ShoulderR_rVect = new Vector3(GSDRI.CornerRL_Outer.x, tIntHeight, GSDRI.CornerRL_Outer.z); - RampR_Override = new Vector3(GSDRI.CornerRL_RampOuter.x, tIntHeight, GSDRI.CornerRL_RampOuter.z); - bRecordShoulderForNormals = true; - } - else - { - t2DDist = Vector2.SqrMagnitude(CornerRL - lVect2D); - if (t2DDist < mCornerDist) - { - bImmuneL = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerRL = true; - - if (!bFirstInterNode) - { - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iFLane1R; - if (xNode.iConstruction.bFLane1Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iFLane2R; - if (xNode.iConstruction.bFLane2Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iFLane3R; - if (xNode.iConstruction.bFLane3Done_Final_ThisRound) { vList = null; } - } - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderL_rVect = new Vector3(CornerRL.x, tIntHeight, CornerRL.y); - ShoulderL_lVect = new Vector3(GSDRI.CornerRL_Outer.x, tIntHeight, GSDRI.CornerRL_Outer.z); - RampL_Override = new Vector3(GSDRI.CornerRL_RampOuter.x, tIntHeight, GSDRI.CornerRL_RampOuter.z); - bRecordShoulderLForNormals = true; - } - } - //LR: - if (GSDRI.OddAngle > 90f) { mCornerDist = tempRoadDef * bMod1; } else { mCornerDist = tempRoadDef * bMod2; } - mCornerDist *= mCornerDist; - t2DDist = Vector2.SqrMagnitude(CornerLR - rVect2D); - if (t2DDist < mCornerDist) - { - bImmuneR = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerLR = true; - - if (!bFirstInterNode) - { - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iBLane1R; - if (xNode.iConstruction.bBLane1Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iBLane2R; - if (xNode.iConstruction.bBLane2Done_Final_ThisRound) { vList = null; } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iBLane3R; - if (xNode.iConstruction.bBLane3Done_Final_ThisRound) { vList = null; } - } - - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderR_lVect = new Vector3(CornerLR.x, tIntHeight, CornerLR.y); - ShoulderR_rVect = new Vector3(GSDRI.CornerLR_Outer.x, tIntHeight, GSDRI.CornerLR_Outer.z); - RampR_Override = new Vector3(GSDRI.CornerLR_RampOuter.x, tIntHeight, GSDRI.CornerLR_RampOuter.z); - bRecordShoulderForNormals = true; - } - else - { - t2DDist = Vector2.SqrMagnitude(CornerLR - lVect2D); - if (t2DDist < mCornerDist) - { - bImmuneL = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerLR = true; - - if (bFirstInterNode) - { - vList = null; - vList = xNode.iConstruction.iBLane0L; - if (xNode.iConstruction.bBLane0Done_Final_ThisRound) { vList = null; } - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - else - { - //2nd node can only come through LR as front with L - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iFLane1R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iFLane2R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iFLane3R; - } - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderL_rVect = new Vector3(CornerLR.x, tIntHeight, CornerLR.y); - ShoulderL_lVect = new Vector3(GSDRI.CornerLR_Outer.x, tIntHeight, GSDRI.CornerLR_Outer.z); - RampL_Override = new Vector3(GSDRI.CornerLR_RampOuter.x, tIntHeight, GSDRI.CornerLR_RampOuter.z); - bRecordShoulderLForNormals = true; - } - } - //LL: - if (GSDRI.EvenAngle > 90f) { mCornerDist = tempRoadDef * bMod1; } else { mCornerDist = tempRoadDef * bMod2; } - mCornerDist *= mCornerDist; - t2DDist = Vector2.SqrMagnitude(CornerLL - rVect2D); - if (t2DDist < mCornerDist) - { - bImmuneR = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerLL = true; - - - if (!bFirstInterNode) - { - vList = null; - vList = xNode.iConstruction.iFLane0L; - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderR_lVect = new Vector3(CornerLL.x, tIntHeight, CornerLL.y); - ShoulderR_rVect = new Vector3(GSDRI.CornerLL_Outer.x, tIntHeight, GSDRI.CornerLL_Outer.z); - RampR_Override = new Vector3(GSDRI.CornerLL_RampOuter.x, tIntHeight, GSDRI.CornerLL_RampOuter.z); - bRecordShoulderForNormals = true; - } - else - { - t2DDist = Vector2.SqrMagnitude(CornerLL - lVect2D); - if (t2DDist < mCornerDist) - { - bImmuneL = true; bInter_CurreIsCorner = true; bInter_CurreIsCornerLL = true; - - if (bFirstInterNode) - { - vList = null; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - vList = xNode.iConstruction.iFLane1R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - vList = xNode.iConstruction.iFLane2R; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - vList = xNode.iConstruction.iFLane3R; - } - eList = new List(); - if (vList != null) - { - for (int m = 1; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - else - { - vList = null; - vList = xNode.iConstruction.iBLane0L; - if (xNode.iConstruction.bBLane0Done_Final_ThisRound) { vList = null; } - eList = new List(); - if (vList != null) - { - for (int m = 0; m < vList.Count; m++) - { - if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) - { - if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) - { - eList.Add(m); - } - } - } - for (int m = (eList.Count - 1); m >= 0; m--) - { - vList.RemoveAt(eList[m]); - } - } - eList = null; - } - - ShoulderL_rVect = new Vector3(CornerLL.x, tIntHeight, CornerLL.y); - ShoulderL_lVect = new Vector3(GSDRI.CornerLL_Outer.x, tIntHeight, GSDRI.CornerLL_Outer.z); - RampL_Override = new Vector3(GSDRI.CornerLL_RampOuter.x, tIntHeight, GSDRI.CornerLL_RampOuter.z); - bRecordShoulderLForNormals = true; - } - } - - if (bImmuneR) - { - bOverrideRampR = true; - if (!tRoad.RCS.ImmuneVects.Contains(ShoulderR_lVect)) { tRoad.RCS.ImmuneVects.Add(ShoulderR_lVect); } - if (!tRoad.RCS.ImmuneVects.Contains(ShoulderR_rVect)) { tRoad.RCS.ImmuneVects.Add(ShoulderR_rVect); } - } - if (bImmuneL) - { - bOverrideRampL = true; - if (!tRoad.RCS.ImmuneVects.Contains(ShoulderL_rVect)) { tRoad.RCS.ImmuneVects.Add(ShoulderL_rVect); } - if (!tRoad.RCS.ImmuneVects.Contains(ShoulderL_lVect)) { tRoad.RCS.ImmuneVects.Add(ShoulderL_lVect); } - } - } - - if (bShrinkRoadB) - { - - if (lVect_Prev != new Vector3(0f, 0f, 0f)) - { - tRoad.RCS.RoadVectors.Add(lVect_Prev); - tRoad.RCS.RoadVectors.Add(lVect_Prev); - tRoad.RCS.RoadVectors.Add(lVect_Prev); - tRoad.RCS.RoadVectors.Add(lVect_Prev); - } - } - if (bShrinkRoadF) - { - if (lVect != new Vector3(0f, 0f, 0f)) - { - tRoad.RCS.RoadVectors.Add(lVect); - tRoad.RCS.RoadVectors.Add(lVect); - tRoad.RCS.RoadVectors.Add(lVect); - tRoad.RCS.RoadVectors.Add(lVect); - } - } - - tRoad.RCS.RoadVectors.Add(lVect); - tRoad.RCS.RoadVectors.Add(lVect); - tRoad.RCS.RoadVectors.Add(rVect); - tRoad.RCS.RoadVectors.Add(rVect); - - - - //Add bounds for later removal: - if (!bIsBridge && !bIsTunnel && bMaxIntersection && bWasPrevMaxInter && bInterseOn) - { - bool bGoAhead = true; - if (xNode.bIsEndPoint) - { - if (xNode.idOnSpline == 1) - { - if (i < xNode.tTime) - { - bGoAhead = false; - } - } - else - { - if (i > xNode.tTime) - { - bGoAhead = false; - } - } - } - - //Get this and prev lvect rvect rects: - if ((Vector3.SqrMagnitude(xNode.pos - tVect) < CullDistanceSQ) && bGoAhead) - { - GSD.Roads.GSDRoadUtil.Construction2DRect vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( - new Vector2(lVect.x, lVect.z), - new Vector2(rVect.x, rVect.z), - new Vector2(lVect_Prev.x, lVect_Prev.z), - new Vector2(rVect_Prev.x, rVect_Prev.z), - tLastInterHeight - ); - - tRoad.RCS.tIntersectionBounds.Add(vRect); - // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.position = lVect; - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22"; - // - // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.position = rVect; - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22"; - } - } - - //Ramp construction: - RampR_L = ShoulderR_rVect; - RampL_R = ShoulderL_lVect; - if (bIsBridge) - { - RampR_R = RampR_L; - RampL_L = RampL_R; - } - else - { - RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)) + gHeight; ; - if (bOverrideRampR) { RampR_R = RampR_Override; } //Overrides will come from intersection. - SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); - RampR_R.y -= 0.35f; - - RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)) + gHeight; ; - if (bOverrideRampL) { RampL_L = RampL_Override; } //Overrides will come from intersection. - SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); - RampL_L.y -= 0.35f; - bOverrideRampR = false; - bOverrideRampL = false; - } - - //If necessary during intersection construction, sometimes an addition will be created inbetween intersection corner points. - //This addition will create a dip between corner points to 100% ensure there is no shoulder visible on the roads between corner points. - bTriggerInterAddition = false; - if (bMaxIntersection && bInterseOn) - { - if (bFirstInterNode) - { - if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerLL) || (bInter_PrevWasCornerRR && bInter_CurreIsCornerRL)) - { - bTriggerInterAddition = true; - } - } - else - { - if (!GSDRI.bFlipped) - { - if ((bInter_PrevWasCornerLL && bInter_CurreIsCornerRL) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR) || (bInter_PrevWasCornerRR && bInter_CurreIsCornerLR)) - { - bTriggerInterAddition = true; - } - } - else - { - if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR) || (bInter_PrevWasCornerRL && bInter_CurreIsCornerLL)) - { - bTriggerInterAddition = true; - } - } - } - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - bTriggerInterAddition = false; - } - - //For 3-way intersections: - bSpecialThreeWayIgnoreR = false; - bSpecialThreeWayIgnoreL = false; - if (GSDRI.IgnoreSide > -1) - { - if (GSDRI.IgnoreSide == 0) - { - //RR to RL: - if (bFirstInterNode && (bInter_PrevWasCornerRR && bInter_CurreIsCornerRL)) - { - bTriggerInterAddition = false; - } - } - else if (GSDRI.IgnoreSide == 1) - { - //RL to LL: - if (!bFirstInterNode && ((bInter_PrevWasCornerRL && bInter_CurreIsCornerLL) || (bInter_PrevWasCornerLL && bInter_CurreIsCornerRL))) - { - //bTriggerInterAddition = false; - if (GSDRI.bFlipped) - { - bSpecialThreeWayIgnoreR = true; - } - else - { - bSpecialThreeWayIgnoreL = true; - } - } - } - else if (GSDRI.IgnoreSide == 2) - { - //LL to LR: - if (bFirstInterNode && (bInter_PrevWasCornerLR && bInter_CurreIsCornerLL)) - { - bTriggerInterAddition = false; - } - } - else if (GSDRI.IgnoreSide == 3) - { - //LR to RR: - if (!bFirstInterNode && ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR))) - { - //bTriggerInterAddition = false; - if (GSDRI.bFlipped) - { - bSpecialThreeWayIgnoreL = true; - } - else - { - bSpecialThreeWayIgnoreR = true; - } - } - } - } - - if (bTriggerInterAddition) - { - iTemp_HeightVect = new Vector3(0f, 0f, 0f); - rVect_iTemp = (((rVect_Prev - rVect) * 0.5f) + rVect) + iTemp_HeightVect; - lVect_iTemp = (((lVect_Prev - lVect) * 0.5f) + lVect) + iTemp_HeightVect; - ShoulderR_R_iTemp = (((ShoulderR_PrevRVect - ShoulderR_rVect) * 0.5f) + ShoulderR_rVect) + iTemp_HeightVect; - ShoulderL_L_iTemp = (((ShoulderL_PrevLVect - ShoulderL_lVect) * 0.5f) + ShoulderL_lVect) + iTemp_HeightVect; - RampR_R_iTemp = (((RampR_PrevR - RampR_R) * 0.5f) + RampR_R) + iTemp_HeightVect; - RampR_L_iTemp = (((RampR_PrevL - RampR_L) * 0.5f) + RampR_L) + iTemp_HeightVect; - RampL_R_iTemp = (((RampL_PrevR - RampL_R) * 0.5f) + RampL_R) + iTemp_HeightVect; - RampL_L_iTemp = (((RampL_PrevL - RampL_L) * 0.5f) + RampL_L) + iTemp_HeightVect; - - // ShoulderL_L_iTemp = lVect_iTemp; - // RampL_R_iTemp = lVect_iTemp; - // RampL_L_iTemp = lVect_iTemp; - // - // ShoulderR_R_iTemp = rVect_iTemp; - // RampR_R_iTemp = rVect_iTemp; - // RampR_L_iTemp = rVect_iTemp; - } - - if (bTriggerInterAddition && !(GSDRI.bFlipped && !bFirstInterNode)) - { - if (bFirstInterNode) - { - if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerRL && !bSpecialThreeWayIgnoreR)) - { - //Right shoulder: - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - //Ramps: - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - } - if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerLL && !bSpecialThreeWayIgnoreL)) - { - //Left shoulder: - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - //Ramp: - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - } - } - else - { - if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerRR && !bSpecialThreeWayIgnoreR)) - { - //Right shoulder: - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - //Ramps: - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - } - if ((bInter_PrevWasCornerLL && bInter_CurreIsCornerRL && !bSpecialThreeWayIgnoreL)) - { - //Left shoulder: - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - //Ramp: - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - } - } - } - else if (bTriggerInterAddition && (GSDRI.bFlipped && !bFirstInterNode)) - { - if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR && !bSpecialThreeWayIgnoreL)) - { - //Left shoulder: - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); - //Ramp: - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); - } - if ((bInter_PrevWasCornerRL && bInter_CurreIsCornerLL && !bSpecialThreeWayIgnoreR)) - { - //Right shoulder: - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); - //Ramps: - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); - } - } - } - - - - - //Right shoulder: - if (!bShoulderSkipR) - { - if (bRecordShoulderForNormals) - { - tRoad.RCS.normals_ShoulderR_averageStartIndexes.Add(tRoad.RCS.ShoulderR_Vectors.Count); - } - - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - - //Double up to prevent normal errors from intersection subtraction: - if (bImmuneR && bRecordShoulderForNormals) - { - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - } - } - - //Left shoulder: - if (!bShoulderSkipL) - { - if (bRecordShoulderLForNormals) - { - tRoad.RCS.normals_ShoulderL_averageStartIndexes.Add(tRoad.RCS.ShoulderL_Vectors.Count); - } - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); - - //Double up to prevent normal errors from intersection subtraction: - if (bImmuneL && bRecordShoulderForNormals) - { - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); - } - } - - //Previous storage: - tVect_Prev = tVect; - rVect_Prev = rVect; - lVect_Prev = lVect; - ShoulderR_PrevLVect = ShoulderR_lVect; - ShoulderL_PrevRVect = ShoulderL_rVect; - // ShoulderR_PrevRVect3 = ShoulderR_PrevRVect2; - // ShoulderL_PrevLVect3 = ShoulderL_PrevLVect2; - // ShoulderR_PrevRVect2 = ShoulderR_PrevRVect; - // ShoulderL_PrevLVect2 = ShoulderL_PrevLVect; - ShoulderR_PrevRVect = ShoulderR_rVect; - ShoulderL_PrevLVect = ShoulderL_lVect; - RampR_PrevR = RampR_R; - RampR_PrevL = RampR_L; - RampL_PrevR = RampL_R; - RampL_PrevL = RampL_L; - - //Store more prev variables: - bWasPrevMaxInter = bMaxIntersection; - bInter_PrevWasCorner = bInter_CurreIsCorner; - bInter_PrevWasCornerRR = bInter_CurreIsCornerRR; - bInter_PrevWasCornerRL = bInter_CurreIsCornerRL; - bInter_PrevWasCornerLL = bInter_CurreIsCornerLL; - bInter_PrevWasCornerLR = bInter_CurreIsCornerLR; - - // i+=Step;//Master step incrementer. - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_FinalizeInter"); } - //Finalize intersection vectors: - if (bInterseOn) - { - RoadJob_Prelim_FinalizeInter(ref tRoad); - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_RoadConnections"); } - //Creates road connections if necessary: - // float ExtraHeight = 0f; - // float RampPercent = 0.2f; - if (tSpline.bSpecialEndNode_IsStart_Delay) - { - Vector3[] RoadConn_verts = new Vector3[4]; - - RampR_R = tRoad.RCS.ShoulderR_Vectors[7]; - ShoulderR_rVect = tRoad.RCS.ShoulderR_Vectors[3]; - rVect = tRoad.RCS.ShoulderR_Vectors[0]; - - tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R); - tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect); - tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect); - - RampL_L = tRoad.RCS.ShoulderL_Vectors[4]; - ShoulderL_lVect = tRoad.RCS.ShoulderL_Vectors[0]; - lVect = tRoad.RCS.ShoulderL_Vectors[3]; - - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L); - tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L); - tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect); - tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); - - RoadConn_verts[0] = lVect; - RoadConn_verts[1] = rVect; - tSpline.GetSplineValue_Both(RoadConnection_StartMin1, out tVect, out POS); - RoadSeperation = tSpline.SpecialEndNodeDelay_Start_Result / 2f; - rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); - ShoulderSeperation = RoadSeperation + ShoulderWidth; - OuterShoulderWidthR = ShoulderSeperation; - OuterShoulderWidthL = ShoulderSeperation; - RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; - RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; - ShoulderR_rVect = (tVect + new Vector3(ShoulderSeperation * POS.normalized.z, 0, ShoulderSeperation * -POS.normalized.x)); - ShoulderL_lVect = (tVect + new Vector3(ShoulderSeperation * -POS.normalized.z, 0, ShoulderSeperation * POS.normalized.x)); - RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)); - SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); - RampR_R.y -= 0.45f; - RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)); - SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); - RampL_L.y -= 0.45f; - - - - tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect + tHeight0); - tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect + tHeight0); - - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); - tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); - - RoadConn_verts[2] = lVect + tHeight0; - RoadConn_verts[3] = rVect + tHeight0; - //Tris: - int[] RoadConn_tris = new int[6]; - RoadConn_tris[0] = 2; - RoadConn_tris[1] = 0; - RoadConn_tris[2] = 3; - RoadConn_tris[3] = 0; - RoadConn_tris[4] = 1; - RoadConn_tris[5] = 3; - - Vector3[] RoadConn_normals = new Vector3[4]; - RoadConn_normals[0] = -Vector3.forward; - RoadConn_normals[1] = -Vector3.forward; - RoadConn_normals[2] = -Vector3.forward; - RoadConn_normals[3] = -Vector3.forward; - Vector2[] RoadConn_uv = new Vector2[4]; - float tMod1 = -1; - float tMod2 = -1; - - if (tRoad.opt_Lanes == 2) - { - tMod1 = 0.5f - (LaneWidth / tSpline.SpecialEndNodeDelay_Start_Result); - tMod2 = 0.5f + (LaneWidth / tSpline.SpecialEndNodeDelay_Start_Result); - } - else if (tRoad.opt_Lanes == 4) - { - tMod1 = 0.5f - ((LaneWidth * 2f) / tSpline.SpecialEndNodeDelay_Start_Result); - tMod2 = 0.5f + ((LaneWidth * 2f) / tSpline.SpecialEndNodeDelay_Start_Result); - } - RoadConn_uv[0] = new Vector2(tMod1, 0f); - RoadConn_uv[1] = new Vector2(tMod2, 0f); - RoadConn_uv[2] = new Vector2(0f, 1f); - RoadConn_uv[3] = new Vector2(1f, 1f); - - - tRoad.RCS.RoadConnections_verts.Add(RoadConn_verts); - tRoad.RCS.RoadConnections_tris.Add(RoadConn_tris); - tRoad.RCS.RoadConnections_normals.Add(RoadConn_normals); - tRoad.RCS.RoadConnections_uv.Add(RoadConn_uv); - } - else if (tSpline.bSpecialEndNode_IsEnd_Delay) - { - Vector3[] RoadConn_verts = new Vector3[4]; - int rrCount = tRoad.RCS.ShoulderR_Vectors.Count; - RampR_R = tRoad.RCS.ShoulderR_Vectors[rrCount - 1]; - ShoulderR_rVect = tRoad.RCS.ShoulderR_Vectors[rrCount - 3]; - rVect = tRoad.RCS.ShoulderR_Vectors[rrCount - 7]; - - //Right shoulder: - tRoad.RCS.ShoulderR_Vectors.Add(rVect); - tRoad.RCS.ShoulderR_Vectors.Add(rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - - rrCount = tRoad.RCS.ShoulderL_Vectors.Count; - RampL_L = tRoad.RCS.ShoulderL_Vectors[rrCount - 3]; - ShoulderL_lVect = tRoad.RCS.ShoulderL_Vectors[rrCount - 1]; - lVect = tRoad.RCS.ShoulderL_Vectors[rrCount - 5]; - - //Left shoulder: - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(lVect); - tRoad.RCS.ShoulderL_Vectors.Add(lVect); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - - RoadConn_verts[0] = lVect; - RoadConn_verts[1] = rVect; - tSpline.GetSplineValue_Both(RoadConnection_FinalMax1, out tVect, out POS); - RoadSeperation = tSpline.SpecialEndNodeDelay_End_Result / 2f; - rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); - ShoulderSeperation = RoadSeperation + ShoulderWidth; - OuterShoulderWidthR = ShoulderSeperation; - OuterShoulderWidthL = ShoulderSeperation; - RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; - RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; - ShoulderR_rVect = (tVect + new Vector3(ShoulderSeperation * POS.normalized.z, 0, ShoulderSeperation * -POS.normalized.x)); - ShoulderL_lVect = (tVect + new Vector3(ShoulderSeperation * -POS.normalized.z, 0, ShoulderSeperation * POS.normalized.x)); - RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)); - SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); - RampR_R.y -= 0.35f; - RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)); - SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); - RampL_L.y -= 0.35f; - - //Right shoulder: - tRoad.RCS.ShoulderR_Vectors.Add(rVect); - tRoad.RCS.ShoulderR_Vectors.Add(rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); - - //Left shoulder: - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(lVect); - tRoad.RCS.ShoulderL_Vectors.Add(lVect); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); - - RoadConn_verts[2] = lVect; - RoadConn_verts[3] = rVect; - //Tris: - int[] RoadConn_tris = new int[6]; - RoadConn_tris[0] = 0; - RoadConn_tris[1] = 2; - RoadConn_tris[2] = 1; - RoadConn_tris[3] = 2; - RoadConn_tris[4] = 3; - RoadConn_tris[5] = 1; - - Vector3[] RoadConn_normals = new Vector3[4]; - RoadConn_normals[0] = -Vector3.forward; - RoadConn_normals[1] = -Vector3.forward; - RoadConn_normals[2] = -Vector3.forward; - RoadConn_normals[3] = -Vector3.forward; - Vector2[] RoadConn_uv = new Vector2[4]; - float tMod = (RoadWidth / tSpline.SpecialEndNodeDelay_End_Result) / 2f; - RoadConn_uv[0] = new Vector2(tMod, 0f); - RoadConn_uv[1] = new Vector2(tMod * 3f, 0f); - RoadConn_uv[2] = new Vector2(0f, 1f); - RoadConn_uv[3] = new Vector2(1f, 1f); - tRoad.RCS.RoadConnections_verts.Add(RoadConn_verts); - tRoad.RCS.RoadConnections_tris.Add(RoadConn_tris); - tRoad.RCS.RoadConnections_normals.Add(RoadConn_normals); - tRoad.RCS.RoadConnections_uv.Add(RoadConn_uv); - } - if (tRoad.bProfiling) { UnityEngine.Profiling.Profiler.EndSample(); } - } - - #region "Road prelim helpers" - private static Vector3 GVC(Vector3 v1, float tHeight) - { - return new Vector3(v1.x, tHeight, v1.z); - } - - /// - /// Usage: tDir = forward dir of player. tVect = direction from player to enemy - /// - /// - /// true if this instance is vect in front the specified tDir tVect; otherwise, false. - /// - /// - /// If set to true t dir. - /// - /// - /// If set to true t vect. - /// - private static bool IsVectInFront(Vector3 tDir, Vector3 tVect) - { - return (Vector3.Dot(tDir.normalized, tVect) > 0); - } - - private static Vector2 ConvertVect3_To_Vect2(Vector3 tVect) - { - return new Vector2(tVect.x, tVect.z); - } - - private static void InterFinalizeiBLane0(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode) - { - if (xNode.iConstruction.bBLane0Done_Final) { return; } - - xNode.iConstruction.bBLane0Done = true; - if (GSDRI.bFlipped && !bFirstInterNode) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[4], tIntHeight)); - xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - } - else - { - xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - } - } - else - { - if (bLRtoRR) - { - xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerLR_CornerRR[0], tIntHeight)); - xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerLR_CornerRR[1], tIntHeight)); - } - else if (bLLtoLR) - { - xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); - xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - } - } - xNode.iConstruction.bBLane0Done_Final = true; - xNode.iConstruction.bBLane0Done_Final_ThisRound = true; - } - - private static void InterFinalizeiBLane1(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b0LAdded, ref bool b1RAdded) - { - if (xNode.iConstruction.bBLane1Done_Final) { return; } - - if (b0LAdded && !xNode.iConstruction.bBLane0Done_Final) - { - xNode.iConstruction.iBLane0L.RemoveAt(xNode.iConstruction.iBLane0L.Count - 1); - b0LAdded = false; - InterFinalizeiBLane0(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode); - } - xNode.iConstruction.bBLane1Done = true; - xNode.iConstruction.bBLane0Done = true; - - if (GSDRI.bFlipped && !bFirstInterNode) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); - xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - } - else - { - xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); //b1RAdded = true; - } - } - else - { - if (bLRtoRR) - { - xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerLR_CornerRR[1], tIntHeight)); - xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerLR_CornerRR[2], tIntHeight)); //b1RAdded = true; - } - else if (bLLtoLR) - { - xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); - xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); //b1RAdded = true; - } - } - xNode.iConstruction.bBLane1Done_Final = true; - xNode.iConstruction.bBLane1Done_Final_ThisRound = true; - - if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - xNode.iConstruction.bBackRRpassed = true; - } - } - - private static void InterFinalizeiBLane2(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b2LAdded, ref bool b1LAdded, ref bool b0LAdded, ref bool b1RAdded) - { - if (xNode.iConstruction.bBLane2Done_Final) { return; } - - if (b1LAdded && !xNode.iConstruction.bBLane1Done_Final) - { - xNode.iConstruction.iBLane1L.RemoveAt(xNode.iConstruction.iBLane1L.Count - 1); - b1LAdded = false; - InterFinalizeiBLane1(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b0LAdded, ref b1RAdded); - } - xNode.iConstruction.bBLane1Done = true; - xNode.iConstruction.bBLane2Done = true; - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - if (GSDRI.bFlipped && !bFirstInterNode) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); - xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); - } - } - else - { - if (bLRtoRR) - { - xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerLR_CornerRR[2], tIntHeight)); - xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerLR_CornerRR[3], tIntHeight)); - } - else if (bLLtoLR) - { - xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); - xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); - } - } - } - xNode.iConstruction.bBLane2Done_Final = true; - xNode.iConstruction.bBLane2Done_Final_ThisRound = true; - - if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - xNode.iConstruction.bBackRRpassed = true; - } - } - - private static void InterFinalizeiBLane3(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b2LAdded, ref bool b1LAdded, ref bool b0LAdded, ref bool b1RAdded) - { - if (b2LAdded && !xNode.iConstruction.bBLane2Done_Final) - { - xNode.iConstruction.iBLane2L.RemoveAt(xNode.iConstruction.iBLane2L.Count - 1); - b2LAdded = false; - InterFinalizeiBLane2(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); - } - xNode.iConstruction.bBLane2Done = true; - xNode.iConstruction.bBLane3Done = true; - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (GSDRI.bFlipped && !bFirstInterNode) - { - xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); - xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); - } - else - { - if (bLRtoRR) - { - xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerLR_CornerRR[3], tIntHeight)); - xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerLR_CornerRR[4], tIntHeight)); - } - else if (bLLtoLR) - { - xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); - xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerLL_CornerLR[4], tIntHeight)); - } - } - } - xNode.iConstruction.bBLane3Done_Final = true; - xNode.iConstruction.bBLane3Done_Final_ThisRound = true; - - if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - xNode.iConstruction.bBackRRpassed = true; - } - } - #endregion - - #endregion - - #region "Intersection Prelim" - private static void RoadJob_Prelim_Inter(ref GSDRoad tRoad) - { - GSDSplineC tSpline = tRoad.GSDSpline; - float RoadWidth = tRoad.RoadWidth(); - float ShoulderWidth = tRoad.opt_ShoulderWidth; - float RoadSeperation = RoadWidth / 2f; - float RoadSeperation_NoTurn = RoadWidth / 2f; - float ShoulderSeperation = RoadSeperation + ShoulderWidth; if (ShoulderSeperation < 0f) { } - float LaneWidth = tRoad.opt_LaneWidth; - float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); - float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); - Vector3 POS = default(Vector3); - bool bIsPastInter = false; - bool bOldMethod = false; - //bool bCancel = false; if (bTempCancel) { } - bool bTempCancel = false; if (bTempCancel) { } - - //If left collides with left, etc - - //This will speed up later calculations for intersection 4 corner construction: - int mCount = tSpline.GetNodeCount(); - float PreInter_RoadWidthMod = 4.5f; - if (!bOldMethod) - { - PreInter_RoadWidthMod = 5.5f; - } - float preInterDistance = (tSpline.RoadWidth * PreInter_RoadWidthMod) / tSpline.distance; - GSDSplineN iNode = null; - for (int j = 0; j < mCount; j++) - { - bTempCancel = false; - if (tSpline.mNodes[j].bIsIntersection) - { - iNode = tSpline.mNodes[j]; - //First node set min / max float: - if (iNode.iConstruction == null) { iNode.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); } - if (!iNode.iConstruction.tempconstruction_HasProcessed_Inter1) - { - preInterDistance = (iNode.GSDSpline.RoadWidth * PreInter_RoadWidthMod) / iNode.GSDSpline.distance; - iNode.iConstruction.tempconstruction_InterStart = iNode.tTime - preInterDistance; - iNode.iConstruction.tempconstruction_InterEnd = iNode.tTime + preInterDistance; - if (iNode.iConstruction.tempconstruction_InterStart > 1f) { iNode.iConstruction.tempconstruction_InterStart = 1f; } - if (iNode.iConstruction.tempconstruction_InterStart < 0f) { iNode.iConstruction.tempconstruction_InterStart = 0f; } - if (iNode.iConstruction.tempconstruction_InterEnd > 1f) { iNode.iConstruction.tempconstruction_InterEnd = 1f; } - if (iNode.iConstruction.tempconstruction_InterEnd < 0f) { iNode.iConstruction.tempconstruction_InterEnd = 0f; } - iNode.iConstruction.tempconstruction_HasProcessed_Inter1 = true; - } - - if (string.Compare(iNode.UID, iNode.GSDRI.Node1.UID) == 0) - { - iNode = iNode.GSDRI.Node2; - } - else - { - iNode = iNode.GSDRI.Node1; - } - - //Grab other intersection node and set min / max float - try - { - if (!iNode.iConstruction.tempconstruction_HasProcessed_Inter1) - { - preInterDistance = (iNode.GSDSpline.RoadWidth * PreInter_RoadWidthMod) / iNode.GSDSpline.distance; - iNode.iConstruction.tempconstruction_InterStart = iNode.tTime - preInterDistance; - iNode.iConstruction.tempconstruction_InterEnd = iNode.tTime + preInterDistance; - if (iNode.iConstruction.tempconstruction_InterStart > 1f) { iNode.iConstruction.tempconstruction_InterStart = 1f; } - if (iNode.iConstruction.tempconstruction_InterStart < 0f) { iNode.iConstruction.tempconstruction_InterStart = 0f; } - if (iNode.iConstruction.tempconstruction_InterEnd > 1f) { iNode.iConstruction.tempconstruction_InterEnd = 1f; } - if (iNode.iConstruction.tempconstruction_InterEnd < 0f) { iNode.iConstruction.tempconstruction_InterEnd = 0f; } - iNode.iConstruction.tempconstruction_HasProcessed_Inter1 = true; - } - } - catch - { - //Do nothing - } - } - } - - //Now get the four points per intersection: - GSDSplineN oNode1 = null; - GSDSplineN oNode2 = null; - float PreInterPrecision1 = -1f; - float PreInterPrecision2 = -1f; - Vector3 PreInterVect = default(Vector3); - Vector3 PreInterVectR = default(Vector3); - Vector3 PreInterVectR_RightTurn = default(Vector3); - Vector3 PreInterVectL = default(Vector3); - Vector3 PreInterVectL_RightTurn = default(Vector3); - GSDRoadIntersection GSDRI = null; - - for (int j = 0; j < mCount; j++) - { - oNode1 = tSpline.mNodes[j]; - if (oNode1.bIsIntersection) - { - oNode1 = oNode1.GSDRI.Node1; - oNode2 = oNode1.GSDRI.Node2; - if (bOldMethod) - { - PreInterPrecision1 = 0.1f / oNode1.GSDSpline.distance; - PreInterPrecision2 = 0.1f / oNode2.GSDSpline.distance; - } - else - { - PreInterPrecision1 = 4f / oNode1.GSDSpline.distance; - PreInterPrecision2 = 4f / oNode2.GSDSpline.distance; - } - GSDRI = oNode1.GSDRI; - try - { - if (oNode1.iConstruction.tempconstruction_HasProcessed_Inter2 && oNode2.iConstruction.tempconstruction_HasProcessed_Inter2) - { - continue; - } - } - catch - { - continue; - } - GSDRI = oNode1.GSDRI; - GSDRI.CornerRR1 = false; - GSDRI.CornerRR2 = false; - GSDRI.CornerRL1 = false; - GSDRI.CornerRL2 = false; - GSDRI.CornerLR1 = false; - GSDRI.CornerLR2 = false; - GSDRI.CornerLL1 = false; - GSDRI.CornerLL2 = false; - - if (!oNode1.iConstruction.tempconstruction_HasProcessed_Inter2) - { - oNode1.iConstruction.tempconstruction_R = new List(); - oNode1.iConstruction.tempconstruction_L = new List(); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - oNode1.iConstruction.tempconstruction_R_RightTurn = new List(); - oNode1.iConstruction.tempconstruction_L_RightTurn = new List(); - } - - for (float i = oNode1.iConstruction.tempconstruction_InterStart; i < oNode1.iConstruction.tempconstruction_InterEnd; i += PreInterPrecision1) - { - oNode1.GSDSpline.GetSplineValue_Both(i, out PreInterVect, out POS); - - bIsPastInter = oNode1.GSDSpline.IntersectionIsPast(ref i, ref oNode1); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bIsPastInter) - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); - } - else - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - else - { - PreInterVectR = (PreInterVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); - } - - oNode1.iConstruction.tempconstruction_R.Add(new Vector2(PreInterVectR.x, PreInterVectR.z)); - oNode1.iConstruction.tempconstruction_L.Add(new Vector2(PreInterVectL.x, PreInterVectL.z)); - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - PreInterVectR_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - oNode1.iConstruction.tempconstruction_R_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectR_RightTurn)); - - PreInterVectL_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); - oNode1.iConstruction.tempconstruction_L_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectL_RightTurn)); - } - } - } - - //Process second node: - if (oNode2.iConstruction == null) { oNode2.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); } - if (!oNode2.iConstruction.tempconstruction_HasProcessed_Inter2) - { - oNode2.iConstruction.tempconstruction_R = new List(); - oNode2.iConstruction.tempconstruction_L = new List(); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - oNode2.iConstruction.tempconstruction_R_RightTurn = new List(); - oNode2.iConstruction.tempconstruction_L_RightTurn = new List(); - } - - for (float i = oNode2.iConstruction.tempconstruction_InterStart; i < oNode2.iConstruction.tempconstruction_InterEnd; i += PreInterPrecision2) - { - oNode2.GSDSpline.GetSplineValue_Both(i, out PreInterVect, out POS); - - bIsPastInter = oNode2.GSDSpline.IntersectionIsPast(ref i, ref oNode2); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bIsPastInter) - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); - } - else - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - else - { - PreInterVectR = (PreInterVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); - PreInterVectL = (PreInterVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); - } - - oNode2.iConstruction.tempconstruction_R.Add(new Vector2(PreInterVectR.x, PreInterVectR.z)); - oNode2.iConstruction.tempconstruction_L.Add(new Vector2(PreInterVectL.x, PreInterVectL.z)); - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - PreInterVectR_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - oNode2.iConstruction.tempconstruction_R_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectR_RightTurn)); - - PreInterVectL_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); - oNode2.iConstruction.tempconstruction_L_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectL_RightTurn)); - } - } - } - - - - bool bFlipped = false; - bool bFlippedSet = false; - int hCount1 = oNode1.iConstruction.tempconstruction_R.Count; - int hCount2 = oNode2.iConstruction.tempconstruction_R.Count; - int N1RCount = oNode1.iConstruction.tempconstruction_R.Count; - int N1LCount = oNode1.iConstruction.tempconstruction_L.Count; - int N2RCount = oNode2.iConstruction.tempconstruction_R.Count; - int N2LCount = oNode2.iConstruction.tempconstruction_L.Count; - - int[] tCounts = new int[4]; - tCounts[0] = N1RCount; - tCounts[1] = N1LCount; - tCounts[2] = N2RCount; - tCounts[3] = N2LCount; - - //RR: - int MaxCount = -1; - MaxCount = Mathf.Max(N2RCount, N2LCount); - for (int h = 0; h < hCount1; h++) - { - for (int k = 0; k < MaxCount; k++) - { - if (k < N2RCount) - { - if (Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]) < tRoad.opt_RoadDefinition) - { - bFlipped = false; - bFlippedSet = true; - break; - } - } - if (k < N2LCount) - { - if (Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]) < tRoad.opt_RoadDefinition) - { - bFlipped = true; - bFlippedSet = true; - break; - } - } - } - if (bFlippedSet) { break; } - } - oNode1.GSDRI.bFlipped = bFlipped; - - - //Three-way intersections lane specifics: - GSDRI.bNode2B_LeftTurnLane = true; - GSDRI.bNode2B_RightTurnLane = true; - GSDRI.bNode2F_LeftTurnLane = true; - GSDRI.bNode2F_RightTurnLane = true; - - //Three-way intersections: - GSDRI.IgnoreSide = -1; - GSDRI.IgnoreCorner = -1; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.FourWay; - if (GSDRI.bFirstSpecial_First) - { - GSDRI.IgnoreSide = 3; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 0; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 1; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - else - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - - - } - else if (GSDRI.bFirstSpecial_Last) - { - GSDRI.IgnoreSide = 1; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 2; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 3; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - else - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - - } - if (!bFlipped) - { - if (GSDRI.bSecondSpecial_First) - { - GSDRI.IgnoreSide = 2; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 3; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 0; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - else - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - - } - else if (GSDRI.bSecondSpecial_Last) - { - GSDRI.IgnoreSide = 0; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 1; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 2; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - else - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - - } - } - else - { - if (GSDRI.bSecondSpecial_First) - { - GSDRI.IgnoreSide = 0; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 1; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 2; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - else - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - - } - else if (GSDRI.bSecondSpecial_Last) - { - GSDRI.IgnoreSide = 2; - GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; - if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) - { - GSDRI.IgnoreCorner = 3; - } - else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) - { - GSDRI.IgnoreCorner = 0; - } - - if (!oNode1.GSDRI.bFlipped) - { - GSDRI.bNode2B_LeftTurnLane = false; - GSDRI.bNode2F_RightTurnLane = false; - } - else - { - GSDRI.bNode2F_LeftTurnLane = false; - GSDRI.bNode2B_RightTurnLane = false; - } - } - } - - //Find corners: - Vector2 tFoundVectRR = default(Vector2); - Vector2 tFoundVectRL = default(Vector2); - Vector2 tFoundVectLR = default(Vector2); - Vector2 tFoundVectLL = default(Vector2); - if (!bOldMethod) - { - //RR: - if (!bFlipped) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R_RightTurn, ref oNode2.iConstruction.tempconstruction_R); - } - else - { - tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R); - } - } - else - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R_RightTurn, ref oNode2.iConstruction.tempconstruction_L); - } - else - { - tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L); - } - } - - //RL: - if (!bFlipped) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L_RightTurn); - } - else - { - tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L); - } - } - else - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R_RightTurn); - } - else - { - tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R); - } - } - - //LL: - if (!bFlipped) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L_RightTurn, ref oNode2.iConstruction.tempconstruction_L); - } - else - { - tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L); - } - } - else - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L_RightTurn, ref oNode2.iConstruction.tempconstruction_R); - } - else - { - tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R); - } - } - - //LR: - if (!bFlipped) - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R_RightTurn); - } - else - { - tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R); - } - } - else - { - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L_RightTurn); - } - else - { - tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L); - } - } - } - else - { - //Now two lists of R and L on each intersection node, now match: - float eDistanceRR = 5000f; - float oDistanceRR = 0f; - float eDistanceRL = 5000f; - float oDistanceRL = 0f; - float eDistanceLR = 5000f; - float oDistanceLR = 0f; - float eDistanceLL = 5000f; - float oDistanceLL = 0f; - bool bHasBeen1mRR = false; - bool bHasBeen1mRL = false; - bool bHasBeen1mLR = false; - bool bHasBeen1mLL = false; - bool bHasBeen1mRR_ignore = false; - bool bHasBeen1mRL_ignore = false; - bool bHasBeen1mLR_ignore = false; - bool bHasBeen1mLL_ignore = false; - bool bHasBeen1mRR_ignore_Max = false; - bool bHasBeen1mRL_ignore_Max = false; - bool bHasBeen1mLR_ignore_Max = false; - bool bHasBeen1mLL_ignore_Max = false; - float mMin = 0.2f; - float mMax = 0.5f; - - MaxCount = Mathf.Max(tCounts); - int MaxHCount = Mathf.Max(hCount1, hCount2); - for (int h = 0; h < MaxHCount; h++) - { - bHasBeen1mRR = false; - bHasBeen1mRL = false; - bHasBeen1mLR = false; - bHasBeen1mLL = false; - bHasBeen1mRR_ignore = false; - bHasBeen1mRL_ignore = false; - bHasBeen1mLR_ignore = false; - bHasBeen1mLL_ignore = false; - for (int k = 0; k < MaxCount; k++) - { - if (!bFlipped) - { - //RR: - if (!bHasBeen1mRR_ignore_Max && !bHasBeen1mRR_ignore && (h < N1RCount && k < N2RCount)) - { - oDistanceRR = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]); - if (oDistanceRR < eDistanceRR) - { - eDistanceRR = oDistanceRR; - tFoundVectRR = oNode1.iConstruction.tempconstruction_R[h]; //RR - if (eDistanceRR < 0.07f) { bHasBeen1mRR_ignore_Max = true; } - } - if (oDistanceRR > mMax && bHasBeen1mRR) { bHasBeen1mRR_ignore = true; } - if (oDistanceRR < mMin) { bHasBeen1mRR = true; } - } - //RL: - if (!bHasBeen1mRL_ignore_Max && !bHasBeen1mRL_ignore && (h < N1RCount && k < N2LCount)) - { - oDistanceRL = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]); - if (oDistanceRL < eDistanceRL) - { - eDistanceRL = oDistanceRL; - tFoundVectRL = oNode1.iConstruction.tempconstruction_R[h]; //RL - if (eDistanceRL < 0.07f) { bHasBeen1mRL_ignore_Max = true; } - } - if (oDistanceRL > mMax && bHasBeen1mRL) { bHasBeen1mRL_ignore = true; } - if (oDistanceRL < mMin) { bHasBeen1mRL = true; } - } - //LR: - if (!bHasBeen1mLR_ignore_Max && !bHasBeen1mLR_ignore && (h < N1LCount && k < N2RCount)) - { - oDistanceLR = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_R[k]); - if (oDistanceLR < eDistanceLR) - { - eDistanceLR = oDistanceLR; - tFoundVectLR = oNode1.iConstruction.tempconstruction_L[h]; //LR - if (eDistanceLR < 0.07f) { bHasBeen1mLR_ignore_Max = true; } - } - if (oDistanceLR > mMax && bHasBeen1mLR) { bHasBeen1mLR_ignore = true; } - if (oDistanceLR < mMin) { bHasBeen1mLR = true; } - } - //LL: - if (!bHasBeen1mLL_ignore_Max && !bHasBeen1mLL_ignore && (h < N1LCount && k < N2LCount)) - { - oDistanceLL = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_L[k]); - if (oDistanceLL < eDistanceLL) - { - eDistanceLL = oDistanceLL; - tFoundVectLL = oNode1.iConstruction.tempconstruction_L[h]; //LL - if (eDistanceLL < 0.07f) { bHasBeen1mLL_ignore_Max = true; } - } - if (oDistanceLL > mMax && bHasBeen1mLL) { bHasBeen1mLL_ignore = true; } - if (oDistanceLL < mMin) { bHasBeen1mLL = true; } - } - } - else - { - //RR: - if (!bHasBeen1mRR_ignore_Max && !bHasBeen1mRR_ignore && (h < N1RCount && k < N2LCount)) - { - oDistanceRR = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]); - if (oDistanceRR < eDistanceRR) - { - eDistanceRR = oDistanceRR; - tFoundVectRR = oNode1.iConstruction.tempconstruction_R[h]; //RR - if (eDistanceRR < 0.07f) { bHasBeen1mRR_ignore_Max = true; } - } - if (oDistanceRR > mMax && bHasBeen1mRR) { bHasBeen1mRR_ignore = true; } - if (oDistanceRR < mMin) { bHasBeen1mRR = true; } - } - //RL: - if (!bHasBeen1mRL_ignore_Max && !bHasBeen1mRL_ignore && (h < N1RCount && k < N2RCount)) - { - oDistanceRL = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]); - if (oDistanceRL < eDistanceRL) - { - eDistanceRL = oDistanceRL; - tFoundVectRL = oNode1.iConstruction.tempconstruction_R[h]; //RL - if (eDistanceRL < 0.07f) { bHasBeen1mRL_ignore_Max = true; } - } - if (oDistanceRL > mMax && bHasBeen1mRL) { bHasBeen1mRL_ignore = true; } - if (oDistanceRL < mMin) { bHasBeen1mRL = true; } - } - //LR: - if (!bHasBeen1mLR_ignore_Max && !bHasBeen1mLR_ignore && (h < N1LCount && k < N2LCount)) - { - oDistanceLR = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_L[k]); - if (oDistanceLR < eDistanceLR) - { - eDistanceLR = oDistanceLR; - tFoundVectLR = oNode1.iConstruction.tempconstruction_L[h]; //LR - if (eDistanceLR < 0.07f) { bHasBeen1mLR_ignore_Max = true; } - } - if (oDistanceLR > mMax && bHasBeen1mLR) { bHasBeen1mLR_ignore = true; } - if (oDistanceLR < mMin) { bHasBeen1mLR = true; } - } - //LL: - if (!bHasBeen1mLL_ignore_Max && !bHasBeen1mLL_ignore && (h < N1LCount && k < N2RCount)) - { - oDistanceLL = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_R[k]); - if (oDistanceLL < eDistanceLL) - { - eDistanceLL = oDistanceLL; - tFoundVectLL = oNode1.iConstruction.tempconstruction_L[h]; //LL - if (eDistanceLL < 0.07f) { bHasBeen1mLL_ignore_Max = true; } - } - if (oDistanceLL > mMax && bHasBeen1mLL) { bHasBeen1mLL_ignore = true; } - if (oDistanceLL < mMin) { bHasBeen1mLL = true; } - } - } - } - } - } - - oNode1.iConstruction.tempconstruction_HasProcessed_Inter2 = true; - oNode2.iConstruction.tempconstruction_HasProcessed_Inter2 = true; - - Vector3 tVectRR = new Vector3(tFoundVectRR.x, 0f, tFoundVectRR.y); - Vector3 tVectRL = new Vector3(tFoundVectRL.x, 0f, tFoundVectRL.y); - Vector3 tVectLR = new Vector3(tFoundVectLR.x, 0f, tFoundVectLR.y); - Vector3 tVectLL = new Vector3(tFoundVectLL.x, 0f, tFoundVectLL.y); - - oNode1.GSDRI.CornerRR = tVectRR; - oNode1.GSDRI.CornerRL = tVectRL; - oNode1.GSDRI.CornerLR = tVectLR; - oNode1.GSDRI.CornerLL = tVectLL; - - float[] tMaxFloats = new float[4]; - tMaxFloats[0] = Vector3.Distance(((tVectRR - tVectRL) * 0.5f) + tVectRL, oNode1.pos) * 1.25f; - tMaxFloats[1] = Vector3.Distance(((tVectRR - tVectLR) * 0.5f) + tVectLR, oNode1.pos) * 1.25f; - tMaxFloats[2] = Vector3.Distance(((tVectRL - tVectLL) * 0.5f) + tVectLL, oNode1.pos) * 1.25f; - tMaxFloats[3] = Vector3.Distance(((tVectLR - tVectLL) * 0.5f) + tVectLL, oNode1.pos) * 1.25f; - GSDRI.MaxInterDistance = Mathf.Max(tMaxFloats); - - float[] tMaxFloatsSQ = new float[4]; - tMaxFloatsSQ[0] = Vector3.SqrMagnitude((((tVectRR - tVectRL) * 0.5f) + tVectRL) - oNode1.pos) * 1.25f; - tMaxFloatsSQ[1] = Vector3.SqrMagnitude((((tVectRR - tVectLR) * 0.5f) + tVectLR) - oNode1.pos) * 1.25f; - tMaxFloatsSQ[2] = Vector3.SqrMagnitude((((tVectRL - tVectLL) * 0.5f) + tVectLL) - oNode1.pos) * 1.25f; - tMaxFloatsSQ[3] = Vector3.SqrMagnitude((((tVectLR - tVectLL) * 0.5f) + tVectLL) - oNode1.pos) * 1.25f; - GSDRI.MaxInterDistanceSQ = Mathf.Max(tMaxFloatsSQ); - - float TotalLanes = (int)(RoadWidth / LaneWidth); - float TotalLanesI = TotalLanes; - float LanesPerSide = TotalLanes / 2f; - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - TotalLanesI = TotalLanes + 2f; - //Lower left to lower right: - GSDRI.fCornerLR_CornerRR = new Vector3[5]; - GSDRI.fCornerLR_CornerRR[0] = tVectLR; - GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * (LanesPerSide / TotalLanesI)) + tVectLR; - GSDRI.fCornerLR_CornerRR[2] = ((tVectRR - tVectLR) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLR; - GSDRI.fCornerLR_CornerRR[3] = ((tVectRR - tVectLR) * ((LanesPerSide + 1 + LanesPerSide) / TotalLanesI)) + tVectLR; - GSDRI.fCornerLR_CornerRR[4] = tVectRR; - //Upper right to lower right: - GSDRI.fCornerRL_CornerRR = new Vector3[5]; - GSDRI.fCornerRL_CornerRR[0] = tVectRL; - GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * (1 / TotalLanesI)) + tVectRL; - GSDRI.fCornerRL_CornerRR[2] = ((tVectRR - tVectRL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectRL; - GSDRI.fCornerRL_CornerRR[3] = ((tVectRR - tVectRL) * ((LanesPerSide + 2) / TotalLanesI)) + tVectRL; - GSDRI.fCornerRL_CornerRR[4] = tVectRR; - //Upper left to upper right: - GSDRI.fCornerLL_CornerRL = new Vector3[5]; - GSDRI.fCornerLL_CornerRL[0] = tVectLL; - GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * (1 / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerRL[2] = ((tVectRL - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerRL[3] = ((tVectRL - tVectLL) * ((LanesPerSide + 2) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerRL[4] = tVectRL; - //Upper left to lower left: - GSDRI.fCornerLL_CornerLR = new Vector3[5]; - GSDRI.fCornerLL_CornerLR[0] = tVectLL; - GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerLR[2] = ((tVectLR - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerLR[3] = ((tVectLR - tVectLL) * ((LanesPerSide + 1 + LanesPerSide) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerLR[4] = tVectLR; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - TotalLanesI = TotalLanes + 1; - //Lower left to lower right: - GSDRI.fCornerLR_CornerRR = new Vector3[4]; - GSDRI.fCornerLR_CornerRR[0] = tVectLR; - GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * (LanesPerSide / TotalLanesI)) + tVectLR; - GSDRI.fCornerLR_CornerRR[2] = ((tVectRR - tVectLR) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLR; - GSDRI.fCornerLR_CornerRR[3] = tVectRR; - //Upper right to lower right: - GSDRI.fCornerRL_CornerRR = new Vector3[4]; - GSDRI.fCornerRL_CornerRR[0] = tVectRL; - GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * (LanesPerSide / TotalLanesI)) + tVectRL; - GSDRI.fCornerRL_CornerRR[2] = ((tVectRR - tVectRL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectRL; - GSDRI.fCornerRL_CornerRR[3] = tVectRR; - //Upper left to upper right: - GSDRI.fCornerLL_CornerRL = new Vector3[4]; - GSDRI.fCornerLL_CornerRL[0] = tVectLL; - GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerRL[2] = ((tVectRL - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerRL[3] = tVectRL; - //Upper left to lower left: - GSDRI.fCornerLL_CornerLR = new Vector3[4]; - GSDRI.fCornerLL_CornerLR[0] = tVectLL; - GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerLR[2] = ((tVectLR - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; - GSDRI.fCornerLL_CornerLR[3] = tVectLR; - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - TotalLanesI = TotalLanes + 0; - //Lower left to lower right: - GSDRI.fCornerLR_CornerRR = new Vector3[3]; - GSDRI.fCornerLR_CornerRR[0] = tVectLR; - GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * 0.5f) + tVectLR; - GSDRI.fCornerLR_CornerRR[2] = tVectRR; - //Upper right to lower right: - GSDRI.fCornerRL_CornerRR = new Vector3[3]; - GSDRI.fCornerRL_CornerRR[0] = tVectRL; - GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * 0.5f) + tVectRL; - GSDRI.fCornerRL_CornerRR[2] = tVectRR; - //Upper left to upper right: - GSDRI.fCornerLL_CornerRL = new Vector3[3]; - GSDRI.fCornerLL_CornerRL[0] = tVectLL; - GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * 0.5f) + tVectLL; - GSDRI.fCornerLL_CornerRL[2] = tVectRL; - //Upper left to lower left: - GSDRI.fCornerLL_CornerLR = new Vector3[3]; - GSDRI.fCornerLL_CornerLR[0] = tVectLL; - GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * 0.5f) + tVectLL; - GSDRI.fCornerLL_CornerLR[2] = tVectLR; - } - - //Use node1/node2 for angles instead - float tShoulderWidth = ShoulderWidth * 1.75f; - float tRampWidth = ShoulderWidth * 2f; - - oNode1.GSDRI.OddAngle = Vector3.Angle(GSDRI.Node2.tangent, GSDRI.Node1.tangent); - oNode1.GSDRI.EvenAngle = 180f - Vector3.Angle(GSDRI.Node2.tangent, GSDRI.Node1.tangent); - - GSD.Roads.GSDIntersectionObjects.GetFourPoints(GSDRI, out GSDRI.CornerRR_Outer, out GSDRI.CornerRL_Outer, out GSDRI.CornerLL_Outer, out GSDRI.CornerLR_Outer, tShoulderWidth); - GSD.Roads.GSDIntersectionObjects.GetFourPoints(GSDRI, out GSDRI.CornerRR_RampOuter, out GSDRI.CornerRL_RampOuter, out GSDRI.CornerLL_RampOuter, out GSDRI.CornerLR_RampOuter, tRampWidth); - - GSDRI.ConstructBoundsRect(); - GSDRI.CornerRR_2D = new Vector2(tVectRR.x, tVectRR.z); - GSDRI.CornerRL_2D = new Vector2(tVectRL.x, tVectRL.z); - GSDRI.CornerLL_2D = new Vector2(tVectLL.x, tVectLL.z); - GSDRI.CornerLR_2D = new Vector2(tVectLR.x, tVectLR.z); - - if (!oNode1.GSDRI.bSameSpline) - { - if (string.Compare(tRoad.GSDSpline.UID, oNode1.GSDSpline.tRoad.GSDSpline.UID) != 0) - { - AddIntersectionBounds(ref oNode1.GSDSpline.tRoad, ref tRoad.RCS); - } - else if (string.Compare(tRoad.GSDSpline.UID, oNode2.GSDSpline.tRoad.GSDSpline.UID) != 0) - { - AddIntersectionBounds(ref oNode2.GSDSpline.tRoad, ref tRoad.RCS); - } - } - } - } - } - - private static Vector2 IntersectionCornerCalc(ref List PrimaryList, ref List SecondaryList) - { - int PrimaryCount = PrimaryList.Count; - int SecondaryCount = SecondaryList.Count; - Vector2 t2D_Line1Start = default(Vector2); - Vector2 t2D_Line1End = default(Vector2); - Vector2 t2D_Line2Start = default(Vector2); - Vector2 t2D_Line2End = default(Vector2); - bool bDidIntersect = false; - Vector2 tIntersectLocation = default(Vector2); - for (int i = 1; i < PrimaryCount; i++) - { - bDidIntersect = false; - t2D_Line1Start = PrimaryList[i - 1]; - t2D_Line1End = PrimaryList[i]; - for (int k = 1; k < SecondaryCount; k++) - { - bDidIntersect = false; - t2D_Line2Start = SecondaryList[k - 1]; - t2D_Line2End = SecondaryList[k]; - bDidIntersect = GSDRootUtil.Intersects2D(ref t2D_Line1Start, ref t2D_Line1End, ref t2D_Line2Start, ref t2D_Line2End, out tIntersectLocation); - if (bDidIntersect) - { - return tIntersectLocation; - } - } - } - return tIntersectLocation; - } - - private static void AddIntersectionBounds(ref GSDRoad tRoad, ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - bool bIsBridge = false; - bool bBridgeInitial = false; if (bBridgeInitial == false) { } - bool bTempbridge = false; - bool bBridgeLast = false; if (bBridgeLast == false) { } - - bool bIsTunnel = false; - bool bTunnelInitial = false; if (bTunnelInitial == false) { } - bool bTempTunnel = false; - bool bTunnelLast = false; if (bTunnelLast == false) { } - - GSDRoadIntersection GSDRI = null; - bool bIsPastInter = false; - bool bMaxIntersection = false; - bool bWasPrevMaxInter = false; - Vector3 tVect = default(Vector3); - Vector3 POS = default(Vector3); - float tIntHeight = 0f; - float tIntStrength = 0f; - float tIntStrength_temp = 0f; - // float tIntDistCheck = 75f; - bool bFirstInterNode = false; - Vector3 tVect_Prev = default(Vector3); if (tVect_Prev == default(Vector3)) { } - Vector3 rVect_Prev = default(Vector3); if (rVect_Prev == default(Vector3)) { } - Vector3 lVect_Prev = default(Vector3); if (lVect_Prev == default(Vector3)) { } - Vector3 rVect = default(Vector3); if (rVect == default(Vector3)) { } - Vector3 lVect = default(Vector3); if (lVect == default(Vector3)) { } - Vector3 ShoulderR_rVect = default(Vector3); if (ShoulderR_rVect == default(Vector3)) { } - Vector3 ShoulderR_lVect = default(Vector3); if (ShoulderR_lVect == default(Vector3)) { } - Vector3 ShoulderL_rVect = default(Vector3); if (ShoulderL_rVect == default(Vector3)) { } - Vector3 ShoulderL_lVect = default(Vector3); if (ShoulderL_lVect == default(Vector3)) { } - - Vector3 RampR_R = default(Vector3); - Vector3 RampR_L = default(Vector3); - Vector3 RampL_R = default(Vector3); - Vector3 RampL_L = default(Vector3); - float ShoulderR_OuterAngle = 0f; if (ShoulderR_OuterAngle < 0f) { } - float ShoulderL_OuterAngle = 0f; if (ShoulderL_OuterAngle < 0f) { } - Vector3 ShoulderR_PrevLVect = default(Vector3); if (ShoulderR_PrevLVect == default(Vector3)) { } - Vector3 ShoulderL_PrevRVect = default(Vector3); if (ShoulderL_PrevRVect == default(Vector3)) { } - Vector3 ShoulderR_PrevRVect = default(Vector3); if (ShoulderR_PrevRVect == default(Vector3)) { } - Vector3 ShoulderL_PrevLVect = default(Vector3); if (ShoulderL_PrevLVect == default(Vector3)) { } - // Vector3 ShoulderR_PrevRVect2 = default(Vector3); - // Vector3 ShoulderL_PrevLVect2 = default(Vector3); - // Vector3 ShoulderR_PrevRVect3 = default(Vector3); - // Vector3 ShoulderL_PrevLVect3 = default(Vector3); - Vector3 RampR_PrevR = default(Vector3); if (RampR_PrevR == default(Vector3)) { } - Vector3 RampR_PrevL = default(Vector3); if (RampR_PrevL == default(Vector3)) { } - Vector3 RampL_PrevR = default(Vector3); if (RampL_PrevR == default(Vector3)) { } - Vector3 RampL_PrevL = default(Vector3); if (RampL_PrevL == default(Vector3)) { } - GSDSplineC tSpline = tRoad.GSDSpline; - //Road width: - float RoadWidth = tRoad.RoadWidth(); - float ShoulderWidth = tRoad.opt_ShoulderWidth; - float RoadSeperation = RoadWidth / 2f; - float RoadSeperation_NoTurn = RoadWidth / 2f; - float ShoulderSeperation = RoadSeperation + ShoulderWidth; - float LaneWidth = tRoad.opt_LaneWidth; - float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); - float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); - float ShoulderSep1Lane = (ShoulderSeperation + (LaneWidth * 0.5f)); if (ShoulderSep1Lane < 0f) { } - float ShoulderSep2Lane = (ShoulderSeperation + (LaneWidth * 1.5f)); if (ShoulderSep2Lane < 0f) { } - - // float tAngle = 0f; - // float OrigStep = 0.06f; - float Step = tRoad.opt_RoadDefinition / tSpline.distance; - - GSDSplineN xNode = null; - float tInterSubtract = 4f; - float tLastInterHeight = -4f; - - // GameObject xObj = null; - // xObj = GameObject.Find("temp22"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp22"); - // } - // xObj = GameObject.Find("temp23"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp23"); - // } - // xObj = GameObject.Find("temp22_RR"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp22_RR"); - // } - // xObj = GameObject.Find("temp22_RL"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp22_RL"); - // } - // xObj = GameObject.Find("temp22_LR"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp22_LR"); - // } - // xObj = GameObject.Find("temp22_LL"); - // while(xObj != null){ - // Object.DestroyImmediate(xObj); - // xObj = GameObject.Find("temp22_LL"); - // } - - bool bFinalEnd = false; - float i = 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; - } - - // int StartIndex = tSpline.GetClosestRoadDefIndex(StartMin,true,false); - // int EndIndex = tSpline.GetClosestRoadDefIndex(FinalMax,false,true); - // float cDist = 0f; - bool kSkip = true; - bool kSkipFinal = false; - int kCount = 0; - int kFinalCount = tSpline.RoadDefKeysArray.Length; - int spamcheckmax1 = 18000; - int spamcheck1 = 0; - - if (IsApproximately(StartMin, 0f, 0.0001f)) - { - kSkip = false; - } - if (IsApproximately(FinalMax, 1f, 0.0001f)) - { - kSkipFinal = true; - } - - while (!bFinalEnd && spamcheck1 < spamcheckmax1) - { - spamcheck1++; - - if (kSkip) - { - i = StartMin; - kSkip = false; - } - else - { - if (kCount >= kFinalCount) - { - i = FinalMax; - if (kSkipFinal) { break; } - } - else - { - i = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); - kCount += 1; - } - } - - if (i > 1f) { break; } - if (i < 0f) { i = 0f; } - - if (IsApproximately(i, FinalMax, 0.00001f)) - { - bFinalEnd = true; - } - else if (i > FinalMax) - { - if (tSpline.bSpecialEndControlNode) - { - i = FinalMax; - bFinalEnd = true; - } - else - { - bFinalEnd = true; - break; - } - } - - tSpline.GetSplineValue_Both(i, out tVect, out POS); - bIsPastInter = false; - tIntStrength = tSpline.IntersectionStrength(ref tVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - if (IsApproximately(tIntStrength, 1f, 0.001f) || tIntStrength > 1f) - { - bMaxIntersection = true; - } - else - { - bMaxIntersection = false; - } - - if (bMaxIntersection) - { - if (string.Compare(xNode.UID, GSDRI.Node1.UID) == 0) - { - bFirstInterNode = true; - } - else - { - bFirstInterNode = false; - } - - //Convoluted for initial trigger: - bBridgeInitial = false; - bBridgeLast = false; - bTempbridge = tSpline.IsInBridge(i); - if (!bIsBridge && bTempbridge) - { - bIsBridge = true; - bBridgeInitial = true; - } - else if (bIsBridge && !bTempbridge) - { - bIsBridge = false; - } - //Check if this is the last bridge run for this bridge: - if (bIsBridge) - { - bTempbridge = tSpline.IsInBridge(i + Step); - if (!bTempbridge) - { - bBridgeLast = true; - } - } - - - //Convoluted for initial trigger: - bTunnelInitial = false; - bTunnelLast = false; - bTempTunnel = tSpline.IsInTunnel(i); - if (!bIsTunnel && bTempTunnel) - { - bIsTunnel = true; - bTunnelInitial = true; - } - else if (bIsTunnel && !bTempTunnel) - { - bIsTunnel = false; - } - //Check if this is the last Tunnel run for this Tunnel: - if (bIsTunnel) - { - bTempTunnel = tSpline.IsInTunnel(i + Step); - if (!bTempTunnel) - { - bTunnelLast = true; - } - } - - if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - rVect = (tVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bIsPastInter) - { - rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); ; - } - else - { - rVect = (tVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); - } - } - else - { - rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); - lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); - } - - if (tIntStrength >= 1f) - { - tVect.y -= tInterSubtract; - tLastInterHeight = tVect.y; - rVect.y -= tInterSubtract; - lVect.y -= tInterSubtract; - } - else - { - if (!IsApproximately(tIntStrength, 0f, 0.001f)) { tVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect.y); } - tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref rVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); - if (!IsApproximately(tIntStrength_temp, 0f, 0.001f)) { rVect.y = (tIntStrength_temp * tIntHeight) + ((1 - tIntStrength_temp) * rVect.y); ShoulderR_lVect = rVect; } - } - - //Add bounds for later removal: - GSD.Roads.GSDRoadUtil.Construction2DRect vRect = null; - if (!bIsBridge && !bIsTunnel && bMaxIntersection && bWasPrevMaxInter) - { - bool bGoAhead = true; - if (xNode.bIsEndPoint) - { - if (xNode.idOnSpline == 1) - { - if (i < xNode.tTime) - { - bGoAhead = false; - } - } - else - { - if (i > xNode.tTime) - { - bGoAhead = false; - } - } - } - //Get this and prev lvect rvect rects: - if (Vector3.Distance(xNode.pos, tVect) < (3f * RoadWidth) && bGoAhead) - { - if (GSDRI.bFlipped && !bFirstInterNode) - { - vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( - new Vector2(rVect.x, rVect.z), - new Vector2(lVect.x, lVect.z), - new Vector2(rVect_Prev.x, rVect_Prev.z), - new Vector2(lVect_Prev.x, lVect_Prev.z), - tLastInterHeight - ); - } - else - { - vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( - new Vector2(lVect.x, lVect.z), - new Vector2(rVect.x, rVect.z), - new Vector2(lVect_Prev.x, lVect_Prev.z), - new Vector2(rVect_Prev.x, rVect_Prev.z), - tLastInterHeight - ); - } - // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.position = lVect; - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22"; - // - // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // tObj.transform.position = rVect; - // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); - // tObj.transform.name = "temp22"; - - RCS.tIntersectionBounds.Add(vRect); - } - } - } - - bWasPrevMaxInter = bMaxIntersection; - tVect_Prev = tVect; - rVect_Prev = rVect; - lVect_Prev = lVect; - ShoulderR_PrevLVect = ShoulderR_lVect; - ShoulderL_PrevRVect = ShoulderL_rVect; - // ShoulderR_PrevRVect3 = ShoulderR_PrevRVect2; - // ShoulderL_PrevLVect3 = ShoulderL_PrevLVect2; - // ShoulderR_PrevRVect2 = ShoulderR_PrevRVect; - // ShoulderL_PrevLVect2 = ShoulderL_PrevLVect; - ShoulderR_PrevRVect = ShoulderR_rVect; - ShoulderL_PrevLVect = ShoulderL_lVect; - RampR_PrevR = RampR_R; - RampR_PrevL = RampR_L; - RampL_PrevR = RampL_R; - RampL_PrevL = RampL_L; - // i+=Step; - } - } - #endregion - - #region "Intersection Prelim Finalization" - private static void RoadJob_Prelim_FinalizeInter(ref GSDRoad tRoad) - { - int mCount = tRoad.GSDSpline.GetNodeCount(); - GSDSplineN tNode; - for (int i = 0; i < mCount; i++) - { - tNode = tRoad.GSDSpline.mNodes[i]; - if (tNode.bIsIntersection) - { - Inter_OrganizeVertices(ref tNode, ref tRoad); - tNode.iConstruction.Nullify(); - tNode.iConstruction = null; - } - } - } - - private static bool Inter_OrganizeVerticesMatchEdges(ref List tList1, ref List tList2, bool bSkip1 = false, bool bSkipFirstListOne = false, bool bSkipBoth = false) - { - List PrimaryList; - List SecondaryList; - - List tList1New; - List tList2New; - - if (bSkip1) - { - if (bSkipBoth) - { - tList1New = new List(); - tList2New = new List(); - for (int i = 1; i < tList1.Count; i++) - { - tList1New.Add(tList1[i]); - } - for (int i = 1; i < tList2.Count; i++) - { - tList2New.Add(tList2[i]); - } - } - else - { - if (bSkipFirstListOne) - { - tList1New = new List(); - for (int i = 1; i < tList1.Count; i++) - { - tList1New.Add(tList1[i]); - } - tList2New = tList2; - } - else - { - tList2New = new List(); - for (int i = 1; i < tList2.Count; i++) - { - tList2New.Add(tList2[i]); - } - tList1New = tList1; - } - } - } - else - { - tList1New = tList1; - tList2New = tList2; - } - - int tList1Count = tList1New.Count; - int tList2Count = tList2New.Count; - if (tList1Count == tList2Count) { return false; } - - if (tList1Count > tList2Count) - { - PrimaryList = tList1New; - SecondaryList = tList2New; - } - else - { - PrimaryList = tList2New; - SecondaryList = tList1New; - } - - if (SecondaryList == null || SecondaryList.Count == 0) { return true; } - SecondaryList.Clear(); - SecondaryList = null; - SecondaryList = new List(); - for (int i = 0; i < PrimaryList.Count; i++) - { - SecondaryList.Add(PrimaryList[i]); - } - - - if (tList1Count > tList2Count) - { - tList2 = SecondaryList; - } - else - { - tList1 = SecondaryList; - } - - return false; - } - - private static void Inter_OrganizeVerticesMatchShoulder(ref List tShoulderList, ref List tToMatch, int StartI, ref Vector3 StartVec, ref Vector3 EndVect, float tHeight, bool bIsF = false) - { - // return; - List BackupList = new List(); - for (int i = 0; i < tToMatch.Count; i++) - { - BackupList.Add(tToMatch[i]); - } - Vector2 t2D = default(Vector2); - Vector2 t2D_Start = ConvertVect3_To_Vect2(StartVec); - Vector2 t2D_End = ConvertVect3_To_Vect2(EndVect); - int RealStartID = -1; - StartI = StartI - 30; - if (StartI < 0) { StartI = 0; } - for (int i = StartI; i < tShoulderList.Count; i++) - { - t2D = ConvertVect3_To_Vect2(tShoulderList[i]); - // if(t2D.x > 745f && t2D.x < 755f && t2D.y > 1240f && t2D.y < 1250f){ - // int agfsdajgsd = 1; - // } - if (t2D == t2D_Start) - { - //if(tShoulderList[i] == StartVec){ - RealStartID = i; - break; - } - } - - tToMatch.Clear(); tToMatch = null; - tToMatch = new List(); - - int spamcounter = 0; - bool bBackup = false; - if (RealStartID == -1) - { - bBackup = true; - } - - if (!bBackup) - { - if (bIsF) - { - for (int i = RealStartID; i > 0; i -= 8) - { - t2D = ConvertVect3_To_Vect2(tShoulderList[i]); - tToMatch.Add(tShoulderList[i]); - if (t2D == t2D_End) - { - //if(tShoulderList[i] == EndVect){ - break; - } - spamcounter += 1; - if (spamcounter > 100) - { - bBackup = true; - break; - } - } - } - else - { - for (int i = RealStartID; i < tShoulderList.Count; i += 8) - { - t2D = ConvertVect3_To_Vect2(tShoulderList[i]); - tToMatch.Add(tShoulderList[i]); - if (t2D == t2D_End) - { - //if(tShoulderList[i] == EndVect){ - break; - } - spamcounter += 1; - if (spamcounter > 100) - { - bBackup = true; - break; - } - } - } - } - //// - // if(!bBackup){ - // for(int i=0;i(); - // for(int i=0;i 0); if (biBLane0L == false) { } - bool biBLane0R = (iCon.iBLane0R.Count > 0); if (biBLane0R == false) { } - bool biBMainPlateL = (iCon.iBMainPlateL.Count > 0); if (biBMainPlateL == false) { } - bool biBMainPlateR = (iCon.iBMainPlateR.Count > 0); if (biBMainPlateR == false) { } - bool biFLane0L = (iCon.iFLane0L.Count > 0); if (biFLane0L == false) { } - bool biFLane0R = (iCon.iFLane0R.Count > 0); if (biFLane0R == false) { } - bool biFMainPlateL = (iCon.iFMainPlateL.Count > 0); if (biFMainPlateL == false) { } - bool biFMainPlateR = (iCon.iFMainPlateR.Count > 0); if (biFMainPlateR == false) { } - bool biBLane2L = (iCon.iBLane2L.Count > 0); if (biBLane2L == false) { } - bool biBLane2R = (iCon.iBLane2R.Count > 0); if (biBLane2R == false) { } - bool biFLane2L = (iCon.iFLane2L.Count > 0); if (biFLane2L == false) { } - bool biFLane2R = (iCon.iFLane2R.Count > 0); if (biFLane2R == false) { } - bool biBLane3L = (iCon.iBLane3L.Count > 0); if (biBLane3L == false) { } - bool biBLane3R = (iCon.iBLane3R.Count > 0); if (biBLane3R == false) { } - bool biFLane3L = (iCon.iFLane3L.Count > 0); if (biFLane3L == false) { } - bool biFLane3R = (iCon.iFLane3R.Count > 0); if (biFLane3R == false) { } - - mCount = tRoad.RCS.RoadVectors.Count; - int cCount = tRoad.GSDSpline.GetNodeCount(); - int tStartI = 0; - int tEndI = mCount; - //Start and end the next loop after this one later for opt: - if (cCount > 2) - { - if (!tRoad.GSDSpline.mNodes[0].bIsIntersection && !tRoad.GSDSpline.mNodes[1].bIsIntersection) - { - for (int i = 2; i < cCount; i++) - { - if (tRoad.GSDSpline.mNodes[i].bIsIntersection) - { - if (i - 2 >= 1) - { - tStartI = (int)(tRoad.GSDSpline.mNodes[i - 2].tTime * mCount); - } - break; - } - } - } - } - if (cCount > 3) - { - if (!tRoad.GSDSpline.mNodes[cCount - 1].bIsIntersection && !tRoad.GSDSpline.mNodes[cCount - 2].bIsIntersection) - { - for (int i = (cCount - 3); i >= 0; i--) - { - if (tRoad.GSDSpline.mNodes[i].bIsIntersection) - { - if (i + 2 < cCount) - { - tEndI = (int)(tRoad.GSDSpline.mNodes[i + 2].tTime * mCount); - } - break; - } - } - } - } - - if (tStartI > 0) - { - if (tStartI % 2 != 0) - { - tStartI += 1; - } - } - if (tStartI > mCount) { tStartI = mCount - 4; } - if (tStartI < 0) { tStartI = 0; } - if (tEndI < mCount) - { - if (tEndI % 2 != 0) - { - tEndI += 1; - } - } - if (tEndI > mCount) { tEndI = mCount - 4; } - if (tEndI < 0) { tEndI = 0; } - - for (int i = tStartI; i < tEndI; i += 2) - { - tVect = tRoad.RCS.RoadVectors[i]; - for (int j = 0; j < 1; j++) - { - if (biBLane0L && Vector3.SqrMagnitude(tVect - iCon.iBLane0L[j]) < 0.01f && !bSkipB) - { - iCon.iBLane0L[j] = tVect; - } - if (biBMainPlateL && Vector3.SqrMagnitude(tVect - iCon.iBMainPlateL[j]) < 0.01f && !bSkipB) - { - iCon.iBMainPlateL[j] = tVect; - } - if (biBMainPlateR && Vector3.SqrMagnitude(tVect - iCon.iBMainPlateR[j]) < 0.01f && !bSkipB) - { - iCon.iBMainPlateR[j] = tVect; - } - if (biFLane0L && Vector3.SqrMagnitude(tVect - iCon.iFLane0L[j]) < 0.01f && !bSkipF) - { - iCon.iFLane0L[j] = tVect; - } - if (biFMainPlateL && Vector3.SqrMagnitude(tVect - iCon.iFMainPlateL[j]) < 0.01f && !bSkipF) - { - iCon.iFMainPlateL[j] = tVect; - } - if (biFMainPlateR && Vector3.SqrMagnitude(tVect - iCon.iFMainPlateR[j]) < 0.01f && !bSkipF) - { - iCon.iFMainPlateR[j] = tVect; - } - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (biBLane3L && Vector3.SqrMagnitude(tVect - iCon.iBLane3L[j]) < 0.01f && !bSkipB) - { - iCon.iBLane3L[j] = tVect; - } - if (biBLane3R && Vector3.SqrMagnitude(tVect - iCon.iBLane3R[j]) < 0.01f && !bSkipB) - { - iCon.iBLane3R[j] = tVect; - } - if (biFLane3L && Vector3.SqrMagnitude(tVect - iCon.iFLane3L[j]) < 0.01f && !bSkipF) - { - iCon.iFLane3L[j] = tVect; - } - if (biFLane3R && Vector3.SqrMagnitude(tVect - iCon.iFLane3R[j]) < 0.01f && !bSkipF) - { - iCon.iFLane3R[j] = tVect; - } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - if (biBLane2L && Vector3.SqrMagnitude(tVect - iCon.iBLane2L[j]) < 0.01f && !bSkipB) - { - iCon.iBLane2L[j] = tVect; - } - if (biBLane2R && Vector3.SqrMagnitude(tVect - iCon.iBLane2R[j]) < 0.01f && !bSkipB) - { - iCon.iBLane2R[j] = tVect; - } - if (biFLane2L && Vector3.SqrMagnitude(tVect - iCon.iFLane2L[j]) < 0.01f && !bSkipF) - { - iCon.iFLane2L[j] = tVect; - } - if (biFLane2R && Vector3.SqrMagnitude(tVect - iCon.iFLane2R[j]) < 0.01f && !bSkipF) - { - iCon.iFLane2R[j] = tVect; - } - } - } - } - - // float b0 = -1f; - // float f0 = -1f; - // - // if(!bSkipB){ b0 = iCon.iBMainPlateL[0].y; } - // if(!bSkipF){ f0 = iCon.iFMainPlateL[0].y; } - // - // if(iCon.iBLane0R == null || iCon.iBLane0R.Count == 0){ - // bSkipB = true; - // } - if (iCon.iBMainPlateR == null || iCon.iBMainPlateR.Count == 0) - { - bSkipB = true; - } - if (iCon.iBMainPlateL == null || iCon.iBMainPlateL.Count == 0) - { - bSkipB = true; - } - - if (!bSkipB) { iCon.iBLane0R[0] = ((iCon.iBMainPlateR[0] - iCon.iBMainPlateL[0]) * 0.5f + iCon.iBMainPlateL[0]); } - if (!bSkipF) { iCon.iFLane0R[0] = ((iCon.iFMainPlateR[0] - iCon.iFMainPlateL[0]) * 0.5f + iCon.iFMainPlateL[0]); } - - // if(tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane){ - if (!bSkipB) - { - iCon.iBLane1L[0] = iCon.iBLane0R[0]; - iCon.iBLane1R[0] = new Vector3(iCon.iBLane1R[0].x, iCon.iBLane1L[0].y, iCon.iBLane1R[0].z); - } - - if (!bSkipF) - { - iCon.iFLane1L[0] = iCon.iFLane0R[0]; - iCon.iFLane1R[0] = new Vector3(iCon.iFLane1R[0].x, iCon.iFLane1L[0].y, iCon.iFLane1R[0].z); - } - // } - - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (!bSkipB) { iCon.iBLane3L[0] = new Vector3(iCon.iBLane3L[0].x, iCon.iBLane3R[0].y, iCon.iBLane3L[0].z); } - if (!bSkipF) { iCon.iFLane3L[0] = new Vector3(iCon.iFLane3L[0].x, iCon.iFLane3R[0].y, iCon.iFLane3L[0].z); } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - if (!bSkipB) { iCon.iBLane2L[0] = new Vector3(iCon.iBLane2L[0].x, iCon.iBLane2R[0].y, iCon.iBLane2L[0].z); } - if (!bSkipF) { iCon.iFLane2L[0] = new Vector3(iCon.iFLane2L[0].x, iCon.iFLane2R[0].y, iCon.iFLane2L[0].z); } - } - - List iBLane0 = null; - List iBLane1 = null; - List iBLane2 = null; - List iBLane3 = null; - if (!bSkipB) - { - iBLane0 = InterVertices(iCon.iBLane0L, iCon.iBLane0R, tNode.GSDRI.Height); - iBLane1 = InterVertices(iCon.iBLane1L, iCon.iBLane1R, tNode.GSDRI.Height); - if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { iBLane2 = InterVertices(iCon.iBLane2L, iCon.iBLane2R, tNode.GSDRI.Height); } - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) { iBLane3 = InterVertices(iCon.iBLane3L, iCon.iBLane3R, tNode.GSDRI.Height); } - } - - //Front lanes: - List iFLane0 = null; - List iFLane1 = null; - List iFLane2 = null; - List iFLane3 = null; - if (!bSkipF) - { - iFLane0 = InterVertices(iCon.iFLane0L, iCon.iFLane0R, tNode.GSDRI.Height); - iFLane1 = InterVertices(iCon.iFLane1L, iCon.iFLane1R, tNode.GSDRI.Height); - if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { iFLane2 = InterVertices(iCon.iFLane2L, iCon.iFLane2R, tNode.GSDRI.Height); } - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) { iFLane3 = InterVertices(iCon.iFLane3L, iCon.iFLane3R, tNode.GSDRI.Height); } - } - - //Main plates: - List iBMainPlate = null; - List iFMainPlate = null; - if (!bSkipB) - { - iBMainPlate = InterVertices(iCon.iBMainPlateL, iCon.iBMainPlateR, tNode.GSDRI.Height); - } - if (!bSkipF) - { - iFMainPlate = InterVertices(iCon.iFMainPlateL, iCon.iFMainPlateR, tNode.GSDRI.Height); - } - // //Marker plates: - // List iBMarkerPlate = InterVertices(iCon.iBMarkerPlateL,iCon.iBMarkerPlateR, tNode.GSDRI.Height); - // List iFMarkerPlate = InterVertices(iCon.iFMarkerPlateL,iCon.iFMarkerPlateR, tNode.GSDRI.Height); - // - //Now add these to RCS: - if (!bSkipB) - { - tRoad.RCS.iBLane0s.Add(iBLane0.ToArray()); - tRoad.RCS.iBLane0s_tID.Add(GSDRI); - tRoad.RCS.iBLane0s_nID.Add(tNode); - tRoad.RCS.iBLane1s.Add(iBLane1.ToArray()); - tRoad.RCS.iBLane1s_tID.Add(GSDRI); - tRoad.RCS.iBLane1s_nID.Add(tNode); - if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (iBLane2 != null) - { - tRoad.RCS.iBLane2s.Add(iBLane2.ToArray()); - tRoad.RCS.iBLane2s_tID.Add(GSDRI); - tRoad.RCS.iBLane2s_nID.Add(tNode); - } - } - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tRoad.RCS.iBLane3s.Add(iBLane3.ToArray()); - tRoad.RCS.iBLane3s_tID.Add(GSDRI); - tRoad.RCS.iBLane3s_nID.Add(tNode); - } - } - //Front lanes: - if (!bSkipF) - { - tRoad.RCS.iFLane0s.Add(iFLane0.ToArray()); - tRoad.RCS.iFLane0s_tID.Add(GSDRI); - tRoad.RCS.iFLane0s_nID.Add(tNode); - tRoad.RCS.iFLane1s.Add(iFLane1.ToArray()); - tRoad.RCS.iFLane1s_tID.Add(GSDRI); - tRoad.RCS.iFLane1s_nID.Add(tNode); - if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - tRoad.RCS.iFLane2s.Add(iFLane2.ToArray()); - tRoad.RCS.iFLane2s_tID.Add(GSDRI); - tRoad.RCS.iFLane2s_nID.Add(tNode); - } - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - tRoad.RCS.iFLane3s.Add(iFLane3.ToArray()); - tRoad.RCS.iFLane3s_tID.Add(GSDRI); - tRoad.RCS.iFLane3s_nID.Add(tNode); - } - } - //Main plates: - if (iBMainPlate != null && !bSkipB) - { - tRoad.RCS.iBMainPlates.Add(iBMainPlate.ToArray()); - tRoad.RCS.iBMainPlates_tID.Add(GSDRI); - tRoad.RCS.iBMainPlates_nID.Add(tNode); - } - if (iFMainPlate != null && !bSkipF) - { - tRoad.RCS.iFMainPlates.Add(iFMainPlate.ToArray()); - tRoad.RCS.iFMainPlates_tID.Add(GSDRI); - tRoad.RCS.iFMainPlates_nID.Add(tNode); - } - // //Marker plates: - // tRoad.RCS.iBMarkerPlates.Add(iBMarkerPlate.ToArray()); - // tRoad.RCS.iFMarkerPlates.Add(iFMarkerPlate.ToArray()); - // tRoad.RCS.IntersectionTypes.Add((int)tNode.GSDRI.rType); - - if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (!bSkipB) { tRoad.RCS.iBLane1s_IsMiddleLane.Add(true); } - if (!bSkipF) { tRoad.RCS.iFLane1s_IsMiddleLane.Add(true); } - } - else - { - if (!bSkipB) { tRoad.RCS.iBLane1s_IsMiddleLane.Add(false); } - if (!bSkipF) { tRoad.RCS.iFLane1s_IsMiddleLane.Add(false); } - } - } - - private static bool IsVecSame(ref Vector3 tVect1, Vector3 tVect2) - { - return ((Vector3.SqrMagnitude(tVect1 - tVect2) < 0.01f)); - } - - private static List InterVertices(List tL, List tR, float tHeight) - { - if (tL.Count == 0 || tR.Count == 0) { return null; } - - List tList = new List(); - int tCountL = tL.Count; - int tCountR = tR.Count; - int spamcheck = 0; - - while (tCountL < tCountR && spamcheck < 5000) - { - tL.Add(tL[tCountL - 1]); - tCountL = tL.Count; - spamcheck += 1; - } - - spamcheck = 0; - while (tCountR < tCountL && spamcheck < 5000) - { - tR.Add(tR[tCountR - 1]); - tCountR = tR.Count; - spamcheck += 1; - } - - if (spamcheck > 4000) - { - Debug.LogWarning("spamcheck InterVertices"); - } - - int tCount = Mathf.Max(tCountL, tCountR); - for (int i = 0; i < tCount; i++) - { - tList.Add(tL[i]); - tList.Add(tL[i]); - tList.Add(tR[i]); - tList.Add(tR[i]); - } - return tList; - } - #endregion - - /// - /// Handles most triangles and normals construction. In certain scenarios for efficiency reasons UV might also be processed. - /// - /// - /// The road construction buffer, by reference. - /// / - public static void RoadJob1(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - //Triangles and normals: - // if(RCS.tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_IntersectionCleanup"); } - if (RCS.bInterseOn) { ProcessRoad_IntersectionCleanup(ref RCS); } - // if(RCS.tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } - - ProcessRoad_Tris_Bulk(ref RCS); - - RCS.tris_ShoulderR = ProcessRoad_Tris_Shoulder(RCS.ShoulderR_Vectors.Count); - RCS.tris_ShoulderL = ProcessRoad_Tris_Shoulder(RCS.ShoulderL_Vectors.Count); - if (RCS.tRoad.opt_bShoulderCuts || RCS.tRoad.opt_bDynamicCuts) - { - ProcessRoad_Tris_ShoulderCutsR(ref RCS); - ProcessRoad_Tris_ShoulderCutsL(ref RCS); - } - - ProcessRoad_Normals_Bulk(ref RCS); - ProcessRoad_Normals_Shoulders(ref RCS); - } - - /// - /// Handles most UV and tangent construction. Some scenarios might involve triangles and normals or lack UV construction for efficiency reasons. - /// - /// - /// The road construction buffer, by reference. - /// - public static void RoadJob2(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - //Bridge UV is processed with tris and normals. - - //For one big road mesh: - if (RCS.bRoadOn) - { - if (!RCS.tMeshSkip) { RCS.uv = ProcessRoad_UVs(RCS.RoadVectors.ToArray()); } - if (!RCS.tMesh_SRSkip) { RCS.uv_SR = ProcessRoad_UVs_Shoulder(RCS.ShoulderR_Vectors.ToArray()); } - if (!RCS.tMesh_SLSkip) { RCS.uv_SL = ProcessRoad_UVs_Shoulder(RCS.ShoulderL_Vectors.ToArray()); } - - //UVs for pavement: - if (!RCS.tMeshSkip) - { - int vCount = RCS.RoadVectors.Count; - RCS.uv2 = new Vector2[vCount]; - for (int i = 0; i < vCount; i++) - { - RCS.uv2[i] = new Vector2(RCS.RoadVectors[i].x * 0.2f, RCS.RoadVectors[i].z * 0.2f); - } - } - } - - //For road cuts: - if (RCS.tRoad.opt_bRoadCuts || RCS.tRoad.opt_bDynamicCuts) - { - ProcessRoad_UVs_RoadCuts(ref RCS); - int cCount = RCS.cut_RoadVectors.Count; - for (int i = 0; i < cCount; i++) - { - RCS.cut_tangents.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris[i], RCS.cut_normals[i], RCS.cut_uv[i], RCS.cut_RoadVectors[i].ToArray())); - RCS.cut_tangents_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris[i], RCS.cut_normals[i], RCS.cut_uv_world[i], RCS.cut_RoadVectors[i].ToArray())); - } - } - if (RCS.tRoad.opt_bShoulderCuts || RCS.tRoad.opt_bDynamicCuts) - { - int rCount = RCS.cut_ShoulderR_Vectors.Count; - for (int i = 0; i < rCount; i++) - { - ProcessRoad_UVs_ShoulderCut(ref RCS, false, i); - RCS.cut_tangents_SR.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderR[i], RCS.cut_normals_ShoulderR[i], RCS.cut_uv_SR[i], RCS.cut_ShoulderR_Vectors[i].ToArray())); - RCS.cut_tangents_SR_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderR[i], RCS.cut_normals_ShoulderR[i], RCS.cut_uv_SR_world[i], RCS.cut_ShoulderR_Vectors[i].ToArray())); - } - int lCount = RCS.cut_ShoulderL_Vectors.Count; - for (int i = 0; i < lCount; i++) - { - ProcessRoad_UVs_ShoulderCut(ref RCS, true, i); - RCS.cut_tangents_SL.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderL[i], RCS.cut_normals_ShoulderL[i], RCS.cut_uv_SL[i], RCS.cut_ShoulderL_Vectors[i].ToArray())); - RCS.cut_tangents_SL_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderL[i], RCS.cut_normals_ShoulderL[i], RCS.cut_uv_SL_world[i], RCS.cut_ShoulderL_Vectors[i].ToArray())); - } - } - if (RCS.bInterseOn) - { - ProcessRoad_UVs_Intersections(ref RCS); - } - - // throw new System.Exception("FFFFFFFF"); - - if (RCS.bRoadOn) - { - if (!RCS.tMeshSkip) { RCS.tangents = GSDRootUtil.ProcessTangents(RCS.tris, RCS.normals, RCS.uv, RCS.RoadVectors.ToArray()); } - if (!RCS.tMeshSkip) { RCS.tangents2 = GSDRootUtil.ProcessTangents(RCS.tris, RCS.normals, RCS.uv2, RCS.RoadVectors.ToArray()); } - if (!RCS.tMesh_SRSkip) { RCS.tangents_SR = GSDRootUtil.ProcessTangents(RCS.tris_ShoulderR, RCS.normals_ShoulderR, RCS.uv_SR, RCS.ShoulderR_Vectors.ToArray()); } - if (!RCS.tMesh_SLSkip) { RCS.tangents_SL = GSDRootUtil.ProcessTangents(RCS.tris_ShoulderL, RCS.normals_ShoulderL, RCS.uv_SL, RCS.ShoulderL_Vectors.ToArray()); } - for (int i = 0; i < RCS.tMesh_RoadConnections.Count; i++) - { - RCS.RoadConnections_tangents.Add(GSDRootUtil.ProcessTangents(RCS.RoadConnections_tris[i], RCS.RoadConnections_normals[i], RCS.RoadConnections_uv[i], RCS.RoadConnections_verts[i])); - } - } - - if (RCS.bInterseOn) - { - //Back lanes: - int vCount = RCS.iBLane0s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBLane0s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane0s_tris[i], RCS.iBLane0s_normals[i], RCS.iBLane0s_uv[i], RCS.iBLane0s[i])); - } - vCount = RCS.iBLane1s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBLane1s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane1s_tris[i], RCS.iBLane1s_normals[i], RCS.iBLane1s_uv[i], RCS.iBLane1s[i])); - } - vCount = RCS.iBLane2s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBLane2s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane2s_tris[i], RCS.iBLane2s_normals[i], RCS.iBLane2s_uv[i], RCS.iBLane2s[i])); - } - vCount = RCS.iBLane3s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBLane3s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane3s_tris[i], RCS.iBLane3s_normals[i], RCS.iBLane3s_uv[i], RCS.iBLane3s[i])); - } - //Front lanes: - vCount = RCS.iFLane0s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFLane0s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane0s_tris[i], RCS.iFLane0s_normals[i], RCS.iFLane0s_uv[i], RCS.iFLane0s[i])); - } - vCount = RCS.iFLane1s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFLane1s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane1s_tris[i], RCS.iFLane1s_normals[i], RCS.iFLane1s_uv[i], RCS.iFLane1s[i])); - } - vCount = RCS.iFLane2s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFLane2s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane2s_tris[i], RCS.iFLane2s_normals[i], RCS.iFLane2s_uv[i], RCS.iFLane2s[i])); - } - vCount = RCS.iFLane3s.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFLane3s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane3s_tris[i], RCS.iFLane3s_normals[i], RCS.iFLane3s_uv[i], RCS.iFLane3s[i])); - } - //Main plates: - vCount = RCS.iBMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBMainPlates_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBMainPlates_tris[i], RCS.iBMainPlates_normals[i], RCS.iBMainPlates_uv[i], RCS.iBMainPlates[i])); - } - vCount = RCS.iBMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iBMainPlates_tangents2.Add(GSDRootUtil.ProcessTangents(RCS.iBMainPlates_tris[i], RCS.iBMainPlates_normals[i], RCS.iBMainPlates_uv2[i], RCS.iBMainPlates[i])); - } - vCount = RCS.iFMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFMainPlates_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFMainPlates_tris[i], RCS.iFMainPlates_normals[i], RCS.iFMainPlates_uv[i], RCS.iFMainPlates[i])); - } - vCount = RCS.iFMainPlates.Count; - for (int i = 0; i < vCount; i++) - { - RCS.iFMainPlates_tangents2.Add(GSDRootUtil.ProcessTangents(RCS.iFMainPlates_tris[i], RCS.iFMainPlates_normals[i], RCS.iFMainPlates_uv2[i], RCS.iFMainPlates[i])); - } - } - } - - #region "Intersection Cleanup" - private static void ProcessRoad_IntersectionCleanup(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - List tList = RCS.tIntersectionBounds; - int mCount = tList.Count; - RCS.ShoulderR_Vectors = ProcessRoad_IntersectionCleanup_Helper(ref RCS.ShoulderR_Vectors, ref tList, mCount, ref RCS.ImmuneVects); - RCS.ShoulderL_Vectors = ProcessRoad_IntersectionCleanup_Helper(ref RCS.ShoulderL_Vectors, ref tList, mCount, ref RCS.ImmuneVects); - } - - private static List ProcessRoad_IntersectionCleanup_Helper(ref List tVects, ref List tList, int mCount, ref HashSet ImmuneVects) - { - GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; - int MVL = tVects.Count; - //Vector3 tVect = default(Vector3); - Vector2 Vect2D = default(Vector2); - Vector2 tNearVect = default(Vector2); - float tMax2 = 2000f; - float tMax2SQ = 0f; - // GameObject tObj = GameObject.Find("Inter1"); - // Vector2 tObj2D = ConvertVect3_To_Vect2(tObj.transform.position); - // int fCount = 0; - // bool bTempNow = false; - for (int i = 0; i < mCount; i++) - { - tRect = tList[i]; - tMax2 = tRect.MaxDistance * 1.5f; - tMax2SQ = (tMax2 * tMax2); - - // Debug.Log (tRect.ToString()); - - for (int j = 0; j < MVL; j++) - { - Vect2D.x = tVects[j].x; - Vect2D.y = tVects[j].z; - - if (Vector2.SqrMagnitude(Vect2D - tRect.P1) > tMax2SQ) - { - j += 32; - continue; - } - - // if(Vector2.Distance(Vect2D,tObj2D) < 20f && (j % 16 == 0)){ - // fCount+=1; - // GameObject xObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // xObj.transform.localScale = new Vector3(0.05f,40f,0.05f); - // xObj.transform.position = tVects[j]; - // xObj.name = "temp22"; - // } - - // bTempNow = false; - if (tRect.Contains(ref Vect2D)) - { - if (ImmuneVects.Contains(tVects[j])) { continue; } - // if(Vect2D == tRect.P1){ - // continue; - // }else if(Vect2D == tRect.P2){ - // continue; - // }else if(Vect2D == tRect.P3){ - // continue; - // }else if(Vect2D == tRect.P4){ - // continue; - // } - - - // if(Mathf.Approximately(tVects[j].x,303.1898f)){ - // GameObject hObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // hObj.transform.localScale = new Vector3(0.05f,40f,0.05f); - // hObj.transform.position = tVects[j]; - // hObj.name = "temp23"; - // bTempNow = true; - // Debug.Log (tVects[j]); - // } - - //Calling near when it shouldn't ? - if (tRect.Near(ref Vect2D, out tNearVect)) - { //If near the rect, set it equal - tVects[j] = new Vector3(tNearVect.x, tVects[j].y, tNearVect.y); - } - else - { - tVects[j] = new Vector3(tVects[j].x, tRect.Height, tVects[j].z); - } - - - - - - //ImmuneVects.Add(tVects[j]); - - // if(bTempNow){ - // GameObject xObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - // xObj.transform.localScale = new Vector3(0.05f,40f,0.05f); - // xObj.transform.position = tVects[j]; - // xObj.name = "temp22"; - // Debug.Log ("to: " + tVects[j]); - // } - } - } - } - // Debug.Log ("Fcount: " + fCount); - - return tVects; - } - #endregion - - #region "Tris" - private static void ProcessRoad_Tris_Bulk(ref GSD.Roads.RoadConstructorBufferMaker RCS) - {//, ref Mesh tShoulderR, ref Mesh tShoulderL){ - //Next come the triangles. Since we want two triangles, each defined by three integers, the triangles array will have six elements in total. - //Remembering the clockwise rule for ordering the corners, the lower left triangle will use 0, 2, 1 as its corner indices, while the upper right one will use 2, 3, 1. - - RCS.tris = ProcessRoad_Tris_Bulk_Helper(RCS.RoadVectors.Count); - if (RCS.tRoad.opt_bRoadCuts || RCS.tRoad.opt_bDynamicCuts) - { - ProcessRoad_Tris_RoadCuts(ref RCS); - } - - if (RCS.bInterseOn) - { - //For intersection parts: - //Back lanes: - ProcessRoad_Tris_iProcessor(ref RCS.iBLane0s_tris, ref RCS.iBLane0s); - ProcessRoad_Tris_iProcessor(ref RCS.iBLane1s_tris, ref RCS.iBLane1s); - ProcessRoad_Tris_iProcessor(ref RCS.iBLane2s_tris, ref RCS.iBLane2s); - ProcessRoad_Tris_iProcessor(ref RCS.iBLane3s_tris, ref RCS.iBLane3s); - //Front lanes: - ProcessRoad_Tris_iProcessor(ref RCS.iFLane0s_tris, ref RCS.iFLane0s); - ProcessRoad_Tris_iProcessor(ref RCS.iFLane1s_tris, ref RCS.iFLane1s); - ProcessRoad_Tris_iProcessor(ref RCS.iFLane2s_tris, ref RCS.iFLane2s); - ProcessRoad_Tris_iProcessor(ref RCS.iFLane3s_tris, ref RCS.iFLane3s); - //Main plates: - ProcessRoad_Tris_iProcessor(ref RCS.iBMainPlates_tris, ref RCS.iBMainPlates); - ProcessRoad_Tris_iProcessor(ref RCS.iFMainPlates_tris, ref RCS.iFMainPlates); - } - } - - private static int[] ProcessRoad_Tris_Bulk_Helper(int MVL) - { - int TriCount = 0; - int x1, x2, x3; - int xCount = (int)(MVL * 0.25f * 6) - 6; - // if(xCount < 0){ xCount = 0; } - int[] tri = new int[xCount]; - for (int i = 0; i < MVL; i += 4) - { - if (i + 4 == MVL) { break; } - - x1 = i; - x2 = i + 4; - x3 = i + 2; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - - x1 = i + 4; - x2 = i + 6; - x3 = i + 2; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - } - return tri; - } - - private static void ProcessRoad_Tris_RoadCuts(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - //Road cuts aren't working right for the special nodes on cuts - int cCount = RCS.RoadCuts.Count; - int PrevRoadCutIndex = 0; - int CurrentRoadCutIndex = 0; - List> tVects = new List>(); - List tVectListSingle = null; - Vector3 xVect = default(Vector3); - for (int j = 0; j < cCount; j++) - { - CurrentRoadCutIndex = RCS.RoadCuts[j]; - tVectListSingle = new List(); - RCS.cut_RoadVectorsHome.Add(RCS.RoadVectors[PrevRoadCutIndex]); - xVect = RCS.RoadVectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) - { - tVectListSingle.Add(RCS.RoadVectors[i] - xVect); - } - tVects.Add(tVectListSingle); - PrevRoadCutIndex = CurrentRoadCutIndex - 4; - if (PrevRoadCutIndex < 0) { PrevRoadCutIndex = 0; } - } - int mMax = RCS.RoadVectors.Count; - tVectListSingle = new List(); - RCS.cut_RoadVectorsHome.Add(RCS.RoadVectors[PrevRoadCutIndex]); - xVect = RCS.RoadVectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < mMax; i++) - { - tVectListSingle.Add(RCS.RoadVectors[i] - xVect); - } - tVects.Add(tVectListSingle); - - int vCount = tVects.Count; - List tTris = new List(); - for (int i = 0; i < vCount; i++) - { - int[] tTriSingle = ProcessRoad_Tris_Bulk_Helper(tVects[i].Count); - tTris.Add(tTriSingle); - } - - RCS.cut_RoadVectors = tVects; - RCS.cut_tris = tTris; - } - - private static void ProcessRoad_Tris_ShoulderCutsR(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - int cCount = RCS.ShoulderCutsR.Count; - int PrevRoadCutIndex = 0; - int CurrentRoadCutIndex = 0; - List> tVects = new List>(); - List tVectListSingle = null; - Vector3 xVect = default(Vector3); - for (int j = 0; j < cCount; j++) - { - CurrentRoadCutIndex = RCS.ShoulderCutsR[j]; - tVectListSingle = new List(); - RCS.cut_ShoulderR_VectorsHome.Add(RCS.ShoulderR_Vectors[PrevRoadCutIndex]); - xVect = RCS.ShoulderR_Vectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) - { - tVectListSingle.Add(RCS.ShoulderR_Vectors[i] - xVect); - } - tVects.Add(tVectListSingle); - PrevRoadCutIndex = CurrentRoadCutIndex - 8; - if (PrevRoadCutIndex < 0) { PrevRoadCutIndex = 0; } - } - int mMax = RCS.ShoulderR_Vectors.Count; - tVectListSingle = new List(); - RCS.cut_ShoulderR_VectorsHome.Add(RCS.ShoulderR_Vectors[PrevRoadCutIndex]); - xVect = RCS.ShoulderR_Vectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < mMax; i++) - { - tVectListSingle.Add(RCS.ShoulderR_Vectors[i] - xVect); - } - tVects.Add(tVectListSingle); - - int vCount = tVects.Count; - List tTris = new List(); - for (int i = 0; i < vCount; i++) - { - int[] tTriSingle = ProcessRoad_Tris_Shoulder(tVects[i].Count); - tTris.Add(tTriSingle); - } - - RCS.cut_ShoulderR_Vectors = tVects; - RCS.cut_tris_ShoulderR = tTris; - } - - private static void ProcessRoad_Tris_ShoulderCutsL(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - int cCount = RCS.ShoulderCutsL.Count; - int PrevRoadCutIndex = 0; - int CurrentRoadCutIndex = 0; - List> tVects = new List>(); - List tVectListSingle = null; - Vector3 xVect = default(Vector3); - for (int j = 0; j < cCount; j++) - { - CurrentRoadCutIndex = RCS.ShoulderCutsR[j]; - tVectListSingle = new List(); - RCS.cut_ShoulderL_VectorsHome.Add(RCS.ShoulderL_Vectors[PrevRoadCutIndex]); - xVect = RCS.ShoulderL_Vectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) - { - tVectListSingle.Add(RCS.ShoulderL_Vectors[i] - xVect); - } - tVects.Add(tVectListSingle); - PrevRoadCutIndex = CurrentRoadCutIndex - 8; - if (PrevRoadCutIndex < 0) { PrevRoadCutIndex = 0; } - } - int mMax = RCS.ShoulderL_Vectors.Count; - tVectListSingle = new List(); - RCS.cut_ShoulderL_VectorsHome.Add(RCS.ShoulderL_Vectors[PrevRoadCutIndex]); - xVect = RCS.ShoulderL_Vectors[PrevRoadCutIndex]; - for (int i = PrevRoadCutIndex; i < mMax; i++) - { - tVectListSingle.Add(RCS.ShoulderL_Vectors[i] - xVect); - } - tVects.Add(tVectListSingle); - - int vCount = tVects.Count; - List tTris = new List(); - for (int i = 0; i < vCount; i++) - { - int[] tTriSingle = ProcessRoad_Tris_Shoulder(tVects[i].Count); - tTris.Add(tTriSingle); - } - - RCS.cut_ShoulderL_Vectors = tVects; - RCS.cut_tris_ShoulderL = tTris; - } - - private static int[] ProcessRoad_Tris_Shoulder(int MVL) - { - int TriCount = 0; - int x1, x2, x3; - int xCount = (int)((MVL / 2) * 0.25f * 6) - 6; - if (xCount < 0) { xCount = 0; } - xCount = xCount * 2; - - int[] tri = new int[xCount]; - for (int i = 0; i < MVL; i += 8) - { - if (i + 8 == MVL) { break; } - - x1 = i; - x2 = i + 8; - x3 = i + 2; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - - x1 = i + 8; - x2 = i + 10; - x3 = i + 2; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - - x1 = i + 4; - x2 = i + 12; - x3 = i + 6; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - - x1 = i + 12; - x2 = i + 14; - x3 = i + 6; - - tri[TriCount] = x1; TriCount += 1; - tri[TriCount] = x2; TriCount += 1; - tri[TriCount] = x3; TriCount += 1; - } - return tri; - } - - //For intersection parts: - private static void ProcessRoad_Tris_iProcessor(ref List TriList, ref List VertexList) - { - if (TriList == null) { TriList = new List(); } - int vListCount = VertexList.Count; - int[] tris; - for (int i = 0; i < vListCount; i++) - { - tris = ProcessRoad_Tris_Bulk_Helper(VertexList[i].Length); - TriList.Add(tris); - } - } - #endregion - - #region "Normals" - private static void ProcessRoad_Normals_Bulk(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - //A mesh with just the vertices and triangles set up will be visible in the editor but will not look very convincing since it is not correctly shaded without the normals. - //The normals for the flat plane are very simple - they are all identical and point in the negative Z direction in the plane's local space. - //With the normals added, the plane will be correctly shaded but remember that you need a light in the scene to see the effect. - //Bridge normals are processed at same time as tris. - int MVL = RCS.RoadVectors.Count; - Vector3[] normals = new Vector3[MVL]; - // Vector3 tVect = -Vector3.forward; - // for(int i=0;i NormalList, ref List VertexList) - { - if (NormalList == null) { NormalList = new List(); } - int vListCount = VertexList.Count; - Vector3[] normals; - int MVL = -1; - // Vector3 tVect = -Vector3.forward; - for (int i = 0; i < vListCount; i++) - { - MVL = VertexList[i].Length; - normals = new Vector3[MVL]; - // for(int j=0;j 0 || (tDistanceLeftSum+tDistanceLeft) > 1f){ - // tDistanceLeftSum = 0.998f + (0.0001f*bHitMaxL); - // tDistanceLeft = 0.001f; - // bHitMaxL+=1; - // } - // if(bHitMaxR > 0 || (tDistanceRightSum+tDistanceRight) > 1f){ - // tDistanceRightSum = 0.998f + (0.0001f*bHitMaxR); - // tDistanceRight = 0.001f; - // bHitMaxR+=1; - // } - - tAdd1 = tDistanceLeftSum; if (tAdd1 > 1f) { tAdd1 = 1f; } - tAdd2 = tDistanceRightSum; if (tAdd2 > 1f) { tAdd2 = 1f; } - tAdd3 = tDistanceLeft + tDistanceLeftSum; if (tAdd3 > 1f) { tAdd3 = 1f; } - tAdd4 = tDistanceRight + tDistanceRightSum; if (tAdd4 > 1f) { tAdd4 = 1f; } - - uv[i] = new Vector2(0f, tAdd1); - uv[i + 2] = new Vector2(1f, tAdd2); - uv[i + 4] = new Vector2(0f, tAdd3); - uv[i + 6] = new Vector2(1f, tAdd4); - //Debug.Log (tAdd3 + " R:"+ tAdd4 + " RLoc: " + tVerts[i+6]); - } - - - - //Debug.Log ("1.0 R:1.0 RLoc: " + tVerts[i+6]); - - //Last segment needs adjusted due to double vertices: - if ((i + 7) == MVL) - { - if (bOddToggle) - { - //First set: Debug.Log ("+5:"+i+" "+(i+2)+" "+(i+4)+" "+(i+6)); - uv[MVL - 3] = uv[i + 4]; - uv[MVL - 1] = uv[i + 6]; - } - else - { - //Last set: Debug.Log ("+3:"+i+" "+(i+2)+" "+(i+4)+" "+(i+6)); - uv[MVL - 4] = uv[i + 4]; - uv[MVL - 2] = uv[i + 6]; - } - } - - - - if (bOddToggle) - { - i += 5; - - if (i + 6 >= MVL) - { - uv[i + 4 - 5] = new Vector2(0f, 1f); - uv[i + 6 - 5] = new Vector2(1f, 1f); - } - - } - else - { - i += 3; - - if (i + 6 >= MVL) - { - uv[i + 4 - 3] = new Vector2(0f, 1f); - uv[i + 6 - 3] = new Vector2(1f, 1f); - } - } - - - - tDistanceLeftSum += tDistanceLeft; - tDistanceRightSum += tDistanceRight; - //tDistanceSum+=tDistance; - bOddToggle = !bOddToggle; - } - - // uv[MVL-1].y = 1f; - // uv[MVL-2].y = 1f; - // uv[MVL-3].y = 1f; - // uv[MVL-4].y = 1f; - - return uv; - } - #endregion - #endregion - - #region "Set vector heights" - private static void SetVectorHeight2(ref Vector3 tWorldVect, ref float p, ref List> tList, ref GSDSplineC tSpline) - { - int mCount = tList.Count; - int i = 0; - - if (mCount < 1) { tWorldVect.y = 0f; return; } - - float cValue = 0f; - for (i = 0; i < (mCount - 1); i++) - { - if (p >= tList[i].Key && p < tList[i + 1].Key) - { - cValue = tList[i].Value; - if (i > 3) - { - if (tList[i - 1].Value < cValue) - { - cValue = tList[i - 1].Value; - } - if (tList[i - 2].Value < cValue) - { - cValue = tList[i - 2].Value; - } - if (tList[i - 3].Value < cValue) - { - cValue = tList[i - 3].Value; - } - } - if (i < (mCount - 3)) - { - if (tList[i + 1].Value < cValue) - { - cValue = tList[i + 1].Value; - } - if (tList[i + 2].Value < cValue) - { - cValue = tList[i + 2].Value; - } - if (tList[i + 3].Value < cValue) - { - cValue = tList[i + 3].Value; - } - } - break; - } - } - - //if(p > 0.95f && GSDRootUtil.IsApproximately(cValue,0f,0.001f)){ - // float DeadValue = 0f; - // Vector3 tPos = tSpline.GetSplineValue(p,false); - // if(!tSpline.IsNearIntersection(ref tPos,ref DeadValue)){ - // cValue = tList[tList.Count-1].Value; - // } - //} - - //Zero protection: - if (GSDRootUtil.IsApproximately(cValue, 0f, 0.001f) && tWorldVect.y > 0f) - { - cValue = tWorldVect.y - 0.35f; - } - - tWorldVect.y = cValue; - } - #endregion - - private static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - private static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - - public class RoadTerrainInfo - { - public Rect tBounds; - public int GSDID; - public int hmWidth; - public int hmHeight; - public Vector3 tPos; - public Vector3 tSize; - public float[,] heights; - } - } - - #region "Threading core" - public class GSDThreadedJob - { - private bool m_IsDone = false; - private object m_Handle = new object(); - private System.Threading.Thread m_Thread = null; - - public bool IsDone - { - get - { - bool tmp; - lock (m_Handle) - { - tmp = m_IsDone; - } - return tmp; - } - set - { - lock (m_Handle) - { - m_IsDone = value; - } - } - } - - public virtual void Start() - { - m_Thread = new System.Threading.Thread(Run); - m_Thread.Start(); - } - - public virtual void Abort() - { - m_Thread.Abort(); - } - - protected virtual void ThreadFunction() { } - - protected virtual void OnFinished() { } - - public virtual bool Update() - { - if (IsDone) - { - OnFinished(); - return true; - } - return false; - } - private void Run() - { - ThreadFunction(); - IsDone = true; - } - } - - public class GSDJob : GSDThreadedJob - { - //public Vector3[] InData; // arbitary job data - //public Vector3[] OutData; // arbitary job data - - protected override void ThreadFunction() - { - // Do your threaded task. DON'T use the Unity API here - //for (int i = 0; i < 100000000; i++){ - //InData[i % InData.Length] += InData[(i+1) % InData.Length]; - //} - } - - protected override void OnFinished() - { - // This is executed by the Unity main thread when the job is finished - //for (int i = 0; i < InData.Length; i++){ - //Debug.Log("Results(" + i + "): " + InData[i]); - //} - } - } - #endregion - - public class TerrainCalcs : GSDThreadedJob - { - private object GSDm_Handle = new object(); - private List TTDList; - private GSDSplineC tSpline; - private GSDRoad tRoad; - - public void Setup(ref List _TTDList, GSDSplineC _tSpline, GSDRoad _tRoad) - { - TTDList = _TTDList; - tSpline = _tSpline; - tRoad = _tRoad; - } - - protected override void ThreadFunction() - { - float Step = (tRoad.opt_RoadDefinition * 0.4f) / tSpline.distance; - if (Step > 2f) { Step = 2f; } - if (Step < 1f) { Step = 1f; } - // float tDistance = tRoad.RoadWidth()*2f; - - // Vector3 tVect,POS; - foreach (GSD.Roads.GSDTerraforming.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 - { - GSDTerraformingT.DoRects(tSpline, TTD); - } - catch (System.Exception e) - { - lock (GSDm_Handle) - { - tRoad.bEditorError = true; - tRoad.tError = 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 = GSDTerraformingT.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight); - // tSpline.HeightHistory.Add(new KeyValuePair(i,PrevHeight*TTD.TerrainSize.y)); - // } - // - // for(int i=0;i a, KeyValuePair b) - { - return a.Key.CompareTo(b.Key); - } - } - - public static class TerrainCalcs_Static - { - public static void RunMe(ref List TTDList, GSDSplineC tSpline, GSDRoad tRoad) - { - float Step = (tRoad.opt_RoadDefinition * 0.4f) / tSpline.distance; - if (Step > 2f) { Step = 2f; } - if (Step < 1f) { Step = 1f; } - // float tDistance = tRoad.RoadWidth()*2f; - - // Vector3 tVect,POS; - - foreach (GSD.Roads.GSDTerraforming.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){ - if (tRoad.bProfiling) - { - UnityEngine.Profiling.Profiler.BeginSample("DoRects"); - } - GSDTerraformingT.DoRects(tSpline, TTD); - - if (tRoad.bProfiling) - { - UnityEngine.Profiling.Profiler.EndSample(); - } - // }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 = GSDTerraformingT.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight); - // tSpline.HeightHistory.Add(new KeyValuePair(i,PrevHeight*TTD.TerrainSize.y)); - // } - // - // for(int i=0;i a, KeyValuePair b) - { - return a.Key.CompareTo(b.Key); - } - } - - public class RoadCalcs1 : GSDThreadedJob - { - private object GSDm_Handle = new object(); - private GSD.Roads.RoadConstructorBufferMaker RCS; - private GSDRoad tRoad; - - public void Setup(ref GSD.Roads.RoadConstructorBufferMaker _RCS, ref GSDRoad _tRoad) - { - RCS = _RCS; - tRoad = _tRoad; - } - - protected override void ThreadFunction() - { - try - { - GSDRoadCreationT.RoadJob_Prelim(ref tRoad); - GSDRoadCreationT.RoadJob1(ref RCS); - } - catch (System.Exception e) - { - lock (GSDm_Handle) - { - tRoad.bEditorError = true; - tRoad.tError = e; - } - throw e; - } - } - - public GSD.Roads.RoadConstructorBufferMaker GetRCS() - { - GSD.Roads.RoadConstructorBufferMaker tRCS; - lock (GSDm_Handle) - { - tRCS = RCS; - } - return tRCS; - } - } - - public static class RoadCalcs1_static - { - public static void RunMe(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - GSDRoadCreationT.RoadJob1(ref RCS); - } - } - - public class RoadCalcs2 : GSDThreadedJob - { - private object GSDm_Handle = new object(); - private GSD.Roads.RoadConstructorBufferMaker RCS; - public void Setup(ref GSD.Roads.RoadConstructorBufferMaker _RCS) - { - RCS = _RCS; - } - - protected override void ThreadFunction() - { - try - { - GSDRoadCreationT.RoadJob2(ref RCS); - } - catch (System.Exception e) - { - lock (GSDm_Handle) - { - RCS.tRoad.bEditorError = true; - RCS.tRoad.tError = e; - } - } - } - - public GSD.Roads.RoadConstructorBufferMaker GetRCS() - { - GSD.Roads.RoadConstructorBufferMaker tRCS; - lock (GSDm_Handle) - { - tRCS = RCS; - } - return tRCS; - } - } - - public static class RoadCalcs2_static - { - public static void RunMe(ref GSD.Roads.RoadConstructorBufferMaker RCS) - { - GSDRoadCreationT.RoadJob2(ref RCS); - } - } - -#endif +#region "Imports" +using UnityEngine; +#if UNITY_EDITOR +using System.Collections; +using System.Collections.Generic; +using GSD; +#endif +#endregion + + +namespace GSD.Threaded +{ +#if UNITY_EDITOR + + + public static class GSDTerraformingT + { + public class TerrainBoundsMaker + { + public List triList; + public GSD.Roads.GSDRoadUtil.Construction2DRect tRect; + public float MinI = 0f; + public float MaxI = 1f; + } + + + /* + static Vector3 ProcessLineHeights_PrevVect = new Vector3(0f, 0f, 0f); + + + public static float ProcessLineHeights(GSDSplineC tSpline, ref Vector3 tVect, ref Vector3 POS, float tDistance, GSD.Roads.GSDTerraforming.TempTerrainData TTD, float PrevDesiredHeight) + { + Vector3 ShoulderR_rVect = new Vector3(0f, 0f, 0f); + Vector3 ShoulderL_lVect = new Vector3(0f, 0f, 0f); + + float DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect, ref TTD, ref tSpline); + float nResult = 0f; + bool bIntersection = tSpline.IsNearIntersection(ref tVect, ref nResult); + if(bIntersection) + { + if(nResult < tVect.y) + { + tVect.y = nResult; + DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect, ref TTD, ref tSpline); + } + } + + int x1 = 0, y1 = 0; + GetTempHeights_Coordinates(ref tVect, ref TTD, out x1, out y1); + + bool bOverride = false; + int StepMod = (int) (1 / TTD.HMRatio); + for(float i = tDistance; i >= 1f; i -= StepMod) + { + ShoulderR_rVect = (tVect + new Vector3(i * POS.normalized.z, 0, i * -POS.normalized.x)); + GetTempHeights_Coordinates(ref ShoulderR_rVect, ref TTD, out x1, out y1); + if(TTD.heights[x1, y1] > DesiredHeight) + { + bOverride = true; + } + if(bOverride || !TTD.tHeights[x1, y1]) + { + TTD.tHeights[x1, y1] = true; + TTD.cX[TTD.cI] = x1; + TTD.cY[TTD.cI] = y1; + TTD.cH[TTD.cI] = DesiredHeight; + TTD.oldH[TTD.cI] = TTD.heights[x1, y1]; + TTD.cI += 1; + } + bOverride = false; + + ShoulderL_lVect = (tVect + new Vector3(i * -POS.normalized.z, 0, i * POS.normalized.x)); + GetTempHeights_Coordinates(ref ShoulderL_lVect, ref TTD, out x1, out y1); + if(TTD.heights[x1, y1] > DesiredHeight) + { + bOverride = true; + } + if(bOverride || !TTD.tHeights[x1, y1]) + { + TTD.tHeights[x1, y1] = true; + TTD.cX[TTD.cI] = x1; + TTD.cY[TTD.cI] = y1; + TTD.cH[TTD.cI] = DesiredHeight; + TTD.oldH[TTD.cI] = TTD.heights[x1, y1]; + TTD.cI += 1; + } + bOverride = false; + } + + GetTempHeights_Coordinates(ref tVect, ref TTD, out x1, out y1); + if(TTD.heights[x1, y1] > DesiredHeight || (tVect.y < ProcessLineHeights_PrevVect.y)) + { + bOverride = true; + } + if(bOverride || !TTD.tHeights[x1, y1]) + { + TTD.tHeights[x1, y1] = true; + TTD.cX[TTD.cI] = x1; + TTD.cY[TTD.cI] = y1; + if(tDistance > 15f && TTD.HMRatio > 0.24f) + { + TTD.cH[TTD.cI] = DesiredHeight - 0.0002f; + } + else + { + TTD.cH[TTD.cI] = DesiredHeight; + } + TTD.oldH[TTD.cI] = TTD.heights[x1, y1]; + TTD.cI += 1; + } + + ProcessLineHeights_PrevVect = tVect; + return DesiredHeight; + } + + + private static float ProcessLineHeights_GetDesiredHeight(Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref GSDSplineC tSpline) + { + return ((((tVect - TTD.TerrainPos).y) - tSpline.tRoad.opt_TerrainSubtract_Alt) / TTD.TerrainSize.y); + } + */ + + + private static void GetTempHeights_Coordinates(ref Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, out int x, out int y) + { + //Get the normalized position of this game object relative to the terrain: + Vector3 tempCoord = (tVect - TTD.TerrainPos); + + Vector3 coord; + coord.x = tempCoord.x / TTD.TerrainSize.x; + coord.y = tempCoord.y / TTD.TerrainSize.y; + coord.z = tempCoord.z / TTD.TerrainSize.z; + + //Get the position of the terrain heightmap where this game object is: + y = (int) (coord.x * TTD.HM); + x = (int) (coord.z * TTD.HM); + } + + + private static void GetTempDetails_Coordinates(ref Vector3 tVect, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, out int x, out int y) + { + //Get the normalized position of this game object relative to the terrain: + Vector3 tempCoord = (tVect - TTD.TerrainPos); + + Vector3 coord; + coord.x = tempCoord.x / TTD.TerrainSize.x; + coord.y = tempCoord.y / TTD.TerrainSize.y; + coord.z = tempCoord.z / TTD.TerrainSize.z; + + //Get the position of the terrain heightmap where this game object is: + y = (int) (coord.x * TTD.DetailMaxIndex); + x = (int) (coord.z * TTD.DetailMaxIndex); + } + + + //Privatized for obfuscate: + public static void DoRects(GSDSplineC tSpline, GSD.Roads.GSDTerraforming.TempTerrainData TTD) + { + DoRectsDo(ref tSpline, ref TTD); + } + + + private static void DoRectsDo(ref GSDSplineC tSpline, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD) + { + float Sep = tSpline.tRoad.RoadWidth() * 0.5f; + float HeightSep = Sep + (tSpline.tRoad.opt_MatchHeightsDistance * 0.5f); + List TBMList = new List(); + // List triList = new List(); + List TreerectList = new List(); + float tStep = tSpline.tRoad.opt_RoadDefinition / tSpline.distance; + // tStep *= 0.5f; + + //Start initializing the loop. Convuluted to handle special control nodes, so roads don't get rendered where they aren't supposed to, while still preserving the proper curvature. + float FinalMax = 1f; + float StartMin = 0f; + if (tSpline.bSpecialEndControlNode) + { //If control node, start after the control node: + FinalMax = tSpline.mNodes[tSpline.GetNodeCount() - 2].tTime; + } + if (tSpline.bSpecialStartControlNode) + { //If ends in control node, end construction before the control node: + StartMin = tSpline.mNodes[1].tTime; + } + // bool bFinalEnd = false; + // float RoadConnection_StartMin1 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. + // float RoadConnection_FinalMax1 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. + if (tSpline.bSpecialEndNode_IsStart_Delay) + { + StartMin += (tSpline.SpecialEndNodeDelay_Start / tSpline.distance); //If there's a start delay (in meters), delay the start of road construction: Due to special control nodes for road connections or 3 way intersections. + } + else if (tSpline.bSpecialEndNode_IsEnd_Delay) + { + FinalMax -= (tSpline.SpecialEndNodeDelay_End / tSpline.distance); //If there's a end delay (in meters), cut early the end of road construction: Due to special control nodes for road connections or 3 way intersections. + } + // float RoadConnection_StartMin2 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. + // float RoadConnection_FinalMax2 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. + + FinalMax = FinalMax + tStep; + + Vector3 tVect1 = default(Vector3); + Vector3 tVect2 = default(Vector3); + Vector3 POS1 = default(Vector3); + Vector3 POS2 = default(Vector3); + if (FinalMax > 1f) + { + FinalMax = 1f; + } + + float tNext = 0f; + float fValue1, fValue2; + float fValueMod = tSpline.tRoad.opt_RoadDefinition / tSpline.distance; + bool bIsPastInter = false; + float tIntStrength = 0f; + float tIntStrength2 = 0f; + // bool bMaxIntersection = false; + // bool bFirstInterNode = false; + GSDSplineN xNode = null; + float tIntHeight = 0f; + float tIntHeight2 = 0f; + GSDRoadIntersection GSDRI = null; + float T1SUB = 0f; + float T2SUB = 0f; + bool bIntStr1_Full = false; + bool bIntStr1_FullPrev = false; + bool bIntStr1_FullNext = false; + bool bIntStr2_Full = false; + bool bIntStr2_FullPrev = false; + bool bIntStr2_FullNext = false; + Vector3 tVect3 = default(Vector3); + // bool bStarted = false; + // bool T3Added = false; + List tXYs = new List(); + float TreeClearDist = tSpline.tRoad.opt_ClearTreesDistance; + if (TreeClearDist < tSpline.tRoad.RoadWidth()) + { + TreeClearDist = tSpline.tRoad.RoadWidth(); + } + GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; + float tGrade = 0f; + for (float index = StartMin; index < FinalMax; index += tStep) + { + if (tSpline.tRoad.opt_HeightModEnabled) + { + if (index > 1f) + { + break; + } + tNext = index + tStep; + if (tNext > 1f) + { + break; + } + + tSpline.GetSplineValue_Both(index, out tVect1, out POS1); + + if (tNext <= 1f) + { + tSpline.GetSplineValue_Both(tNext, out tVect2, out POS2); + } + else + { + tSpline.GetSplineValue_Both(1f, out tVect2, out POS2); + } + + //Determine if intersection: + bIsPastInter = false; //If past intersection + tIntStrength = tSpline.IntersectionStrength(ref tVect1, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref index, ref xNode); + // if(IsApproximately(tIntStrength,1f,0.001f) || tIntStrength > 1f){ + // bMaxIntersection = true; + // }else{ + // bMaxIntersection = false; + // } + // bFirstInterNode = false; + + tIntStrength2 = tSpline.IntersectionStrength(ref tVect2, ref tIntHeight2, ref GSDRI, ref bIsPastInter, ref index, ref xNode); + if (tIntStrength2 > 1f) + { + tIntStrength2 = 1f; + } + + T1SUB = tVect1.y; + T2SUB = tVect2.y; + + if (tIntStrength > 1f) + { + tIntStrength = 1f; + } + if (tIntStrength >= 0f) + {// || IsApproximately(tIntStrength,0f,0.01f)){ + if (IsApproximately(tIntStrength, 1f, 0.01f)) + { + T1SUB = tIntHeight; + bIntStr1_Full = true; + bIntStr1_FullNext = false; + } + else + { + bIntStr1_Full = false; + bIntStr1_FullNext = (tIntStrength2 >= 1f); + if (!IsApproximately(tIntStrength, 0f, 0.01f)) + { + T1SUB = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect1.y); + } + // if(tIntStrength <= 0f){ T1SUB = (tIntStrength*tIntHeight) + ((1-tIntStrength)*tVect1.y); } + } + + if ((bIntStr1_Full && !bIntStr1_FullPrev) || (!bIntStr1_Full && bIntStr1_FullNext)) + { + tGrade = tSpline.GetCurrentNode(index).GradeToPrevValue; + if (tGrade < 0f) + { + T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); + } + else + { + T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); + } + + // if(tGrade < 0f){ + // T1SUB *= -1f; + // } + } + else if (bIntStr1_Full && !bIntStr1_FullNext) + { + tGrade = tSpline.GetCurrentNode(index).GradeToNextValue; + if (tGrade < 0f) + { + T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); + } + else + { + T1SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); + } + // if(tGrade < 0f){ + // T1SUB *= -1f; + // } + } + else + { + T1SUB -= 0.02f; + } + bIntStr1_FullPrev = bIntStr1_Full; + } + + if (tIntStrength2 >= 0f || IsApproximately(tIntStrength2, 0f, 0.01f)) + { + // if(!IsApproximately(tIntStrength,1f,0.01f)){ + if (IsApproximately(tIntStrength, 1f, 0.01f)) + { + bIntStr2_Full = true; + T2SUB = tIntHeight2; + } + else + { + bIntStr2_Full = false; + if (!IsApproximately(tIntStrength2, 0f, 0.01f)) + { T2SUB = (tIntStrength2 * tIntHeight) + ((1 - tIntStrength2) * tVect2.y); } + // if(tIntStrength2 <= 0f){ T2SUB = (tIntStrength2*tIntHeight) + ((1-tIntStrength2)*tVect2.y); } + } + + if ((bIntStr2_Full && !bIntStr2_FullPrev)) + { + tGrade = tSpline.GetCurrentNode(index).GradeToPrevValue; + if (tGrade < 0f) + { + T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); + } + else + { + T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); + } + // T2SUB -= tIntHeight2 - tVect2.y; + } + else if (bIntStr2_Full && !bIntStr2_FullNext) + { + tGrade = tSpline.GetCurrentNode(index).GradeToNextValue; + if (tGrade < 0f) + { + T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, (tGrade / 20f) * -1f); + } + else + { + T2SUB -= Mathf.Lerp(0.02f, GSDRI.GradeMod, tGrade / 20f); + } + // if(tGrade < 0f){ + // T2SUB *= -1f; + // } + // T2SUB -= tIntHeight2 - tVect2.y; + } + else if (!bIntStr2_Full) + { + if (tNext + tStep < 1f) + { + tVect3 = tSpline.GetSplineValue(tNext + tStep, false); + tIntStrength2 = tSpline.IntersectionStrength(ref tVect3, ref tIntHeight2, ref GSDRI, ref bIsPastInter, ref index, ref xNode); + } + else + { + tIntStrength2 = 0f; + } + + if (tIntStrength2 >= 1f) + { + T2SUB -= 0.06f; + } + else + { + T2SUB -= 0.02f; + } + } + else + { + T2SUB -= 0.02f; + } + bIntStr2_FullPrev = bIntStr2_Full; + } + + fValue1 = index - fValueMod; + fValue2 = index + fValueMod; + if (fValue1 < 0) + { + fValue1 = 0; + } + if (fValue2 > 1) + { + fValue2 = 1; + } + + tXYs.Add(CreateTris(fValue1, fValue2, ref tVect1, ref POS1, ref tVect2, ref POS2, Sep, ref TBMList, ref T1SUB, ref T2SUB, ref TTD, HeightSep)); + + //Details and trees: + tRect = SetDetailCoords(index, ref tVect1, ref POS1, ref tVect2, ref POS2, tSpline.tRoad.opt_ClearDetailsDistance, TreeClearDist, ref TTD, ref tSpline); + if (tSpline.tRoad.opt_TreeModEnabled && tRect != null) + { + TreerectList.Add(tRect); + } + } + else + { + if (index > 1f) + { + break; + } + tNext = index + tStep; + if (tNext > 1f) + { + break; + } + + tSpline.GetSplineValue_Both(index, out tVect1, out POS1); + + if (tNext <= 1f) + { + tSpline.GetSplineValue_Both(tNext, out tVect2, out POS2); + } + else + { + tSpline.GetSplineValue_Both(1f, out tVect2, out POS2); + } + + //Details and trees: + tRect = SetDetailCoords(index, ref tVect1, ref POS1, ref tVect2, ref POS2, tSpline.tRoad.opt_ClearDetailsDistance, TreeClearDist, ref TTD, ref tSpline); + if (tSpline.tRoad.opt_TreeModEnabled && tRect != null) + { + TreerectList.Add(tRect); + } + } + } + + if (tSpline.tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("DoRectsTree"); + } + if (tSpline.tRoad.opt_TreeModEnabled && TreerectList != null && TreerectList.Count > 0) + { + int tCount = TTD.TreeSize; + int jCount = TreerectList.Count; + Vector3 tVect3D = default(Vector3); + Vector2 tVect2D = default(Vector2); + TreeInstance tTree; + for (int i = 0; i < tCount; i++) + { + tTree = TTD.TreesCurrent[i]; + + tVect3D = tTree.position; + tVect3D.x *= TTD.TerrainSize.z; + tVect3D.y *= TTD.TerrainSize.y; + tVect3D.z *= TTD.TerrainSize.x; + tVect3D += TTD.TerrainPos; + tVect2D.x = tVect3D.x; + tVect2D.y = tVect3D.z; + + for (int j = 0; j < jCount; j++) + { + if (TreerectList[j].Contains(ref tVect2D)) + { + TTD.TreesOld.Add(TTD.TreesCurrent[i]); + tTree = TTD.TreesCurrent[i]; + tTree.prototypeIndex = -2; + TTD.TreesCurrent[i] = tTree; + TTD.TreesI += 1; + break; + } + } + } + TTD.TreesCurrent.RemoveAll(item => item.prototypeIndex < -1); + } + if (tSpline.tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + if (!tSpline.tRoad.opt_HeightModEnabled) + { + return; + } + + // //Temp testing: + // tSpline.mNodes[22].tTriList = new List(); + // int tCount = triList.Count; + // for(int i=0;i(); + + + float tFloat = -1f; + Sep = tSpline.tRoad.RoadWidth() * 1.5f; + int k = 0; + int[] tXY = null; + int tXYsCount = tXYs.Count; + bool bIsBridge = false; + bool bIsTunnel = false; + for (float index = StartMin; index < FinalMax; index += tStep) + { + if (TBMList.Count > 0) + { + if (TBMList[0].MaxI < index) + { + CleanupTris(index, ref TBMList); + } + } + else + { + break; + } + + //If in bridg mode: + if (tSpline.IsInBridgeTerrain(index)) + { + bIsBridge = true; + } + else + { + bIsBridge = false; + } + //If in tunnel mode: + if (tSpline.IsInTunnelTerrain(index)) + { + bIsTunnel = true; + } + else + { + bIsTunnel = false; + } + + if (k < tXYsCount) + { + tXY = tXYs[k]; + tFloat = ProcessCoordinateGrabber(ref index, ref tSpline, ref TTD, ref TBMList, ref tXY, bIsBridge, bIsTunnel); + if (!IsApproximately(tFloat, 0f, 0.0001f)) + { + tSpline.HeightHistory.Add(new KeyValuePair(index, tFloat)); + } + } + else + { + break; + } + k += 1; + } + } + + + private static void CleanupTris(float CurrentI, ref List tList) + { + int mCount = tList.Count; + int LastIndexToRemove = -1; + for (int index = 0; index < mCount; index++) + { + if (tList[index].MaxI < CurrentI) + { + LastIndexToRemove = index; + } + else + { + break; + } + } + if (LastIndexToRemove >= 0) + { + tList.RemoveRange(0, LastIndexToRemove); + } + // + // mCount = rectList.Count; + // LastIndexToRemove = -1; + // for(int i=0;i= 0){ + // rectList.RemoveRange(0,LastIndexToRemove); + // } + } + + + private static int[] CreateTris(float i, float i2, ref Vector3 tVect1, ref Vector3 POS1, ref Vector3 tVect2, ref Vector3 POS2, float Sep, ref List tList, ref float T1SUB, ref float T2SUB, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, float HeightSep) + { + Vector3 lVect1 = (tVect1 + new Vector3(Sep * -POS1.normalized.z, 0, Sep * POS1.normalized.x)); + Vector3 rVect1 = (tVect1 + new Vector3(Sep * POS1.normalized.z, 0, Sep * -POS1.normalized.x)); + Vector3 lVect2 = (tVect2 + new Vector3(Sep * -POS2.normalized.z, 0, Sep * POS2.normalized.x)); + Vector3 rVect2 = (tVect2 + new Vector3(Sep * POS2.normalized.z, 0, Sep * -POS2.normalized.x)); + + lVect1.y = T1SUB; + rVect1.y = T1SUB; + lVect2.y = T2SUB; + rVect2.y = T2SUB; + + TerrainBoundsMaker TBM = new TerrainBoundsMaker(); + TBM.triList = new List(); + + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect1, rVect1, lVect2, i, i2)); + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect2, rVect1, rVect2, i, i2)); + + Vector3 lVect1far = (tVect1 + new Vector3(HeightSep * -POS1.normalized.z, 0, HeightSep * POS1.normalized.x)); + Vector3 rVect1far = (tVect1 + new Vector3(HeightSep * POS1.normalized.z, 0, HeightSep * -POS1.normalized.x)); + Vector3 lVect2far = (tVect2 + new Vector3(HeightSep * -POS2.normalized.z, 0, HeightSep * POS2.normalized.x)); + Vector3 rVect2far = (tVect2 + new Vector3(HeightSep * POS2.normalized.z, 0, HeightSep * -POS2.normalized.x)); + + lVect1far.y = lVect1.y; + lVect2far.y = lVect2.y; + rVect1far.y = rVect1.y; + rVect2far.y = rVect2.y; + + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect1far, lVect1, lVect2far, i, i2)); + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(lVect2far, lVect1, lVect2, i, i2)); + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(rVect1, rVect1far, rVect2, i, i2)); + TBM.triList.Add(new GSD.Roads.GSDRoadUtil.Construction3DTri(rVect2, rVect1far, rVect2far, i, i2)); + + TBM.tRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f); + // tRect.MinI = i; + // tRect.MaxI = i2; + + TBM.MinI = i; + TBM.MaxI = i2; + + tList.Add(TBM); + + int[] Xs = new int[4]; + int[] Ys = new int[4]; + + int x1, y1; + GetTempHeights_Coordinates(ref lVect1far, ref TTD, out x1, out y1); + Xs[0] = x1; + Ys[0] = y1; + GetTempHeights_Coordinates(ref lVect2far, ref TTD, out x1, out y1); + Xs[1] = x1; + Ys[1] = y1; + GetTempHeights_Coordinates(ref rVect1far, ref TTD, out x1, out y1); + Xs[2] = x1; + Ys[2] = y1; + GetTempHeights_Coordinates(ref rVect2far, ref TTD, out x1, out y1); + Xs[3] = x1; + Ys[3] = y1; + + int Min = Mathf.Min(Xs); + int Max = Mathf.Max(Xs); + Xs[0] = Min - 2; + Xs[2] = Max + 2; + Min = Mathf.Min(Ys); + Max = Mathf.Max(Ys); + Xs[1] = Min - 2; + Xs[3] = Max + 2; + + return Xs; + } + + + private static GSD.Roads.GSDRoadUtil.Construction2DRect SetDetailCoords(float param, ref Vector3 tVect1, ref Vector3 POS1, ref Vector3 tVect2, ref Vector3 POS2, float Sep, float TreeSep, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref GSDSplineC tSpline) + { + Vector3 lVect1far = default(Vector3); + Vector3 rVect1far = default(Vector3); + Vector3 lVect2far = default(Vector3); + Vector3 rVect2far = default(Vector3); + + bool bIsInBridge = tSpline.IsInBridgeTerrain(param); + bool bIsInTunnel = tSpline.IsInTunnelTerrain(param); + int x2, y2, x3, y3; + GetTempHeights_Coordinates(ref tVect1, ref TTD, out x2, out y2); + if (x2 >= TTD.HM) + { + x2 = -1; + } + if (y2 >= TTD.HM) + { + y2 = -1; + } + if (x2 < 0) + { + x2 = -1; + } + if (y2 < 0) + { + y2 = -1; + } + if (x2 == -1) + { + return null; + } + if (y2 == -1) + { + return null; + } + + float tDiff1 = ((TTD.heights[x2, y2] * (float) TTD.TerrainSize.y) - tVect1.y); + GetTempHeights_Coordinates(ref tVect2, ref TTD, out x3, out y3); + if (x3 >= TTD.HM) + { + x3 = -1; + } + if (y3 >= TTD.HM) + { + y3 = -1; + } + if (x3 < 0) + { + x3 = -1; + } + if (y3 < 0) + { + y3 = -1; + } + if (x3 == -1) + { + return null; + } + if (y3 == -1) + { + return null; + } + float tDiff2 = ((TTD.heights[x3, y3] * (float) TTD.TerrainSize.y) - tVect2.y); + + + + GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; + if (tSpline.tRoad.opt_TreeModEnabled) + { + bool bQuit = false; + if (x2 == -1) + { + bQuit = true; + } + if (y2 == -1) + { + bQuit = true; + } + + if (bIsInBridge && !bQuit) + { + if (tDiff1 < 0f) + { + tDiff1 *= -1f; + } + if (tDiff2 < 0f) + { + tDiff2 *= -1f; + } + if (tDiff1 > tSpline.tRoad.opt_ClearTreesDistanceHeight) + { + bQuit = true; + } + if (tDiff2 > tSpline.tRoad.opt_ClearTreesDistanceHeight) + { + bQuit = true; + } + } + if (bIsInTunnel && !bQuit) + { + if (tDiff1 < 0f) + { + if ((tDiff1 * -1f) > tSpline.tRoad.opt_ClearTreesDistanceHeight) + { + bQuit = true; + } + } + else + { + if (tDiff1 > (tSpline.tRoad.opt_ClearTreesDistanceHeight * 0.1f)) + { + bQuit = true; + } + } + if (tDiff2 < 0f) + { + if ((tDiff2 * -1f) > tSpline.tRoad.opt_ClearTreesDistanceHeight) + { + bQuit = true; + } + } + else + { + if (tDiff2 > (tSpline.tRoad.opt_ClearTreesDistanceHeight * 0.1f)) + { + bQuit = true; + } + } + } + + if (!bQuit) + { + TreeSep = TreeSep * 0.5f; + lVect1far = (tVect1 + new Vector3(TreeSep * -POS1.normalized.z, 0, TreeSep * POS1.normalized.x)); + rVect1far = (tVect1 + new Vector3(TreeSep * POS1.normalized.z, 0, TreeSep * -POS1.normalized.x)); + lVect2far = (tVect2 + new Vector3(TreeSep * -POS2.normalized.z, 0, TreeSep * POS2.normalized.x)); + rVect2far = (tVect2 + new Vector3(TreeSep * POS2.normalized.z, 0, TreeSep * -POS2.normalized.x)); + tRect = new GSD.Roads.GSDRoadUtil.Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f); + } + } + + if (tSpline.tRoad.opt_DetailModEnabled) + { + if (bIsInBridge || bIsInTunnel) + { + if (tDiff1 < 0f) + { + tDiff1 *= -1f; + } + if (tDiff2 < 0f) + { + tDiff2 *= -1f; + } + + bool bQuit = false; + if (x2 == -1) + { + bQuit = true; + } + if (y2 == -1) + { + bQuit = true; + } + + if (tDiff1 > tSpline.tRoad.opt_ClearDetailsDistanceHeight) + { + bQuit = true; + } + if (tDiff2 > tSpline.tRoad.opt_ClearDetailsDistanceHeight) + { + bQuit = true; + } + + if (bQuit) + { + return tRect; + } + } + + Sep = Sep * 0.5f; + + lVect1far = (tVect1 + new Vector3(Sep * -POS1.normalized.z, 0, Sep * POS1.normalized.x)); + rVect1far = (tVect1 + new Vector3(Sep * POS1.normalized.z, 0, Sep * -POS1.normalized.x)); + lVect2far = (tVect2 + new Vector3(Sep * -POS2.normalized.z, 0, Sep * POS2.normalized.x)); + rVect2far = (tVect2 + new Vector3(Sep * POS2.normalized.z, 0, Sep * -POS2.normalized.x)); + + int[] Xs = new int[4]; + int[] Ys = new int[4]; + + int x1, y1; + GetTempDetails_Coordinates(ref lVect1far, ref TTD, out x1, out y1); + Xs[0] = x1; + Ys[0] = y1; + GetTempDetails_Coordinates(ref lVect2far, ref TTD, out x1, out y1); + Xs[1] = x1; + Ys[1] = y1; + GetTempDetails_Coordinates(ref rVect1far, ref TTD, out x1, out y1); + Xs[2] = x1; + Ys[2] = y1; + GetTempDetails_Coordinates(ref rVect2far, ref TTD, out x1, out y1); + Xs[3] = x1; + Ys[3] = y1; + // + // if(TTD.DetailLayersCount == 1 && x1 > 0 && y1 > 0){ + // Debug.Log(Xs[0]+","+Ys[0] + " " + Xs[1]+","+Ys[1]); + // } + + int MinX = Mathf.Min(Xs); + int MinY = Mathf.Min(Ys); + int MaxX = Mathf.Max(Xs); + int MaxY = Mathf.Max(Ys); + + if (MinX >= TTD.DetailMaxIndex) + { + MinX = TTD.DetailMaxIndex - 1; + } + if (MinY >= TTD.DetailMaxIndex) + { + MinY = TTD.DetailMaxIndex - 1; + } + if (MaxX >= TTD.DetailMaxIndex) + { + MaxX = TTD.DetailMaxIndex - 1; + } + if (MaxY >= TTD.DetailMaxIndex) + { + MaxY = TTD.DetailMaxIndex - 1; + } + + if (MinX < 0) + { + MinX = 0; + } + if (MinY < 0) + { + MinY = 0; + } + if (MaxX < 0) + { + MaxX = 0; + } + if (MaxY < 0) + { + MaxY = 0; + } + + // int DetailI = 0; + if (tSpline.tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("Dorectsdetails"); + } + int tInt = 0; + for (int index = MinX; index <= MaxX; index++) + { + for (int k = MinY; k <= MaxY; k++) + { + //Bitfield for identification: + tInt = k; + tInt = tInt << 16; + tInt = tInt | (ushort) index; + if (!TTD.DetailHasProcessed.Contains(tInt)) + { + // for(int h=0;h 0){ + + TTD.MainDetailsX.Add((ushort) index); + TTD.MainDetailsY.Add((ushort) k); + + // DetailI = TTD.DetailsI[h]; + + // TTD.DetailsX[h].Add((ushort)i); + // TTD.DetailsY[h].Add((ushort)k); + + // TTD.DetailsX[h][DetailI] = (ushort)i; + // TTD.DetailsY[h][DetailI] = (ushort)k; + // TTD.OldDetailsValue[h][DetailI] = (ushort)TTD.DetailValues[h][i,k]; + // TTD.DetailValues[h][i,k] = 0; + + // TTD.DetailsI[h]+=1; + + // } + TTD.DetailHasProcessed.Add(tInt); + } + } + } + if (tSpline.tRoad.bProfiling) + { UnityEngine.Profiling.Profiler.EndSample(); } + } + + return tRect; + } + + + private static float ProcessCoordinateGrabber(ref float param, ref GSDSplineC tSpline, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD, ref List tList, ref int[] tXY, bool bIsBridge, bool bIsTunnel) + { + int MinX = tXY[0]; + int MinY = tXY[1]; + int MaxX = tXY[2]; + int MaxY = tXY[3]; + + if (MinX >= TTD.TerrainMaxIndex) + { + MinX = TTD.TerrainMaxIndex - 1; + } + if (MinY >= TTD.TerrainMaxIndex) + { + MinY = TTD.TerrainMaxIndex - 1; + } + if (MaxX >= TTD.TerrainMaxIndex) + { + MaxX = TTD.TerrainMaxIndex - 1; + } + if (MaxY >= TTD.TerrainMaxIndex) + { + MaxY = TTD.TerrainMaxIndex - 1; + } + + if (MinX < 0) + { + MinX = 0; + } + if (MinY < 0) + { + MinY = 0; + } + if (MaxX < 0) + { + MaxX = 0; + } + if (MaxY < 0) + { + MaxY = 0; + } + + Vector3 xVect = default(Vector3); + bool bAdjusted = false; + float tHeight = -1f; + float tReturnFloat = 0f; + // int dX = 0; + // int dY = 0; + // int tdX = 0; + // int tdY = 0; + // bool bOneHit = false; + + for (int index = MinX; index <= MaxX; index++) + { + for (int k = MinY; k <= MaxY; k++) + { + if (TTD.tHeights[index, k] != true) + { + if (TTD.cX.Length <= TTD.cI) + { + break; + } + + xVect = ConvertTerrainCoordToWorldVect(index, k, TTD.heights[index, k], ref TTD); + AdjustedTerrainVect_Tri(ref param, out bAdjusted, out tHeight, ref xVect, ref tList, bIsBridge, bIsTunnel); + + if (bAdjusted) + { + tHeight -= tSpline.tRoad.opt_TerrainSubtract_Match; + if (tHeight < 0f) + { + tHeight = 0f; + } + xVect.y = tHeight; + tHeight = ((tHeight) / TTD.TerrainSize.y); + + //Set height values: + TTD.tHeights[index, k] = true; + TTD.cX[TTD.cI] = (ushort) index; + TTD.cY[TTD.cI] = (ushort) k; + TTD.oldH[TTD.cI] = TTD.heights[index, k]; + TTD.heights[index, k] = tHeight; + TTD.cI += 1; + + tReturnFloat = xVect.y; + // bOneHit = true; + } + } + else + { + xVect = ConvertTerrainCoordToWorldVect(index, k, TTD.heights[index, k], ref TTD); + AdjustedTerrainVect_Tri(ref param, out bAdjusted, out tHeight, ref xVect, ref tList, bIsBridge, bIsTunnel); + + if (bAdjusted) + { + tHeight -= tSpline.tRoad.opt_TerrainSubtract_Match; + if (tHeight < 0f) + { + tHeight = 0f; + } + tReturnFloat = tHeight; + // bOneHit = true; + } + } + } + } + + if (bIsBridge && IsApproximately(tReturnFloat, 0f, 0.0001f)) + { + tReturnFloat = tSpline.GetSplineValue(param, false).y; + } + + return tReturnFloat; + } + + + private static Vector3 ConvertTerrainCoordToWorldVect(int x, int y, float tHeight, ref GSD.Roads.GSDTerraforming.TempTerrainData TTD) + { + //Get the normalized position of this game object relative to the terrain: + float x1 = x / ((float) TTD.HM - 1f); + x1 = x1 * TTD.TerrainSize.x; + + float z1 = y / ((float) TTD.HM - 1f); + z1 = z1 * TTD.TerrainSize.z; + + float y1 = tHeight * TTD.TerrainSize.y; + + Vector3 xVect = new Vector3(z1, y1, x1); + xVect += TTD.TerrainPos; + + return xVect; + } + + + private static void AdjustedTerrainVect_Tri(ref float param, out bool bAdjusted, out float tHeight, ref Vector3 xVect, ref List tList, bool bIsBridge, bool bIsTunnel) + { + float OrigHeight = xVect.y; + int mCount = tList.Count; + int tCount = 0; + GSD.Roads.GSDRoadUtil.Construction3DTri tTri; + TerrainBoundsMaker TBM; + bAdjusted = false; + tHeight = 0f; + Vector2 t2D = new Vector2(xVect.x, xVect.z); + for (int index = 0; index < mCount; index++) + { + TBM = tList[index]; + if (param < TBM.MinI) + { + return; + } + if (param > TBM.MaxI) + { + continue; + } + if (TBM.tRect.Contains(ref t2D)) + { + tCount = TBM.triList.Count; + for (int k = 0; k < tCount; k++) + { + tTri = TBM.triList[k]; + if (tTri.Contains2D(ref t2D)) + { + tHeight = tTri.LinePlaneIntersection(ref xVect).y; + if (bIsBridge) + { + if (OrigHeight > (tHeight - 0.03f)) + { + tHeight -= 0.03f; + bAdjusted = true; + return; + } + } + else if (bIsTunnel) + { + if (OrigHeight < (tHeight + 0.03f)) + { + tHeight += 0.03f; + bAdjusted = true; + return; + } + } + else + { + bAdjusted = true; + return; + } + } + } + } + } + } + + + private static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + private static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + } + + + public static class GSDRoadCreationT + { + #region "Road Prelim" + //Privatized for obfuscate: + public static void RoadJob_Prelim(ref GSDRoad tRoad) + { + RoadJob_DoPrelim(ref tRoad); + } + + + // TODO: Optimize Code and OutComment ifs which do nothing... // FH 29.01.19 + private static void RoadJob_DoPrelim(ref GSDRoad tRoad) + { + GSDSplineC tSpline = tRoad.GSDSpline; + //Road,shoulder,ramp and lane widths: + float RoadWidth = tRoad.RoadWidth(); + float ShoulderWidth = tRoad.opt_ShoulderWidth; + float RoadSeperation = RoadWidth / 2f; + float RoadSeperation_NoTurn = RoadWidth / 2f; + float ShoulderSeperation = RoadSeperation + ShoulderWidth; + float LaneWidth = tRoad.opt_LaneWidth; + float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); + float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); + float ShoulderSep1Lane = (ShoulderSeperation + (LaneWidth * 0.5f)); + float ShoulderSep2Lane = (ShoulderSeperation + (LaneWidth * 1.5f)); + + //Vector3 buffers used in construction: + Vector3 rVect = default(Vector3); + Vector3 lVect = default(Vector3); + Vector3 ShoulderR_rVect = default(Vector3); + Vector3 ShoulderR_lVect = default(Vector3); + Vector3 ShoulderL_rVect = default(Vector3); + Vector3 ShoulderL_lVect = default(Vector3); + Vector3 RampR_R = default(Vector3); + Vector3 RampR_L = default(Vector3); + Vector3 RampL_R = default(Vector3); + Vector3 RampL_L = default(Vector3); + float ShoulderR_OuterAngle = 0f; + if (ShoulderR_OuterAngle < 0f) + { } + float ShoulderL_OuterAngle = 0f; + if (ShoulderL_OuterAngle < 0f) + { } + // Vector3 ShoulderR_OuterDirection = default(Vector3); + // Vector3 ShoulderL_OuterDirection = default(Vector3); + + //Previous temp storage values: + Vector3 tVect_Prev = default(Vector3); + if (tVect_Prev == default(Vector3)) + { } //Prev step storage of road variable. + Vector3 rVect_Prev = default(Vector3); + if (rVect_Prev == default(Vector3)) + { }//Prev step storage of road variable. + Vector3 lVect_Prev = default(Vector3); + if (lVect_Prev == default(Vector3)) + { }//Prev step storage of road variable. + Vector3 ShoulderR_PrevLVect = default(Vector3); + if (ShoulderR_PrevLVect == default(Vector3)) + { }//Prev step storage of shoulder variable. + Vector3 ShoulderL_PrevRVect = default(Vector3); + if (ShoulderL_PrevRVect == default(Vector3)) + { }//Prev step storage of shoulder variable. + Vector3 ShoulderR_PrevRVect = default(Vector3); + if (ShoulderR_PrevRVect == default(Vector3)) + { }//Prev step storage of shoulder variable. + Vector3 ShoulderL_PrevLVect = default(Vector3); + if (ShoulderL_PrevLVect == default(Vector3)) + { }//Prev step storage of shoulder variable. + // Vector3 ShoulderR_PrevRVect2 = default(Vector3); //Prev storage of shoulder variable (2 step history). + // Vector3 ShoulderL_PrevLVect2 = default(Vector3); //Prev storage of shoulder variable (2 step history). + // Vector3 ShoulderR_PrevRVect3 = default(Vector3); //Prev storage of shoulder variable (3 step history). + // Vector3 ShoulderL_PrevLVect3 = default(Vector3); //Prev storage of shoulder variable (3 step history). + Vector3 RampR_PrevR = default(Vector3); + if (RampR_PrevR == default(Vector3)) + { }//Prev storage of ramp variables (outer shoulder). + Vector3 RampR_PrevL = default(Vector3); + if (RampR_PrevL == default(Vector3)) + { }//Prev storage of ramp variables (outer shoulder). + Vector3 RampL_PrevR = default(Vector3); + if (RampL_PrevR == default(Vector3)) + { }//Prev storage of ramp variables (outer shoulder). + Vector3 RampL_PrevL = default(Vector3); + if (RampL_PrevL == default(Vector3)) + { }//Prev storage of ramp variables (outer shoulder). + // Vector3 ShoulderR_OuterDirectionPrev = default(Vector3); //Prev storage of outer shoulder direction (euler). + // Vector3 ShoulderL_OuterDirectionPrev = default(Vector3); //Prev storage of outer shoulder direction (euler). + + //Height and angle variables, used to change certain parameters of road depending on past & future angle and height changes. + // float tAngle = 0f; + // float OrigStep = 0.06f; + float Step = tRoad.opt_RoadDefinition / tSpline.distance; + // float AngleStep = 5f; + Vector3 tHeight0 = new Vector3(0f, 0.1f, 0f); + // Vector3 tHeight2 = new Vector3(0f,0.15f,0f); + // Vector3 tHeight1 = new Vector3(0f,0.2f,0f); + float OuterShoulderWidthR = 0f; + float OuterShoulderWidthL = 0f; + float RampOuterWidthR = (OuterShoulderWidthR / 6f) + OuterShoulderWidthR; + float RampOuterWidthL = (OuterShoulderWidthL / 6f) + OuterShoulderWidthL; + Vector3 tVect = default(Vector3); + Vector3 POS = default(Vector3); + float TempY = 0f; + // bool bTempYWasNegative = false; + // Vector3 tY = new Vector3(0f,0f,0f); + float tHeightAdded = 0f; + if (tHeightAdded < 0f) + { } + // float[] HeightChecks = new float[5]; + Vector3 gHeight = default(Vector3); + + //Bridge variables: + bool bIsBridge = false; + if (bIsBridge == false) + { } + bool bTempbridge = false; + if (bTempbridge == false) + { } + bool bBridgeInitial = false; + if (bBridgeInitial == false) + { } + bool bBridgeLast = false; + if (bBridgeLast == false) + { } + float BridgeUpComing; + // int BridgeLIndex; + // int BridgeRIndex; + + //Tunnel variables: + bool bIsTunnel = false; + if (bIsTunnel == false) + { } + bool bTempTunnel = false; + if (bTempTunnel == false) + { } + bool bTunnelInitial = false; + if (bTunnelInitial == false) + { } + bool bTunnelLast = false; + if (bTunnelLast == false) + { } + float TunnelUpComing = 0f; + if (TunnelUpComing < 0f) + { } + // int TunnelLIndex; + // int TunnelRIndex; + + //Intersection variables and buffers: + float tIntHeight = 0f; + if (tIntHeight < 0f) + { } + float tIntStrength = 0f; + if (tIntStrength < 0f) + { } + float tIntStrength_temp = 0f; + if (tIntStrength_temp < 0f) + { } + // float tIntDistCheck = 75f; + GSDRoadIntersection GSDRI = null; + bool bIsPastInter = false; + bool bMaxIntersection = false; + bool bWasPrevMaxInter = false; + GSDSplineN xNode = null; + float tInterSubtract = 4f; + float tLastInterHeight = -4f; + bool bOverrideRampR = false; + bool bOverrideRampL = false; + Vector3 RampR_Override = default(Vector3); + Vector3 RampL_Override = default(Vector3); + bool bFirstInterNode = false; + bool bInter_PrevWasCorner = false; + if (bInter_PrevWasCorner == false) + { } + bool bInter_CurreIsCorner = false; + bool bInter_CurreIsCornerRR = false; + bool bInter_CurreIsCornerRL = false; + bool bInter_CurreIsCornerLL = false; + bool bInter_CurreIsCornerLR = false; + bool bInter_PrevWasCornerRR = false; + bool bInter_PrevWasCornerRL = false; + bool bInter_PrevWasCornerLL = false; + bool bInter_PrevWasCornerLR = false; + Vector3 iTemp_HeightVect = default(Vector3); + Vector3 rVect_iTemp = default(Vector3); + Vector3 lVect_iTemp = default(Vector3); + Vector3 ShoulderR_R_iTemp = default(Vector3); + Vector3 ShoulderL_L_iTemp = default(Vector3); + Vector3 RampR_R_iTemp = default(Vector3); + Vector3 RampR_L_iTemp = default(Vector3); + Vector3 RampL_R_iTemp = default(Vector3); + Vector3 RampL_L_iTemp = default(Vector3); + Vector3 tempIVect_Prev = default(Vector3); + Vector3 tempIVect = tVect; + bool b0LAdded = false; + if (b0LAdded == false) + { } + bool b1LAdded = false; + if (b1LAdded == false) + { } + bool b2LAdded = false; + if (b2LAdded == false) + { } + bool b3LAdded = false; + if (b3LAdded == false) + { } + bool f0LAdded = false; + if (f0LAdded == false) + { } + bool f1LAdded = false; + if (f1LAdded == false) + { } + bool f2LAdded = false; + if (f2LAdded == false) + { } + bool f3LAdded = false; + if (f3LAdded == false) + { } + bool b0RAdded = false; + if (b0RAdded == false) + { } + bool b1RAdded = false; + if (b1RAdded == false) + { } + bool b2RAdded = false; + if (b2RAdded == false) + { } + bool b3RAdded = false; + if (b3RAdded == false) + { } + bool f0RAdded = false; + if (f0RAdded == false) + { } + bool f1RAdded = false; + if (f1RAdded == false) + { } + bool f2RAdded = false; + if (f2RAdded == false) + { } + bool f3RAdded = false; + if (f3RAdded == false) + { } + bool bInterTestAddAfterR = false; + if (bInterTestAddAfterR == false) + { } + bool bInterTestAddAfterL = false; + if (bInterTestAddAfterL == false) + { } + // Vector3 InterTestVect1 = default(Vector3); + // Vector3 InterTestVect2 = default(Vector3); + // Vector3 InterTestVect3 = default(Vector3); + // Vector3 InterTestVect4 = default(Vector3); + bool bShoulderSkipR = false; + bool bShoulderSkipL = false; + bool bShrinkRoadB = false; + bool bShrinkRoadFNext = false; + bool bShrinkRoadF = false; + bool bIsNextInter = false; + GSDSplineN cNode = null; + int NodeID = -1; + int NodeIDPrev = -1; + int NodeCount = tSpline.GetNodeCount(); + bool bDynamicCut = false; + float CullDistanceSQ = (3f * RoadWidth) * (3f * RoadWidth); + float mCornerDist = 0f; + Vector2 CornerRR = default(Vector2); + if (CornerRR == default(Vector2)) + { } + Vector2 CornerRL = default(Vector2); + if (CornerRL == default(Vector2)) + { } + Vector2 CornerLR = default(Vector2); + if (CornerLR == default(Vector2)) + { } + Vector2 CornerLL = default(Vector2); + if (CornerLL == default(Vector2)) + { } + Vector2 rVect2D = default(Vector2); + if (rVect2D == default(Vector2)) + { } + Vector2 lVect2D = default(Vector2); + if (lVect2D == default(Vector2)) + { } + Vector3 tempIVect_prev = default(Vector3); + if (tempIVect_prev == default(Vector3)) + { } + Vector3 POS_Next = default(Vector3); + if (POS_Next == default(Vector3)) + { } + Vector3 tVect_Next = default(Vector3); + if (tVect_Next == default(Vector3)) + { } + Vector3 rVect_Next = default(Vector3); + if (rVect_Next == default(Vector3)) + { } + Vector3 lVect_Next = default(Vector3); + if (lVect_Next == default(Vector3)) + { } + Vector3 xHeight = default(Vector3); + if (xHeight == default(Vector3)) + { } + bool bLRtoRR = false; + bool bLLtoLR = false; + bool bLine = false; + bool bImmuneR = false; + bool bImmuneL = false; + bool bSpecAddedL = false; + if (bSpecAddedL == false) + { } + bool bSpecAddedR = false; + if (bSpecAddedR == false) + { } + bool bTriggerInterAddition = false; + bool bSpecialThreeWayIgnoreR = false; + bool bSpecialThreeWayIgnoreL = false; + // int eCount = -1; + // int eIndex = -1; + // int uCount = -1; + // int uIndex = -1; + float bMod1 = 1.75f; + float bMod2 = 1.25f; + float t2DDist = -1f; + List vList = null; + List eList = null; + float tParam2 = 0f; + float tParam1 = 0f; + bool bRecordShoulderForNormals = false; + bool bRecordShoulderLForNormals = false; + + //Unused for now, for later partial construction methods: + bool bInterseOn = tRoad.RCS.bInterseOn; + // bool bBridgesOn = tRoad.RCS.bBridgesOn; + // if(tRoad.RCS.bRoadOn){ + bInterseOn = true; + // } + + //Prelim intersection construction and profiling: + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_Inter"); + } + if (bInterseOn) + { + RoadJob_Prelim_Inter(ref tRoad); + } + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("RoadPrelimForLoop"); + } + + //Road/shoulder cuts: Init necessary since a road cut is added for the last segment after this function: + if (tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts) + { + tRoad.RCS.RoadCutNodes.Add(tSpline.mNodes[0]); + } + if (tRoad.opt_bShoulderCuts || tRoad.opt_bDynamicCuts) + { + tRoad.RCS.ShoulderCutsLNodes.Add(tSpline.mNodes[0]); + tRoad.RCS.ShoulderCutsRNodes.Add(tSpline.mNodes[0]); + } + + //Start initializing the loop. Convuluted to handle special control nodes, so roads don't get rendered where they aren't supposed to, while still preserving the proper curvature. + float FinalMax = 1f; + float StartMin = 0f; + if (tSpline.bSpecialEndControlNode) + { //If control node, start after the control node: + FinalMax = tSpline.mNodes[tSpline.GetNodeCount() - 2].tTime; + } + if (tSpline.bSpecialStartControlNode) + { //If ends in control node, end construction before the control node: + StartMin = tSpline.mNodes[1].tTime; + } + bool bFinalEnd = false; + float RoadConnection_StartMin1 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. + float RoadConnection_FinalMax1 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. + if (tSpline.bSpecialEndNode_IsStart_Delay) + { + StartMin += (tSpline.SpecialEndNodeDelay_Start / tSpline.distance); //If there's a start delay (in meters), delay the start of road construction: Due to special control nodes for road connections or 3 way intersections. + } + else if (tSpline.bSpecialEndNode_IsEnd_Delay) + { + FinalMax -= (tSpline.SpecialEndNodeDelay_End / tSpline.distance); //If there's a end delay (in meters), cut early the end of road construction: Due to special control nodes for road connections or 3 way intersections. + } + // float RoadConnection_StartMin2 = StartMin; //Storage of incremental start values for the road connection mesh construction at the end of this function. + // float RoadConnection_FinalMax2 = FinalMax; //Storage of incremental end values for the road connection mesh construction at the end of this function. + float i = StartMin; + + // int StartIndex = tSpline.GetClosestRoadDefIndex(StartMin,true,false); + // int EndIndex = tSpline.GetClosestRoadDefIndex(FinalMax,false,true); + // float cDist = 0f; + bool kSkip = true; + bool kSkipFinal = false; + int kCount = 0; + int vCount = kCount; + int kFinalCount = tSpline.RoadDefKeysArray.Length; + int spamcheckmax1 = 18000; + int spamcheck1 = 0; + + if (IsApproximately(StartMin, 0f, 0.0001f)) + { + kSkip = false; + } + if (IsApproximately(FinalMax, 1f, 0.0001f)) + { + kSkipFinal = true; + } + + //If startmin > 0 then kcount needs to start at proper road def + // bool bStartMinEnabled = false; + int StartMinIndex1 = 0; + + if (StartMin > 0f) + { + kCount = tSpline.GetClosestRoadDefIndex(StartMin, true, false); + // bStartMinEnabled = true; + StartMinIndex1 = 1; + } + + while (!bFinalEnd && spamcheck1 < spamcheckmax1) + { + spamcheck1++; + + if (kSkip) + { + i = StartMin; + kSkip = false; + } + else + { + if (kCount >= kFinalCount) + { + i = FinalMax; + if (kSkipFinal) + { break; } + } + else + { + i = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); + kCount += 1; + } + } + + if (i > 1f) + { + break; + } + if (i < 0f) + { + i = 0f; + } + + if (IsApproximately(i, FinalMax, 0.00001f)) + { + bFinalEnd = true; + } + else if (i > FinalMax) + { + if (tSpline.bSpecialEndControlNode) + { + i = FinalMax; + bFinalEnd = true; + } + else + { + bFinalEnd = true; + break; + } + } + cNode = tSpline.GetCurrentNode(i); //Set the current node. + NodeID = cNode.idOnSpline; //Set the current node ID. + if (NodeID != NodeIDPrev && (tRoad.opt_bRoadCuts || tRoad.opt_bDynamicCuts)) + { //If different than the previous node id, time to make a cut, if necessary: + //Don't ever cut the first node, last node, intersection node, special control nodes, bridge nodes or bridge control nodes: + if (NodeID > StartMinIndex1 && NodeID < (NodeCount - 1) && !cNode.bIsIntersection && !cNode.bSpecialEndNode) + { // && !cNode.bIsBridge_PreNode && !cNode.bIsBridge_PostNode){ + if (tRoad.opt_bDynamicCuts) + { + bDynamicCut = cNode.bRoadCut; + } + else + { + bDynamicCut = true; + } + + if (bDynamicCut) + { + tRoad.RCS.RoadCuts.Add(tRoad.RCS.RoadVectors.Count); //Add the vector index to cut later. + tRoad.RCS.RoadCutNodes.Add(cNode); //Store the node which was at the beginning of this cut. + } + if (tRoad.opt_bShoulderCuts && bDynamicCut) + { //If option shoulder cuts is on. + tRoad.RCS.ShoulderCutsL.Add(tRoad.RCS.ShoulderL_Vectors.Count); //Add the vector index to cut later. + tRoad.RCS.ShoulderCutsLNodes.Add(cNode); //Store the node which was at the beginning of this cut. + tRoad.RCS.ShoulderCutsR.Add(tRoad.RCS.ShoulderR_Vectors.Count); //Add the vector index to cut later. + tRoad.RCS.ShoulderCutsRNodes.Add(cNode); //Store the node which was at the beginning of this cut. + } + } + } + if (NodeID != NodeIDPrev) + { + if (tRoad.RCS.RoadVectors.Count > 0) + { + cNode.bInitialRoadHeight = tRoad.RCS.RoadVectors[tRoad.RCS.RoadVectors.Count - 1].y; + } + } + NodeIDPrev = NodeID; //Store the previous node ID for the next round. Done now with road cuts as far as this function is concerned. + + //Set all necessary intersection triggers to false: + bInter_CurreIsCorner = false; + bInter_CurreIsCornerRR = false; + bInter_CurreIsCornerRL = false; + bInter_CurreIsCornerLL = false; + bInter_CurreIsCornerLR = false; + b0LAdded = false; + b1LAdded = false; + b2LAdded = false; + b3LAdded = false; + f0LAdded = false; + f1LAdded = false; + f2LAdded = false; + f3LAdded = false; + b0RAdded = false; + b1RAdded = false; + b2RAdded = false; + b3RAdded = false; + f0RAdded = false; + f1RAdded = false; + f2RAdded = false; + f3RAdded = false; + bInterTestAddAfterR = false; + bInterTestAddAfterL = false; + bShoulderSkipR = false; + bShoulderSkipL = false; + bShrinkRoadB = false; + bShrinkRoadF = false; + bIsNextInter = false; + if (bShrinkRoadFNext) + { + bShrinkRoadFNext = false; + bShrinkRoadF = true; + } + bRecordShoulderForNormals = false; + bRecordShoulderLForNormals = false; + + //Bridges: Note: This is convoluted due to need for triggers: + bBridgeInitial = false; + bBridgeLast = false; + bTempbridge = tSpline.IsInBridge(i); + if (!bIsBridge && bTempbridge) + { + bIsBridge = true; + bBridgeInitial = true; + } + else if (bIsBridge && !bTempbridge) + { + bIsBridge = false; + } + //Check if this is the last bridge run for this bridge: + if (bIsBridge) + { + bTempbridge = tSpline.IsInBridge(i + Step); + if (!bTempbridge) + { + bBridgeLast = true; + } + } + + //Tunnels: Note: This is convoluted due to need for triggers: + bTunnelInitial = false; + bTunnelLast = false; + bTempTunnel = tSpline.IsInTunnel(i); + if (!bIsTunnel && bTempTunnel) + { + bIsTunnel = true; + bTunnelInitial = true; + } + else if (bIsTunnel && !bTempTunnel) + { + bIsTunnel = false; + } + //Check if this is the last Tunnel run for this Tunnel: + if (bIsTunnel) + { + bTempTunnel = tSpline.IsInTunnel(i + Step); + if (!bTempTunnel) + { + bTunnelLast = true; + } + } + + //Master Vector3 for the current road construction location: + tSpline.GetSplineValue_Both(i, out tVect, out POS); + + // Profiler.EndSample(); + // Profiler.BeginSample("Test2"); + + //Detect downward or upward slope: + TempY = POS.y; + // bTempYWasNegative = false; + if (TempY < 0f) + { + // bTempYWasNegative = true; + TempY *= -1f; + } + if (tVect.y < 0f) + { + tVect.y = 0f; + } + + //Determine if intersection: + if (bInterseOn) + { + bIsPastInter = false; //If past intersection + tIntStrength = tRoad.GSDSpline.IntersectionStrength(ref tVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); + bMaxIntersection = (tIntStrength >= 1f); //1f strength = max intersection + bFirstInterNode = false; + } + + //Outer widths: + if (bMaxIntersection && bInterseOn) + { + GSDRI.SignHeight = tIntHeight; + xNode.iConstruction.bBLane0Done_Final_ThisRound = false; + xNode.iConstruction.bBLane1Done_Final_ThisRound = false; + xNode.iConstruction.bBLane2Done_Final_ThisRound = false; + xNode.iConstruction.bBLane3Done_Final_ThisRound = false; + xNode.iConstruction.bFLane0Done_Final_ThisRound = false; + xNode.iConstruction.bFLane1Done_Final_ThisRound = false; + xNode.iConstruction.bFLane2Done_Final_ThisRound = false; + xNode.iConstruction.bFLane3Done_Final_ThisRound = false; + xNode.iConstruction.bIsFrontFirstRound = false; + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + OuterShoulderWidthR = ShoulderSeperation; + OuterShoulderWidthL = ShoulderSeperation; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + OuterShoulderWidthR = ShoulderSep1Lane; + OuterShoulderWidthL = ShoulderSep1Lane; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bIsPastInter) + { + OuterShoulderWidthR = ShoulderSep1Lane; + OuterShoulderWidthL = ShoulderSep2Lane; + } + else + { + OuterShoulderWidthR = ShoulderSep2Lane; + OuterShoulderWidthL = ShoulderSep1Lane; + } + } + } + else + { + if (TempY < 0.5f || bIsBridge || bIsTunnel) + { + OuterShoulderWidthR = ShoulderSeperation; + OuterShoulderWidthL = ShoulderSeperation; + } + else + { + OuterShoulderWidthR = ShoulderSeperation + (TempY * 0.05f); + OuterShoulderWidthL = ShoulderSeperation + (TempY * 0.05f); + } + } + + if (bIsBridge) + { //No ramps for bridges: + RampOuterWidthR = OuterShoulderWidthR; + RampOuterWidthL = OuterShoulderWidthL; + } + else + { + RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; + RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; + } + + //The master outer road edges vector locations: + if (bMaxIntersection && bInterseOn) + { //If in maximum intersection, adjust road edge (also the shoulder inner edges): + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + rVect = (tVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bIsPastInter) + { + rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + ; + } + else + { + rVect = (tVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + } + else + { + rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); + } + } + else + { + //Typical road/shoulder inner edge location: + rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); + } + + //Shoulder right vectors: + ShoulderR_rVect = (tVect + new Vector3(OuterShoulderWidthR * POS.normalized.z, 0, OuterShoulderWidthR * -POS.normalized.x)); + ShoulderR_lVect = rVect; //Note that the shoulder inner edge is the same as the road edge vector. + //Shoulder left vectors: + ShoulderL_rVect = lVect; //Note that the shoulder inner edge is the same as the road edge vector. + ShoulderL_lVect = (tVect + new Vector3(OuterShoulderWidthL * -POS.normalized.z, 0, OuterShoulderWidthL * POS.normalized.x)); + + // Profiler.EndSample(); + // Profiler.BeginSample("Test3"); + + //Now to start the main lane construction for the intersection: + if (bMaxIntersection && bInterseOn) + { + // if(kCount >= tSpline.RoadDefKeysArray.Length){ + // vCount = tSpline.RoadDefKeysArray.Length-1; + // }else{ + // vCount = kCount-1; + // } + vCount = kCount; + + tParam2 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[vCount]); + float tInterStrNext = tRoad.GSDSpline.IntersectionStrength_Next(tSpline.GetSplineValue(tParam2, false)); + if (IsApproximately(tInterStrNext, 1f, 0.001f) || tInterStrNext > 1f) + { + bIsNextInter = true; + } + else + { + bIsNextInter = false; + } + + if (string.Compare(xNode.UID, GSDRI.Node1.UID) == 0) + { + bFirstInterNode = true; + } + else + { + bFirstInterNode = false; + } + + tempIVect = tVect; + if (bIsPastInter) + { + bool bLLtoRL = bFirstInterNode; + bool bRLtoRR = !bFirstInterNode; + if (xNode.iConstruction.iFLane0L.Count == 0) + { + xNode.iConstruction.bIsFrontFirstRound = true; + xNode.iConstruction.bIsFrontFirstRoundTriggered = true; + xNode.iConstruction.bFLane0Done_Final_ThisRound = true; + xNode.iConstruction.bFLane1Done_Final_ThisRound = true; + xNode.iConstruction.bFLane2Done_Final_ThisRound = true; + xNode.iConstruction.bFLane3Done_Final_ThisRound = true; + + if (GSDRI.bFlipped && !bFirstInterNode) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); + xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); + xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerLL_CornerLR[4], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + } + } + else + { + if (bLLtoRL) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[4], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[3], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerLL_CornerRL[2], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerLL_CornerRL[1], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerLL_CornerRL[0], tIntHeight)); + } + } + else if (bRLtoRR) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[4], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane3L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane3R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iFLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); + } + } + } + + xNode.iConstruction.ShoulderFR_End = xNode.iConstruction.iFLane0L[0]; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane3R[0]; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane2R[0]; + } + else + { + xNode.iConstruction.ShoulderFL_End = xNode.iConstruction.iFLane1R[0]; + } + xNode.iConstruction.ShoulderFL_StartIndex = tRoad.RCS.ShoulderL_Vectors.Count - 2; + xNode.iConstruction.ShoulderFR_StartIndex = tRoad.RCS.ShoulderR_Vectors.Count - 2; + } + + //Line 0: + xNode.iConstruction.f0LAttempt = rVect; + if (!xNode.iConstruction.bFLane0Done && !GSDRI.Contains(ref rVect)) + { + xNode.iConstruction.iFLane0L.Add(GVC(rVect, tIntHeight)); + f0LAdded = true; + } + + //Line 1: + // if(f0LAdded){ + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tempIVect = tVect; + if (!xNode.iConstruction.bFLane1Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) + { + if (f0LAdded) + { + xNode.iConstruction.iFLane0R.Add(GVC(tempIVect, tIntHeight)); + f0RAdded = true; + } + xNode.iConstruction.iFLane1L.Add(GVC(tempIVect, tIntHeight)); + f1LAdded = true; + } + else + { + if (f0LAdded) + { + xNode.iConstruction.iFLane0L.RemoveAt(xNode.iConstruction.iFLane0L.Count - 1); + f0LAdded = false; + } + } + } + else + { + tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0f, (LaneWidth * 0.5f) * -POS.normalized.x)); + if (!xNode.iConstruction.bFLane1Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) + { + if (f0LAdded) + { + xNode.iConstruction.iFLane0R.Add(GVC(tempIVect, tIntHeight)); + f0RAdded = true; + } + xNode.iConstruction.iFLane1L.Add(GVC(tempIVect, tIntHeight)); + f1LAdded = true; + } + else + { + if (f0LAdded) + { + xNode.iConstruction.iFLane0L.RemoveAt(xNode.iConstruction.iFLane0L.Count - 1); + f0LAdded = false; + } + } + } + //} + xNode.iConstruction.f0RAttempt = tempIVect; + xNode.iConstruction.f1LAttempt = tempIVect; + + //Line 2: + //if(f1LAdded){ + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tempIVect = lVect; + if (!xNode.iConstruction.bFLane2Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) + { + if (f1LAdded) + { + xNode.iConstruction.iFLane1R.Add(GVC(tempIVect, tIntHeight)); + f1RAdded = true; + } + } + else + { + if (f1LAdded && xNode.iConstruction.iFLane1L.Count > 1) + { + xNode.iConstruction.iFLane1L.RemoveAt(xNode.iConstruction.iFLane1L.Count - 1); + f1LAdded = false; + } + } + } + else + { + tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0f, (LaneWidth * 0.5f) * POS.normalized.x)); + tempIVect_prev = tempIVect; + if (!xNode.iConstruction.bFLane2Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(tempIVect, rVect)) + { + if (f1LAdded) + { + xNode.iConstruction.iFLane1R.Add(GVC(tempIVect, tIntHeight)); + f1RAdded = true; + } + xNode.iConstruction.iFLane2L.Add(GVC(tempIVect, tIntHeight)); + f2LAdded = true; + } + else + { + if (f1LAdded) + { xNode.iConstruction.iFLane1L.RemoveAt(xNode.iConstruction.iFLane1L.Count - 1); f1LAdded = false; f1RAdded = false; } + } + } + //} + xNode.iConstruction.f1RAttempt = tempIVect; + xNode.iConstruction.f2LAttempt = tempIVect; + + //Line 3 / 4: + //if(f2LAdded){ + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.x)); + if (!xNode.iConstruction.bFLane3Done && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(lVect, tempIVect)) + { + + xNode.iConstruction.iFLane3L.Add(GVC(tempIVect, tIntHeight)); + f3LAdded = true; + xNode.iConstruction.iFLane3R.Add(GVC(lVect, tIntHeight)); + f3RAdded = true; + // if(bIsNextInter && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay){ + if (f2LAdded) + { + xNode.iConstruction.iFLane2R.Add(GVC(tempIVect, tIntHeight)); + f2RAdded = true; + } + // } + } + else + { + if (f2LAdded) + { + xNode.iConstruction.iFLane2L.RemoveAt(xNode.iConstruction.iFLane2L.Count - 1); + f2LAdded = false; + } + } + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.x)); + if (f2LAdded && !GSDRI.Contains(ref tempIVect) && !GSDRI.ContainsLine(rVect, tempIVect)) + { + xNode.iConstruction.iFLane2R.Add(GVC(tempIVect, tIntHeight)); + f2RAdded = true; + } + else if (f2LAdded) + { + xNode.iConstruction.iFLane2L.RemoveAt(xNode.iConstruction.iFLane2L.Count - 1); + f2LAdded = false; + } + } + + // } + xNode.iConstruction.f2RAttempt = tempIVect; + xNode.iConstruction.f3LAttempt = tempIVect; + xNode.iConstruction.f3RAttempt = lVect; + + if (!bIsNextInter && !xNode.iConstruction.bFDone) + { + // xNode.iConstruction.bFDone = true; + xNode.iConstruction.bFLane0Done = true; + xNode.iConstruction.bFLane1Done = true; + xNode.iConstruction.bFLane2Done = true; + xNode.iConstruction.bFLane3Done = true; + + POS_Next = default(Vector3); + tVect_Next = default(Vector3); + + tParam1 = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); + tSpline.GetSplineValue_Both(tParam1, out tVect_Next, out POS_Next); + rVect_Next = (tVect_Next + new Vector3(RoadSeperation * POS_Next.normalized.z, 0, RoadSeperation * -POS_Next.normalized.x)); + lVect_Next = (tVect_Next + new Vector3(RoadSeperation * -POS_Next.normalized.z, 0, RoadSeperation * POS_Next.normalized.x)); + + xNode.iConstruction.iFLane0L.Add(GVC(rVect_Next, tIntHeight)); + xNode.iConstruction.iFLane0R.Add(GVC(tVect_Next, tIntHeight)); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); + if (tRoad.opt_Lanes == 2) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.475f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 4) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.488f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 6) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.492f) + lVect_Next, tIntHeight)); + } + + if (tRoad.opt_Lanes == 2) + { + xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.03f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 4) + { + xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.015f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 6) + { + xNode.iConstruction.iFLane3L.Add(GVC(((rVect_Next - lVect_Next) * 0.01f) + lVect_Next, tIntHeight)); + } + + xNode.iConstruction.iFLane3R.Add(GVC(lVect_Next, tIntHeight)); + // xNode.iConstruction.iFLane2L.Add(GVC(tVect_Next,tIntHeight)); + // xNode.iConstruction.iFLane2R.Add(GVC(lVect_Next,tIntHeight)); + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); + if (tRoad.opt_Lanes == 2) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.475f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 4) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.488f) + lVect_Next, tIntHeight)); + } + else if (tRoad.opt_Lanes == 6) + { + xNode.iConstruction.iFLane1R.Add(GVC(((rVect_Next - lVect_Next) * 0.492f) + lVect_Next, tIntHeight)); + } + xNode.iConstruction.iFLane2L.Add(GVC(tVect_Next, tIntHeight)); + xNode.iConstruction.iFLane2R.Add(GVC(lVect_Next, tIntHeight)); + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iFLane1L.Add(GVC(tVect_Next, tIntHeight)); + xNode.iConstruction.iFLane1R.Add(GVC(lVect_Next, tIntHeight)); + } + bShrinkRoadFNext = true; + // bShrinkRoadF = true; + } + + } + else + { + bLRtoRR = bFirstInterNode; + bLLtoLR = !bFirstInterNode; + //B: + //Line 0: + tempIVect = lVect; + bool bFirst123 = false; + if (xNode.iConstruction.iBLane0R.Count == 0) + { + xNode.iConstruction.iBLane0L.Add(lVect_Prev); + xNode.iConstruction.iBLane0R.Add(tVect_Prev); + bShrinkRoadB = true; + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iBLane1L.Add(tVect_Prev); + xNode.iConstruction.iBLane1R.Add((tVect_Prev + new Vector3((LaneWidth * 0.05f) * POS.normalized.z, 0, (LaneWidth * 0.05f) * -POS.normalized.x))); + xNode.iConstruction.iBLane3L.Add(((lVect_Prev - rVect_Prev) * 0.03f) + rVect_Prev); + xNode.iConstruction.iBLane3R.Add(rVect_Prev); + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iBLane1L.Add(tVect_Prev); + xNode.iConstruction.iBLane1R.Add((tVect_Prev + new Vector3((LaneWidth * 0.05f) * POS.normalized.z, 0, (LaneWidth * 0.05f) * -POS.normalized.x))); + xNode.iConstruction.iBLane2L.Add(xNode.iConstruction.iBLane1R[0]); + xNode.iConstruction.iBLane2R.Add(rVect_Prev); + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iBLane1L.Add(tVect_Prev); + xNode.iConstruction.iBLane1R.Add(rVect_Prev); + } + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; + xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane3R[0]; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; + xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane2R[0]; + } + else + { + xNode.iConstruction.ShoulderBL_Start = xNode.iConstruction.iBLane0L[0]; + xNode.iConstruction.ShoulderBR_Start = xNode.iConstruction.iBLane1R[0]; + } + + xNode.iConstruction.ShoulderBL_StartIndex = tRoad.RCS.ShoulderL_Vectors.Count - 2; + xNode.iConstruction.ShoulderBR_StartIndex = tRoad.RCS.ShoulderR_Vectors.Count - 2; + // bFirst123 = true; + // goto InterSkip; + } + + bLine = false; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x))); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x))); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + bLine = !GSDRI.ContainsLine(lVect, tVect); + } + if (!xNode.iConstruction.bBLane0Done && !GSDRI.Contains(ref tempIVect) && bLine) + { + xNode.iConstruction.iBLane0L.Add(GVC(tempIVect, tIntHeight)); + b0LAdded = true; + } + else if (!xNode.iConstruction.bBLane0Done_Final) + { + //Finalize lane 0: + InterFinalizeiBLane0(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode); + } + + //Line 1: + if (xNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (xNode.iConstruction.iBLane0L.Count == 2) + { + tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x)); + xNode.iConstruction.iBLane0R.Add(GVC(tempIVect, tIntHeight)); + b0RAdded = true; + } + } + tempIVect_Prev = tempIVect; + tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * -POS.normalized.z, 0, (LaneWidth * 0.5f) * POS.normalized.x)); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tempIVect = tVect; + } + bLine = false; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + bLine = !GSDRI.ContainsLine(tempIVect, (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0, (LaneWidth * 0.5f) * -POS.normalized.x))); + } + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + bLine = !GSDRI.ContainsLine(tempIVect, rVect); + } + else + { + bLine = !GSDRI.ContainsLine(tempIVect, rVect); + } + tempIVect_Prev = tempIVect; + if (b0LAdded && !xNode.iConstruction.bBLane1Done && !GSDRI.Contains(ref tempIVect) && bLine) + { + if (b0LAdded && (xNode.iConstruction.iBLane0L.Count != 2 || GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane)) + { + xNode.iConstruction.iBLane0R.Add(GVC(tempIVect, tIntHeight)); + b0RAdded = true; + } + xNode.iConstruction.iBLane1L.Add(GVC(tempIVect, tIntHeight)); + b1LAdded = true; + } + else if (!xNode.iConstruction.bBLane1Done_Final) + { + //Finalize lane 1: + InterFinalizeiBLane1(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b0LAdded, ref b1RAdded); + } + + //Line 2: + if (xNode.iConstruction.iBLane1R.Count == 0 && xNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.iBLane1R.Add(GVC(tVect, tIntHeight)); + b1RAdded = true; + xNode.iConstruction.iBLane2L.Add(GVC(tVect, tIntHeight)); + b2LAdded = true; + b2LAdded = true; + } + else + { + tempIVect = (tVect + new Vector3((LaneWidth * 0.5f) * POS.normalized.z, 0, (LaneWidth * 0.5f) * -POS.normalized.x)); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tempIVect = rVect; + } + if (b1LAdded) + { + bLine = !GSDRI.ContainsLine(tempIVect, tempIVect_Prev); + } + else + { + bLine = !GSDRI.ContainsLine(tempIVect, rVect); + } + if (!xNode.iConstruction.bBLane2Done && !GSDRI.Contains(ref tempIVect) && bLine) + { + if (b1LAdded) + { + xNode.iConstruction.iBLane1R.Add(GVC(tempIVect, tIntHeight)); + b1RAdded = true; + } + xNode.iConstruction.iBLane2L.Add(GVC(tempIVect, tIntHeight)); + b2LAdded = true; + } + else if (!xNode.iConstruction.bBLane2Done_Final) + { + InterFinalizeiBLane2(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); + } + } + + //Line 3 / 4: + tempIVect = (tVect + new Vector3(((LaneWidth * 0.5f) + RoadSeperation) * POS.normalized.z, 0, ((LaneWidth * 0.5f) + RoadSeperation) * -POS.normalized.x)); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tempIVect = rVect; + } + if (!xNode.iConstruction.bBLane3Done && !GSDRI.ContainsLine(rVect, tempIVect) && !GSDRI.ContainsLine(rVect, lVect)) + { + xNode.iConstruction.iBLane3L.Add(GVC(tempIVect, tIntHeight)); + b3LAdded = true; + xNode.iConstruction.iBLane3R.Add(GVC(rVect, tIntHeight)); + b3RAdded = true; + if (!bFirst123 && GSDRI.iType == GSDRoadIntersection.IntersectionTypeEnum.FourWay) + { + if (b2LAdded) + { + xNode.iConstruction.iBLane2R.Add(GVC(tempIVect, tIntHeight)); + b2RAdded = true; + } + } + } + else if (!xNode.iConstruction.bBLane3Done_Final) + { + InterFinalizeiBLane3(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); + } + + } + } + + // InterSkip: + + if (!bIsBridge) + { + BridgeUpComing = tRoad.GSDSpline.BridgeUpComing(i); + // if(TempY < 0.5f){ + // gHeight = tHeight0; + // }else if(TempY < 2f){ + // gHeight = tHeight2; + // }else{ + // if(bTempYWasNegative){ + // tY = new Vector3(0f,(TempY*0.035f),0f); + // } + // if(tY.y < tHeight1.y){ + // tY = tHeight1; + // } + // gHeight = tY; + // } + if (BridgeUpComing < 0.2f) + { + BridgeUpComing = 0.2f; + } + // gHeight.y = gHeight.y * BridgeUpComing; + + // if(tRoad.opt_MatchTerrain){ + gHeight.y = 0f; + // } + + lVect += gHeight; + rVect += gHeight; + ShoulderR_lVect += gHeight; + ShoulderL_rVect += gHeight; + ShoulderL_lVect += gHeight; + ShoulderR_rVect += gHeight; + tHeightAdded = gHeight.y; + } + + + if (tIntStrength >= 1f) + { + tVect.y -= tInterSubtract; + tLastInterHeight = tVect.y; + rVect.y -= tInterSubtract; + lVect.y -= tInterSubtract; + + ShoulderL_rVect.y = tIntHeight; + ShoulderR_lVect.y = tIntHeight; + ShoulderR_rVect.y = tIntHeight; + ShoulderL_lVect.y = tIntHeight; + + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_rVect.y); } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_lVect.y); } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_rVect.y); } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_lVect.y); } + } + else if (tIntStrength > 0f) + { + + rVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * rVect.y); + ShoulderR_lVect = rVect; + lVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * lVect.y); + ShoulderL_rVect = lVect; + ShoulderR_rVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * ShoulderR_rVect.y); + ShoulderL_lVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * ShoulderL_lVect.y); + + // if(!Mathf.Approximately(tIntStrength,0f)){ tVect.y = (tIntStrength*tIntHeight) + ((1-tIntStrength)*tVect.y); } + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*rVect.y); ShoulderR_lVect = rVect; } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*lVect.y); ShoulderL_rVect = lVect; } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderR_rVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderR_rVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderR_rVect.y); } + // + // tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref ShoulderL_lVect,ref tIntHeight, ref GSDRI,ref bIsPastInter,ref i, ref xNode); + // if(!Mathf.Approximately(tIntStrength_temp,0f)){ ShoulderL_lVect.y = (tIntStrength_temp*tIntHeight) + ((1-tIntStrength_temp)*ShoulderL_lVect.y); } + } + + //Ramp: + RampR_L = ShoulderR_rVect; + RampL_R = ShoulderL_lVect; + if (bIsBridge) + { + RampR_R = RampR_L; + RampL_L = RampL_R; + } + else + { + RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)) + gHeight; + SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); + RampR_R.y -= 0.35f; + + RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)) + gHeight; + SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); + RampL_L.y -= 0.35f; + } + + //Merge points to intersection corners if necessary: + if (bMaxIntersection && !bIsBridge && !bIsTunnel && bInterseOn) + { + mCornerDist = tRoad.opt_RoadDefinition * 1.35f; + mCornerDist *= mCornerDist; + + CornerRR = new Vector2(GSDRI.CornerRR.x, GSDRI.CornerRR.z); + CornerRL = new Vector2(GSDRI.CornerRL.x, GSDRI.CornerRL.z); + CornerLR = new Vector2(GSDRI.CornerLR.x, GSDRI.CornerLR.z); + CornerLL = new Vector2(GSDRI.CornerLL.x, GSDRI.CornerLL.z); + rVect2D = new Vector2(rVect.x, rVect.z); + lVect2D = new Vector2(lVect.x, lVect.z); + bOverrideRampR = false; + bOverrideRampL = false; + bImmuneR = false; + bImmuneL = false; + bMod1 = 1.75f; + bMod2 = 1.25f; + t2DDist = -1f; + + //Find equatable lane vect and move it too + // eCount = -1; + // eIndex = -1; + // uCount = -1; + // uIndex = -1; + + xHeight = new Vector3(0f, -0.1f, 0f); + bSpecAddedL = false; + bSpecAddedR = false; + + if (bFirstInterNode) + { + bSpecAddedL = (b0LAdded || f0LAdded); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + bSpecAddedR = (b1RAdded || f1LAdded); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + bSpecAddedR = (b2RAdded || f2LAdded); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + bSpecAddedR = (b3RAdded || f3LAdded); + } + } + + float tempRoadDef = Mathf.Clamp(tRoad.opt_LaneWidth, 3f, 5f); + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + + } + + //RR: + if (GSDRI.EvenAngle > 90f) + { + mCornerDist = tempRoadDef * bMod1; + } + else + { + mCornerDist = tempRoadDef * bMod2; + } + mCornerDist *= mCornerDist; + t2DDist = Vector2.SqrMagnitude(CornerRR - rVect2D); + if (t2DDist < mCornerDist) + { + bImmuneR = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerRR = true; + + if (bFirstInterNode) + { + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iBLane1R; + if (xNode.iConstruction.bBLane1Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iBLane2R; + if (xNode.iConstruction.bBLane2Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iBLane3R; + if (xNode.iConstruction.bBLane3Done_Final_ThisRound) + { + vList = null; + } + } + + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x, 0.01f) && IsApproximately(vList[m].z, GSDRI.CornerRR.z, 0.01f))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + else + { + //2nd node can only come through RR as front with R + vList = null; + vList = xNode.iConstruction.iFLane0L; + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x, 0.01f) && IsApproximately(vList[m].z, GSDRI.CornerRR.z, 0.01f))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderR_lVect = new Vector3(CornerRR.x, tIntHeight, CornerRR.y); + ShoulderR_rVect = new Vector3(GSDRI.CornerRR_Outer.x, tIntHeight, GSDRI.CornerRR_Outer.z); + RampR_Override = new Vector3(GSDRI.CornerRR_RampOuter.x, tIntHeight, GSDRI.CornerRR_RampOuter.z); + bRecordShoulderForNormals = true; + } + else + { + t2DDist = Vector2.SqrMagnitude(CornerRR - lVect2D); + if (t2DDist < mCornerDist) + { + bImmuneL = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerRR = true; + + //2nd node can come in via left + if (!bFirstInterNode) + { + vList = null; + vList = xNode.iConstruction.iBLane0L; + if (xNode.iConstruction.bBLane0Done_Final_ThisRound) + { + vList = null; + } + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRR.x) && IsApproximately(vList[m].z, GSDRI.CornerRR.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderL_rVect = new Vector3(CornerRR.x, tIntHeight, CornerRR.y); + ShoulderL_lVect = new Vector3(GSDRI.CornerRR_Outer.x, tIntHeight, GSDRI.CornerRR_Outer.z); + RampL_Override = new Vector3(GSDRI.CornerRR_RampOuter.x, tIntHeight, GSDRI.CornerRR_RampOuter.z); + bRecordShoulderLForNormals = true; + } + } + //RL: + if (GSDRI.OddAngle > 90f) + { + mCornerDist = tempRoadDef * bMod1; + } + else + { + mCornerDist = tempRoadDef * bMod2; + } + mCornerDist *= mCornerDist; + t2DDist = Vector2.SqrMagnitude(CornerRL - rVect2D); + if (t2DDist < mCornerDist) + { + bImmuneR = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerRL = true; + + if (bFirstInterNode) + { + vList = null; + vList = xNode.iConstruction.iFLane0L; + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + else + { + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iBLane1R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iBLane2R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iBLane3R; + } + + //Hitting RL from backside with second node: + if (!bFirstInterNode) + { + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) + { + eList.Add(m); + if (m == vList.Count - 1) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + b1RAdded = false; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + b2RAdded = false; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + b3RAdded = false; + } + } + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + } + eList = null; + } + + ShoulderR_lVect = new Vector3(CornerRL.x, tIntHeight, CornerRL.y); + ShoulderR_rVect = new Vector3(GSDRI.CornerRL_Outer.x, tIntHeight, GSDRI.CornerRL_Outer.z); + RampR_Override = new Vector3(GSDRI.CornerRL_RampOuter.x, tIntHeight, GSDRI.CornerRL_RampOuter.z); + bRecordShoulderForNormals = true; + } + else + { + t2DDist = Vector2.SqrMagnitude(CornerRL - lVect2D); + if (t2DDist < mCornerDist) + { + bImmuneL = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerRL = true; + + if (!bFirstInterNode) + { + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iFLane1R; + if (xNode.iConstruction.bFLane1Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iFLane2R; + if (xNode.iConstruction.bFLane2Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iFLane3R; + if (xNode.iConstruction.bFLane3Done_Final_ThisRound) + { + vList = null; + } + } + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerRL.x) && IsApproximately(vList[m].z, GSDRI.CornerRL.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderL_rVect = new Vector3(CornerRL.x, tIntHeight, CornerRL.y); + ShoulderL_lVect = new Vector3(GSDRI.CornerRL_Outer.x, tIntHeight, GSDRI.CornerRL_Outer.z); + RampL_Override = new Vector3(GSDRI.CornerRL_RampOuter.x, tIntHeight, GSDRI.CornerRL_RampOuter.z); + bRecordShoulderLForNormals = true; + } + } + //LR: + if (GSDRI.OddAngle > 90f) + { + mCornerDist = tempRoadDef * bMod1; + } + else + { + mCornerDist = tempRoadDef * bMod2; + } + mCornerDist *= mCornerDist; + t2DDist = Vector2.SqrMagnitude(CornerLR - rVect2D); + if (t2DDist < mCornerDist) + { + bImmuneR = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerLR = true; + + if (!bFirstInterNode) + { + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iBLane1R; + if (xNode.iConstruction.bBLane1Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iBLane2R; + if (xNode.iConstruction.bBLane2Done_Final_ThisRound) + { + vList = null; + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iBLane3R; + if (xNode.iConstruction.bBLane3Done_Final_ThisRound) + { + vList = null; + } + } + + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderR_lVect = new Vector3(CornerLR.x, tIntHeight, CornerLR.y); + ShoulderR_rVect = new Vector3(GSDRI.CornerLR_Outer.x, tIntHeight, GSDRI.CornerLR_Outer.z); + RampR_Override = new Vector3(GSDRI.CornerLR_RampOuter.x, tIntHeight, GSDRI.CornerLR_RampOuter.z); + bRecordShoulderForNormals = true; + } + else + { + t2DDist = Vector2.SqrMagnitude(CornerLR - lVect2D); + if (t2DDist < mCornerDist) + { + bImmuneL = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerLR = true; + + if (bFirstInterNode) + { + vList = null; + vList = xNode.iConstruction.iBLane0L; + if (xNode.iConstruction.bBLane0Done_Final_ThisRound) + { + vList = null; + } + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + else + { + //2nd node can only come through LR as front with L + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iFLane1R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iFLane2R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iFLane3R; + } + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLR.x) && IsApproximately(vList[m].z, GSDRI.CornerLR.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderL_rVect = new Vector3(CornerLR.x, tIntHeight, CornerLR.y); + ShoulderL_lVect = new Vector3(GSDRI.CornerLR_Outer.x, tIntHeight, GSDRI.CornerLR_Outer.z); + RampL_Override = new Vector3(GSDRI.CornerLR_RampOuter.x, tIntHeight, GSDRI.CornerLR_RampOuter.z); + bRecordShoulderLForNormals = true; + } + } + //LL: + if (GSDRI.EvenAngle > 90f) + { + mCornerDist = tempRoadDef * bMod1; + } + else + { + mCornerDist = tempRoadDef * bMod2; + } + mCornerDist *= mCornerDist; + t2DDist = Vector2.SqrMagnitude(CornerLL - rVect2D); + if (t2DDist < mCornerDist) + { + bImmuneR = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerLL = true; + + + if (!bFirstInterNode) + { + vList = null; + vList = xNode.iConstruction.iFLane0L; + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderR_lVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderR_lVect = new Vector3(CornerLL.x, tIntHeight, CornerLL.y); + ShoulderR_rVect = new Vector3(GSDRI.CornerLL_Outer.x, tIntHeight, GSDRI.CornerLL_Outer.z); + RampR_Override = new Vector3(GSDRI.CornerLL_RampOuter.x, tIntHeight, GSDRI.CornerLL_RampOuter.z); + bRecordShoulderForNormals = true; + } + else + { + t2DDist = Vector2.SqrMagnitude(CornerLL - lVect2D); + if (t2DDist < mCornerDist) + { + bImmuneL = true; + bInter_CurreIsCorner = true; + bInter_CurreIsCornerLL = true; + + if (bFirstInterNode) + { + vList = null; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + vList = xNode.iConstruction.iFLane1R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + vList = xNode.iConstruction.iFLane2R; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + vList = xNode.iConstruction.iFLane3R; + } + eList = new List(); + if (vList != null) + { + for (int m = 1; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + else + { + vList = null; + vList = xNode.iConstruction.iBLane0L; + if (xNode.iConstruction.bBLane0Done_Final_ThisRound) + { + vList = null; + } + eList = new List(); + if (vList != null) + { + for (int m = 0; m < vList.Count; m++) + { + if (Vector3.SqrMagnitude(vList[m] - ShoulderL_rVect) < 0.01f) + { + if (!(IsApproximately(vList[m].x, GSDRI.CornerLL.x) && IsApproximately(vList[m].z, GSDRI.CornerLL.z))) + { + eList.Add(m); + } + } + } + for (int m = (eList.Count - 1); m >= 0; m--) + { + vList.RemoveAt(eList[m]); + } + } + eList = null; + } + + ShoulderL_rVect = new Vector3(CornerLL.x, tIntHeight, CornerLL.y); + ShoulderL_lVect = new Vector3(GSDRI.CornerLL_Outer.x, tIntHeight, GSDRI.CornerLL_Outer.z); + RampL_Override = new Vector3(GSDRI.CornerLL_RampOuter.x, tIntHeight, GSDRI.CornerLL_RampOuter.z); + bRecordShoulderLForNormals = true; + } + } + + if (bImmuneR) + { + bOverrideRampR = true; + if (!tRoad.RCS.ImmuneVects.Contains(ShoulderR_lVect)) + { + tRoad.RCS.ImmuneVects.Add(ShoulderR_lVect); + } + if (!tRoad.RCS.ImmuneVects.Contains(ShoulderR_rVect)) + { + tRoad.RCS.ImmuneVects.Add(ShoulderR_rVect); + } + } + if (bImmuneL) + { + bOverrideRampL = true; + if (!tRoad.RCS.ImmuneVects.Contains(ShoulderL_rVect)) + { + tRoad.RCS.ImmuneVects.Add(ShoulderL_rVect); + } + if (!tRoad.RCS.ImmuneVects.Contains(ShoulderL_lVect)) + { + tRoad.RCS.ImmuneVects.Add(ShoulderL_lVect); + } + } + } + + if (bShrinkRoadB) + { + + if (lVect_Prev != new Vector3(0f, 0f, 0f)) + { + tRoad.RCS.RoadVectors.Add(lVect_Prev); + tRoad.RCS.RoadVectors.Add(lVect_Prev); + tRoad.RCS.RoadVectors.Add(lVect_Prev); + tRoad.RCS.RoadVectors.Add(lVect_Prev); + } + } + if (bShrinkRoadF) + { + if (lVect != new Vector3(0f, 0f, 0f)) + { + tRoad.RCS.RoadVectors.Add(lVect); + tRoad.RCS.RoadVectors.Add(lVect); + tRoad.RCS.RoadVectors.Add(lVect); + tRoad.RCS.RoadVectors.Add(lVect); + } + } + + tRoad.RCS.RoadVectors.Add(lVect); + tRoad.RCS.RoadVectors.Add(lVect); + tRoad.RCS.RoadVectors.Add(rVect); + tRoad.RCS.RoadVectors.Add(rVect); + + + + //Add bounds for later removal: + if (!bIsBridge && !bIsTunnel && bMaxIntersection && bWasPrevMaxInter && bInterseOn) + { + bool bGoAhead = true; + if (xNode.bIsEndPoint) + { + if (xNode.idOnSpline == 1) + { + if (i < xNode.tTime) + { + bGoAhead = false; + } + } + else + { + if (i > xNode.tTime) + { + bGoAhead = false; + } + } + } + + //Get this and prev lvect rvect rects: + if ((Vector3.SqrMagnitude(xNode.pos - tVect) < CullDistanceSQ) && bGoAhead) + { + GSD.Roads.GSDRoadUtil.Construction2DRect vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( + new Vector2(lVect.x, lVect.z), + new Vector2(rVect.x, rVect.z), + new Vector2(lVect_Prev.x, lVect_Prev.z), + new Vector2(rVect_Prev.x, rVect_Prev.z), + tLastInterHeight + ); + + tRoad.RCS.tIntersectionBounds.Add(vRect); + // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.position = lVect; + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22"; + // + // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.position = rVect; + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22"; + } + } + + //Ramp construction: + RampR_L = ShoulderR_rVect; + RampL_R = ShoulderL_lVect; + if (bIsBridge) + { + RampR_R = RampR_L; + RampL_L = RampL_R; + } + else + { + RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)) + gHeight; + if (bOverrideRampR) + { + RampR_R = RampR_Override; + } //Overrides will come from intersection. + SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); + RampR_R.y -= 0.35f; + + RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)) + gHeight; + if (bOverrideRampL) + { + RampL_L = RampL_Override; + } //Overrides will come from intersection. + SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); + RampL_L.y -= 0.35f; + bOverrideRampR = false; + bOverrideRampL = false; + } + + //If necessary during intersection construction, sometimes an addition will be created inbetween intersection corner points. + //This addition will create a dip between corner points to 100% ensure there is no shoulder visible on the roads between corner points. + bTriggerInterAddition = false; + if (bMaxIntersection && bInterseOn) + { + if (bFirstInterNode) + { + if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerLL) || (bInter_PrevWasCornerRR && bInter_CurreIsCornerRL)) + { + bTriggerInterAddition = true; + } + } + else + { + if (!GSDRI.bFlipped) + { + if ((bInter_PrevWasCornerLL && bInter_CurreIsCornerRL) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR) || (bInter_PrevWasCornerRR && bInter_CurreIsCornerLR)) + { + bTriggerInterAddition = true; + } + } + else + { + if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR) || (bInter_PrevWasCornerRL && bInter_CurreIsCornerLL)) + { + bTriggerInterAddition = true; + } + } + } + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + bTriggerInterAddition = false; + } + + //For 3-way intersections: + bSpecialThreeWayIgnoreR = false; + bSpecialThreeWayIgnoreL = false; + if (GSDRI.IgnoreSide > -1) + { + if (GSDRI.IgnoreSide == 0) + { + //RR to RL: + if (bFirstInterNode && (bInter_PrevWasCornerRR && bInter_CurreIsCornerRL)) + { + bTriggerInterAddition = false; + } + } + else if (GSDRI.IgnoreSide == 1) + { + //RL to LL: + if (!bFirstInterNode && ((bInter_PrevWasCornerRL && bInter_CurreIsCornerLL) || (bInter_PrevWasCornerLL && bInter_CurreIsCornerRL))) + { + //bTriggerInterAddition = false; + if (GSDRI.bFlipped) + { + bSpecialThreeWayIgnoreR = true; + } + else + { + bSpecialThreeWayIgnoreL = true; + } + } + } + else if (GSDRI.IgnoreSide == 2) + { + //LL to LR: + if (bFirstInterNode && (bInter_PrevWasCornerLR && bInter_CurreIsCornerLL)) + { + bTriggerInterAddition = false; + } + } + else if (GSDRI.IgnoreSide == 3) + { + //LR to RR: + if (!bFirstInterNode && ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR) || (bInter_PrevWasCornerLR && bInter_CurreIsCornerRR))) + { + //bTriggerInterAddition = false; + if (GSDRI.bFlipped) + { + bSpecialThreeWayIgnoreL = true; + } + else + { + bSpecialThreeWayIgnoreR = true; + } + } + } + } + + if (bTriggerInterAddition) + { + iTemp_HeightVect = new Vector3(0f, 0f, 0f); + rVect_iTemp = (((rVect_Prev - rVect) * 0.5f) + rVect) + iTemp_HeightVect; + lVect_iTemp = (((lVect_Prev - lVect) * 0.5f) + lVect) + iTemp_HeightVect; + ShoulderR_R_iTemp = (((ShoulderR_PrevRVect - ShoulderR_rVect) * 0.5f) + ShoulderR_rVect) + iTemp_HeightVect; + ShoulderL_L_iTemp = (((ShoulderL_PrevLVect - ShoulderL_lVect) * 0.5f) + ShoulderL_lVect) + iTemp_HeightVect; + RampR_R_iTemp = (((RampR_PrevR - RampR_R) * 0.5f) + RampR_R) + iTemp_HeightVect; + RampR_L_iTemp = (((RampR_PrevL - RampR_L) * 0.5f) + RampR_L) + iTemp_HeightVect; + RampL_R_iTemp = (((RampL_PrevR - RampL_R) * 0.5f) + RampL_R) + iTemp_HeightVect; + RampL_L_iTemp = (((RampL_PrevL - RampL_L) * 0.5f) + RampL_L) + iTemp_HeightVect; + + // ShoulderL_L_iTemp = lVect_iTemp; + // RampL_R_iTemp = lVect_iTemp; + // RampL_L_iTemp = lVect_iTemp; + // + // ShoulderR_R_iTemp = rVect_iTemp; + // RampR_R_iTemp = rVect_iTemp; + // RampR_L_iTemp = rVect_iTemp; + } + + if (bTriggerInterAddition && !(GSDRI.bFlipped && !bFirstInterNode)) + { + if (bFirstInterNode) + { + if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerRL && !bSpecialThreeWayIgnoreR)) + { + //Right shoulder: + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + //Ramps: + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + } + if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerLL && !bSpecialThreeWayIgnoreL)) + { + //Left shoulder: + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + //Ramp: + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + } + } + else + { + if ((bInter_PrevWasCornerLR && bInter_CurreIsCornerRR && !bSpecialThreeWayIgnoreR)) + { + //Right shoulder: + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + //Ramps: + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + } + if ((bInter_PrevWasCornerLL && bInter_CurreIsCornerRL && !bSpecialThreeWayIgnoreL)) + { + //Left shoulder: + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + //Ramp: + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + } + } + } + else if (bTriggerInterAddition && (GSDRI.bFlipped && !bFirstInterNode)) + { + if ((bInter_PrevWasCornerRR && bInter_CurreIsCornerLR && !bSpecialThreeWayIgnoreL)) + { + //Left shoulder: + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(lVect_iTemp); + //Ramp: + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R_iTemp); + } + if ((bInter_PrevWasCornerRL && bInter_CurreIsCornerLL && !bSpecialThreeWayIgnoreR)) + { + //Right shoulder: + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(rVect_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_R_iTemp); + //Ramps: + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R_iTemp); + } + } + } + + + + + //Right shoulder: + if (!bShoulderSkipR) + { + if (bRecordShoulderForNormals) + { + tRoad.RCS.normals_ShoulderR_averageStartIndexes.Add(tRoad.RCS.ShoulderR_Vectors.Count); + } + + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + + //Double up to prevent normal errors from intersection subtraction: + if (bImmuneR && bRecordShoulderForNormals) + { + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_lVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_L); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + } + } + + //Left shoulder: + if (!bShoulderSkipL) + { + if (bRecordShoulderLForNormals) + { + tRoad.RCS.normals_ShoulderL_averageStartIndexes.Add(tRoad.RCS.ShoulderL_Vectors.Count); + } + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); + + //Double up to prevent normal errors from intersection subtraction: + if (bImmuneL && bRecordShoulderForNormals) + { + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_rVect); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_R); + } + } + + //Previous storage: + tVect_Prev = tVect; + rVect_Prev = rVect; + lVect_Prev = lVect; + ShoulderR_PrevLVect = ShoulderR_lVect; + ShoulderL_PrevRVect = ShoulderL_rVect; + // ShoulderR_PrevRVect3 = ShoulderR_PrevRVect2; + // ShoulderL_PrevLVect3 = ShoulderL_PrevLVect2; + // ShoulderR_PrevRVect2 = ShoulderR_PrevRVect; + // ShoulderL_PrevLVect2 = ShoulderL_PrevLVect; + ShoulderR_PrevRVect = ShoulderR_rVect; + ShoulderL_PrevLVect = ShoulderL_lVect; + RampR_PrevR = RampR_R; + RampR_PrevL = RampR_L; + RampL_PrevR = RampL_R; + RampL_PrevL = RampL_L; + + //Store more prev variables: + bWasPrevMaxInter = bMaxIntersection; + bInter_PrevWasCorner = bInter_CurreIsCorner; + bInter_PrevWasCornerRR = bInter_CurreIsCornerRR; + bInter_PrevWasCornerRL = bInter_CurreIsCornerRL; + bInter_PrevWasCornerLL = bInter_CurreIsCornerLL; + bInter_PrevWasCornerLR = bInter_CurreIsCornerLR; + + // i+=Step;//Master step incrementer. + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_FinalizeInter"); + } + //Finalize intersection vectors: + if (bInterseOn) + { + RoadJob_Prelim_FinalizeInter(ref tRoad); + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("RoadJob_Prelim_RoadConnections"); + } + //Creates road connections if necessary: + // float ExtraHeight = 0f; + // float RampPercent = 0.2f; + if (tSpline.bSpecialEndNode_IsStart_Delay) + { + Vector3[] RoadConn_verts = new Vector3[4]; + + RampR_R = tRoad.RCS.ShoulderR_Vectors[7]; + ShoulderR_rVect = tRoad.RCS.ShoulderR_Vectors[3]; + rVect = tRoad.RCS.ShoulderR_Vectors[0]; + + tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R); + tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect); + tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect); + + RampL_L = tRoad.RCS.ShoulderL_Vectors[4]; + ShoulderL_lVect = tRoad.RCS.ShoulderL_Vectors[0]; + lVect = tRoad.RCS.ShoulderL_Vectors[3]; + + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L); + tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L); + tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect); + tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect); + + RoadConn_verts[0] = lVect; + RoadConn_verts[1] = rVect; + tSpline.GetSplineValue_Both(RoadConnection_StartMin1, out tVect, out POS); + RoadSeperation = tSpline.SpecialEndNodeDelay_Start_Result / 2f; + rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); + ShoulderSeperation = RoadSeperation + ShoulderWidth; + OuterShoulderWidthR = ShoulderSeperation; + OuterShoulderWidthL = ShoulderSeperation; + RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; + RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; + ShoulderR_rVect = (tVect + new Vector3(ShoulderSeperation * POS.normalized.z, 0, ShoulderSeperation * -POS.normalized.x)); + ShoulderL_lVect = (tVect + new Vector3(ShoulderSeperation * -POS.normalized.z, 0, ShoulderSeperation * POS.normalized.x)); + RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)); + SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); + RampR_R.y -= 0.45f; + RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)); + SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); + RampL_L.y -= 0.45f; + + + + tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, RampR_R + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, ShoulderR_rVect + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect + tHeight0); + tRoad.RCS.ShoulderR_Vectors.Insert(0, rVect + tHeight0); + + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, RampL_L + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, lVect + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); + tRoad.RCS.ShoulderL_Vectors.Insert(0, ShoulderL_lVect + tHeight0); + + RoadConn_verts[2] = lVect + tHeight0; + RoadConn_verts[3] = rVect + tHeight0; + //Tris: + int[] RoadConn_tris = new int[6]; + RoadConn_tris[0] = 2; + RoadConn_tris[1] = 0; + RoadConn_tris[2] = 3; + RoadConn_tris[3] = 0; + RoadConn_tris[4] = 1; + RoadConn_tris[5] = 3; + + Vector3[] RoadConn_normals = new Vector3[4]; + RoadConn_normals[0] = -Vector3.forward; + RoadConn_normals[1] = -Vector3.forward; + RoadConn_normals[2] = -Vector3.forward; + RoadConn_normals[3] = -Vector3.forward; + Vector2[] RoadConn_uv = new Vector2[4]; + float tMod1 = -1; + float tMod2 = -1; + + if (tRoad.opt_Lanes == 2) + { + tMod1 = 0.5f - (LaneWidth / tSpline.SpecialEndNodeDelay_Start_Result); + tMod2 = 0.5f + (LaneWidth / tSpline.SpecialEndNodeDelay_Start_Result); + } + else if (tRoad.opt_Lanes == 4) + { + tMod1 = 0.5f - ((LaneWidth * 2f) / tSpline.SpecialEndNodeDelay_Start_Result); + tMod2 = 0.5f + ((LaneWidth * 2f) / tSpline.SpecialEndNodeDelay_Start_Result); + } + RoadConn_uv[0] = new Vector2(tMod1, 0f); + RoadConn_uv[1] = new Vector2(tMod2, 0f); + RoadConn_uv[2] = new Vector2(0f, 1f); + RoadConn_uv[3] = new Vector2(1f, 1f); + + + tRoad.RCS.RoadConnections_verts.Add(RoadConn_verts); + tRoad.RCS.RoadConnections_tris.Add(RoadConn_tris); + tRoad.RCS.RoadConnections_normals.Add(RoadConn_normals); + tRoad.RCS.RoadConnections_uv.Add(RoadConn_uv); + } + else if (tSpline.bSpecialEndNode_IsEnd_Delay) + { + Vector3[] RoadConn_verts = new Vector3[4]; + int rrCount = tRoad.RCS.ShoulderR_Vectors.Count; + RampR_R = tRoad.RCS.ShoulderR_Vectors[rrCount - 1]; + ShoulderR_rVect = tRoad.RCS.ShoulderR_Vectors[rrCount - 3]; + rVect = tRoad.RCS.ShoulderR_Vectors[rrCount - 7]; + + //Right shoulder: + tRoad.RCS.ShoulderR_Vectors.Add(rVect); + tRoad.RCS.ShoulderR_Vectors.Add(rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + + rrCount = tRoad.RCS.ShoulderL_Vectors.Count; + RampL_L = tRoad.RCS.ShoulderL_Vectors[rrCount - 3]; + ShoulderL_lVect = tRoad.RCS.ShoulderL_Vectors[rrCount - 1]; + lVect = tRoad.RCS.ShoulderL_Vectors[rrCount - 5]; + + //Left shoulder: + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(lVect); + tRoad.RCS.ShoulderL_Vectors.Add(lVect); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + + RoadConn_verts[0] = lVect; + RoadConn_verts[1] = rVect; + tSpline.GetSplineValue_Both(RoadConnection_FinalMax1, out tVect, out POS); + RoadSeperation = tSpline.SpecialEndNodeDelay_End_Result / 2f; + rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); + ShoulderSeperation = RoadSeperation + ShoulderWidth; + OuterShoulderWidthR = ShoulderSeperation; + OuterShoulderWidthL = ShoulderSeperation; + RampOuterWidthR = (OuterShoulderWidthR / 4f) + OuterShoulderWidthR; + RampOuterWidthL = (OuterShoulderWidthL / 4f) + OuterShoulderWidthL; + ShoulderR_rVect = (tVect + new Vector3(ShoulderSeperation * POS.normalized.z, 0, ShoulderSeperation * -POS.normalized.x)); + ShoulderL_lVect = (tVect + new Vector3(ShoulderSeperation * -POS.normalized.z, 0, ShoulderSeperation * POS.normalized.x)); + RampR_R = (tVect + new Vector3(RampOuterWidthR * POS.normalized.z, 0, RampOuterWidthR * -POS.normalized.x)); + SetVectorHeight2(ref RampR_R, ref i, ref tSpline.HeightHistory, ref tSpline); + RampR_R.y -= 0.35f; + RampL_L = (tVect + new Vector3(RampOuterWidthL * -POS.normalized.z, 0, RampOuterWidthL * POS.normalized.x)); + SetVectorHeight2(ref RampL_L, ref i, ref tSpline.HeightHistory, ref tSpline); + RampL_L.y -= 0.35f; + + //Right shoulder: + tRoad.RCS.ShoulderR_Vectors.Add(rVect); + tRoad.RCS.ShoulderR_Vectors.Add(rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(ShoulderR_rVect); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + tRoad.RCS.ShoulderR_Vectors.Add(RampR_R); + + //Left shoulder: + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(lVect); + tRoad.RCS.ShoulderL_Vectors.Add(lVect); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(RampL_L); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + tRoad.RCS.ShoulderL_Vectors.Add(ShoulderL_lVect); + + RoadConn_verts[2] = lVect; + RoadConn_verts[3] = rVect; + //Tris: + int[] RoadConn_tris = new int[6]; + RoadConn_tris[0] = 0; + RoadConn_tris[1] = 2; + RoadConn_tris[2] = 1; + RoadConn_tris[3] = 2; + RoadConn_tris[4] = 3; + RoadConn_tris[5] = 1; + + Vector3[] RoadConn_normals = new Vector3[4]; + RoadConn_normals[0] = -Vector3.forward; + RoadConn_normals[1] = -Vector3.forward; + RoadConn_normals[2] = -Vector3.forward; + RoadConn_normals[3] = -Vector3.forward; + Vector2[] RoadConn_uv = new Vector2[4]; + float tMod = (RoadWidth / tSpline.SpecialEndNodeDelay_End_Result) / 2f; + RoadConn_uv[0] = new Vector2(tMod, 0f); + RoadConn_uv[1] = new Vector2(tMod * 3f, 0f); + RoadConn_uv[2] = new Vector2(0f, 1f); + RoadConn_uv[3] = new Vector2(1f, 1f); + tRoad.RCS.RoadConnections_verts.Add(RoadConn_verts); + tRoad.RCS.RoadConnections_tris.Add(RoadConn_tris); + tRoad.RCS.RoadConnections_normals.Add(RoadConn_normals); + tRoad.RCS.RoadConnections_uv.Add(RoadConn_uv); + } + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + } + + + #region "Road prelim helpers" + private static Vector3 GVC(Vector3 v1, float tHeight) + { + return new Vector3(v1.x, tHeight, v1.z); + } + + + /// + /// Usage: tDir = forward dir of player. tVect = direction from player to enemy + /// + /// + /// true if this instance is vect in front the specified tDir tVect; otherwise, false. + /// + /// + /// If set to true t dir. + /// + /// + /// If set to true t vect. + /// + private static bool IsVectInFront(Vector3 tDir, Vector3 tVect) + { + return (Vector3.Dot(tDir.normalized, tVect) > 0); + } + + + private static Vector2 ConvertVect3_To_Vect2(Vector3 tVect) + { + return new Vector2(tVect.x, tVect.z); + } + + + private static void InterFinalizeiBLane0(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode) + { + if (xNode.iConstruction.bBLane0Done_Final) + { + return; + } + + xNode.iConstruction.bBLane0Done = true; + if (GSDRI.bFlipped && !bFirstInterNode) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[4], tIntHeight)); + xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + } + else + { + xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + } + } + else + { + if (bLRtoRR) + { + xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerLR_CornerRR[0], tIntHeight)); + xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerLR_CornerRR[1], tIntHeight)); + } + else if (bLLtoLR) + { + xNode.iConstruction.iBLane0L.Add(GVC(GSDRI.fCornerLL_CornerLR[0], tIntHeight)); + xNode.iConstruction.iBLane0R.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + } + } + xNode.iConstruction.bBLane0Done_Final = true; + xNode.iConstruction.bBLane0Done_Final_ThisRound = true; + } + + + private static void InterFinalizeiBLane1(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b0LAdded, ref bool b1RAdded) + { + if (xNode.iConstruction.bBLane1Done_Final) + { + return; + } + + if (b0LAdded && !xNode.iConstruction.bBLane0Done_Final) + { + xNode.iConstruction.iBLane0L.RemoveAt(xNode.iConstruction.iBLane0L.Count - 1); + b0LAdded = false; + InterFinalizeiBLane0(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode); + } + xNode.iConstruction.bBLane1Done = true; + xNode.iConstruction.bBLane0Done = true; + + if (GSDRI.bFlipped && !bFirstInterNode) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[3], tIntHeight)); + xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + } + else + { + xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); //b1RAdded = true; + } + } + else + { + if (bLRtoRR) + { + xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerLR_CornerRR[1], tIntHeight)); + xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerLR_CornerRR[2], tIntHeight)); //b1RAdded = true; + } + else if (bLLtoLR) + { + xNode.iConstruction.iBLane1L.Add(GVC(GSDRI.fCornerLL_CornerLR[1], tIntHeight)); + xNode.iConstruction.iBLane1R.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); //b1RAdded = true; + } + } + xNode.iConstruction.bBLane1Done_Final = true; + xNode.iConstruction.bBLane1Done_Final_ThisRound = true; + + if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + xNode.iConstruction.bBackRRpassed = true; + } + } + + + private static void InterFinalizeiBLane2(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b2LAdded, ref bool b1LAdded, ref bool b0LAdded, ref bool b1RAdded) + { + if (xNode.iConstruction.bBLane2Done_Final) + { + return; + } + + if (b1LAdded && !xNode.iConstruction.bBLane1Done_Final) + { + xNode.iConstruction.iBLane1L.RemoveAt(xNode.iConstruction.iBLane1L.Count - 1); + b1LAdded = false; + InterFinalizeiBLane1(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b0LAdded, ref b1RAdded); + } + xNode.iConstruction.bBLane1Done = true; + xNode.iConstruction.bBLane2Done = true; + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes || GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + if (GSDRI.bFlipped && !bFirstInterNode) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[2], tIntHeight)); + xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); + } + } + else + { + if (bLRtoRR) + { + xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerLR_CornerRR[2], tIntHeight)); + xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerLR_CornerRR[3], tIntHeight)); + } + else if (bLLtoLR) + { + xNode.iConstruction.iBLane2L.Add(GVC(GSDRI.fCornerLL_CornerLR[2], tIntHeight)); + xNode.iConstruction.iBLane2R.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); + } + } + } + xNode.iConstruction.bBLane2Done_Final = true; + xNode.iConstruction.bBLane2Done_Final_ThisRound = true; + + if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + xNode.iConstruction.bBackRRpassed = true; + } + } + + + private static void InterFinalizeiBLane3(ref GSDSplineN xNode, ref GSDRoadIntersection GSDRI, ref float tIntHeight, bool bLRtoRR, bool bLLtoLR, bool bFirstInterNode, ref bool b2LAdded, ref bool b1LAdded, ref bool b0LAdded, ref bool b1RAdded) + { + if (b2LAdded && !xNode.iConstruction.bBLane2Done_Final) + { + xNode.iConstruction.iBLane2L.RemoveAt(xNode.iConstruction.iBLane2L.Count - 1); + b2LAdded = false; + InterFinalizeiBLane2(ref xNode, ref GSDRI, ref tIntHeight, bLRtoRR, bLLtoLR, bFirstInterNode, ref b2LAdded, ref b1LAdded, ref b0LAdded, ref b1RAdded); + } + xNode.iConstruction.bBLane2Done = true; + xNode.iConstruction.bBLane3Done = true; + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (GSDRI.bFlipped && !bFirstInterNode) + { + xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerRL_CornerRR[1], tIntHeight)); + xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerRL_CornerRR[0], tIntHeight)); + } + else + { + if (bLRtoRR) + { + xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerLR_CornerRR[3], tIntHeight)); + xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerLR_CornerRR[4], tIntHeight)); + } + else if (bLLtoLR) + { + xNode.iConstruction.iBLane3L.Add(GVC(GSDRI.fCornerLL_CornerLR[3], tIntHeight)); + xNode.iConstruction.iBLane3R.Add(GVC(GSDRI.fCornerLL_CornerLR[4], tIntHeight)); + } + } + } + xNode.iConstruction.bBLane3Done_Final = true; + xNode.iConstruction.bBLane3Done_Final_ThisRound = true; + + if (bFirstInterNode && GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + xNode.iConstruction.bBackRRpassed = true; + } + } + #endregion + + #endregion + + + #region "Intersection Prelim" + private static void RoadJob_Prelim_Inter(ref GSDRoad tRoad) + { + GSDSplineC tSpline = tRoad.GSDSpline; + float RoadWidth = tRoad.RoadWidth(); + float ShoulderWidth = tRoad.opt_ShoulderWidth; + float RoadSeperation = RoadWidth / 2f; + float RoadSeperation_NoTurn = RoadWidth / 2f; + float ShoulderSeperation = RoadSeperation + ShoulderWidth; + if (ShoulderSeperation < 0f) + { } + float LaneWidth = tRoad.opt_LaneWidth; + float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); + float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); + Vector3 POS = default(Vector3); + bool bIsPastInter = false; + bool bOldMethod = false; + //bool bCancel = false; if (bTempCancel) { } + bool bTempCancel = false; + if (bTempCancel) + { } + + //If left collides with left, etc + + //This will speed up later calculations for intersection 4 corner construction: + int mCount = tSpline.GetNodeCount(); + float PreInter_RoadWidthMod = 4.5f; + if (!bOldMethod) + { + PreInter_RoadWidthMod = 5.5f; + } + float preInterDistance = (tSpline.RoadWidth * PreInter_RoadWidthMod) / tSpline.distance; + GSDSplineN iNode = null; + for (int j = 0; j < mCount; j++) + { + bTempCancel = false; + if (tSpline.mNodes[j].bIsIntersection) + { + iNode = tSpline.mNodes[j]; + //First node set min / max float: + if (iNode.iConstruction == null) + { iNode.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); } + if (!iNode.iConstruction.tempconstruction_HasProcessed_Inter1) + { + preInterDistance = (iNode.GSDSpline.RoadWidth * PreInter_RoadWidthMod) / iNode.GSDSpline.distance; + iNode.iConstruction.tempconstruction_InterStart = iNode.tTime - preInterDistance; + iNode.iConstruction.tempconstruction_InterEnd = iNode.tTime + preInterDistance; + if (iNode.iConstruction.tempconstruction_InterStart > 1f) + { iNode.iConstruction.tempconstruction_InterStart = 1f; } + if (iNode.iConstruction.tempconstruction_InterStart < 0f) + { iNode.iConstruction.tempconstruction_InterStart = 0f; } + if (iNode.iConstruction.tempconstruction_InterEnd > 1f) + { iNode.iConstruction.tempconstruction_InterEnd = 1f; } + if (iNode.iConstruction.tempconstruction_InterEnd < 0f) + { iNode.iConstruction.tempconstruction_InterEnd = 0f; } + iNode.iConstruction.tempconstruction_HasProcessed_Inter1 = true; + } + + if (string.Compare(iNode.UID, iNode.GSDRI.Node1.UID) == 0) + { + iNode = iNode.GSDRI.Node2; + } + else + { + iNode = iNode.GSDRI.Node1; + } + + //Grab other intersection node and set min / max float + try + { + if (!iNode.iConstruction.tempconstruction_HasProcessed_Inter1) + { + preInterDistance = (iNode.GSDSpline.RoadWidth * PreInter_RoadWidthMod) / iNode.GSDSpline.distance; + iNode.iConstruction.tempconstruction_InterStart = iNode.tTime - preInterDistance; + iNode.iConstruction.tempconstruction_InterEnd = iNode.tTime + preInterDistance; + if (iNode.iConstruction.tempconstruction_InterStart > 1f) + { iNode.iConstruction.tempconstruction_InterStart = 1f; } + if (iNode.iConstruction.tempconstruction_InterStart < 0f) + { iNode.iConstruction.tempconstruction_InterStart = 0f; } + if (iNode.iConstruction.tempconstruction_InterEnd > 1f) + { iNode.iConstruction.tempconstruction_InterEnd = 1f; } + if (iNode.iConstruction.tempconstruction_InterEnd < 0f) + { iNode.iConstruction.tempconstruction_InterEnd = 0f; } + iNode.iConstruction.tempconstruction_HasProcessed_Inter1 = true; + } + } + catch + { + //Do nothing + } + } + } + + //Now get the four points per intersection: + GSDSplineN oNode1 = null; + GSDSplineN oNode2 = null; + float PreInterPrecision1 = -1f; + float PreInterPrecision2 = -1f; + Vector3 PreInterVect = default(Vector3); + Vector3 PreInterVectR = default(Vector3); + Vector3 PreInterVectR_RightTurn = default(Vector3); + Vector3 PreInterVectL = default(Vector3); + Vector3 PreInterVectL_RightTurn = default(Vector3); + GSDRoadIntersection GSDRI = null; + + for (int j = 0; j < mCount; j++) + { + oNode1 = tSpline.mNodes[j]; + if (oNode1.bIsIntersection) + { + oNode1 = oNode1.GSDRI.Node1; + oNode2 = oNode1.GSDRI.Node2; + if (bOldMethod) + { + PreInterPrecision1 = 0.1f / oNode1.GSDSpline.distance; + PreInterPrecision2 = 0.1f / oNode2.GSDSpline.distance; + } + else + { + PreInterPrecision1 = 4f / oNode1.GSDSpline.distance; + PreInterPrecision2 = 4f / oNode2.GSDSpline.distance; + } + GSDRI = oNode1.GSDRI; + try + { + if (oNode1.iConstruction.tempconstruction_HasProcessed_Inter2 && oNode2.iConstruction.tempconstruction_HasProcessed_Inter2) + { + continue; + } + } + catch + { + continue; + } + GSDRI = oNode1.GSDRI; + GSDRI.CornerRR1 = false; + GSDRI.CornerRR2 = false; + GSDRI.CornerRL1 = false; + GSDRI.CornerRL2 = false; + GSDRI.CornerLR1 = false; + GSDRI.CornerLR2 = false; + GSDRI.CornerLL1 = false; + GSDRI.CornerLL2 = false; + + if (!oNode1.iConstruction.tempconstruction_HasProcessed_Inter2) + { + oNode1.iConstruction.tempconstruction_R = new List(); + oNode1.iConstruction.tempconstruction_L = new List(); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + oNode1.iConstruction.tempconstruction_R_RightTurn = new List(); + oNode1.iConstruction.tempconstruction_L_RightTurn = new List(); + } + + for (float i = oNode1.iConstruction.tempconstruction_InterStart; i < oNode1.iConstruction.tempconstruction_InterEnd; i += PreInterPrecision1) + { + oNode1.GSDSpline.GetSplineValue_Both(i, out PreInterVect, out POS); + + bIsPastInter = oNode1.GSDSpline.IntersectionIsPast(ref i, ref oNode1); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bIsPastInter) + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + } + else + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + else + { + PreInterVectR = (PreInterVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); + } + + oNode1.iConstruction.tempconstruction_R.Add(new Vector2(PreInterVectR.x, PreInterVectR.z)); + oNode1.iConstruction.tempconstruction_L.Add(new Vector2(PreInterVectL.x, PreInterVectL.z)); + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + PreInterVectR_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + oNode1.iConstruction.tempconstruction_R_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectR_RightTurn)); + + PreInterVectL_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + oNode1.iConstruction.tempconstruction_L_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectL_RightTurn)); + } + } + } + + //Process second node: + if (oNode2.iConstruction == null) + { oNode2.iConstruction = new GSD.Roads.GSDIntersections.iConstructionMaker(); } + if (!oNode2.iConstruction.tempconstruction_HasProcessed_Inter2) + { + oNode2.iConstruction.tempconstruction_R = new List(); + oNode2.iConstruction.tempconstruction_L = new List(); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + oNode2.iConstruction.tempconstruction_R_RightTurn = new List(); + oNode2.iConstruction.tempconstruction_L_RightTurn = new List(); + } + + for (float i = oNode2.iConstruction.tempconstruction_InterStart; i < oNode2.iConstruction.tempconstruction_InterEnd; i += PreInterPrecision2) + { + oNode2.GSDSpline.GetSplineValue_Both(i, out PreInterVect, out POS); + + bIsPastInter = oNode2.GSDSpline.IntersectionIsPast(ref i, ref oNode2); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bIsPastInter) + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + } + else + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + PreInterVectR = (PreInterVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + else + { + PreInterVectR = (PreInterVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); + PreInterVectL = (PreInterVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); + } + + oNode2.iConstruction.tempconstruction_R.Add(new Vector2(PreInterVectR.x, PreInterVectR.z)); + oNode2.iConstruction.tempconstruction_L.Add(new Vector2(PreInterVectL.x, PreInterVectL.z)); + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + PreInterVectR_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + oNode2.iConstruction.tempconstruction_R_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectR_RightTurn)); + + PreInterVectL_RightTurn = (PreInterVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + oNode2.iConstruction.tempconstruction_L_RightTurn.Add(ConvertVect3_To_Vect2(PreInterVectL_RightTurn)); + } + } + } + + + + bool bFlipped = false; + bool bFlippedSet = false; + int hCount1 = oNode1.iConstruction.tempconstruction_R.Count; + int hCount2 = oNode2.iConstruction.tempconstruction_R.Count; + int N1RCount = oNode1.iConstruction.tempconstruction_R.Count; + int N1LCount = oNode1.iConstruction.tempconstruction_L.Count; + int N2RCount = oNode2.iConstruction.tempconstruction_R.Count; + int N2LCount = oNode2.iConstruction.tempconstruction_L.Count; + + int[] tCounts = new int[4]; + tCounts[0] = N1RCount; + tCounts[1] = N1LCount; + tCounts[2] = N2RCount; + tCounts[3] = N2LCount; + + //RR: + int MaxCount = -1; + MaxCount = Mathf.Max(N2RCount, N2LCount); + for (int h = 0; h < hCount1; h++) + { + for (int k = 0; k < MaxCount; k++) + { + if (k < N2RCount) + { + if (Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]) < tRoad.opt_RoadDefinition) + { + bFlipped = false; + bFlippedSet = true; + break; + } + } + if (k < N2LCount) + { + if (Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]) < tRoad.opt_RoadDefinition) + { + bFlipped = true; + bFlippedSet = true; + break; + } + } + } + if (bFlippedSet) + { break; } + } + oNode1.GSDRI.bFlipped = bFlipped; + + + //Three-way intersections lane specifics: + GSDRI.bNode2B_LeftTurnLane = true; + GSDRI.bNode2B_RightTurnLane = true; + GSDRI.bNode2F_LeftTurnLane = true; + GSDRI.bNode2F_RightTurnLane = true; + + //Three-way intersections: + GSDRI.IgnoreSide = -1; + GSDRI.IgnoreCorner = -1; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.FourWay; + if (GSDRI.bFirstSpecial_First) + { + GSDRI.IgnoreSide = 3; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 0; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 1; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + else + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + + + } + else if (GSDRI.bFirstSpecial_Last) + { + GSDRI.IgnoreSide = 1; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 2; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 3; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + else + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + + } + if (!bFlipped) + { + if (GSDRI.bSecondSpecial_First) + { + GSDRI.IgnoreSide = 2; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 3; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 0; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + else + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + + } + else if (GSDRI.bSecondSpecial_Last) + { + GSDRI.IgnoreSide = 0; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 1; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 2; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + else + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + + } + } + else + { + if (GSDRI.bSecondSpecial_First) + { + GSDRI.IgnoreSide = 0; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 1; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 2; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + else + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + + } + else if (GSDRI.bSecondSpecial_Last) + { + GSDRI.IgnoreSide = 2; + GSDRI.iType = GSDRoadIntersection.IntersectionTypeEnum.ThreeWay; + if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.StopSign_AllWay) + { + GSDRI.IgnoreCorner = 3; + } + else if (GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight1 || GSDRI.iStopType == GSDRoadIntersection.iStopTypeEnum.TrafficLight2) + { + GSDRI.IgnoreCorner = 0; + } + + if (!oNode1.GSDRI.bFlipped) + { + GSDRI.bNode2B_LeftTurnLane = false; + GSDRI.bNode2F_RightTurnLane = false; + } + else + { + GSDRI.bNode2F_LeftTurnLane = false; + GSDRI.bNode2B_RightTurnLane = false; + } + } + } + + //Find corners: + Vector2 tFoundVectRR = default(Vector2); + Vector2 tFoundVectRL = default(Vector2); + Vector2 tFoundVectLR = default(Vector2); + Vector2 tFoundVectLL = default(Vector2); + if (!bOldMethod) + { + //RR: + if (!bFlipped) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R_RightTurn, ref oNode2.iConstruction.tempconstruction_R); + } + else + { + tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R); + } + } + else + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R_RightTurn, ref oNode2.iConstruction.tempconstruction_L); + } + else + { + tFoundVectRR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L); + } + } + + //RL: + if (!bFlipped) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L_RightTurn); + } + else + { + tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_L); + } + } + else + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R_RightTurn); + } + else + { + tFoundVectRL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_R, ref oNode2.iConstruction.tempconstruction_R); + } + } + + //LL: + if (!bFlipped) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L_RightTurn, ref oNode2.iConstruction.tempconstruction_L); + } + else + { + tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L); + } + } + else + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L_RightTurn, ref oNode2.iConstruction.tempconstruction_R); + } + else + { + tFoundVectLL = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R); + } + } + + //LR: + if (!bFlipped) + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R_RightTurn); + } + else + { + tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_R); + } + } + else + { + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L_RightTurn); + } + else + { + tFoundVectLR = IntersectionCornerCalc(ref oNode1.iConstruction.tempconstruction_L, ref oNode2.iConstruction.tempconstruction_L); + } + } + } + else + { + //Now two lists of R and L on each intersection node, now match: + float eDistanceRR = 5000f; + float oDistanceRR = 0f; + float eDistanceRL = 5000f; + float oDistanceRL = 0f; + float eDistanceLR = 5000f; + float oDistanceLR = 0f; + float eDistanceLL = 5000f; + float oDistanceLL = 0f; + bool bHasBeen1mRR = false; + bool bHasBeen1mRL = false; + bool bHasBeen1mLR = false; + bool bHasBeen1mLL = false; + bool bHasBeen1mRR_ignore = false; + bool bHasBeen1mRL_ignore = false; + bool bHasBeen1mLR_ignore = false; + bool bHasBeen1mLL_ignore = false; + bool bHasBeen1mRR_ignore_Max = false; + bool bHasBeen1mRL_ignore_Max = false; + bool bHasBeen1mLR_ignore_Max = false; + bool bHasBeen1mLL_ignore_Max = false; + float mMin = 0.2f; + float mMax = 0.5f; + + MaxCount = Mathf.Max(tCounts); + int MaxHCount = Mathf.Max(hCount1, hCount2); + for (int h = 0; h < MaxHCount; h++) + { + bHasBeen1mRR = false; + bHasBeen1mRL = false; + bHasBeen1mLR = false; + bHasBeen1mLL = false; + bHasBeen1mRR_ignore = false; + bHasBeen1mRL_ignore = false; + bHasBeen1mLR_ignore = false; + bHasBeen1mLL_ignore = false; + for (int k = 0; k < MaxCount; k++) + { + if (!bFlipped) + { + //RR: + if (!bHasBeen1mRR_ignore_Max && !bHasBeen1mRR_ignore && (h < N1RCount && k < N2RCount)) + { + oDistanceRR = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]); + if (oDistanceRR < eDistanceRR) + { + eDistanceRR = oDistanceRR; + tFoundVectRR = oNode1.iConstruction.tempconstruction_R[h]; //RR + if (eDistanceRR < 0.07f) + { bHasBeen1mRR_ignore_Max = true; } + } + if (oDistanceRR > mMax && bHasBeen1mRR) + { bHasBeen1mRR_ignore = true; } + if (oDistanceRR < mMin) + { bHasBeen1mRR = true; } + } + //RL: + if (!bHasBeen1mRL_ignore_Max && !bHasBeen1mRL_ignore && (h < N1RCount && k < N2LCount)) + { + oDistanceRL = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]); + if (oDistanceRL < eDistanceRL) + { + eDistanceRL = oDistanceRL; + tFoundVectRL = oNode1.iConstruction.tempconstruction_R[h]; //RL + if (eDistanceRL < 0.07f) + { bHasBeen1mRL_ignore_Max = true; } + } + if (oDistanceRL > mMax && bHasBeen1mRL) + { bHasBeen1mRL_ignore = true; } + if (oDistanceRL < mMin) + { bHasBeen1mRL = true; } + } + //LR: + if (!bHasBeen1mLR_ignore_Max && !bHasBeen1mLR_ignore && (h < N1LCount && k < N2RCount)) + { + oDistanceLR = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_R[k]); + if (oDistanceLR < eDistanceLR) + { + eDistanceLR = oDistanceLR; + tFoundVectLR = oNode1.iConstruction.tempconstruction_L[h]; //LR + if (eDistanceLR < 0.07f) + { bHasBeen1mLR_ignore_Max = true; } + } + if (oDistanceLR > mMax && bHasBeen1mLR) + { bHasBeen1mLR_ignore = true; } + if (oDistanceLR < mMin) + { bHasBeen1mLR = true; } + } + //LL: + if (!bHasBeen1mLL_ignore_Max && !bHasBeen1mLL_ignore && (h < N1LCount && k < N2LCount)) + { + oDistanceLL = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_L[k]); + if (oDistanceLL < eDistanceLL) + { + eDistanceLL = oDistanceLL; + tFoundVectLL = oNode1.iConstruction.tempconstruction_L[h]; //LL + if (eDistanceLL < 0.07f) + { bHasBeen1mLL_ignore_Max = true; } + } + if (oDistanceLL > mMax && bHasBeen1mLL) + { bHasBeen1mLL_ignore = true; } + if (oDistanceLL < mMin) + { bHasBeen1mLL = true; } + } + } + else + { + //RR: + if (!bHasBeen1mRR_ignore_Max && !bHasBeen1mRR_ignore && (h < N1RCount && k < N2LCount)) + { + oDistanceRR = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_L[k]); + if (oDistanceRR < eDistanceRR) + { + eDistanceRR = oDistanceRR; + tFoundVectRR = oNode1.iConstruction.tempconstruction_R[h]; //RR + if (eDistanceRR < 0.07f) + { bHasBeen1mRR_ignore_Max = true; } + } + if (oDistanceRR > mMax && bHasBeen1mRR) + { bHasBeen1mRR_ignore = true; } + if (oDistanceRR < mMin) + { bHasBeen1mRR = true; } + } + //RL: + if (!bHasBeen1mRL_ignore_Max && !bHasBeen1mRL_ignore && (h < N1RCount && k < N2RCount)) + { + oDistanceRL = Vector2.Distance(oNode1.iConstruction.tempconstruction_R[h], oNode2.iConstruction.tempconstruction_R[k]); + if (oDistanceRL < eDistanceRL) + { + eDistanceRL = oDistanceRL; + tFoundVectRL = oNode1.iConstruction.tempconstruction_R[h]; //RL + if (eDistanceRL < 0.07f) + { bHasBeen1mRL_ignore_Max = true; } + } + if (oDistanceRL > mMax && bHasBeen1mRL) + { bHasBeen1mRL_ignore = true; } + if (oDistanceRL < mMin) + { bHasBeen1mRL = true; } + } + //LR: + if (!bHasBeen1mLR_ignore_Max && !bHasBeen1mLR_ignore && (h < N1LCount && k < N2LCount)) + { + oDistanceLR = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_L[k]); + if (oDistanceLR < eDistanceLR) + { + eDistanceLR = oDistanceLR; + tFoundVectLR = oNode1.iConstruction.tempconstruction_L[h]; //LR + if (eDistanceLR < 0.07f) + { bHasBeen1mLR_ignore_Max = true; } + } + if (oDistanceLR > mMax && bHasBeen1mLR) + { bHasBeen1mLR_ignore = true; } + if (oDistanceLR < mMin) + { bHasBeen1mLR = true; } + } + //LL: + if (!bHasBeen1mLL_ignore_Max && !bHasBeen1mLL_ignore && (h < N1LCount && k < N2RCount)) + { + oDistanceLL = Vector2.Distance(oNode1.iConstruction.tempconstruction_L[h], oNode2.iConstruction.tempconstruction_R[k]); + if (oDistanceLL < eDistanceLL) + { + eDistanceLL = oDistanceLL; + tFoundVectLL = oNode1.iConstruction.tempconstruction_L[h]; //LL + if (eDistanceLL < 0.07f) + { bHasBeen1mLL_ignore_Max = true; } + } + if (oDistanceLL > mMax && bHasBeen1mLL) + { bHasBeen1mLL_ignore = true; } + if (oDistanceLL < mMin) + { bHasBeen1mLL = true; } + } + } + } + } + } + + oNode1.iConstruction.tempconstruction_HasProcessed_Inter2 = true; + oNode2.iConstruction.tempconstruction_HasProcessed_Inter2 = true; + + Vector3 tVectRR = new Vector3(tFoundVectRR.x, 0f, tFoundVectRR.y); + Vector3 tVectRL = new Vector3(tFoundVectRL.x, 0f, tFoundVectRL.y); + Vector3 tVectLR = new Vector3(tFoundVectLR.x, 0f, tFoundVectLR.y); + Vector3 tVectLL = new Vector3(tFoundVectLL.x, 0f, tFoundVectLL.y); + + oNode1.GSDRI.CornerRR = tVectRR; + oNode1.GSDRI.CornerRL = tVectRL; + oNode1.GSDRI.CornerLR = tVectLR; + oNode1.GSDRI.CornerLL = tVectLL; + + float[] tMaxFloats = new float[4]; + tMaxFloats[0] = Vector3.Distance(((tVectRR - tVectRL) * 0.5f) + tVectRL, oNode1.pos) * 1.25f; + tMaxFloats[1] = Vector3.Distance(((tVectRR - tVectLR) * 0.5f) + tVectLR, oNode1.pos) * 1.25f; + tMaxFloats[2] = Vector3.Distance(((tVectRL - tVectLL) * 0.5f) + tVectLL, oNode1.pos) * 1.25f; + tMaxFloats[3] = Vector3.Distance(((tVectLR - tVectLL) * 0.5f) + tVectLL, oNode1.pos) * 1.25f; + GSDRI.MaxInterDistance = Mathf.Max(tMaxFloats); + + float[] tMaxFloatsSQ = new float[4]; + tMaxFloatsSQ[0] = Vector3.SqrMagnitude((((tVectRR - tVectRL) * 0.5f) + tVectRL) - oNode1.pos) * 1.25f; + tMaxFloatsSQ[1] = Vector3.SqrMagnitude((((tVectRR - tVectLR) * 0.5f) + tVectLR) - oNode1.pos) * 1.25f; + tMaxFloatsSQ[2] = Vector3.SqrMagnitude((((tVectRL - tVectLL) * 0.5f) + tVectLL) - oNode1.pos) * 1.25f; + tMaxFloatsSQ[3] = Vector3.SqrMagnitude((((tVectLR - tVectLL) * 0.5f) + tVectLL) - oNode1.pos) * 1.25f; + GSDRI.MaxInterDistanceSQ = Mathf.Max(tMaxFloatsSQ); + + float TotalLanes = (int) (RoadWidth / LaneWidth); + float TotalLanesI = TotalLanes; + float LanesPerSide = TotalLanes / 2f; + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + TotalLanesI = TotalLanes + 2f; + //Lower left to lower right: + GSDRI.fCornerLR_CornerRR = new Vector3[5]; + GSDRI.fCornerLR_CornerRR[0] = tVectLR; + GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * (LanesPerSide / TotalLanesI)) + tVectLR; + GSDRI.fCornerLR_CornerRR[2] = ((tVectRR - tVectLR) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLR; + GSDRI.fCornerLR_CornerRR[3] = ((tVectRR - tVectLR) * ((LanesPerSide + 1 + LanesPerSide) / TotalLanesI)) + tVectLR; + GSDRI.fCornerLR_CornerRR[4] = tVectRR; + //Upper right to lower right: + GSDRI.fCornerRL_CornerRR = new Vector3[5]; + GSDRI.fCornerRL_CornerRR[0] = tVectRL; + GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * (1 / TotalLanesI)) + tVectRL; + GSDRI.fCornerRL_CornerRR[2] = ((tVectRR - tVectRL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectRL; + GSDRI.fCornerRL_CornerRR[3] = ((tVectRR - tVectRL) * ((LanesPerSide + 2) / TotalLanesI)) + tVectRL; + GSDRI.fCornerRL_CornerRR[4] = tVectRR; + //Upper left to upper right: + GSDRI.fCornerLL_CornerRL = new Vector3[5]; + GSDRI.fCornerLL_CornerRL[0] = tVectLL; + GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * (1 / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerRL[2] = ((tVectRL - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerRL[3] = ((tVectRL - tVectLL) * ((LanesPerSide + 2) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerRL[4] = tVectRL; + //Upper left to lower left: + GSDRI.fCornerLL_CornerLR = new Vector3[5]; + GSDRI.fCornerLL_CornerLR[0] = tVectLL; + GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerLR[2] = ((tVectLR - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerLR[3] = ((tVectLR - tVectLL) * ((LanesPerSide + 1 + LanesPerSide) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerLR[4] = tVectLR; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + TotalLanesI = TotalLanes + 1; + //Lower left to lower right: + GSDRI.fCornerLR_CornerRR = new Vector3[4]; + GSDRI.fCornerLR_CornerRR[0] = tVectLR; + GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * (LanesPerSide / TotalLanesI)) + tVectLR; + GSDRI.fCornerLR_CornerRR[2] = ((tVectRR - tVectLR) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLR; + GSDRI.fCornerLR_CornerRR[3] = tVectRR; + //Upper right to lower right: + GSDRI.fCornerRL_CornerRR = new Vector3[4]; + GSDRI.fCornerRL_CornerRR[0] = tVectRL; + GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * (LanesPerSide / TotalLanesI)) + tVectRL; + GSDRI.fCornerRL_CornerRR[2] = ((tVectRR - tVectRL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectRL; + GSDRI.fCornerRL_CornerRR[3] = tVectRR; + //Upper left to upper right: + GSDRI.fCornerLL_CornerRL = new Vector3[4]; + GSDRI.fCornerLL_CornerRL[0] = tVectLL; + GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerRL[2] = ((tVectRL - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerRL[3] = tVectRL; + //Upper left to lower left: + GSDRI.fCornerLL_CornerLR = new Vector3[4]; + GSDRI.fCornerLL_CornerLR[0] = tVectLL; + GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * (LanesPerSide / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerLR[2] = ((tVectLR - tVectLL) * ((LanesPerSide + 1) / TotalLanesI)) + tVectLL; + GSDRI.fCornerLL_CornerLR[3] = tVectLR; + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + TotalLanesI = TotalLanes + 0; + //Lower left to lower right: + GSDRI.fCornerLR_CornerRR = new Vector3[3]; + GSDRI.fCornerLR_CornerRR[0] = tVectLR; + GSDRI.fCornerLR_CornerRR[1] = ((tVectRR - tVectLR) * 0.5f) + tVectLR; + GSDRI.fCornerLR_CornerRR[2] = tVectRR; + //Upper right to lower right: + GSDRI.fCornerRL_CornerRR = new Vector3[3]; + GSDRI.fCornerRL_CornerRR[0] = tVectRL; + GSDRI.fCornerRL_CornerRR[1] = ((tVectRR - tVectRL) * 0.5f) + tVectRL; + GSDRI.fCornerRL_CornerRR[2] = tVectRR; + //Upper left to upper right: + GSDRI.fCornerLL_CornerRL = new Vector3[3]; + GSDRI.fCornerLL_CornerRL[0] = tVectLL; + GSDRI.fCornerLL_CornerRL[1] = ((tVectRL - tVectLL) * 0.5f) + tVectLL; + GSDRI.fCornerLL_CornerRL[2] = tVectRL; + //Upper left to lower left: + GSDRI.fCornerLL_CornerLR = new Vector3[3]; + GSDRI.fCornerLL_CornerLR[0] = tVectLL; + GSDRI.fCornerLL_CornerLR[1] = ((tVectLR - tVectLL) * 0.5f) + tVectLL; + GSDRI.fCornerLL_CornerLR[2] = tVectLR; + } + + //Use node1/node2 for angles instead + float tShoulderWidth = ShoulderWidth * 1.75f; + float tRampWidth = ShoulderWidth * 2f; + + oNode1.GSDRI.OddAngle = Vector3.Angle(GSDRI.Node2.tangent, GSDRI.Node1.tangent); + oNode1.GSDRI.EvenAngle = 180f - Vector3.Angle(GSDRI.Node2.tangent, GSDRI.Node1.tangent); + + GSD.Roads.GSDIntersectionObjects.GetFourPoints(GSDRI, out GSDRI.CornerRR_Outer, out GSDRI.CornerRL_Outer, out GSDRI.CornerLL_Outer, out GSDRI.CornerLR_Outer, tShoulderWidth); + GSD.Roads.GSDIntersectionObjects.GetFourPoints(GSDRI, out GSDRI.CornerRR_RampOuter, out GSDRI.CornerRL_RampOuter, out GSDRI.CornerLL_RampOuter, out GSDRI.CornerLR_RampOuter, tRampWidth); + + GSDRI.ConstructBoundsRect(); + GSDRI.CornerRR_2D = new Vector2(tVectRR.x, tVectRR.z); + GSDRI.CornerRL_2D = new Vector2(tVectRL.x, tVectRL.z); + GSDRI.CornerLL_2D = new Vector2(tVectLL.x, tVectLL.z); + GSDRI.CornerLR_2D = new Vector2(tVectLR.x, tVectLR.z); + + if (!oNode1.GSDRI.bSameSpline) + { + if (string.Compare(tRoad.GSDSpline.UID, oNode1.GSDSpline.tRoad.GSDSpline.UID) != 0) + { + AddIntersectionBounds(ref oNode1.GSDSpline.tRoad, ref tRoad.RCS); + } + else if (string.Compare(tRoad.GSDSpline.UID, oNode2.GSDSpline.tRoad.GSDSpline.UID) != 0) + { + AddIntersectionBounds(ref oNode2.GSDSpline.tRoad, ref tRoad.RCS); + } + } + } + } + } + + + private static Vector2 IntersectionCornerCalc(ref List PrimaryList, ref List SecondaryList) + { + int PrimaryCount = PrimaryList.Count; + int SecondaryCount = SecondaryList.Count; + Vector2 t2D_Line1Start = default(Vector2); + Vector2 t2D_Line1End = default(Vector2); + Vector2 t2D_Line2Start = default(Vector2); + Vector2 t2D_Line2End = default(Vector2); + bool bDidIntersect = false; + Vector2 tIntersectLocation = default(Vector2); + for (int i = 1; i < PrimaryCount; i++) + { + bDidIntersect = false; + t2D_Line1Start = PrimaryList[i - 1]; + t2D_Line1End = PrimaryList[i]; + for (int k = 1; k < SecondaryCount; k++) + { + bDidIntersect = false; + t2D_Line2Start = SecondaryList[k - 1]; + t2D_Line2End = SecondaryList[k]; + bDidIntersect = GSDRootUtil.Intersects2D(ref t2D_Line1Start, ref t2D_Line1End, ref t2D_Line2Start, ref t2D_Line2End, out tIntersectLocation); + if (bDidIntersect) + { + return tIntersectLocation; + } + } + } + return tIntersectLocation; + } + + + private static void AddIntersectionBounds(ref GSDRoad tRoad, ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + bool bIsBridge = false; + bool bBridgeInitial = false; + if (bBridgeInitial == false) + { } + bool bTempbridge = false; + bool bBridgeLast = false; + if (bBridgeLast == false) + { } + + bool bIsTunnel = false; + bool bTunnelInitial = false; + if (bTunnelInitial == false) + { } + bool bTempTunnel = false; + bool bTunnelLast = false; + if (bTunnelLast == false) + { } + + GSDRoadIntersection GSDRI = null; + bool bIsPastInter = false; + bool bMaxIntersection = false; + bool bWasPrevMaxInter = false; + Vector3 tVect = default(Vector3); + Vector3 POS = default(Vector3); + float tIntHeight = 0f; + float tIntStrength = 0f; + float tIntStrength_temp = 0f; + // float tIntDistCheck = 75f; + bool bFirstInterNode = false; + Vector3 tVect_Prev = default(Vector3); + if (tVect_Prev == default(Vector3)) + { } + Vector3 rVect_Prev = default(Vector3); + if (rVect_Prev == default(Vector3)) + { } + Vector3 lVect_Prev = default(Vector3); + if (lVect_Prev == default(Vector3)) + { } + Vector3 rVect = default(Vector3); + if (rVect == default(Vector3)) + { } + Vector3 lVect = default(Vector3); + if (lVect == default(Vector3)) + { } + Vector3 ShoulderR_rVect = default(Vector3); + if (ShoulderR_rVect == default(Vector3)) + { } + Vector3 ShoulderR_lVect = default(Vector3); + if (ShoulderR_lVect == default(Vector3)) + { } + Vector3 ShoulderL_rVect = default(Vector3); + if (ShoulderL_rVect == default(Vector3)) + { } + Vector3 ShoulderL_lVect = default(Vector3); + if (ShoulderL_lVect == default(Vector3)) + { } + + Vector3 RampR_R = default(Vector3); + Vector3 RampR_L = default(Vector3); + Vector3 RampL_R = default(Vector3); + Vector3 RampL_L = default(Vector3); + float ShoulderR_OuterAngle = 0f; + if (ShoulderR_OuterAngle < 0f) + { } + float ShoulderL_OuterAngle = 0f; + if (ShoulderL_OuterAngle < 0f) + { } + Vector3 ShoulderR_PrevLVect = default(Vector3); + if (ShoulderR_PrevLVect == default(Vector3)) + { } + Vector3 ShoulderL_PrevRVect = default(Vector3); + if (ShoulderL_PrevRVect == default(Vector3)) + { } + Vector3 ShoulderR_PrevRVect = default(Vector3); + if (ShoulderR_PrevRVect == default(Vector3)) + { } + Vector3 ShoulderL_PrevLVect = default(Vector3); + if (ShoulderL_PrevLVect == default(Vector3)) + { } + // Vector3 ShoulderR_PrevRVect2 = default(Vector3); + // Vector3 ShoulderL_PrevLVect2 = default(Vector3); + // Vector3 ShoulderR_PrevRVect3 = default(Vector3); + // Vector3 ShoulderL_PrevLVect3 = default(Vector3); + Vector3 RampR_PrevR = default(Vector3); + if (RampR_PrevR == default(Vector3)) + { } + Vector3 RampR_PrevL = default(Vector3); + if (RampR_PrevL == default(Vector3)) + { } + Vector3 RampL_PrevR = default(Vector3); + if (RampL_PrevR == default(Vector3)) + { } + Vector3 RampL_PrevL = default(Vector3); + if (RampL_PrevL == default(Vector3)) + { } + GSDSplineC tSpline = tRoad.GSDSpline; + //Road width: + float RoadWidth = tRoad.RoadWidth(); + float ShoulderWidth = tRoad.opt_ShoulderWidth; + float RoadSeperation = RoadWidth / 2f; + float RoadSeperation_NoTurn = RoadWidth / 2f; + float ShoulderSeperation = RoadSeperation + ShoulderWidth; + float LaneWidth = tRoad.opt_LaneWidth; + float RoadSep1Lane = (RoadSeperation + (LaneWidth * 0.5f)); + float RoadSep2Lane = (RoadSeperation + (LaneWidth * 1.5f)); + float ShoulderSep1Lane = (ShoulderSeperation + (LaneWidth * 0.5f)); + if (ShoulderSep1Lane < 0f) + { } + float ShoulderSep2Lane = (ShoulderSeperation + (LaneWidth * 1.5f)); + if (ShoulderSep2Lane < 0f) + { } + + // float tAngle = 0f; + // float OrigStep = 0.06f; + float Step = tRoad.opt_RoadDefinition / tSpline.distance; + + GSDSplineN xNode = null; + float tInterSubtract = 4f; + float tLastInterHeight = -4f; + + // GameObject xObj = null; + // xObj = GameObject.Find("temp22"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp22"); + // } + // xObj = GameObject.Find("temp23"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp23"); + // } + // xObj = GameObject.Find("temp22_RR"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp22_RR"); + // } + // xObj = GameObject.Find("temp22_RL"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp22_RL"); + // } + // xObj = GameObject.Find("temp22_LR"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp22_LR"); + // } + // xObj = GameObject.Find("temp22_LL"); + // while(xObj != null){ + // Object.DestroyImmediate(xObj); + // xObj = GameObject.Find("temp22_LL"); + // } + + bool bFinalEnd = false; + float i = 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; + } + + // int StartIndex = tSpline.GetClosestRoadDefIndex(StartMin,true,false); + // int EndIndex = tSpline.GetClosestRoadDefIndex(FinalMax,false,true); + // float cDist = 0f; + bool kSkip = true; + bool kSkipFinal = false; + int kCount = 0; + int kFinalCount = tSpline.RoadDefKeysArray.Length; + int spamcheckmax1 = 18000; + int spamcheck1 = 0; + + if (IsApproximately(StartMin, 0f, 0.0001f)) + { + kSkip = false; + } + if (IsApproximately(FinalMax, 1f, 0.0001f)) + { + kSkipFinal = true; + } + + while (!bFinalEnd && spamcheck1 < spamcheckmax1) + { + spamcheck1++; + + if (kSkip) + { + i = StartMin; + kSkip = false; + } + else + { + if (kCount >= kFinalCount) + { + i = FinalMax; + if (kSkipFinal) + { break; } + } + else + { + i = tSpline.TranslateInverseParamToFloat(tSpline.RoadDefKeysArray[kCount]); + kCount += 1; + } + } + + if (i > 1f) + { break; } + if (i < 0f) + { i = 0f; } + + if (IsApproximately(i, FinalMax, 0.00001f)) + { + bFinalEnd = true; + } + else if (i > FinalMax) + { + if (tSpline.bSpecialEndControlNode) + { + i = FinalMax; + bFinalEnd = true; + } + else + { + bFinalEnd = true; + break; + } + } + + tSpline.GetSplineValue_Both(i, out tVect, out POS); + bIsPastInter = false; + tIntStrength = tSpline.IntersectionStrength(ref tVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); + if (IsApproximately(tIntStrength, 1f, 0.001f) || tIntStrength > 1f) + { + bMaxIntersection = true; + } + else + { + bMaxIntersection = false; + } + + if (bMaxIntersection) + { + if (string.Compare(xNode.UID, GSDRI.Node1.UID) == 0) + { + bFirstInterNode = true; + } + else + { + bFirstInterNode = false; + } + + //Convoluted for initial trigger: + bBridgeInitial = false; + bBridgeLast = false; + bTempbridge = tSpline.IsInBridge(i); + if (!bIsBridge && bTempbridge) + { + bIsBridge = true; + bBridgeInitial = true; + } + else if (bIsBridge && !bTempbridge) + { + bIsBridge = false; + } + //Check if this is the last bridge run for this bridge: + if (bIsBridge) + { + bTempbridge = tSpline.IsInBridge(i + Step); + if (!bTempbridge) + { + bBridgeLast = true; + } + } + + + //Convoluted for initial trigger: + bTunnelInitial = false; + bTunnelLast = false; + bTempTunnel = tSpline.IsInTunnel(i); + if (!bIsTunnel && bTempTunnel) + { + bIsTunnel = true; + bTunnelInitial = true; + } + else if (bIsTunnel && !bTempTunnel) + { + bIsTunnel = false; + } + //Check if this is the last Tunnel run for this Tunnel: + if (bIsTunnel) + { + bTempTunnel = tSpline.IsInTunnel(i + Step); + if (!bTempTunnel) + { + bTunnelLast = true; + } + } + + if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + rVect = (tVect + new Vector3(RoadSeperation_NoTurn * POS.normalized.z, 0, RoadSeperation_NoTurn * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation_NoTurn * -POS.normalized.z, 0, RoadSeperation_NoTurn * POS.normalized.x)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + else if (GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bIsPastInter) + { + rVect = (tVect + new Vector3(RoadSep1Lane * POS.normalized.z, 0, RoadSep1Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep2Lane * -POS.normalized.z, 0, RoadSep2Lane * POS.normalized.x)); + ; + } + else + { + rVect = (tVect + new Vector3(RoadSep2Lane * POS.normalized.z, 0, RoadSep2Lane * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSep1Lane * -POS.normalized.z, 0, RoadSep1Lane * POS.normalized.x)); + } + } + else + { + rVect = (tVect + new Vector3(RoadSeperation * POS.normalized.z, 0, RoadSeperation * -POS.normalized.x)); + lVect = (tVect + new Vector3(RoadSeperation * -POS.normalized.z, 0, RoadSeperation * POS.normalized.x)); + } + + if (tIntStrength >= 1f) + { + tVect.y -= tInterSubtract; + tLastInterHeight = tVect.y; + rVect.y -= tInterSubtract; + lVect.y -= tInterSubtract; + } + else + { + if (!IsApproximately(tIntStrength, 0f, 0.001f)) + { tVect.y = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect.y); } + tIntStrength_temp = tRoad.GSDSpline.IntersectionStrength(ref rVect, ref tIntHeight, ref GSDRI, ref bIsPastInter, ref i, ref xNode); + if (!IsApproximately(tIntStrength_temp, 0f, 0.001f)) + { rVect.y = (tIntStrength_temp * tIntHeight) + ((1 - tIntStrength_temp) * rVect.y); ShoulderR_lVect = rVect; } + } + + //Add bounds for later removal: + GSD.Roads.GSDRoadUtil.Construction2DRect vRect = null; + if (!bIsBridge && !bIsTunnel && bMaxIntersection && bWasPrevMaxInter) + { + bool bGoAhead = true; + if (xNode.bIsEndPoint) + { + if (xNode.idOnSpline == 1) + { + if (i < xNode.tTime) + { + bGoAhead = false; + } + } + else + { + if (i > xNode.tTime) + { + bGoAhead = false; + } + } + } + //Get this and prev lvect rvect rects: + if (Vector3.Distance(xNode.pos, tVect) < (3f * RoadWidth) && bGoAhead) + { + if (GSDRI.bFlipped && !bFirstInterNode) + { + vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( + new Vector2(rVect.x, rVect.z), + new Vector2(lVect.x, lVect.z), + new Vector2(rVect_Prev.x, rVect_Prev.z), + new Vector2(lVect_Prev.x, lVect_Prev.z), + tLastInterHeight + ); + } + else + { + vRect = new GSD.Roads.GSDRoadUtil.Construction2DRect( + new Vector2(lVect.x, lVect.z), + new Vector2(rVect.x, rVect.z), + new Vector2(lVect_Prev.x, lVect_Prev.z), + new Vector2(rVect_Prev.x, rVect_Prev.z), + tLastInterHeight + ); + } + // GameObject tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.position = lVect; + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22"; + // + // tObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // tObj.transform.position = rVect; + // tObj.transform.localScale = new Vector3(0.2f,20f,0.2f); + // tObj.transform.name = "temp22"; + + RCS.tIntersectionBounds.Add(vRect); + } + } + } + + bWasPrevMaxInter = bMaxIntersection; + tVect_Prev = tVect; + rVect_Prev = rVect; + lVect_Prev = lVect; + ShoulderR_PrevLVect = ShoulderR_lVect; + ShoulderL_PrevRVect = ShoulderL_rVect; + // ShoulderR_PrevRVect3 = ShoulderR_PrevRVect2; + // ShoulderL_PrevLVect3 = ShoulderL_PrevLVect2; + // ShoulderR_PrevRVect2 = ShoulderR_PrevRVect; + // ShoulderL_PrevLVect2 = ShoulderL_PrevLVect; + ShoulderR_PrevRVect = ShoulderR_rVect; + ShoulderL_PrevLVect = ShoulderL_lVect; + RampR_PrevR = RampR_R; + RampR_PrevL = RampR_L; + RampL_PrevR = RampL_R; + RampL_PrevL = RampL_L; + // i+=Step; + } + } + #endregion + + + #region "Intersection Prelim Finalization" + private static void RoadJob_Prelim_FinalizeInter(ref GSDRoad tRoad) + { + int mCount = tRoad.GSDSpline.GetNodeCount(); + GSDSplineN tNode; + for (int index = 0; index < mCount; index++) + { + tNode = tRoad.GSDSpline.mNodes[index]; + if (tNode.bIsIntersection) + { + Inter_OrganizeVertices(ref tNode, ref tRoad); + tNode.iConstruction.Nullify(); + tNode.iConstruction = null; + } + } + } + + + private static bool Inter_OrganizeVerticesMatchEdges(ref List tList1, ref List tList2, bool bSkip1 = false, bool bSkipFirstListOne = false, bool bSkipBoth = false) + { + List PrimaryList; + List SecondaryList; + + List tList1New; + List tList2New; + + if (bSkip1) + { + if (bSkipBoth) + { + tList1New = new List(); + tList2New = new List(); + for (int index = 1; index < tList1.Count; index++) + { + tList1New.Add(tList1[index]); + } + for (int index = 1; index < tList2.Count; index++) + { + tList2New.Add(tList2[index]); + } + } + else + { + if (bSkipFirstListOne) + { + tList1New = new List(); + for (int index = 1; index < tList1.Count; index++) + { + tList1New.Add(tList1[index]); + } + tList2New = tList2; + } + else + { + tList2New = new List(); + for (int index = 1; index < tList2.Count; index++) + { + tList2New.Add(tList2[index]); + } + tList1New = tList1; + } + } + } + else + { + tList1New = tList1; + tList2New = tList2; + } + + int tList1Count = tList1New.Count; + int tList2Count = tList2New.Count; + if (tList1Count == tList2Count) + { + return false; + } + + if (tList1Count > tList2Count) + { + PrimaryList = tList1New; + SecondaryList = tList2New; + } + else + { + PrimaryList = tList2New; + SecondaryList = tList1New; + } + + if (SecondaryList == null || SecondaryList.Count == 0) + { + return true; + } + SecondaryList.Clear(); + SecondaryList = null; + SecondaryList = new List(); + for (int index = 0; index < PrimaryList.Count; index++) + { + SecondaryList.Add(PrimaryList[index]); + } + + + if (tList1Count > tList2Count) + { + tList2 = SecondaryList; + } + else + { + tList1 = SecondaryList; + } + + return false; + } + + + private static void Inter_OrganizeVerticesMatchShoulder(ref List tShoulderList, ref List tToMatch, int StartI, ref Vector3 StartVec, ref Vector3 EndVect, float tHeight, bool bIsF = false) + { + // return; + List BackupList = new List(); + for (int index = 0; index < tToMatch.Count; index++) + { + BackupList.Add(tToMatch[index]); + } + Vector2 t2D = default(Vector2); + Vector2 t2D_Start = ConvertVect3_To_Vect2(StartVec); + Vector2 t2D_End = ConvertVect3_To_Vect2(EndVect); + int RealStartID = -1; + StartI = StartI - 30; + if (StartI < 0) + { + StartI = 0; + } + for (int index = StartI; index < tShoulderList.Count; index++) + { + t2D = ConvertVect3_To_Vect2(tShoulderList[index]); + // if(t2D.x > 745f && t2D.x < 755f && t2D.y > 1240f && t2D.y < 1250f){ + // int agfsdajgsd = 1; + // } + if (t2D == t2D_Start) + { + //if(tShoulderList[i] == StartVec){ + RealStartID = index; + break; + } + } + + tToMatch.Clear(); + tToMatch = null; + tToMatch = new List(); + + int spamcounter = 0; + bool bBackup = false; + if (RealStartID == -1) + { + bBackup = true; + } + + if (!bBackup) + { + if (bIsF) + { + for (int index = RealStartID; index > 0; index -= 8) + { + t2D = ConvertVect3_To_Vect2(tShoulderList[index]); + tToMatch.Add(tShoulderList[index]); + if (t2D == t2D_End) + { + //if(tShoulderList[i] == EndVect){ + break; + } + spamcounter += 1; + if (spamcounter > 100) + { + bBackup = true; + break; + } + } + } + else + { + for (int index = RealStartID; index < tShoulderList.Count; index += 8) + { + t2D = ConvertVect3_To_Vect2(tShoulderList[index]); + tToMatch.Add(tShoulderList[index]); + if (t2D == t2D_End) + { + //if(tShoulderList[i] == EndVect){ + break; + } + spamcounter += 1; + if (spamcounter > 100) + { + bBackup = true; + break; + } + } + } + } + //// + // if(!bBackup){ + // for(int i=0;i(); + // for(int i=0;i 0); + if (biBLane0L == false) + { } + bool biBLane0R = (iCon.iBLane0R.Count > 0); + if (biBLane0R == false) + { } + bool biBMainPlateL = (iCon.iBMainPlateL.Count > 0); + if (biBMainPlateL == false) + { } + bool biBMainPlateR = (iCon.iBMainPlateR.Count > 0); + if (biBMainPlateR == false) + { } + bool biFLane0L = (iCon.iFLane0L.Count > 0); + if (biFLane0L == false) + { } + bool biFLane0R = (iCon.iFLane0R.Count > 0); + if (biFLane0R == false) + { } + bool biFMainPlateL = (iCon.iFMainPlateL.Count > 0); + if (biFMainPlateL == false) + { } + bool biFMainPlateR = (iCon.iFMainPlateR.Count > 0); + if (biFMainPlateR == false) + { } + bool biBLane2L = (iCon.iBLane2L.Count > 0); + if (biBLane2L == false) + { } + bool biBLane2R = (iCon.iBLane2R.Count > 0); + if (biBLane2R == false) + { } + bool biFLane2L = (iCon.iFLane2L.Count > 0); + if (biFLane2L == false) + { } + bool biFLane2R = (iCon.iFLane2R.Count > 0); + if (biFLane2R == false) + { } + bool biBLane3L = (iCon.iBLane3L.Count > 0); + if (biBLane3L == false) + { } + bool biBLane3R = (iCon.iBLane3R.Count > 0); + if (biBLane3R == false) + { } + bool biFLane3L = (iCon.iFLane3L.Count > 0); + if (biFLane3L == false) + { } + bool biFLane3R = (iCon.iFLane3R.Count > 0); + if (biFLane3R == false) + { } + + mCount = tRoad.RCS.RoadVectors.Count; + int cCount = tRoad.GSDSpline.GetNodeCount(); + int tStartI = 0; + int tEndI = mCount; + //Start and end the next loop after this one later for opt: + if (cCount > 2) + { + if (!tRoad.GSDSpline.mNodes[0].bIsIntersection && !tRoad.GSDSpline.mNodes[1].bIsIntersection) + { + for (int i = 2; i < cCount; i++) + { + if (tRoad.GSDSpline.mNodes[i].bIsIntersection) + { + if (i - 2 >= 1) + { + tStartI = (int) (tRoad.GSDSpline.mNodes[i - 2].tTime * mCount); + } + break; + } + } + } + } + if (cCount > 3) + { + if (!tRoad.GSDSpline.mNodes[cCount - 1].bIsIntersection && !tRoad.GSDSpline.mNodes[cCount - 2].bIsIntersection) + { + for (int i = (cCount - 3); i >= 0; i--) + { + if (tRoad.GSDSpline.mNodes[i].bIsIntersection) + { + if (i + 2 < cCount) + { + tEndI = (int) (tRoad.GSDSpline.mNodes[i + 2].tTime * mCount); + } + break; + } + } + } + } + + if (tStartI > 0) + { + if (tStartI % 2 != 0) + { + tStartI += 1; + } + } + if (tStartI > mCount) + { tStartI = mCount - 4; } + if (tStartI < 0) + { tStartI = 0; } + if (tEndI < mCount) + { + if (tEndI % 2 != 0) + { + tEndI += 1; + } + } + if (tEndI > mCount) + { tEndI = mCount - 4; } + if (tEndI < 0) + { tEndI = 0; } + + for (int i = tStartI; i < tEndI; i += 2) + { + tVect = tRoad.RCS.RoadVectors[i]; + for (int j = 0; j < 1; j++) + { + if (biBLane0L && Vector3.SqrMagnitude(tVect - iCon.iBLane0L[j]) < 0.01f && !bSkipB) + { + iCon.iBLane0L[j] = tVect; + } + if (biBMainPlateL && Vector3.SqrMagnitude(tVect - iCon.iBMainPlateL[j]) < 0.01f && !bSkipB) + { + iCon.iBMainPlateL[j] = tVect; + } + if (biBMainPlateR && Vector3.SqrMagnitude(tVect - iCon.iBMainPlateR[j]) < 0.01f && !bSkipB) + { + iCon.iBMainPlateR[j] = tVect; + } + if (biFLane0L && Vector3.SqrMagnitude(tVect - iCon.iFLane0L[j]) < 0.01f && !bSkipF) + { + iCon.iFLane0L[j] = tVect; + } + if (biFMainPlateL && Vector3.SqrMagnitude(tVect - iCon.iFMainPlateL[j]) < 0.01f && !bSkipF) + { + iCon.iFMainPlateL[j] = tVect; + } + if (biFMainPlateR && Vector3.SqrMagnitude(tVect - iCon.iFMainPlateR[j]) < 0.01f && !bSkipF) + { + iCon.iFMainPlateR[j] = tVect; + } + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (biBLane3L && Vector3.SqrMagnitude(tVect - iCon.iBLane3L[j]) < 0.01f && !bSkipB) + { + iCon.iBLane3L[j] = tVect; + } + if (biBLane3R && Vector3.SqrMagnitude(tVect - iCon.iBLane3R[j]) < 0.01f && !bSkipB) + { + iCon.iBLane3R[j] = tVect; + } + if (biFLane3L && Vector3.SqrMagnitude(tVect - iCon.iFLane3L[j]) < 0.01f && !bSkipF) + { + iCon.iFLane3L[j] = tVect; + } + if (biFLane3R && Vector3.SqrMagnitude(tVect - iCon.iFLane3R[j]) < 0.01f && !bSkipF) + { + iCon.iFLane3R[j] = tVect; + } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + if (biBLane2L && Vector3.SqrMagnitude(tVect - iCon.iBLane2L[j]) < 0.01f && !bSkipB) + { + iCon.iBLane2L[j] = tVect; + } + if (biBLane2R && Vector3.SqrMagnitude(tVect - iCon.iBLane2R[j]) < 0.01f && !bSkipB) + { + iCon.iBLane2R[j] = tVect; + } + if (biFLane2L && Vector3.SqrMagnitude(tVect - iCon.iFLane2L[j]) < 0.01f && !bSkipF) + { + iCon.iFLane2L[j] = tVect; + } + if (biFLane2R && Vector3.SqrMagnitude(tVect - iCon.iFLane2R[j]) < 0.01f && !bSkipF) + { + iCon.iFLane2R[j] = tVect; + } + } + } + } + + // float b0 = -1f; + // float f0 = -1f; + // + // if(!bSkipB){ b0 = iCon.iBMainPlateL[0].y; } + // if(!bSkipF){ f0 = iCon.iFMainPlateL[0].y; } + // + // if(iCon.iBLane0R == null || iCon.iBLane0R.Count == 0){ + // bSkipB = true; + // } + if (iCon.iBMainPlateR == null || iCon.iBMainPlateR.Count == 0) + { + bSkipB = true; + } + if (iCon.iBMainPlateL == null || iCon.iBMainPlateL.Count == 0) + { + bSkipB = true; + } + + if (!bSkipB) + { iCon.iBLane0R[0] = ((iCon.iBMainPlateR[0] - iCon.iBMainPlateL[0]) * 0.5f + iCon.iBMainPlateL[0]); } + if (!bSkipF) + { iCon.iFLane0R[0] = ((iCon.iFMainPlateR[0] - iCon.iFMainPlateL[0]) * 0.5f + iCon.iFMainPlateL[0]); } + + // if(tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane){ + if (!bSkipB) + { + iCon.iBLane1L[0] = iCon.iBLane0R[0]; + iCon.iBLane1R[0] = new Vector3(iCon.iBLane1R[0].x, iCon.iBLane1L[0].y, iCon.iBLane1R[0].z); + } + + if (!bSkipF) + { + iCon.iFLane1L[0] = iCon.iFLane0R[0]; + iCon.iFLane1R[0] = new Vector3(iCon.iFLane1R[0].x, iCon.iFLane1L[0].y, iCon.iFLane1R[0].z); + } + // } + + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (!bSkipB) + { iCon.iBLane3L[0] = new Vector3(iCon.iBLane3L[0].x, iCon.iBLane3R[0].y, iCon.iBLane3L[0].z); } + if (!bSkipF) + { iCon.iFLane3L[0] = new Vector3(iCon.iFLane3L[0].x, iCon.iFLane3R[0].y, iCon.iFLane3L[0].z); } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + if (!bSkipB) + { iCon.iBLane2L[0] = new Vector3(iCon.iBLane2L[0].x, iCon.iBLane2R[0].y, iCon.iBLane2L[0].z); } + if (!bSkipF) + { iCon.iFLane2L[0] = new Vector3(iCon.iFLane2L[0].x, iCon.iFLane2R[0].y, iCon.iFLane2L[0].z); } + } + + List iBLane0 = null; + List iBLane1 = null; + List iBLane2 = null; + List iBLane3 = null; + if (!bSkipB) + { + iBLane0 = InterVertices(iCon.iBLane0L, iCon.iBLane0R, tNode.GSDRI.Height); + iBLane1 = InterVertices(iCon.iBLane1L, iCon.iBLane1R, tNode.GSDRI.Height); + if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { iBLane2 = InterVertices(iCon.iBLane2L, iCon.iBLane2R, tNode.GSDRI.Height); } + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { iBLane3 = InterVertices(iCon.iBLane3L, iCon.iBLane3R, tNode.GSDRI.Height); } + } + + //Front lanes: + List iFLane0 = null; + List iFLane1 = null; + List iFLane2 = null; + List iFLane3 = null; + if (!bSkipF) + { + iFLane0 = InterVertices(iCon.iFLane0L, iCon.iFLane0R, tNode.GSDRI.Height); + iFLane1 = InterVertices(iCon.iFLane1L, iCon.iFLane1R, tNode.GSDRI.Height); + if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { iFLane2 = InterVertices(iCon.iFLane2L, iCon.iFLane2R, tNode.GSDRI.Height); } + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { iFLane3 = InterVertices(iCon.iFLane3L, iCon.iFLane3R, tNode.GSDRI.Height); } + } + + //Main plates: + List iBMainPlate = null; + List iFMainPlate = null; + if (!bSkipB) + { + iBMainPlate = InterVertices(iCon.iBMainPlateL, iCon.iBMainPlateR, tNode.GSDRI.Height); + } + if (!bSkipF) + { + iFMainPlate = InterVertices(iCon.iFMainPlateL, iCon.iFMainPlateR, tNode.GSDRI.Height); + } + // //Marker plates: + // List iBMarkerPlate = InterVertices(iCon.iBMarkerPlateL,iCon.iBMarkerPlateR, tNode.GSDRI.Height); + // List iFMarkerPlate = InterVertices(iCon.iFMarkerPlateL,iCon.iFMarkerPlateR, tNode.GSDRI.Height); + // + //Now add these to RCS: + if (!bSkipB) + { + tRoad.RCS.iBLane0s.Add(iBLane0.ToArray()); + tRoad.RCS.iBLane0s_tID.Add(GSDRI); + tRoad.RCS.iBLane0s_nID.Add(tNode); + tRoad.RCS.iBLane1s.Add(iBLane1.ToArray()); + tRoad.RCS.iBLane1s_tID.Add(GSDRI); + tRoad.RCS.iBLane1s_nID.Add(tNode); + if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (iBLane2 != null) + { + tRoad.RCS.iBLane2s.Add(iBLane2.ToArray()); + tRoad.RCS.iBLane2s_tID.Add(GSDRI); + tRoad.RCS.iBLane2s_nID.Add(tNode); + } + } + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tRoad.RCS.iBLane3s.Add(iBLane3.ToArray()); + tRoad.RCS.iBLane3s_tID.Add(GSDRI); + tRoad.RCS.iBLane3s_nID.Add(tNode); + } + } + //Front lanes: + if (!bSkipF) + { + tRoad.RCS.iFLane0s.Add(iFLane0.ToArray()); + tRoad.RCS.iFLane0s_tID.Add(GSDRI); + tRoad.RCS.iFLane0s_nID.Add(tNode); + tRoad.RCS.iFLane1s.Add(iFLane1.ToArray()); + tRoad.RCS.iFLane1s_tID.Add(GSDRI); + tRoad.RCS.iFLane1s_nID.Add(tNode); + if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + tRoad.RCS.iFLane2s.Add(iFLane2.ToArray()); + tRoad.RCS.iFLane2s_tID.Add(GSDRI); + tRoad.RCS.iFLane2s_nID.Add(tNode); + } + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + tRoad.RCS.iFLane3s.Add(iFLane3.ToArray()); + tRoad.RCS.iFLane3s_tID.Add(GSDRI); + tRoad.RCS.iFLane3s_nID.Add(tNode); + } + } + //Main plates: + if (iBMainPlate != null && !bSkipB) + { + tRoad.RCS.iBMainPlates.Add(iBMainPlate.ToArray()); + tRoad.RCS.iBMainPlates_tID.Add(GSDRI); + tRoad.RCS.iBMainPlates_nID.Add(tNode); + } + if (iFMainPlate != null && !bSkipF) + { + tRoad.RCS.iFMainPlates.Add(iFMainPlate.ToArray()); + tRoad.RCS.iFMainPlates_tID.Add(GSDRI); + tRoad.RCS.iFMainPlates_nID.Add(tNode); + } + // //Marker plates: + // tRoad.RCS.iBMarkerPlates.Add(iBMarkerPlate.ToArray()); + // tRoad.RCS.iFMarkerPlates.Add(iFMarkerPlate.ToArray()); + // tRoad.RCS.IntersectionTypes.Add((int)tNode.GSDRI.rType); + + if (tNode.GSDRI.rType != GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (!bSkipB) + { tRoad.RCS.iBLane1s_IsMiddleLane.Add(true); } + if (!bSkipF) + { tRoad.RCS.iFLane1s_IsMiddleLane.Add(true); } + } + else + { + if (!bSkipB) + { tRoad.RCS.iBLane1s_IsMiddleLane.Add(false); } + if (!bSkipF) + { tRoad.RCS.iFLane1s_IsMiddleLane.Add(false); } + } + } + + + private static bool IsVecSame(ref Vector3 tVect1, Vector3 tVect2) + { + return ((Vector3.SqrMagnitude(tVect1 - tVect2) < 0.01f)); + } + + + private static List InterVertices(List tL, List tR, float tHeight) + { + if (tL.Count == 0 || tR.Count == 0) + { return null; } + + List tList = new List(); + int tCountL = tL.Count; + int tCountR = tR.Count; + int spamcheck = 0; + + while (tCountL < tCountR && spamcheck < 5000) + { + tL.Add(tL[tCountL - 1]); + tCountL = tL.Count; + spamcheck += 1; + } + + spamcheck = 0; + while (tCountR < tCountL && spamcheck < 5000) + { + tR.Add(tR[tCountR - 1]); + tCountR = tR.Count; + spamcheck += 1; + } + + if (spamcheck > 4000) + { + Debug.LogWarning("spamcheck InterVertices"); + } + + int tCount = Mathf.Max(tCountL, tCountR); + for (int i = 0; i < tCount; i++) + { + tList.Add(tL[i]); + tList.Add(tL[i]); + tList.Add(tR[i]); + tList.Add(tR[i]); + } + return tList; + } + #endregion + + + /// + /// Handles most triangles and normals construction. In certain scenarios for efficiency reasons UV might also be processed. + /// + /// + /// The road construction buffer, by reference. + /// / + public static void RoadJob1(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + //Triangles and normals: + // if(RCS.tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("ProcessRoad_IntersectionCleanup"); } + if (RCS.bInterseOn) + { + ProcessRoad_IntersectionCleanup(ref RCS); + } + // if(RCS.tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } + + ProcessRoad_Tris_Bulk(ref RCS); + + RCS.tris_ShoulderR = ProcessRoad_Tris_Shoulder(RCS.ShoulderR_Vectors.Count); + RCS.tris_ShoulderL = ProcessRoad_Tris_Shoulder(RCS.ShoulderL_Vectors.Count); + if (RCS.tRoad.opt_bShoulderCuts || RCS.tRoad.opt_bDynamicCuts) + { + ProcessRoad_Tris_ShoulderCutsR(ref RCS); + ProcessRoad_Tris_ShoulderCutsL(ref RCS); + } + + ProcessRoad_Normals_Bulk(ref RCS); + ProcessRoad_Normals_Shoulders(ref RCS); + } + + + /// + /// Handles most UV and tangent construction. Some scenarios might involve triangles and normals or lack UV construction for efficiency reasons. + /// + /// + /// The road construction buffer, by reference. + /// + public static void RoadJob2(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + //Bridge UV is processed with tris and normals. + + //For one big road mesh: + if (RCS.bRoadOn) + { + if (!RCS.tMeshSkip) + { + RCS.uv = ProcessRoad_UVs(RCS.RoadVectors.ToArray()); + } + if (!RCS.tMesh_SRSkip) + { + RCS.uv_SR = ProcessRoad_UVs_Shoulder(RCS.ShoulderR_Vectors.ToArray()); + } + if (!RCS.tMesh_SLSkip) + { + RCS.uv_SL = ProcessRoad_UVs_Shoulder(RCS.ShoulderL_Vectors.ToArray()); + } + + //UVs for pavement: + if (!RCS.tMeshSkip) + { + int vCount = RCS.RoadVectors.Count; + RCS.uv2 = new Vector2[vCount]; + for (int index = 0; index < vCount; index++) + { + RCS.uv2[index] = new Vector2(RCS.RoadVectors[index].x * 0.2f, RCS.RoadVectors[index].z * 0.2f); + } + } + } + + //For road cuts: + if (RCS.tRoad.opt_bRoadCuts || RCS.tRoad.opt_bDynamicCuts) + { + ProcessRoad_UVs_RoadCuts(ref RCS); + int cCount = RCS.cut_RoadVectors.Count; + for (int index = 0; index < cCount; index++) + { + RCS.cut_tangents.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris[index], RCS.cut_normals[index], RCS.cut_uv[index], RCS.cut_RoadVectors[index].ToArray())); + RCS.cut_tangents_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris[index], RCS.cut_normals[index], RCS.cut_uv_world[index], RCS.cut_RoadVectors[index].ToArray())); + } + } + if (RCS.tRoad.opt_bShoulderCuts || RCS.tRoad.opt_bDynamicCuts) + { + int rCount = RCS.cut_ShoulderR_Vectors.Count; + for (int index = 0; index < rCount; index++) + { + ProcessRoad_UVs_ShoulderCut(ref RCS, false, index); + RCS.cut_tangents_SR.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderR[index], RCS.cut_normals_ShoulderR[index], RCS.cut_uv_SR[index], RCS.cut_ShoulderR_Vectors[index].ToArray())); + RCS.cut_tangents_SR_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderR[index], RCS.cut_normals_ShoulderR[index], RCS.cut_uv_SR_world[index], RCS.cut_ShoulderR_Vectors[index].ToArray())); + } + int lCount = RCS.cut_ShoulderL_Vectors.Count; + for (int index = 0; index < lCount; index++) + { + ProcessRoad_UVs_ShoulderCut(ref RCS, true, index); + RCS.cut_tangents_SL.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderL[index], RCS.cut_normals_ShoulderL[index], RCS.cut_uv_SL[index], RCS.cut_ShoulderL_Vectors[index].ToArray())); + RCS.cut_tangents_SL_world.Add(GSDRootUtil.ProcessTangents(RCS.cut_tris_ShoulderL[index], RCS.cut_normals_ShoulderL[index], RCS.cut_uv_SL_world[index], RCS.cut_ShoulderL_Vectors[index].ToArray())); + } + } + if (RCS.bInterseOn) + { + ProcessRoad_UVs_Intersections(ref RCS); + } + + // throw new System.Exception("FFFFFFFF"); + + if (RCS.bRoadOn) + { + if (!RCS.tMeshSkip) + { + RCS.tangents = GSDRootUtil.ProcessTangents(RCS.tris, RCS.normals, RCS.uv, RCS.RoadVectors.ToArray()); + } + if (!RCS.tMeshSkip) + { + RCS.tangents2 = GSDRootUtil.ProcessTangents(RCS.tris, RCS.normals, RCS.uv2, RCS.RoadVectors.ToArray()); + } + if (!RCS.tMesh_SRSkip) + { + RCS.tangents_SR = GSDRootUtil.ProcessTangents(RCS.tris_ShoulderR, RCS.normals_ShoulderR, RCS.uv_SR, RCS.ShoulderR_Vectors.ToArray()); + } + if (!RCS.tMesh_SLSkip) + { + RCS.tangents_SL = GSDRootUtil.ProcessTangents(RCS.tris_ShoulderL, RCS.normals_ShoulderL, RCS.uv_SL, RCS.ShoulderL_Vectors.ToArray()); + } + for (int index = 0; index < RCS.tMesh_RoadConnections.Count; index++) + { + RCS.RoadConnections_tangents.Add(GSDRootUtil.ProcessTangents(RCS.RoadConnections_tris[index], RCS.RoadConnections_normals[index], RCS.RoadConnections_uv[index], RCS.RoadConnections_verts[index])); + } + } + + if (RCS.bInterseOn) + { + //Back lanes: + int vCount = RCS.iBLane0s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBLane0s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane0s_tris[index], RCS.iBLane0s_normals[index], RCS.iBLane0s_uv[index], RCS.iBLane0s[index])); + } + vCount = RCS.iBLane1s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBLane1s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane1s_tris[index], RCS.iBLane1s_normals[index], RCS.iBLane1s_uv[index], RCS.iBLane1s[index])); + } + vCount = RCS.iBLane2s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBLane2s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane2s_tris[index], RCS.iBLane2s_normals[index], RCS.iBLane2s_uv[index], RCS.iBLane2s[index])); + } + vCount = RCS.iBLane3s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBLane3s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBLane3s_tris[index], RCS.iBLane3s_normals[index], RCS.iBLane3s_uv[index], RCS.iBLane3s[index])); + } + //Front lanes: + vCount = RCS.iFLane0s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFLane0s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane0s_tris[index], RCS.iFLane0s_normals[index], RCS.iFLane0s_uv[index], RCS.iFLane0s[index])); + } + vCount = RCS.iFLane1s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFLane1s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane1s_tris[index], RCS.iFLane1s_normals[index], RCS.iFLane1s_uv[index], RCS.iFLane1s[index])); + } + vCount = RCS.iFLane2s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFLane2s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane2s_tris[index], RCS.iFLane2s_normals[index], RCS.iFLane2s_uv[index], RCS.iFLane2s[index])); + } + vCount = RCS.iFLane3s.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFLane3s_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFLane3s_tris[index], RCS.iFLane3s_normals[index], RCS.iFLane3s_uv[index], RCS.iFLane3s[index])); + } + //Main plates: + vCount = RCS.iBMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBMainPlates_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iBMainPlates_tris[index], RCS.iBMainPlates_normals[index], RCS.iBMainPlates_uv[index], RCS.iBMainPlates[index])); + } + vCount = RCS.iBMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iBMainPlates_tangents2.Add(GSDRootUtil.ProcessTangents(RCS.iBMainPlates_tris[index], RCS.iBMainPlates_normals[index], RCS.iBMainPlates_uv2[index], RCS.iBMainPlates[index])); + } + vCount = RCS.iFMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFMainPlates_tangents.Add(GSDRootUtil.ProcessTangents(RCS.iFMainPlates_tris[index], RCS.iFMainPlates_normals[index], RCS.iFMainPlates_uv[index], RCS.iFMainPlates[index])); + } + vCount = RCS.iFMainPlates.Count; + for (int index = 0; index < vCount; index++) + { + RCS.iFMainPlates_tangents2.Add(GSDRootUtil.ProcessTangents(RCS.iFMainPlates_tris[index], RCS.iFMainPlates_normals[index], RCS.iFMainPlates_uv2[index], RCS.iFMainPlates[index])); + } + } + } + + + #region "Intersection Cleanup" + private static void ProcessRoad_IntersectionCleanup(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + List tList = RCS.tIntersectionBounds; + int mCount = tList.Count; + RCS.ShoulderR_Vectors = ProcessRoad_IntersectionCleanup_Helper(ref RCS.ShoulderR_Vectors, ref tList, mCount, ref RCS.ImmuneVects); + RCS.ShoulderL_Vectors = ProcessRoad_IntersectionCleanup_Helper(ref RCS.ShoulderL_Vectors, ref tList, mCount, ref RCS.ImmuneVects); + } + + + private static List ProcessRoad_IntersectionCleanup_Helper(ref List tVects, ref List tList, int mCount, ref HashSet ImmuneVects) + { + GSD.Roads.GSDRoadUtil.Construction2DRect tRect = null; + int MVL = tVects.Count; + //Vector3 tVect = default(Vector3); + Vector2 Vect2D = default(Vector2); + Vector2 tNearVect = default(Vector2); + float tMax2 = 2000f; + float tMax2SQ = 0f; + // GameObject tObj = GameObject.Find("Inter1"); + // Vector2 tObj2D = ConvertVect3_To_Vect2(tObj.transform.position); + // int fCount = 0; + // bool bTempNow = false; + for (int i = 0; i < mCount; i++) + { + tRect = tList[i]; + tMax2 = tRect.MaxDistance * 1.5f; + tMax2SQ = (tMax2 * tMax2); + + // Debug.Log (tRect.ToString()); + + for (int j = 0; j < MVL; j++) + { + Vect2D.x = tVects[j].x; + Vect2D.y = tVects[j].z; + + if (Vector2.SqrMagnitude(Vect2D - tRect.P1) > tMax2SQ) + { + j += 32; + continue; + } + + // if(Vector2.Distance(Vect2D,tObj2D) < 20f && (j % 16 == 0)){ + // fCount+=1; + // GameObject xObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // xObj.transform.localScale = new Vector3(0.05f,40f,0.05f); + // xObj.transform.position = tVects[j]; + // xObj.name = "temp22"; + // } + + // bTempNow = false; + if (tRect.Contains(ref Vect2D)) + { + if (ImmuneVects.Contains(tVects[j])) + { continue; } + // if(Vect2D == tRect.P1){ + // continue; + // }else if(Vect2D == tRect.P2){ + // continue; + // }else if(Vect2D == tRect.P3){ + // continue; + // }else if(Vect2D == tRect.P4){ + // continue; + // } + + + // if(Mathf.Approximately(tVects[j].x,303.1898f)){ + // GameObject hObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // hObj.transform.localScale = new Vector3(0.05f,40f,0.05f); + // hObj.transform.position = tVects[j]; + // hObj.name = "temp23"; + // bTempNow = true; + // Debug.Log (tVects[j]); + // } + + //Calling near when it shouldn't ? + if (tRect.Near(ref Vect2D, out tNearVect)) + { //If near the rect, set it equal + tVects[j] = new Vector3(tNearVect.x, tVects[j].y, tNearVect.y); + } + else + { + tVects[j] = new Vector3(tVects[j].x, tRect.Height, tVects[j].z); + } + + + + + + //ImmuneVects.Add(tVects[j]); + + // if(bTempNow){ + // GameObject xObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + // xObj.transform.localScale = new Vector3(0.05f,40f,0.05f); + // xObj.transform.position = tVects[j]; + // xObj.name = "temp22"; + // Debug.Log ("to: " + tVects[j]); + // } + } + } + } + // Debug.Log ("Fcount: " + fCount); + + return tVects; + } + #endregion + + + #region "Tris" + private static void ProcessRoad_Tris_Bulk(ref GSD.Roads.RoadConstructorBufferMaker RCS) + {//, ref Mesh tShoulderR, ref Mesh tShoulderL){ + //Next come the triangles. Since we want two triangles, each defined by three integers, the triangles array will have six elements in total. + //Remembering the clockwise rule for ordering the corners, the lower left triangle will use 0, 2, 1 as its corner indices, while the upper right one will use 2, 3, 1. + + RCS.tris = ProcessRoad_Tris_Bulk_Helper(RCS.RoadVectors.Count); + if (RCS.tRoad.opt_bRoadCuts || RCS.tRoad.opt_bDynamicCuts) + { + ProcessRoad_Tris_RoadCuts(ref RCS); + } + + if (RCS.bInterseOn) + { + //For intersection parts: + //Back lanes: + ProcessRoad_Tris_iProcessor(ref RCS.iBLane0s_tris, ref RCS.iBLane0s); + ProcessRoad_Tris_iProcessor(ref RCS.iBLane1s_tris, ref RCS.iBLane1s); + ProcessRoad_Tris_iProcessor(ref RCS.iBLane2s_tris, ref RCS.iBLane2s); + ProcessRoad_Tris_iProcessor(ref RCS.iBLane3s_tris, ref RCS.iBLane3s); + //Front lanes: + ProcessRoad_Tris_iProcessor(ref RCS.iFLane0s_tris, ref RCS.iFLane0s); + ProcessRoad_Tris_iProcessor(ref RCS.iFLane1s_tris, ref RCS.iFLane1s); + ProcessRoad_Tris_iProcessor(ref RCS.iFLane2s_tris, ref RCS.iFLane2s); + ProcessRoad_Tris_iProcessor(ref RCS.iFLane3s_tris, ref RCS.iFLane3s); + //Main plates: + ProcessRoad_Tris_iProcessor(ref RCS.iBMainPlates_tris, ref RCS.iBMainPlates); + ProcessRoad_Tris_iProcessor(ref RCS.iFMainPlates_tris, ref RCS.iFMainPlates); + } + } + + + private static int[] ProcessRoad_Tris_Bulk_Helper(int MVL) + { + int TriCount = 0; + int x1, x2, x3; + int xCount = (int) (MVL * 0.25f * 6) - 6; + // if(xCount < 0){ xCount = 0; } + int[] tri = new int[xCount]; + for (int i = 0; i < MVL; i += 4) + { + if (i + 4 == MVL) + { break; } + + x1 = i; + x2 = i + 4; + x3 = i + 2; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + + x1 = i + 4; + x2 = i + 6; + x3 = i + 2; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + } + return tri; + } + + + private static void ProcessRoad_Tris_RoadCuts(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + //Road cuts aren't working right for the special nodes on cuts + int cCount = RCS.RoadCuts.Count; + int PrevRoadCutIndex = 0; + int CurrentRoadCutIndex = 0; + List> tVects = new List>(); + List tVectListSingle = null; + Vector3 xVect = default(Vector3); + for (int j = 0; j < cCount; j++) + { + CurrentRoadCutIndex = RCS.RoadCuts[j]; + tVectListSingle = new List(); + RCS.cut_RoadVectorsHome.Add(RCS.RoadVectors[PrevRoadCutIndex]); + xVect = RCS.RoadVectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) + { + tVectListSingle.Add(RCS.RoadVectors[i] - xVect); + } + tVects.Add(tVectListSingle); + PrevRoadCutIndex = CurrentRoadCutIndex - 4; + if (PrevRoadCutIndex < 0) + { PrevRoadCutIndex = 0; } + } + int mMax = RCS.RoadVectors.Count; + tVectListSingle = new List(); + RCS.cut_RoadVectorsHome.Add(RCS.RoadVectors[PrevRoadCutIndex]); + xVect = RCS.RoadVectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < mMax; i++) + { + tVectListSingle.Add(RCS.RoadVectors[i] - xVect); + } + tVects.Add(tVectListSingle); + + int vCount = tVects.Count; + List tTris = new List(); + for (int i = 0; i < vCount; i++) + { + int[] tTriSingle = ProcessRoad_Tris_Bulk_Helper(tVects[i].Count); + tTris.Add(tTriSingle); + } + + RCS.cut_RoadVectors = tVects; + RCS.cut_tris = tTris; + } + + + private static void ProcessRoad_Tris_ShoulderCutsR(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + int cCount = RCS.ShoulderCutsR.Count; + int PrevRoadCutIndex = 0; + int CurrentRoadCutIndex = 0; + List> tVects = new List>(); + List tVectListSingle = null; + Vector3 xVect = default(Vector3); + for (int j = 0; j < cCount; j++) + { + CurrentRoadCutIndex = RCS.ShoulderCutsR[j]; + tVectListSingle = new List(); + RCS.cut_ShoulderR_VectorsHome.Add(RCS.ShoulderR_Vectors[PrevRoadCutIndex]); + xVect = RCS.ShoulderR_Vectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) + { + tVectListSingle.Add(RCS.ShoulderR_Vectors[i] - xVect); + } + tVects.Add(tVectListSingle); + PrevRoadCutIndex = CurrentRoadCutIndex - 8; + if (PrevRoadCutIndex < 0) + { PrevRoadCutIndex = 0; } + } + int mMax = RCS.ShoulderR_Vectors.Count; + tVectListSingle = new List(); + RCS.cut_ShoulderR_VectorsHome.Add(RCS.ShoulderR_Vectors[PrevRoadCutIndex]); + xVect = RCS.ShoulderR_Vectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < mMax; i++) + { + tVectListSingle.Add(RCS.ShoulderR_Vectors[i] - xVect); + } + tVects.Add(tVectListSingle); + + int vCount = tVects.Count; + List tTris = new List(); + for (int i = 0; i < vCount; i++) + { + int[] tTriSingle = ProcessRoad_Tris_Shoulder(tVects[i].Count); + tTris.Add(tTriSingle); + } + + RCS.cut_ShoulderR_Vectors = tVects; + RCS.cut_tris_ShoulderR = tTris; + } + + + private static void ProcessRoad_Tris_ShoulderCutsL(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + int cCount = RCS.ShoulderCutsL.Count; + int PrevRoadCutIndex = 0; + int CurrentRoadCutIndex = 0; + List> tVects = new List>(); + List tVectListSingle = null; + Vector3 xVect = default(Vector3); + for (int j = 0; j < cCount; j++) + { + CurrentRoadCutIndex = RCS.ShoulderCutsR[j]; + tVectListSingle = new List(); + RCS.cut_ShoulderL_VectorsHome.Add(RCS.ShoulderL_Vectors[PrevRoadCutIndex]); + xVect = RCS.ShoulderL_Vectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < CurrentRoadCutIndex; i++) + { + tVectListSingle.Add(RCS.ShoulderL_Vectors[i] - xVect); + } + tVects.Add(tVectListSingle); + PrevRoadCutIndex = CurrentRoadCutIndex - 8; + if (PrevRoadCutIndex < 0) + { PrevRoadCutIndex = 0; } + } + int mMax = RCS.ShoulderL_Vectors.Count; + tVectListSingle = new List(); + RCS.cut_ShoulderL_VectorsHome.Add(RCS.ShoulderL_Vectors[PrevRoadCutIndex]); + xVect = RCS.ShoulderL_Vectors[PrevRoadCutIndex]; + for (int i = PrevRoadCutIndex; i < mMax; i++) + { + tVectListSingle.Add(RCS.ShoulderL_Vectors[i] - xVect); + } + tVects.Add(tVectListSingle); + + int vCount = tVects.Count; + List tTris = new List(); + for (int i = 0; i < vCount; i++) + { + int[] tTriSingle = ProcessRoad_Tris_Shoulder(tVects[i].Count); + tTris.Add(tTriSingle); + } + + RCS.cut_ShoulderL_Vectors = tVects; + RCS.cut_tris_ShoulderL = tTris; + } + + + private static int[] ProcessRoad_Tris_Shoulder(int MVL) + { + int TriCount = 0; + int x1, x2, x3; + int xCount = (int) ((MVL / 2) * 0.25f * 6) - 6; + if (xCount < 0) + { xCount = 0; } + xCount = xCount * 2; + + int[] tri = new int[xCount]; + for (int i = 0; i < MVL; i += 8) + { + if (i + 8 == MVL) + { break; } + + x1 = i; + x2 = i + 8; + x3 = i + 2; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + + x1 = i + 8; + x2 = i + 10; + x3 = i + 2; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + + x1 = i + 4; + x2 = i + 12; + x3 = i + 6; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + + x1 = i + 12; + x2 = i + 14; + x3 = i + 6; + + tri[TriCount] = x1; + TriCount += 1; + tri[TriCount] = x2; + TriCount += 1; + tri[TriCount] = x3; + TriCount += 1; + } + return tri; + } + + + //For intersection parts: + private static void ProcessRoad_Tris_iProcessor(ref List TriList, ref List VertexList) + { + if (TriList == null) + { TriList = new List(); } + int vListCount = VertexList.Count; + int[] tris; + for (int i = 0; i < vListCount; i++) + { + tris = ProcessRoad_Tris_Bulk_Helper(VertexList[i].Length); + TriList.Add(tris); + } + } + #endregion + + + #region "Normals" + private static void ProcessRoad_Normals_Bulk(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + //A mesh with just the vertices and triangles set up will be visible in the editor but will not look very convincing since it is not correctly shaded without the normals. + //The normals for the flat plane are very simple - they are all identical and point in the negative Z direction in the plane's local space. + //With the normals added, the plane will be correctly shaded but remember that you need a light in the scene to see the effect. + //Bridge normals are processed at same time as tris. + int MVL = RCS.RoadVectors.Count; + Vector3[] normals = new Vector3[MVL]; + // Vector3 tVect = -Vector3.forward; + // for(int i=0;i NormalList, ref List VertexList) + { + if (NormalList == null) + { + NormalList = new List(); + } + int vListCount = VertexList.Count; + Vector3[] normals; + int MVL = -1; + // Vector3 tVect = -Vector3.forward; + for (int index = 0; index < vListCount; index++) + { + MVL = VertexList[index].Length; + normals = new Vector3[MVL]; + // for(int j=0;j 0 || (tDistanceLeftSum+tDistanceLeft) > 1f){ + // tDistanceLeftSum = 0.998f + (0.0001f*bHitMaxL); + // tDistanceLeft = 0.001f; + // bHitMaxL+=1; + // } + // if(bHitMaxR > 0 || (tDistanceRightSum+tDistanceRight) > 1f){ + // tDistanceRightSum = 0.998f + (0.0001f*bHitMaxR); + // tDistanceRight = 0.001f; + // bHitMaxR+=1; + // } + + tAdd1 = tDistanceLeftSum; + if (tAdd1 > 1f) + { tAdd1 = 1f; } + tAdd2 = tDistanceRightSum; + if (tAdd2 > 1f) + { tAdd2 = 1f; } + tAdd3 = tDistanceLeft + tDistanceLeftSum; + if (tAdd3 > 1f) + { tAdd3 = 1f; } + tAdd4 = tDistanceRight + tDistanceRightSum; + if (tAdd4 > 1f) + { tAdd4 = 1f; } + + uv[i] = new Vector2(0f, tAdd1); + uv[i + 2] = new Vector2(1f, tAdd2); + uv[i + 4] = new Vector2(0f, tAdd3); + uv[i + 6] = new Vector2(1f, tAdd4); + //Debug.Log (tAdd3 + " R:"+ tAdd4 + " RLoc: " + tVerts[i+6]); + } + + + + //Debug.Log ("1.0 R:1.0 RLoc: " + tVerts[i+6]); + + //Last segment needs adjusted due to double vertices: + if ((i + 7) == MVL) + { + if (bOddToggle) + { + //First set: Debug.Log ("+5:"+i+" "+(i+2)+" "+(i+4)+" "+(i+6)); + uv[MVL - 3] = uv[i + 4]; + uv[MVL - 1] = uv[i + 6]; + } + else + { + //Last set: Debug.Log ("+3:"+i+" "+(i+2)+" "+(i+4)+" "+(i+6)); + uv[MVL - 4] = uv[i + 4]; + uv[MVL - 2] = uv[i + 6]; + } + } + + + + if (bOddToggle) + { + i += 5; + + if (i + 6 >= MVL) + { + uv[i + 4 - 5] = new Vector2(0f, 1f); + uv[i + 6 - 5] = new Vector2(1f, 1f); + } + + } + else + { + i += 3; + + if (i + 6 >= MVL) + { + uv[i + 4 - 3] = new Vector2(0f, 1f); + uv[i + 6 - 3] = new Vector2(1f, 1f); + } + } + + + + tDistanceLeftSum += tDistanceLeft; + tDistanceRightSum += tDistanceRight; + //tDistanceSum+=tDistance; + bOddToggle = !bOddToggle; + } + + // uv[MVL-1].y = 1f; + // uv[MVL-2].y = 1f; + // uv[MVL-3].y = 1f; + // uv[MVL-4].y = 1f; + + return uv; + } + #endregion + #endregion + + + #region "Set vector heights" + private static void SetVectorHeight2(ref Vector3 tWorldVect, ref float p, ref List> tList, ref GSDSplineC tSpline) + { + int mCount = tList.Count; + int index = 0; + + if (mCount < 1) + { + tWorldVect.y = 0f; + return; + } + + float cValue = 0f; + for (index = 0; index < (mCount - 1); index++) + { + if (p >= tList[index].Key && p < tList[index + 1].Key) + { + cValue = tList[index].Value; + if (index > 3) + { + if (tList[index - 1].Value < cValue) + { + cValue = tList[index - 1].Value; + } + if (tList[index - 2].Value < cValue) + { + cValue = tList[index - 2].Value; + } + if (tList[index - 3].Value < cValue) + { + cValue = tList[index - 3].Value; + } + } + if (index < (mCount - 3)) + { + if (tList[index + 1].Value < cValue) + { + cValue = tList[index + 1].Value; + } + if (tList[index + 2].Value < cValue) + { + cValue = tList[index + 2].Value; + } + if (tList[index + 3].Value < cValue) + { + cValue = tList[index + 3].Value; + } + } + break; + } + } + + //if(p > 0.95f && GSDRootUtil.IsApproximately(cValue,0f,0.001f)){ + // float DeadValue = 0f; + // Vector3 tPos = tSpline.GetSplineValue(p,false); + // if(!tSpline.IsNearIntersection(ref tPos,ref DeadValue)){ + // cValue = tList[tList.Count-1].Value; + // } + //} + + //Zero protection: + if (GSDRootUtil.IsApproximately(cValue, 0f, 0.001f) && tWorldVect.y > 0f) + { + cValue = tWorldVect.y - 0.35f; + } + + tWorldVect.y = cValue; + } + #endregion + + + private static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + private static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + + + public class RoadTerrainInfo + { + public Rect tBounds; + public int GSDID; + public int hmWidth; + public int hmHeight; + public Vector3 tPos; + public Vector3 tSize; + public float[,] heights; + } + } + + + #region "Threading core" + public class GSDThreadedJob + { + private bool m_IsDone = false; + private object m_Handle = new object(); + private System.Threading.Thread m_Thread = null; + + + public bool IsDone + { + get + { + bool tmp; + lock (m_Handle) + { + tmp = m_IsDone; + } + return tmp; + } + set + { + lock (m_Handle) + { + m_IsDone = value; + } + } + } + + + public virtual void Start() + { + m_Thread = new System.Threading.Thread(Run); + m_Thread.Start(); + } + + + public virtual void Abort() + { + m_Thread.Abort(); + } + + + protected virtual void ThreadFunction() { } + + + protected virtual void OnFinished() { } + + + public virtual bool Update() + { + if (IsDone) + { + OnFinished(); + return true; + } + return false; + } + + + private void Run() + { + ThreadFunction(); + IsDone = true; + } + } + + + public class GSDJob : GSDThreadedJob + { + //public Vector3[] InData; // arbitary job data + //public Vector3[] OutData; // arbitary job data + + + protected override void ThreadFunction() + { + // Do your threaded task. DON'T use the Unity API here + //for (int i = 0; i < 100000000; i++){ + //InData[i % InData.Length] += InData[(i+1) % InData.Length]; + //} + } + + + protected override void OnFinished() + { + // This is executed by the Unity main thread when the job is finished + //for (int i = 0; i < InData.Length; i++){ + //Debug.Log("Results(" + i + "): " + InData[i]); + //} + } + } + #endregion + + + public class TerrainCalcs : GSDThreadedJob + { + private object GSDm_Handle = new object(); + private List TTDList; + private GSDSplineC tSpline; + private GSDRoad tRoad; + + + public void Setup(ref List _TTDList, GSDSplineC _tSpline, GSDRoad _tRoad) + { + TTDList = _TTDList; + tSpline = _tSpline; + tRoad = _tRoad; + } + + + protected override void ThreadFunction() + { + float Step = (tRoad.opt_RoadDefinition * 0.4f) / tSpline.distance; + if (Step > 2f) + { + Step = 2f; + } + if (Step < 1f) + { + Step = 1f; + } + // float tDistance = tRoad.RoadWidth()*2f; + + // Vector3 tVect,POS; + foreach (GSD.Roads.GSDTerraforming.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 + { + GSDTerraformingT.DoRects(tSpline, TTD); + } + catch (System.Exception e) + { + lock (GSDm_Handle) + { + tRoad.bEditorError = true; + tRoad.tError = 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 = GSDTerraformingT.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight); + // tSpline.HeightHistory.Add(new KeyValuePair(i,PrevHeight*TTD.TerrainSize.y)); + // } + // + // for(int i=0;i a, KeyValuePair b) + { + return a.Key.CompareTo(b.Key); + } + } + + + public static class TerrainCalcs_Static + { + public static void RunMe(ref List TTDList, GSDSplineC tSpline, GSDRoad tRoad) + { + float Step = (tRoad.opt_RoadDefinition * 0.4f) / tSpline.distance; + if (Step > 2f) + { + Step = 2f; + } + if (Step < 1f) + { + Step = 1f; + } + // float tDistance = tRoad.RoadWidth()*2f; + + // Vector3 tVect,POS; + + foreach (GSD.Roads.GSDTerraforming.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){ + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.BeginSample("DoRects"); + } + GSDTerraformingT.DoRects(tSpline, TTD); + + if (tRoad.bProfiling) + { + UnityEngine.Profiling.Profiler.EndSample(); + } + // }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 = GSDTerraformingT.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight); + // tSpline.HeightHistory.Add(new KeyValuePair(i,PrevHeight*TTD.TerrainSize.y)); + // } + // + // for(int i=0;i a, KeyValuePair b) + { + return a.Key.CompareTo(b.Key); + } + } + + + public class RoadCalcs1 : GSDThreadedJob + { + private object GSDm_Handle = new object(); + private GSD.Roads.RoadConstructorBufferMaker RCS; + private GSDRoad tRoad; + + + public void Setup(ref GSD.Roads.RoadConstructorBufferMaker _RCS, ref GSDRoad _tRoad) + { + RCS = _RCS; + tRoad = _tRoad; + } + + + protected override void ThreadFunction() + { + try + { + GSDRoadCreationT.RoadJob_Prelim(ref tRoad); + GSDRoadCreationT.RoadJob1(ref RCS); + } + catch (System.Exception exception) + { + lock (GSDm_Handle) + { + tRoad.bEditorError = true; + tRoad.tError = exception; + } + throw exception; + } + } + + + public GSD.Roads.RoadConstructorBufferMaker GetRCS() + { + GSD.Roads.RoadConstructorBufferMaker tRCS; + lock (GSDm_Handle) + { + tRCS = RCS; + } + return tRCS; + } + } + + + public static class RoadCalcs1_static + { + public static void RunMe(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + GSDRoadCreationT.RoadJob1(ref RCS); + } + } + + + public class RoadCalcs2 : GSDThreadedJob + { + private object GSDm_Handle = new object(); + private GSD.Roads.RoadConstructorBufferMaker RCS; + + + public void Setup(ref GSD.Roads.RoadConstructorBufferMaker _RCS) + { + RCS = _RCS; + } + + + protected override void ThreadFunction() + { + try + { + GSDRoadCreationT.RoadJob2(ref RCS); + } + catch (System.Exception exception) + { + lock (GSDm_Handle) + { + RCS.tRoad.bEditorError = true; + RCS.tRoad.tError = exception; + } + } + } + + + public GSD.Roads.RoadConstructorBufferMaker GetRCS() + { + GSD.Roads.RoadConstructorBufferMaker tRCS; + lock (GSDm_Handle) + { + tRCS = RCS; + } + return tRCS; + } + } + + + public static class RoadCalcs2_static + { + public static void RunMe(ref GSD.Roads.RoadConstructorBufferMaker RCS) + { + GSDRoadCreationT.RoadJob2(ref RCS); + } + } + +#endif } \ No newline at end of file diff --git a/GSDRootUtil.cs b/GSDRootUtil.cs index 3377d144..3555a8bf 100755 --- a/GSDRootUtil.cs +++ b/GSDRootUtil.cs @@ -1,368 +1,398 @@ -using UnityEngine; -using System.Collections; -using System.Xml; -using System.Xml.Serialization; -using System.IO; -using System.Text; -namespace GSD -{ - public static class GSDRootUtil - { - /// - /// Smooths the input parameter t. - /// If less than k1 ir greater than k2, it uses a sin. - /// Between k1 and k2 it uses linear interp. - /// - public static float Ease(float t, float k1, float k2) - { - float f; - float s; - - f = k1 * 2 / Mathf.PI + k2 - k1 + (1.0f - k2) * 2 / Mathf.PI; - - if (t < k1) - { - s = k1 * (2 / Mathf.PI) * (Mathf.Sin((t / k1) * Mathf.PI / 2 - Mathf.PI / 2) + 1); - } - else if (t < k2) - { - s = (2 * k1 / Mathf.PI + t - k1); - } - else - { - s = 2 * k1 / Mathf.PI + k2 - k1 + ((1 - k2) * (2 / Mathf.PI)) * Mathf.Sin(((t - k2) / (1.0f - k2)) * Mathf.PI / 2); - } - - return (s / f); - } - - /// - /// Returns true if the lines intersect, otherwise false. - /// - /// Line 1 start. - /// Line 1 end. - /// Line 2 start. - /// Line 2 end. - /// If the lines intersect, intersectionPoint holds the intersection point. - /// - public static bool Intersects2D(ref Vector2 Line1S, ref Vector2 Line1E, ref Vector2 Line2S, ref Vector2 Line2E, out Vector2 intersectionPoint) - { - float firstLineSlopeX, firstLineSlopeY, secondLineSlopeX, secondLineSlopeY; - - firstLineSlopeX = Line1E.x - Line1S.x; - firstLineSlopeY = Line1E.y - Line1S.y; - - secondLineSlopeX = Line2E.x - Line2S.x; - secondLineSlopeY = Line2E.y - Line2S.y; - - float s, t; - s = (-firstLineSlopeY * (Line1S.x - Line2S.x) + firstLineSlopeX * (Line1S.y - Line2S.y)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); - t = (secondLineSlopeX * (Line1S.y - Line2S.y) - secondLineSlopeY * (Line1S.x - Line2S.x)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); - - if (s >= 0 && s <= 1 && t >= 0 && t <= 1) - { - float intersectionPointX = Line1S.x + (t * firstLineSlopeX); - float intersectionPointY = Line1S.y + (t * firstLineSlopeY); - - // Collision detected - intersectionPoint = new Vector2(intersectionPointX, intersectionPointY); - return true; - } - - intersectionPoint = Vector2.zero; - return false; // No collision - } - - - public static string GetPrefabString(GameObject tObj) - { - string tString = ""; -#if UNITY_EDITOR - if (tObj != null) - { - tString = UnityEditor.AssetDatabase.GetAssetPath(tObj); - if (tString == null || tString.Length < 1) - { -#if UNITY_2018_2_OR_NEWER - Object parentObject = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(tObj); -#else - Object parentObject = UnityEditor.PrefabUtility.GetPrefabParent(tObj); -#endif - tString = UnityEditor.AssetDatabase.GetAssetPath(parentObject); - } - } -#endif - return tString; - } - - #region "Float comparisons" - public static bool IsApproximately(float a, float b) - { - return IsApproximately(a, b, 0.01f); - } - - public static bool IsApproximately(float a, float b, float tolerance) - { - return Mathf.Abs(a - b) < tolerance; - } - #endregion - - #region "XML" - public static void CreateXML(ref string tPath, object pObject) - { -#if UNITY_WEBPLAYER - return; -#else - string tData = SerializeObject(ref pObject); - StreamWriter writer; - FileInfo t = new FileInfo(tPath); - if (!t.Exists) - { - writer = t.CreateText(); - } - else - { - t.Delete(); - writer = t.CreateText(); - } - writer.Write(tData); - writer.Close(); -#endif - } - - public static string GetString(object pObject) - { - string tData = SerializeObject(ref pObject); - return tData; - } - - public static object LoadXML(ref string tPath) - { -#if UNITY_WEBPLAYER - return null; -#else - StreamReader r = File.OpenText(tPath); - string _info = r.ReadToEnd(); - r.Close(); - object tObject = DeserializeObject(_info); - return tObject; -#endif - } - - public static object LoadData(ref string _info) - { - object tObject = DeserializeObject(_info); - return tObject; - } - - public static void DeleteLibraryXML(string tName, bool bIsExtrusion) - { -#if UNITY_WEBPLAYER - return; -#else - string tPath; - if (bIsExtrusion) - { - tPath = Application.dataPath + "/RoadArchitect/Library/ESO" + tName + ".gsd"; - } - else - { - tPath = Application.dataPath + "/RoadArchitect/Library/EOM" + tName + ".gsd"; - } - if (File.Exists(tPath)) - { - File.Delete(tPath); - } -#endif - } - - private static string SerializeObject(ref object pObject) - { - string XmlizedString = null; - MemoryStream memoryStream = new MemoryStream(); - XmlSerializer xs = new XmlSerializer(typeof(T)); - XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); - xs.Serialize(xmlTextWriter, pObject); - memoryStream = (MemoryStream)xmlTextWriter.BaseStream; - XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray()); - return XmlizedString; - } - - private static object DeserializeObject(string pXmlizedString) - { - XmlSerializer xs = new XmlSerializer(typeof(T)); - MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString)); - return xs.Deserialize(memoryStream); - } - - private static string UTF8ByteArrayToString(byte[] characters) - { - UTF8Encoding encoding = new UTF8Encoding(); - string constructedString = encoding.GetString(characters); - return (constructedString); - } - - private static byte[] StringToUTF8ByteArray(string pXmlString) - { - UTF8Encoding encoding = new UTF8Encoding(); - byte[] byteArray = encoding.GetBytes(pXmlString); - return byteArray; - } - #endregion - - #region "Mesh tangents" - //Thread safe because local scope and by val params - public static Vector4[] ProcessTangents(int[] tris, Vector3[] normals, Vector2[] uvs, Vector3[] verts) - { - int MVL = verts.Length; - if (MVL == 0) { return new Vector4[0]; } - int triangleCount = tris.Length;// mesh.triangles.Length / 3; - Vector3[] tan1 = new Vector3[MVL]; - Vector3[] tan2 = new Vector3[MVL]; - Vector4[] tangents = new Vector4[MVL]; - int i1, i2, i3; - Vector3 v1, v2, v3; - Vector2 w1, w2, w3; - float x1, x2, y1, y2, z1, z2, s1, s2, t1, t2, r; - Vector3 sdir, tdir; - float div = 0f; - for (int a = 0; a < triangleCount; a += 3) - { - i1 = tris[a + 0]; - i2 = tris[a + 1]; - i3 = tris[a + 2]; - - v1 = verts[i1]; - v2 = verts[i2]; - v3 = verts[i3]; - - w1 = uvs[i1]; - w2 = uvs[i2]; - w3 = uvs[i3]; - - x1 = v2.x - v1.x; - x2 = v3.x - v1.x; - y1 = v2.y - v1.y; - y2 = v3.y - v1.y; - z1 = v2.z - v1.z; - z2 = v3.z - v1.z; - - s1 = w2.x - w1.x; - s2 = w3.x - w1.x; - t1 = w2.y - w1.y; - t2 = w3.y - w1.y; - - // r = 1.0f / (s1 * t2 - s2 * t1); - div = (s1 * t2 - s2 * t1); - r = div == 0.0f ? 0.0f : 1.0f / div; - - sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); - - tan1[i1] += sdir; - tan1[i2] += sdir; - tan1[i3] += sdir; - - tan2[i1] += tdir; - tan2[i2] += tdir; - tan2[i3] += tdir; - } - - Vector3 n, t;//,tmp; - for (int i = 0; i < MVL; i++) - { - n = normals[i]; - t = tan1[i]; - - Vector3.OrthoNormalize(ref n, ref t); - tangents[i].x = t.x; - tangents[i].y = t.y; - tangents[i].z = t.z; - tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f; - - // tmp = (t - n * Vector3.Dot(n, t)).normalized; - // tangents[i] = new Vector4(tmp.x, tmp.y, tmp.z); - // tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f; - } - - return tangents; - } - - public static void ProcessTangents(ref Mesh tMesh) - { - Vector3[] tVerts = tMesh.vertices; - Vector2[] tUV = tMesh.uv; - Vector3[] tNormals = tMesh.normals; - int[] tTris = tMesh.triangles; - - tMesh.tangents = ProcessTangents(tTris, tNormals, tUV, tVerts); - } - #endregion - - #region "Default directory for library etc" - public static string Dir_GetBase() - { - return Application.dataPath.Replace("/Assets", "/GSD/"); - } - public static string Dir_GetTH() - { - string xPath = Dir_GetBase() + "TH/"; - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - return xPath; - } - - public static string Dir_GetLibraryBase() - { - return GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Library/"; - } - public static string Dir_GetLibrary() - { - string xPath = Dir_GetLibraryBase(); - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - return xPath; - } - - public static void Dir_GetLibrary_CheckSpecialDirs() - { - string xPath = Dir_GetLibraryBase() + "Q/"; - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - xPath = Dir_GetLibraryBase() + "W/"; - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - xPath = Dir_GetLibraryBase() + "B/"; - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - xPath = Dir_GetLibraryBase() + "B/W/"; - if (!Directory.Exists(xPath)) - { - Directory.CreateDirectory(xPath); - } - } - #endregion - - public static void ForceCollection(bool bWait = false) - { -#if UNITY_EDITOR - System.GC.Collect(); - if (bWait) - { - System.GC.WaitForPendingFinalizers(); - } - Resources.UnloadUnusedAssets(); -#endif - } - } +#region "Imports" +using UnityEngine; +using System.Collections; +using System.Xml; +using System.Xml.Serialization; +using System.IO; +using System.Text; +#endregion + + +namespace GSD +{ + public static class GSDRootUtil + { + /// + /// Smooths the input parameter t. + /// If less than k1 ir greater than k2, it uses a sin. + /// Between k1 and k2 it uses linear interp. + /// + public static float Ease(float t, float k1, float k2) + { + float f; + float s; + + + f = k1 * 2 / Mathf.PI + k2 - k1 + (1.0f - k2) * 2 / Mathf.PI; + + if (t < k1) + { + s = k1 * (2 / Mathf.PI) * (Mathf.Sin((t / k1) * Mathf.PI / 2 - Mathf.PI / 2) + 1); + } + else if (t < k2) + { + s = (2 * k1 / Mathf.PI + t - k1); + } + else + { + s = 2 * k1 / Mathf.PI + k2 - k1 + ((1 - k2) * (2 / Mathf.PI)) * Mathf.Sin(((t - k2) / (1.0f - k2)) * Mathf.PI / 2); + } + + return (s / f); + } + + + /// + /// Returns true if the lines intersect, otherwise false. + /// + /// Line 1 start. + /// Line 1 end. + /// Line 2 start. + /// Line 2 end. + /// If the lines intersect, intersectionPoint holds the intersection point. + /// + public static bool Intersects2D(ref Vector2 Line1S, ref Vector2 Line1E, ref Vector2 Line2S, ref Vector2 Line2E, out Vector2 intersectionPoint) + { + float firstLineSlopeX, firstLineSlopeY, secondLineSlopeX, secondLineSlopeY; + + firstLineSlopeX = Line1E.x - Line1S.x; + firstLineSlopeY = Line1E.y - Line1S.y; + + secondLineSlopeX = Line2E.x - Line2S.x; + secondLineSlopeY = Line2E.y - Line2S.y; + + float s, t; + s = (-firstLineSlopeY * (Line1S.x - Line2S.x) + firstLineSlopeX * (Line1S.y - Line2S.y)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); + t = (secondLineSlopeX * (Line1S.y - Line2S.y) - secondLineSlopeY * (Line1S.x - Line2S.x)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY); + + if (s >= 0 && s <= 1 && t >= 0 && t <= 1) + { + float intersectionPointX = Line1S.x + (t * firstLineSlopeX); + float intersectionPointY = Line1S.y + (t * firstLineSlopeY); + + // Collision detected + intersectionPoint = new Vector2(intersectionPointX, intersectionPointY); + return true; + } + + intersectionPoint = Vector2.zero; + return false; // No collision + } + + + public static string GetPrefabString(GameObject tObj) + { + string tString = ""; +#if UNITY_EDITOR + if (tObj != null) + { + tString = UnityEditor.AssetDatabase.GetAssetPath(tObj); + if (tString == null || tString.Length < 1) + { +#if UNITY_2018_2_OR_NEWER + Object parentObject = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(tObj); +#else + Object parentObject = UnityEditor.PrefabUtility.GetPrefabParent(tObj); +#endif + tString = UnityEditor.AssetDatabase.GetAssetPath(parentObject); + } + } +#endif + return tString; + } + + + #region "Float comparisons" + public static bool IsApproximately(float a, float b) + { + return IsApproximately(a, b, 0.01f); + } + + + public static bool IsApproximately(float a, float b, float tolerance) + { + return Mathf.Abs(a - b) < tolerance; + } + #endregion + + + #region "XML" + public static void CreateXML(ref string tPath, object pObject) + { +#if UNITY_WEBPLAYER + return; +#else + string tData = SerializeObject(ref pObject); + StreamWriter writer; + FileInfo t = new FileInfo(tPath); + if (!t.Exists) + { + writer = t.CreateText(); + } + else + { + t.Delete(); + writer = t.CreateText(); + } + writer.Write(tData); + writer.Close(); +#endif + } + + + public static string GetString(object pObject) + { + string tData = SerializeObject(ref pObject); + return tData; + } + + + public static object LoadXML(ref string tPath) + { +#if UNITY_WEBPLAYER + return null; +#else + StreamReader r = File.OpenText(tPath); + string _info = r.ReadToEnd(); + r.Close(); + object tObject = DeserializeObject(_info); + return tObject; +#endif + } + + + public static object LoadData(ref string _info) + { + object tObject = DeserializeObject(_info); + return tObject; + } + + + public static void DeleteLibraryXML(string tName, bool bIsExtrusion) + { +#if UNITY_WEBPLAYER + return; +#else + string tPath; + if (bIsExtrusion) + { + tPath = Application.dataPath + "/RoadArchitect/Library/ESO" + tName + ".gsd"; + } + else + { + tPath = Application.dataPath + "/RoadArchitect/Library/EOM" + tName + ".gsd"; + } + if (File.Exists(tPath)) + { + File.Delete(tPath); + } +#endif + } + + + private static string SerializeObject(ref object pObject) + { + string XmlizedString = null; + MemoryStream memoryStream = new MemoryStream(); + XmlSerializer xs = new XmlSerializer(typeof(T)); + XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); + xs.Serialize(xmlTextWriter, pObject); + memoryStream = (MemoryStream) xmlTextWriter.BaseStream; + XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray()); + return XmlizedString; + } + + + private static object DeserializeObject(string pXmlizedString) + { + XmlSerializer xs = new XmlSerializer(typeof(T)); + MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString)); + return xs.Deserialize(memoryStream); + } + + + private static string UTF8ByteArrayToString(byte[] characters) + { + UTF8Encoding encoding = new UTF8Encoding(); + string constructedString = encoding.GetString(characters); + return (constructedString); + } + + + private static byte[] StringToUTF8ByteArray(string pXmlString) + { + UTF8Encoding encoding = new UTF8Encoding(); + byte[] byteArray = encoding.GetBytes(pXmlString); + return byteArray; + } + #endregion + + + #region "Mesh tangents" + //Thread safe because local scope and by val params + public static Vector4[] ProcessTangents(int[] tris, Vector3[] normals, Vector2[] uvs, Vector3[] verts) + { + int MVL = verts.Length; + if (MVL == 0) + { + return new Vector4[0]; + } + int triangleCount = tris.Length;// mesh.triangles.Length / 3; + Vector3[] tan1 = new Vector3[MVL]; + Vector3[] tan2 = new Vector3[MVL]; + Vector4[] tangents = new Vector4[MVL]; + int i1, i2, i3; + Vector3 v1, v2, v3; + Vector2 w1, w2, w3; + float x1, x2, y1, y2, z1, z2, s1, s2, t1, t2, r; + Vector3 sdir, tdir; + float div = 0f; + for (int a = 0; a < triangleCount; a += 3) + { + i1 = tris[a + 0]; + i2 = tris[a + 1]; + i3 = tris[a + 2]; + + v1 = verts[i1]; + v2 = verts[i2]; + v3 = verts[i3]; + + w1 = uvs[i1]; + w2 = uvs[i2]; + w3 = uvs[i3]; + + x1 = v2.x - v1.x; + x2 = v3.x - v1.x; + y1 = v2.y - v1.y; + y2 = v3.y - v1.y; + z1 = v2.z - v1.z; + z2 = v3.z - v1.z; + + s1 = w2.x - w1.x; + s2 = w3.x - w1.x; + t1 = w2.y - w1.y; + t2 = w3.y - w1.y; + + // r = 1.0f / (s1 * t2 - s2 * t1); + div = (s1 * t2 - s2 * t1); + r = div == 0.0f ? 0.0f : 1.0f / div; + + sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); + tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); + + tan1[i1] += sdir; + tan1[i2] += sdir; + tan1[i3] += sdir; + + tan2[i1] += tdir; + tan2[i2] += tdir; + tan2[i3] += tdir; + } + + Vector3 n, t;//,tmp; + for (int index = 0; index < MVL; index++) + { + n = normals[index]; + t = tan1[index]; + + Vector3.OrthoNormalize(ref n, ref t); + tangents[index].x = t.x; + tangents[index].y = t.y; + tangents[index].z = t.z; + tangents[index].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[index]) < 0.0f) ? -1.0f : 1.0f; + + // tmp = (t - n * Vector3.Dot(n, t)).normalized; + // tangents[i] = new Vector4(tmp.x, tmp.y, tmp.z); + // tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f; + } + + return tangents; + } + + + public static void ProcessTangents(ref Mesh tMesh) + { + Vector3[] tVerts = tMesh.vertices; + Vector2[] tUV = tMesh.uv; + Vector3[] tNormals = tMesh.normals; + int[] tTris = tMesh.triangles; + + tMesh.tangents = ProcessTangents(tTris, tNormals, tUV, tVerts); + } + #endregion + + + #region "Default directory for library etc" + public static string Dir_GetBase() + { + return Application.dataPath.Replace("/Assets", "/GSD/"); + } + + + public static string Dir_GetTH() + { + string xPath = Dir_GetBase() + "TH/"; + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + return xPath; + } + + + public static string Dir_GetLibraryBase() + { + return GSD.Roads.GSDRoadUtilityEditor.GetBasePath() + "/Editor/Library/"; + } + + + public static string Dir_GetLibrary() + { + string xPath = Dir_GetLibraryBase(); + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + return xPath; + } + + + public static void Dir_GetLibrary_CheckSpecialDirs() + { + string xPath = Dir_GetLibraryBase() + "Q/"; + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + xPath = Dir_GetLibraryBase() + "W/"; + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + xPath = Dir_GetLibraryBase() + "B/"; + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + xPath = Dir_GetLibraryBase() + "B/W/"; + if (!Directory.Exists(xPath)) + { + Directory.CreateDirectory(xPath); + } + } + #endregion + + + public static void ForceCollection(bool bWait = false) + { +#if UNITY_EDITOR + System.GC.Collect(); + if (bWait) + { + System.GC.WaitForPendingFinalizers(); + } + Resources.UnloadUnusedAssets(); +#endif + } + } } \ No newline at end of file diff --git a/GSDTerrain.cs b/GSDTerrain.cs index 6c2a9b11..d7dc69b8 100755 --- a/GSDTerrain.cs +++ b/GSDTerrain.cs @@ -1,100 +1,116 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -#endif -[ExecuteInEditMode] -public class GSDTerrain : MonoBehaviour -{ -#if UNITY_EDITOR - [SerializeField] - [HideInInspector] - private int mGSDID = -1; - - public int GSDID - { - get { return mGSDID; } - set - { - //Do nothing. - } - } - - [HideInInspector] - public Terrain tTerrain; - - //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 SplatSkipBridges = false; - public bool SplatSkipTunnels = false; - public bool SplatSingleRoad = false; - public int SplatSingleChoiceIndex = 0; - public string RoadSingleChoiceUID = ""; - - void OnEnable() - { - CheckID(); - if (!tTerrain) { tTerrain = transform.gameObject.GetComponent(); } - } - - public void CheckID() - { - if (Application.isEditor) - { - if (mGSDID < 0) - { - mGSDID = GetNewID(); - } - if (!tTerrain) { tTerrain = transform.gameObject.GetComponent(); } - } - } - private int GetNewID() - { - Object[] tTerrainObjs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); - List AllIDS = new List(); - foreach (GSDTerrain TID in tTerrainObjs) - { - if (TID.GSDID > 0) - { - AllIDS.Add(TID.GSDID); - } - } - - bool bNotDone = true; - int SpamChecker = 0; - int SpamCheckerMax = AllIDS.Count + 64; - int tRand; - while (bNotDone) - { - if (SpamChecker > SpamCheckerMax) - { - Debug.LogError("Failed to generate GSDTerrainID"); - break; - } - tRand = Random.Range(1, 2000000000); - if (!AllIDS.Contains(tRand)) - { - bNotDone = false; - return tRand; - } - SpamChecker += 1; - } - - return -1; - } -#endif - - void Start() - { -#if UNITY_EDITOR - this.enabled = true; - CheckID(); - if (!tTerrain) { tTerrain = transform.gameObject.GetComponent(); } -#else - this.enabled = false; -#endif - } +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +#endif + + +[ExecuteInEditMode] +public class GSDTerrain : MonoBehaviour +{ +#if UNITY_EDITOR + [SerializeField] + [HideInInspector] + private int mGSDID = -1; + + public int GSDID + { + get { return mGSDID; } + set + { + //Do nothing. + } + } + + [HideInInspector] + public Terrain tTerrain; + + //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 SplatSkipBridges = false; + public bool SplatSkipTunnels = false; + public bool SplatSingleRoad = false; + public int SplatSingleChoiceIndex = 0; + public string RoadSingleChoiceUID = ""; + + + void OnEnable() + { + CheckID(); + if (!tTerrain) + { + tTerrain = transform.gameObject.GetComponent(); + } + } + + + public void CheckID() + { + if (Application.isEditor) + { + if (mGSDID < 0) + { + mGSDID = GetNewID(); + } + if (!tTerrain) + { + tTerrain = transform.gameObject.GetComponent(); + } + } + } + + + private int GetNewID() + { + Object[] tTerrainObjs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); + List AllIDS = new List(); + foreach (GSDTerrain TID in tTerrainObjs) + { + if (TID.GSDID > 0) + { + AllIDS.Add(TID.GSDID); + } + } + + bool bNotDone = true; + int SpamChecker = 0; + int SpamCheckerMax = AllIDS.Count + 64; + int tRand; + while (bNotDone) + { + if (SpamChecker > SpamCheckerMax) + { + Debug.LogError("Failed to generate GSDTerrainID"); + break; + } + tRand = Random.Range(1, 2000000000); + if (!AllIDS.Contains(tRand)) + { + bNotDone = false; + return tRand; + } + SpamChecker += 1; + } + + return -1; + } +#endif + + + void Start() + { +#if UNITY_EDITOR + this.enabled = true; + CheckID(); + if (!tTerrain) + { + tTerrain = transform.gameObject.GetComponent(); + } +#else + this.enabled = false; +#endif + } } \ No newline at end of file diff --git a/GSDTrafficLightController.cs b/GSDTrafficLightController.cs index 8c6b4fda..4bedf72d 100755 --- a/GSDTrafficLightController.cs +++ b/GSDTrafficLightController.cs @@ -1,514 +1,558 @@ -using UnityEngine; -using System.Collections; - -[System.Serializable] -public class GSDTrafficLightController -{ - public GameObject LightLeftObj; - public GameObject LightRightObj; - public GameObject[] LightsObj; - - public MeshRenderer MR_Left; - public MeshRenderer MR_Right; - public MeshRenderer[] MR_MainsStorage; - public MeshRenderer MR_Main; - - public Light LightLeft_R; - public Light LightLeft_Y; - public Light LightLeft_G; - - public Light LightRight_R; - public Light LightRight_Y; - public Light LightRight_G; - - public Light[] Lights_R; - public Light[] Lights_Y; - public Light[] Lights_G; - - //Enums for controller: - public enum iLightControllerEnum { Regular, LeftTurn, MasterLeft1, MasterLeft2, Red } - //Enums for actual lights: - public enum iLightStatusEnum { Regular, LeftTurn, MasterLeft, Red, RightTurn } - public enum iLightSubStatusEnum { Green, Yellow, Red } - public enum iLightYieldSubStatusEnum { Green, Yellow, Red, YellowTurn, GreenTurn } - public iLightStatusEnum iLightStatus = iLightStatusEnum.Red; - public iLightSubStatusEnum iLightSubStatus = iLightSubStatusEnum.Green; - - bool bLeft = false; - bool bRight = false; - bool bMain = false; - bool bUseSharedMaterial = false; - bool bLeftTurnYieldOnGreen = true; - bool bLightsEnabled = true; - - #region "Constructor" - public GSDTrafficLightController(ref GameObject _LightLeft, ref GameObject _LightRight, ref GameObject[] _Lights, ref MeshRenderer _MR_Left, ref MeshRenderer _MR_Right, ref MeshRenderer[] MR_Mains) - { - LightLeftObj = _LightLeft; - LightRightObj = _LightRight; - LightsObj = _Lights; - - MR_Left = _MR_Left; - MR_Right = _MR_Right; - MR_MainsStorage = MR_Mains; - MR_Main = MR_Mains[0]; - - Light[] tLights; - if (LightLeftObj != null) - { - tLights = LightLeftObj.transform.GetComponentsInChildren(); - foreach (Light tLight in tLights) - { - if (tLight.transform.name.ToLower().Contains("redlight")) - { - LightLeft_R = tLight; - } - if (tLight.transform.name.ToLower().Contains("yellowlight")) - { - LightLeft_Y = tLight; - } - if (tLight.transform.name.ToLower().Contains("greenl")) - { - LightLeft_G = tLight; - } - } - } - if (LightRightObj != null) - { - tLights = LightRightObj.transform.GetComponentsInChildren(); - foreach (Light tLight in tLights) - { - if (tLight.transform.name.ToLower().Contains("redlight")) - { - LightRight_R = tLight; - } - if (tLight.transform.name.ToLower().Contains("yellowlight")) - { - LightRight_Y = tLight; - } - if (tLight.transform.name.ToLower().Contains("greenl")) - { - LightRight_G = tLight; - } - } - } - - int mCount = LightsObj.Length; - Lights_R = new Light[mCount]; - Lights_Y = new Light[mCount]; - Lights_G = new Light[mCount]; - for (int i = 0; i < mCount; i++) - { - tLights = LightsObj[i].transform.GetComponentsInChildren(); - foreach (Light tLight in tLights) - { - if (tLight.transform.name.ToLower().Contains("redlight")) - { - Lights_R[i] = tLight; - } - if (tLight.transform.name.ToLower().Contains("yellowlight")) - { - Lights_Y[i] = tLight; - } - if (tLight.transform.name.ToLower().Contains("greenl")) - { - Lights_G[i] = tLight; - } - } - } - } - #endregion - - #region "Update" - public void UpdateLights(iLightStatusEnum tLightStatus, iLightSubStatusEnum tLightSubStatus, bool _bLightsEnabled) - { - bLightsEnabled = _bLightsEnabled; - iLightStatus = tLightStatus; - iLightSubStatus = tLightSubStatus; - bUseSharedMaterial = false; - switch (iLightStatus) - { - case iLightStatusEnum.Regular: - TriggerRegular(); - break; - case iLightStatusEnum.LeftTurn: - TriggerLeftTurn(); - break; - case iLightStatusEnum.MasterLeft: - TriggerMasterLeft(); - break; - case iLightStatusEnum.Red: - TriggerRed(); - break; - case iLightStatusEnum.RightTurn: - TriggerRightTurn(); - break; - } - } - #endregion - - #region "Triggers" - private void TriggerRegular() - { - if (bMain) - { - MRChange(ref MR_Main, iLightSubStatus); - for (int i = 1; i < MR_MainsStorage.Length; i++) - { - MRChange(ref MR_MainsStorage[i], iLightSubStatus); - } - LightChange(0, iLightSubStatus); - } - if (bLeft) - { - if (bLeftTurnYieldOnGreen) - { - if (iLightSubStatus == iLightSubStatusEnum.Green) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.Green); - } - else if (iLightSubStatus == iLightSubStatusEnum.Yellow) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.Yellow); - } - } - else - { - MRChange(ref MR_Left, iLightSubStatusEnum.Red); - LightChange(1, iLightSubStatusEnum.Red); - } - } - if (bRight) - { - MRChange(ref MR_Right, iLightSubStatusEnum.Red); - LightChange(2, iLightSubStatusEnum.Red); - } - } - - private void TriggerLeftTurn() - { - if (bMain) - { - MRChange(ref MR_Main, iLightSubStatusEnum.Red); - for (int i = 1; i < MR_MainsStorage.Length; i++) - { - MRChange(ref MR_MainsStorage[i], iLightSubStatusEnum.Red); - } - LightChange(0, iLightSubStatusEnum.Red); - } - if (bLeft) - { - if (bLeftTurnYieldOnGreen) - { - if (iLightSubStatus == iLightSubStatusEnum.Green) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.GreenTurn); - } - else if (iLightSubStatus == iLightSubStatusEnum.Yellow) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.YellowTurn); - } - LightChange(1, iLightSubStatus); - } - else - { - MRChange(ref MR_Left, iLightSubStatus); - LightChange(1, iLightSubStatus); - } - } - if (bRight) - { - MRChange(ref MR_Right, iLightSubStatusEnum.Red); - LightChange(2, iLightSubStatusEnum.Red); - } - } - - private void TriggerMasterLeft() - { - if (bMain) - { - MRChange(ref MR_Main, iLightSubStatus); - for (int i = 1; i < MR_MainsStorage.Length; i++) - { - MRChange(ref MR_MainsStorage[i], iLightSubStatus); - } - LightChange(0, iLightSubStatus); - } - if (bLeft) - { - if (iLightSubStatus == iLightSubStatusEnum.Green) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.GreenTurn); - } - else if (iLightSubStatus == iLightSubStatusEnum.Yellow) - { - MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.YellowTurn); - } - LightChange(1, iLightSubStatus); - } - if (bRight) - { - MRChange(ref MR_Right, iLightSubStatus); - LightChange(2, iLightSubStatus); - } - } - - private void TriggerRightTurn() - { - if (bMain) - { - MRChange(ref MR_Main, iLightSubStatusEnum.Red); - for (int i = 1; i < MR_MainsStorage.Length; i++) - { - MRChange(ref MR_MainsStorage[i], iLightSubStatusEnum.Red); - } - LightChange(0, iLightSubStatusEnum.Red); - } - if (bLeft) - { - MRChange(ref MR_Left, iLightSubStatusEnum.Red); - LightChange(1, iLightSubStatusEnum.Red); - } - if (bRight) - { - MRChange(ref MR_Right, iLightSubStatus); - LightChange(2, iLightSubStatus); - } - } - - private void TriggerRed() - { - if (bMain) - { - MRChange(ref MR_Main, iLightSubStatusEnum.Red); - for (int i = 1; i < MR_MainsStorage.Length; i++) - { - MRChange(ref MR_MainsStorage[i], iLightSubStatusEnum.Red); - } - LightChange(0, iLightSubStatusEnum.Red); - } - if (bLeft) - { - MRChange(ref MR_Left, iLightSubStatusEnum.Red); - LightChange(1, iLightSubStatusEnum.Red); - } - if (bRight) - { - MRChange(ref MR_Right, iLightSubStatusEnum.Red); - LightChange(2, iLightSubStatusEnum.Red); - } - } - #endregion - - private void MRChange(ref MeshRenderer MR, iLightSubStatusEnum iLSSE) - { - if (bUseSharedMaterial) - { - if (iLSSE == iLightSubStatusEnum.Green) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.667f, 0f); - } - else if (iLSSE == iLightSubStatusEnum.Yellow) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.334f, 0f); - } - else if (iLSSE == iLightSubStatusEnum.Red) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0f, 0f); - } - } - else - { - if (iLSSE == iLightSubStatusEnum.Green) - { - MR.material.mainTextureOffset = new Vector2(0.667f, 0f); - } - else if (iLSSE == iLightSubStatusEnum.Yellow) - { - MR.material.mainTextureOffset = new Vector2(0.334f, 0f); - } - else if (iLSSE == iLightSubStatusEnum.Red) - { - MR.material.mainTextureOffset = new Vector2(0f, 0f); - } - } - } - - private void MRChangeLeftYield(ref MeshRenderer MR, iLightYieldSubStatusEnum iLYSSE) - { - if (bUseSharedMaterial) - { - if (iLYSSE == iLightYieldSubStatusEnum.Green) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.667f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.Yellow) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.334f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.Red) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.YellowTurn) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.6f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.GreenTurn) - { - MR.sharedMaterial.mainTextureOffset = new Vector2(0.8f, 0f); - } - } - else - { - if (iLYSSE == iLightYieldSubStatusEnum.Green) - { - MR.material.mainTextureOffset = new Vector2(0.4f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.Yellow) - { - MR.material.mainTextureOffset = new Vector2(0.2f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.Red) - { - MR.material.mainTextureOffset = new Vector2(0f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.YellowTurn) - { - MR.material.mainTextureOffset = new Vector2(0.6f, 0f); - } - else if (iLYSSE == iLightYieldSubStatusEnum.GreenTurn) - { - MR.material.mainTextureOffset = new Vector2(0.8f, 0f); - } - } - } - - private void LightChange(int tIndex, iLightSubStatusEnum iLSSE) - { - if (!bLightsEnabled) - { - int mCount = MR_MainsStorage.Length; - for (int i = 0; i < mCount; i++) - { - Lights_R[i].enabled = false; - Lights_Y[i].enabled = false; - Lights_G[i].enabled = false; - } - if (LightLeft_R != null) { LightLeft_R.enabled = false; } - if (LightLeft_Y != null) { LightLeft_Y.enabled = false; } - if (LightLeft_G != null) { LightLeft_G.enabled = false; } - if (LightRight_R != null) { LightRight_R.enabled = false; } - if (LightRight_Y != null) { LightRight_Y.enabled = false; } - if (LightRight_G != null) { LightRight_G.enabled = false; } - return; - } - - if (tIndex == 0) - { - //Main: - int mCount = MR_MainsStorage.Length; - for (int i = 0; i < mCount; i++) - { - LightChangeHelper(ref Lights_R[i], ref Lights_Y[i], ref Lights_G[i], iLSSE); - } - } - else if (tIndex == 1) - { - //Left: - LightChangeHelper(ref LightLeft_R, ref LightLeft_Y, ref LightLeft_G, iLSSE); - } - else if (tIndex == 2) - { - //Right: - LightChangeHelper(ref LightRight_R, ref LightRight_Y, ref LightRight_G, iLSSE); - } - } - - private void LightChangeHelper(ref Light tRed, ref Light tYellow, ref Light tGreen, iLightSubStatusEnum iLSSE) - { - if (iLSSE == iLightSubStatusEnum.Green) - { - tRed.enabled = false; - tYellow.enabled = false; - tGreen.enabled = true; - } - else if (iLSSE == iLightSubStatusEnum.Yellow) - { - tRed.enabled = false; - tYellow.enabled = true; - tGreen.enabled = false; - } - else if (iLSSE == iLightSubStatusEnum.Red) - { - tRed.enabled = true; - tYellow.enabled = false; - tGreen.enabled = false; - } - } - - #region "Setup" - public void Setup(bool bLeftYield) - { - SetupObject(MR_Left); - SetupObject(MR_Right); - SetupMainObjects(); - bLeft = (MR_Left != null); - bRight = (MR_Right != null); - bMain = (MR_Main != null); - bLeftTurnYieldOnGreen = bLeftYield; - } - - private void SetupMainObjects() - { - if (MR_Main == null) { return; } - int mCount = MR_MainsStorage.Length; - if (mCount == 0) { return; } - SetupObject(MR_Main); - if (mCount > 1) - { - for (int i = 1; i < mCount; i++) - { - if (bUseSharedMaterial) - { - MR_MainsStorage[i].sharedMaterial = MR_Main.sharedMaterial; - } - else - { - Material[] materials = new Material[1]; - materials[0] = MR_Main.materials[0]; - MR_MainsStorage[i].materials = materials; - - } - - } - } - } - - private void SetupObject(MeshRenderer MR) - { - if (MR != null) { MR.material = MR.material; } - } - #endregion -} - -public class GSDTrafficLightSequence -{ - public bool bLightMasterPath1 = true; - public GSDTrafficLightController.iLightControllerEnum iLightController = GSDTrafficLightController.iLightControllerEnum.Regular; - public GSDTrafficLightController.iLightSubStatusEnum iLightSubcontroller = GSDTrafficLightController.iLightSubStatusEnum.Green; - public float tTime = 10f; - - public GSDTrafficLightSequence(bool bPath1, GSDTrafficLightController.iLightControllerEnum tLightController, GSDTrafficLightController.iLightSubStatusEnum tLightSubcontroller, float xTime) - { - bLightMasterPath1 = bPath1; - iLightController = tLightController; - iLightSubcontroller = tLightSubcontroller; - tTime = xTime; - } - - public string ToStringGSD() - { - return "Path1: " + bLightMasterPath1 + " iLightController: " + iLightController.ToString() + " iLightSubcontroller: " + iLightSubcontroller.ToString() + " tTime: " + tTime.ToString("0F"); - } +using UnityEngine; +using System.Collections; + + +[System.Serializable] +public class GSDTrafficLightController +{ + public GameObject LightLeftObj; + public GameObject LightRightObj; + public GameObject[] LightsObj; + + public MeshRenderer MR_Left; + public MeshRenderer MR_Right; + public MeshRenderer[] MR_MainsStorage; + public MeshRenderer MR_Main; + + public Light LightLeft_R; + public Light LightLeft_Y; + public Light LightLeft_G; + + public Light LightRight_R; + public Light LightRight_Y; + public Light LightRight_G; + + public Light[] Lights_R; + public Light[] Lights_Y; + public Light[] Lights_G; + + //Enums for controller: + public enum iLightControllerEnum { Regular, LeftTurn, MasterLeft1, MasterLeft2, Red } + //Enums for actual lights: + public enum iLightStatusEnum { Regular, LeftTurn, MasterLeft, Red, RightTurn } + public enum iLightSubStatusEnum { Green, Yellow, Red } + public enum iLightYieldSubStatusEnum { Green, Yellow, Red, YellowTurn, GreenTurn } + public iLightStatusEnum iLightStatus = iLightStatusEnum.Red; + public iLightSubStatusEnum iLightSubStatus = iLightSubStatusEnum.Green; + + bool bLeft = false; + bool bRight = false; + bool bMain = false; + bool bUseSharedMaterial = false; + bool bLeftTurnYieldOnGreen = true; + bool bLightsEnabled = true; + + + #region "Constructor" + public GSDTrafficLightController(ref GameObject _LightLeft, ref GameObject _LightRight, ref GameObject[] _Lights, ref MeshRenderer _MR_Left, ref MeshRenderer _MR_Right, ref MeshRenderer[] MR_Mains) + { + LightLeftObj = _LightLeft; + LightRightObj = _LightRight; + LightsObj = _Lights; + + MR_Left = _MR_Left; + MR_Right = _MR_Right; + MR_MainsStorage = MR_Mains; + MR_Main = MR_Mains[0]; + + Light[] tLights; + if (LightLeftObj != null) + { + tLights = LightLeftObj.transform.GetComponentsInChildren(); + foreach (Light tLight in tLights) + { + if (tLight.transform.name.ToLower().Contains("redlight")) + { + LightLeft_R = tLight; + } + if (tLight.transform.name.ToLower().Contains("yellowlight")) + { + LightLeft_Y = tLight; + } + if (tLight.transform.name.ToLower().Contains("greenl")) + { + LightLeft_G = tLight; + } + } + } + if (LightRightObj != null) + { + tLights = LightRightObj.transform.GetComponentsInChildren(); + foreach (Light tLight in tLights) + { + if (tLight.transform.name.ToLower().Contains("redlight")) + { + LightRight_R = tLight; + } + if (tLight.transform.name.ToLower().Contains("yellowlight")) + { + LightRight_Y = tLight; + } + if (tLight.transform.name.ToLower().Contains("greenl")) + { + LightRight_G = tLight; + } + } + } + + int mCount = LightsObj.Length; + Lights_R = new Light[mCount]; + Lights_Y = new Light[mCount]; + Lights_G = new Light[mCount]; + for (int index = 0; index < mCount; index++) + { + tLights = LightsObj[index].transform.GetComponentsInChildren(); + foreach (Light tLight in tLights) + { + if (tLight.transform.name.ToLower().Contains("redlight")) + { + Lights_R[index] = tLight; + } + if (tLight.transform.name.ToLower().Contains("yellowlight")) + { + Lights_Y[index] = tLight; + } + if (tLight.transform.name.ToLower().Contains("greenl")) + { + Lights_G[index] = tLight; + } + } + } + } + #endregion + + + #region "Update" + public void UpdateLights(iLightStatusEnum tLightStatus, iLightSubStatusEnum tLightSubStatus, bool _bLightsEnabled) + { + bLightsEnabled = _bLightsEnabled; + iLightStatus = tLightStatus; + iLightSubStatus = tLightSubStatus; + bUseSharedMaterial = false; + switch (iLightStatus) + { + case iLightStatusEnum.Regular: + TriggerRegular(); + break; + case iLightStatusEnum.LeftTurn: + TriggerLeftTurn(); + break; + case iLightStatusEnum.MasterLeft: + TriggerMasterLeft(); + break; + case iLightStatusEnum.Red: + TriggerRed(); + break; + case iLightStatusEnum.RightTurn: + TriggerRightTurn(); + break; + } + } + #endregion + + + #region "Triggers" + private void TriggerRegular() + { + if (bMain) + { + MRChange(ref MR_Main, iLightSubStatus); + for (int index = 1; index < MR_MainsStorage.Length; index++) + { + MRChange(ref MR_MainsStorage[index], iLightSubStatus); + } + LightChange(0, iLightSubStatus); + } + if (bLeft) + { + if (bLeftTurnYieldOnGreen) + { + if (iLightSubStatus == iLightSubStatusEnum.Green) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.Green); + } + else if (iLightSubStatus == iLightSubStatusEnum.Yellow) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.Yellow); + } + } + else + { + MRChange(ref MR_Left, iLightSubStatusEnum.Red); + LightChange(1, iLightSubStatusEnum.Red); + } + } + if (bRight) + { + MRChange(ref MR_Right, iLightSubStatusEnum.Red); + LightChange(2, iLightSubStatusEnum.Red); + } + } + + + private void TriggerLeftTurn() + { + if (bMain) + { + MRChange(ref MR_Main, iLightSubStatusEnum.Red); + for (int i = 1; i < MR_MainsStorage.Length; i++) + { + MRChange(ref MR_MainsStorage[i], iLightSubStatusEnum.Red); + } + LightChange(0, iLightSubStatusEnum.Red); + } + if (bLeft) + { + if (bLeftTurnYieldOnGreen) + { + if (iLightSubStatus == iLightSubStatusEnum.Green) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.GreenTurn); + } + else if (iLightSubStatus == iLightSubStatusEnum.Yellow) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.YellowTurn); + } + LightChange(1, iLightSubStatus); + } + else + { + MRChange(ref MR_Left, iLightSubStatus); + LightChange(1, iLightSubStatus); + } + } + if (bRight) + { + MRChange(ref MR_Right, iLightSubStatusEnum.Red); + LightChange(2, iLightSubStatusEnum.Red); + } + } + + + private void TriggerMasterLeft() + { + if (bMain) + { + MRChange(ref MR_Main, iLightSubStatus); + for (int index = 1; index < MR_MainsStorage.Length; index++) + { + MRChange(ref MR_MainsStorage[index], iLightSubStatus); + } + LightChange(0, iLightSubStatus); + } + if (bLeft) + { + if (iLightSubStatus == iLightSubStatusEnum.Green) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.GreenTurn); + } + else if (iLightSubStatus == iLightSubStatusEnum.Yellow) + { + MRChangeLeftYield(ref MR_Left, iLightYieldSubStatusEnum.YellowTurn); + } + LightChange(1, iLightSubStatus); + } + if (bRight) + { + MRChange(ref MR_Right, iLightSubStatus); + LightChange(2, iLightSubStatus); + } + } + + + private void TriggerRightTurn() + { + if (bMain) + { + MRChange(ref MR_Main, iLightSubStatusEnum.Red); + for (int index = 1; index < MR_MainsStorage.Length; index++) + { + MRChange(ref MR_MainsStorage[index], iLightSubStatusEnum.Red); + } + LightChange(0, iLightSubStatusEnum.Red); + } + if (bLeft) + { + MRChange(ref MR_Left, iLightSubStatusEnum.Red); + LightChange(1, iLightSubStatusEnum.Red); + } + if (bRight) + { + MRChange(ref MR_Right, iLightSubStatus); + LightChange(2, iLightSubStatus); + } + } + + + private void TriggerRed() + { + if (bMain) + { + MRChange(ref MR_Main, iLightSubStatusEnum.Red); + for (int index = 1; index < MR_MainsStorage.Length; index++) + { + MRChange(ref MR_MainsStorage[index], iLightSubStatusEnum.Red); + } + LightChange(0, iLightSubStatusEnum.Red); + } + if (bLeft) + { + MRChange(ref MR_Left, iLightSubStatusEnum.Red); + LightChange(1, iLightSubStatusEnum.Red); + } + if (bRight) + { + MRChange(ref MR_Right, iLightSubStatusEnum.Red); + LightChange(2, iLightSubStatusEnum.Red); + } + } + #endregion + + + private void MRChange(ref MeshRenderer MR, iLightSubStatusEnum iLSSE) + { + if (bUseSharedMaterial) + { + if (iLSSE == iLightSubStatusEnum.Green) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.667f, 0f); + } + else if (iLSSE == iLightSubStatusEnum.Yellow) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.334f, 0f); + } + else if (iLSSE == iLightSubStatusEnum.Red) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0f, 0f); + } + } + else + { + if (iLSSE == iLightSubStatusEnum.Green) + { + MR.material.mainTextureOffset = new Vector2(0.667f, 0f); + } + else if (iLSSE == iLightSubStatusEnum.Yellow) + { + MR.material.mainTextureOffset = new Vector2(0.334f, 0f); + } + else if (iLSSE == iLightSubStatusEnum.Red) + { + MR.material.mainTextureOffset = new Vector2(0f, 0f); + } + } + } + + + private void MRChangeLeftYield(ref MeshRenderer MR, iLightYieldSubStatusEnum iLYSSE) + { + if (bUseSharedMaterial) + { + if (iLYSSE == iLightYieldSubStatusEnum.Green) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.667f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.Yellow) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.334f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.Red) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.YellowTurn) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.6f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.GreenTurn) + { + MR.sharedMaterial.mainTextureOffset = new Vector2(0.8f, 0f); + } + } + else + { + if (iLYSSE == iLightYieldSubStatusEnum.Green) + { + MR.material.mainTextureOffset = new Vector2(0.4f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.Yellow) + { + MR.material.mainTextureOffset = new Vector2(0.2f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.Red) + { + MR.material.mainTextureOffset = new Vector2(0f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.YellowTurn) + { + MR.material.mainTextureOffset = new Vector2(0.6f, 0f); + } + else if (iLYSSE == iLightYieldSubStatusEnum.GreenTurn) + { + MR.material.mainTextureOffset = new Vector2(0.8f, 0f); + } + } + } + + + private void LightChange(int tIndex, iLightSubStatusEnum iLSSE) + { + if (!bLightsEnabled) + { + int mCount = MR_MainsStorage.Length; + for (int index = 0; index < mCount; index++) + { + Lights_R[index].enabled = false; + Lights_Y[index].enabled = false; + Lights_G[index].enabled = false; + } + if (LightLeft_R != null) + { + LightLeft_R.enabled = false; + } + if (LightLeft_Y != null) + { + LightLeft_Y.enabled = false; + } + if (LightLeft_G != null) + { + LightLeft_G.enabled = false; + } + if (LightRight_R != null) + { + LightRight_R.enabled = false; + } + if (LightRight_Y != null) + { + LightRight_Y.enabled = false; + } + if (LightRight_G != null) + { + LightRight_G.enabled = false; + } + return; + } + + if (tIndex == 0) + { + //Main: + int mCount = MR_MainsStorage.Length; + for (int index = 0; index < mCount; index++) + { + LightChangeHelper(ref Lights_R[index], ref Lights_Y[index], ref Lights_G[index], iLSSE); + } + } + else if (tIndex == 1) + { + //Left: + LightChangeHelper(ref LightLeft_R, ref LightLeft_Y, ref LightLeft_G, iLSSE); + } + else if (tIndex == 2) + { + //Right: + LightChangeHelper(ref LightRight_R, ref LightRight_Y, ref LightRight_G, iLSSE); + } + } + + + private void LightChangeHelper(ref Light tRed, ref Light tYellow, ref Light tGreen, iLightSubStatusEnum iLSSE) + { + if (iLSSE == iLightSubStatusEnum.Green) + { + tRed.enabled = false; + tYellow.enabled = false; + tGreen.enabled = true; + } + else if (iLSSE == iLightSubStatusEnum.Yellow) + { + tRed.enabled = false; + tYellow.enabled = true; + tGreen.enabled = false; + } + else if (iLSSE == iLightSubStatusEnum.Red) + { + tRed.enabled = true; + tYellow.enabled = false; + tGreen.enabled = false; + } + } + + + #region "Setup" + public void Setup(bool bLeftYield) + { + SetupObject(MR_Left); + SetupObject(MR_Right); + SetupMainObjects(); + bLeft = (MR_Left != null); + bRight = (MR_Right != null); + bMain = (MR_Main != null); + bLeftTurnYieldOnGreen = bLeftYield; + } + + + private void SetupMainObjects() + { + if (MR_Main == null) + { + return; + } + int mCount = MR_MainsStorage.Length; + if (mCount == 0) + { + return; + } + SetupObject(MR_Main); + if (mCount > 1) + { + for (int index = 1; index < mCount; index++) + { + if (bUseSharedMaterial) + { + MR_MainsStorage[index].sharedMaterial = MR_Main.sharedMaterial; + } + else + { + Material[] materials = new Material[1]; + materials[0] = MR_Main.materials[0]; + MR_MainsStorage[index].materials = materials; + + } + + } + } + } + + + private void SetupObject(MeshRenderer MR) + { + if (MR != null) + { + MR.material = MR.material; + } + } + #endregion +} + +public class GSDTrafficLightSequence +{ + public bool bLightMasterPath1 = true; + public GSDTrafficLightController.iLightControllerEnum iLightController = GSDTrafficLightController.iLightControllerEnum.Regular; + public GSDTrafficLightController.iLightSubStatusEnum iLightSubcontroller = GSDTrafficLightController.iLightSubStatusEnum.Green; + public float tTime = 10f; + + + public GSDTrafficLightSequence(bool bPath1, GSDTrafficLightController.iLightControllerEnum tLightController, GSDTrafficLightController.iLightSubStatusEnum tLightSubcontroller, float xTime) + { + bLightMasterPath1 = bPath1; + iLightController = tLightController; + iLightSubcontroller = tLightSubcontroller; + tTime = xTime; + } + + + public string ToStringGSD() + { + return "Path1: " + bLightMasterPath1 + " iLightController: " + iLightController.ToString() + " iLightSubcontroller: " + iLightSubcontroller.ToString() + " tTime: " + tTime.ToString("0F"); + } } \ No newline at end of file diff --git a/GSDUnitTests.cs b/GSDUnitTests.cs index bb12965a..b7bb5707 100755 --- a/GSDUnitTests.cs +++ b/GSDUnitTests.cs @@ -1,400 +1,413 @@ -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -using System.Collections; -using System.IO; -using System.Text; -using System.Runtime.Serialization.Formatters.Binary; -using System.Runtime.Serialization; -#endif -namespace GSD.Roads -{ -#if UNITY_EDITOR - public static class GSDUnitTests - { - private static GSDRoadSystem RoadSystem; - - /// - /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. - /// - public static void RoadArchitectUnitTests() - { - CleanupTests(); - - //Create new road system and turn off updates: - GameObject tRoadSystemObj = new GameObject("RoadArchitectSystem1"); - RoadSystem = tRoadSystemObj.AddComponent(); //Add road system component. - RoadSystem.opt_bAllowRoadUpdates = false; - - int numTests = 5; - double totalTestTime = 0f; - for (int i = 1; i <= numTests; i++) - { - UnityEngine.Debug.Log("Running test " + i); - double testTime = RunTest(i); - totalTestTime += testTime; - UnityEngine.Debug.Log("Test " + i + " complete. Test time: " + testTime + "ms"); - } - UnityEngine.Debug.Log("All tests completed. Total test time: " + totalTestTime + "ms"); - - //Turn updates back on and update road: - RoadSystem.opt_bAllowRoadUpdates = true; - RoadSystem.UpdateAllRoads(); - } - - - private static long RunTest(int test) - { - System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); - switch (test) - { - case 1: - RoadArchitectUnitTest1(); //Bridges - break; - case 2: - RoadArchitectUnitTest2(); //2L intersections - break; - case 3: - RoadArchitectUnitTest3(); //4L intersections - break; - case 4: - RoadArchitectUnitTest4(); //Large suspension bridge - break; - case 5: - RoadArchitectUnitTest5(); //Long road: - break; - } - stopwatch.Stop(); - long testTime = stopwatch.ElapsedMilliseconds; - return testTime; - } - - - public static void CleanupTests() - { - Debug.Log("Cleaning up tests"); - //Get the existing road system, if it exists: - GameObject GSDRS = (GameObject)GameObject.Find("RoadArchitectSystem1"); - DestroyTerrainHistory(GSDRS); - Object.DestroyImmediate(GSDRS); - FlattenTerrains(); - } - - - private static void DestroyTerrainHistory(GameObject GSDRS) - { - //Destroy the terrain histories: - if (GSDRS != null) - { - Object[] tRoads = GSDRS.GetComponents(); - foreach (GSDRoad xRoad in tRoads) - { - GSD.Roads.GSDTerraforming.TerrainsReset(xRoad); - } - } - } - - - private static void FlattenTerrains() - { - //Reset all terrains to 0,0 - Object[] zTerrains = Object.FindObjectsOfType(); - foreach (Terrain xTerrain in zTerrains) - { - xTerrain.terrainData.SetHeights(0, 0, new float[513, 513]); - } - } - - private static void RoadArchitectUnitTest1() - { - //Create node locations: - List nodeLocations = new List(); - int MaxCount = 18; - float tMod = 100f; - Vector3 xVect = new Vector3(50f, 40f, 50f); - for (int i = 0; i < MaxCount; i++) - { - //tLocs.Add(xVect + new Vector3(tMod * Mathf.Pow((float)i / ((float)MaxCount * 0.15f), 2f), 1f*((float)i*1.25f), tMod * i)); - nodeLocations.Add(xVect + new Vector3(tMod * Mathf.Pow((float)i / ((float)25 * 0.15f), 2f), 0f, tMod * i)); - } - - //Get road system create road: - GSDRoad tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - - //Bridge0: (Arch) - tRoad.GSDSpline.mNodes[4].bIsBridgeStart = true; - tRoad.GSDSpline.mNodes[4].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[7].bIsBridgeEnd = true; - tRoad.GSDSpline.mNodes[7].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[4].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[7]; - tRoad.GSDSpline.mNodes[4].LoadWizardObjectsFromLibrary("Arch12m-2L", true, true); - - //Bridge1: (Federal causeway) - tRoad.GSDSpline.mNodes[8].bIsBridgeStart = true; - tRoad.GSDSpline.mNodes[8].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[8].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[10]; - tRoad.GSDSpline.mNodes[8].LoadWizardObjectsFromLibrary("Causeway1-2L", true, true); - tRoad.GSDSpline.mNodes[10].bIsBridgeEnd = true; - tRoad.GSDSpline.mNodes[10].bIsBridgeMatched = true; - - //Bridge2: (Steel) - tRoad.GSDSpline.mNodes[11].bIsBridgeStart = true; - tRoad.GSDSpline.mNodes[11].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[11].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[13]; - tRoad.GSDSpline.mNodes[11].LoadWizardObjectsFromLibrary("Steel-2L", true, true); - tRoad.GSDSpline.mNodes[13].bIsBridgeEnd = true; - tRoad.GSDSpline.mNodes[13].bIsBridgeMatched = true; - - //Bridge3: (Causeway) - tRoad.GSDSpline.mNodes[14].bIsBridgeStart = true; - tRoad.GSDSpline.mNodes[14].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[16].bIsBridgeEnd = true; - tRoad.GSDSpline.mNodes[16].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[14].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[16]; - tRoad.GSDSpline.mNodes[14].LoadWizardObjectsFromLibrary("Causeway4-2L", true, true); - } - - /// - /// Create 2L intersections: - /// - private static void RoadArchitectUnitTest2() - { - //Create node locations: - float StartLocX = 800f; - float StartLocY = 200f; - float StartLocYSep = 200f; - float tHeight = 20f; - GSDRoad bRoad = null; if (bRoad == null) { } //Buffer - GSDRoad tRoad = null; if (tRoad == null) { } //Buffer - - //Create base road: - List nodeLocations = new List(); - for (int i = 0; i < 9; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (i * 200f), tHeight, 600f)); - } - bRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - - //Get road system, create road #1: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX, tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Get road system, create road #2: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 2f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); - - //Get road system, create road #3: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 4f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.BothTurnLanes); - - //Get road system, create road #4: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 6f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); - - //Get road system, create road #4: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 8f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); - - GSDRoadAutomation.CreateIntersections_ProgrammaticallyForRoad(bRoad, GSDRoadIntersection.iStopTypeEnum.None, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Now count road intersections, if not 5 throw error - int iCount = 0; - foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) - { - if (tNode.bIsIntersection) - { - iCount += 1; - } - } - if (iCount != 5) - { - Debug.LogError("Unit Test #2 failed: " + iCount.ToString() + " intersections instead of 5."); - } - } - - /// - /// This will create an intersection if two nodes overlap on the road. Only good if the roads only overlap once. - /// - /// - /// - private static void UnitTest_IntersectionHelper(GSDRoad bRoad, GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType, GSDRoadIntersection.RoadTypeEnum rType) - { - GSDSplineN tInter1 = null; - GSDSplineN tInter2 = null; - foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) - { - foreach (GSDSplineN xNode in tRoad.GSDSpline.mNodes) - { - if (GSDRootUtil.IsApproximately(Vector3.Distance(tNode.transform.position, xNode.transform.position), 0f, 0.05f)) - { - tInter1 = tNode; - tInter2 = xNode; - break; - } - } - } - - if (tInter1 != null && tInter2 != null) - { - GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(tInter1, tInter2); - GSDRoadIntersection GSDRI = tInter.GetComponent(); - GSDRI.iStopType = iStopType; - GSDRI.rType = rType; - } - } - - /// - /// Create 4L intersections: - /// - private static void RoadArchitectUnitTest3() - { - //Create node locations: - float StartLocX = 200f; - float StartLocY = 2500f; - float StartLocYSep = 300f; - float tHeight = 20f; - GSDRoad bRoad; //Buffer - GSDRoad tRoad; //Buffer - - //Create base road: - List nodeLocations = new List(); - for (int i = 0; i < 9; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (i * StartLocYSep), tHeight, StartLocY + (StartLocYSep * 2f))); - } - bRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - bRoad.opt_Lanes = 4; - - - //Get road system, create road #1: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX, tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - tRoad.opt_Lanes = 4; - UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Get road system, create road #2: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 2f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - tRoad.opt_Lanes = 4; - UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Get road system, create road #3: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 4f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - tRoad.opt_Lanes = 4; - UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Get road system, create road #4: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 6f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - tRoad.opt_Lanes = 4; - UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Get road system, create road #5: - nodeLocations.Clear(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 8f), tHeight, StartLocY + (i * StartLocYSep))); - } - tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - tRoad.opt_Lanes = 4; - UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); - - //Now count road intersections, if not 5 throw error - int iCount = 0; - foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) - { - if (tNode.bIsIntersection) - { - iCount += 1; - } - } - if (iCount != 5) - { - Debug.LogError("Unit Test #3 failed: " + iCount.ToString() + " intersections instead of 5."); - } - } - - //Large suspension bridge: - private static void RoadArchitectUnitTest4() - { - //Create base road: - List nodeLocations = new List(); - for (int i = 0; i < 5; i++) - { - nodeLocations.Add(new Vector3(3500f, 90f, 200f + (800f * i))); - } - GSDRoad tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - - //Suspension bridge: - tRoad.GSDSpline.mNodes[1].bIsBridgeStart = true; - tRoad.GSDSpline.mNodes[1].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[3].bIsBridgeEnd = true; - tRoad.GSDSpline.mNodes[3].bIsBridgeMatched = true; - tRoad.GSDSpline.mNodes[1].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[3]; - tRoad.GSDSpline.mNodes[1].LoadWizardObjectsFromLibrary("SuspL-2L", true, true); - } - - //Long road - private static void RoadArchitectUnitTest5() - { - //Create base road: - List nodeLocations = new List(); - for (int i = 0; i < 48; i++) - { - nodeLocations.Add(new Vector3(3000f, 40f, 10f + (79f * i))); - } - for (int i = 0; i < 35; i++) - { - nodeLocations.Add(new Vector3(2900f - (79f * i), 30f, 3960f)); - } - for (int i = 0; i < 40; i++) - { - nodeLocations.Add(new Vector3(30, 30f, 3960f - (79f * i))); - } - GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); - } - } -#endif +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +using System.Collections; +using System.IO; +using System.Text; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; +#endif + + +namespace GSD.Roads +{ +#if UNITY_EDITOR + public static class GSDUnitTests + { + private static GSDRoadSystem RoadSystem; + + + /// + /// WARNING: Only call this on an empty scene that has some terrains on it. MicroGSD LLC is not responsbile for data loss if this function is called by user. + /// + public static void RoadArchitectUnitTests() + { + CleanupTests(); + + //Create new road system and turn off updates: + GameObject tRoadSystemObj = new GameObject("RoadArchitectSystem1"); + RoadSystem = tRoadSystemObj.AddComponent(); //Add road system component. + RoadSystem.opt_bAllowRoadUpdates = false; + + int numTests = 5; + double totalTestTime = 0f; + for (int index = 1; index <= numTests; index++) + { + UnityEngine.Debug.Log("Running test " + index); + double testTime = RunTest(index); + totalTestTime += testTime; + UnityEngine.Debug.Log("Test " + index + " complete. Test time: " + testTime + "ms"); + } + UnityEngine.Debug.Log("All tests completed. Total test time: " + totalTestTime + "ms"); + + //Turn updates back on and update road: + RoadSystem.opt_bAllowRoadUpdates = true; + RoadSystem.UpdateAllRoads(); + } + + + private static long RunTest(int test) + { + System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); + switch (test) + { + case 1: + RoadArchitectUnitTest1(); //Bridges + break; + case 2: + RoadArchitectUnitTest2(); //2L intersections + break; + case 3: + RoadArchitectUnitTest3(); //4L intersections + break; + case 4: + RoadArchitectUnitTest4(); //Large suspension bridge + break; + case 5: + RoadArchitectUnitTest5(); //Long road: + break; + } + stopwatch.Stop(); + long testTime = stopwatch.ElapsedMilliseconds; + return testTime; + } + + + public static void CleanupTests() + { + Debug.Log("Cleaning up tests"); + //Get the existing road system, if it exists: + GameObject GSDRS = (GameObject) GameObject.Find("RoadArchitectSystem1"); + DestroyTerrainHistory(GSDRS); + Object.DestroyImmediate(GSDRS); + FlattenTerrains(); + } + + + private static void DestroyTerrainHistory(GameObject GSDRS) + { + //Destroy the terrain histories: + if (GSDRS != null) + { + Object[] tRoads = GSDRS.GetComponents(); + foreach (GSDRoad xRoad in tRoads) + { + GSD.Roads.GSDTerraforming.TerrainsReset(xRoad); + } + } + } + + + private static void FlattenTerrains() + { + //Reset all terrains to 0,0 + Object[] zTerrains = Object.FindObjectsOfType(); + foreach (Terrain xTerrain in zTerrains) + { + xTerrain.terrainData.SetHeights(0, 0, new float[513, 513]); + } + } + + + private static void RoadArchitectUnitTest1() + { + //Create node locations: + List nodeLocations = new List(); + int MaxCount = 18; + float tMod = 100f; + Vector3 xVect = new Vector3(50f, 40f, 50f); + for (int index = 0; index < MaxCount; index++) + { + //tLocs.Add(xVect + new Vector3(tMod * Mathf.Pow((float)i / ((float)MaxCount * 0.15f), 2f), 1f*((float)i*1.25f), tMod * i)); + nodeLocations.Add(xVect + new Vector3(tMod * Mathf.Pow((float) index / ((float) 25 * 0.15f), 2f), 0f, tMod * index)); + } + + //Get road system create road: + GSDRoad tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + + //Bridge0: (Arch) + tRoad.GSDSpline.mNodes[4].bIsBridgeStart = true; + tRoad.GSDSpline.mNodes[4].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[7].bIsBridgeEnd = true; + tRoad.GSDSpline.mNodes[7].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[4].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[7]; + tRoad.GSDSpline.mNodes[4].LoadWizardObjectsFromLibrary("Arch12m-2L", true, true); + + //Bridge1: (Federal causeway) + tRoad.GSDSpline.mNodes[8].bIsBridgeStart = true; + tRoad.GSDSpline.mNodes[8].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[8].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[10]; + tRoad.GSDSpline.mNodes[8].LoadWizardObjectsFromLibrary("Causeway1-2L", true, true); + tRoad.GSDSpline.mNodes[10].bIsBridgeEnd = true; + tRoad.GSDSpline.mNodes[10].bIsBridgeMatched = true; + + //Bridge2: (Steel) + tRoad.GSDSpline.mNodes[11].bIsBridgeStart = true; + tRoad.GSDSpline.mNodes[11].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[11].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[13]; + tRoad.GSDSpline.mNodes[11].LoadWizardObjectsFromLibrary("Steel-2L", true, true); + tRoad.GSDSpline.mNodes[13].bIsBridgeEnd = true; + tRoad.GSDSpline.mNodes[13].bIsBridgeMatched = true; + + //Bridge3: (Causeway) + tRoad.GSDSpline.mNodes[14].bIsBridgeStart = true; + tRoad.GSDSpline.mNodes[14].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[16].bIsBridgeEnd = true; + tRoad.GSDSpline.mNodes[16].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[14].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[16]; + tRoad.GSDSpline.mNodes[14].LoadWizardObjectsFromLibrary("Causeway4-2L", true, true); + } + + + /// + /// Create 2L intersections: + /// + private static void RoadArchitectUnitTest2() + { + //Create node locations: + float StartLocX = 800f; + float StartLocY = 200f; + float StartLocYSep = 200f; + float tHeight = 20f; + GSDRoad bRoad = null; + if (bRoad == null) + { } //Buffer + GSDRoad tRoad = null; + if (tRoad == null) + { } //Buffer + + //Create base road: + List nodeLocations = new List(); + for (int index = 0; index < 9; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (index * 200f), tHeight, 600f)); + } + bRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + + //Get road system, create road #1: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX, tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Get road system, create road #2: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 2f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); + + //Get road system, create road #3: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 4f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.BothTurnLanes); + + //Get road system, create road #4: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 6f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); + + //Get road system, create road #4: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 8f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + //UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.TurnLane); + + GSDRoadAutomation.CreateIntersections_ProgrammaticallyForRoad(bRoad, GSDRoadIntersection.iStopTypeEnum.None, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Now count road intersections, if not 5 throw error + int iCount = 0; + foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) + { + if (tNode.bIsIntersection) + { + iCount += 1; + } + } + if (iCount != 5) + { + Debug.LogError("Unit Test #2 failed: " + iCount.ToString() + " intersections instead of 5."); + } + } + + + /// + /// This will create an intersection if two nodes overlap on the road. Only good if the roads only overlap once. + /// + /// + /// + private static void UnitTest_IntersectionHelper(GSDRoad bRoad, GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType, GSDRoadIntersection.RoadTypeEnum rType) + { + GSDSplineN tInter1 = null; + GSDSplineN tInter2 = null; + foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) + { + foreach (GSDSplineN xNode in tRoad.GSDSpline.mNodes) + { + if (GSDRootUtil.IsApproximately(Vector3.Distance(tNode.transform.position, xNode.transform.position), 0f, 0.05f)) + { + tInter1 = tNode; + tInter2 = xNode; + break; + } + } + } + + if (tInter1 != null && tInter2 != null) + { + GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(tInter1, tInter2); + GSDRoadIntersection GSDRI = tInter.GetComponent(); + GSDRI.iStopType = iStopType; + GSDRI.rType = rType; + } + } + + + /// + /// Create 4L intersections: + /// + private static void RoadArchitectUnitTest3() + { + //Create node locations: + float StartLocX = 200f; + float StartLocY = 2500f; + float StartLocYSep = 300f; + float tHeight = 20f; + GSDRoad bRoad; //Buffer + GSDRoad tRoad; //Buffer + + //Create base road: + List nodeLocations = new List(); + for (int index = 0; index < 9; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (index * StartLocYSep), tHeight, StartLocY + (StartLocYSep * 2f))); + } + bRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + bRoad.opt_Lanes = 4; + + + //Get road system, create road #1: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX, tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + tRoad.opt_Lanes = 4; + UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Get road system, create road #2: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 2f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + tRoad.opt_Lanes = 4; + UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Get road system, create road #3: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 4f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + tRoad.opt_Lanes = 4; + UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Get road system, create road #4: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 6f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + tRoad.opt_Lanes = 4; + UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Get road system, create road #5: + nodeLocations.Clear(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(StartLocX + (StartLocYSep * 8f), tHeight, StartLocY + (index * StartLocYSep))); + } + tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + tRoad.opt_Lanes = 4; + UnitTest_IntersectionHelper(bRoad, tRoad, GSDRoadIntersection.iStopTypeEnum.TrafficLight1, GSDRoadIntersection.RoadTypeEnum.NoTurnLane); + + //Now count road intersections, if not 5 throw error + int iCount = 0; + foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) + { + if (tNode.bIsIntersection) + { + iCount += 1; + } + } + if (iCount != 5) + { + Debug.LogError("Unit Test #3 failed: " + iCount.ToString() + " intersections instead of 5."); + } + } + + + //Large suspension bridge: + private static void RoadArchitectUnitTest4() + { + //Create base road: + List nodeLocations = new List(); + for (int index = 0; index < 5; index++) + { + nodeLocations.Add(new Vector3(3500f, 90f, 200f + (800f * index))); + } + GSDRoad tRoad = GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + + //Suspension bridge: + tRoad.GSDSpline.mNodes[1].bIsBridgeStart = true; + tRoad.GSDSpline.mNodes[1].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[3].bIsBridgeEnd = true; + tRoad.GSDSpline.mNodes[3].bIsBridgeMatched = true; + tRoad.GSDSpline.mNodes[1].BridgeCounterpartNode = tRoad.GSDSpline.mNodes[3]; + tRoad.GSDSpline.mNodes[1].LoadWizardObjectsFromLibrary("SuspL-2L", true, true); + } + + + //Long road + private static void RoadArchitectUnitTest5() + { + //Create base road: + List nodeLocations = new List(); + for (int index = 0; index < 48; index++) + { + nodeLocations.Add(new Vector3(3000f, 40f, 10f + (79f * index))); + } + for (int index = 0; index < 35; index++) + { + nodeLocations.Add(new Vector3(2900f - (79f * index), 30f, 3960f)); + } + for (int index = 0; index < 40; index++) + { + nodeLocations.Add(new Vector3(30, 30f, 3960f - (79f * index))); + } + GSDRoadAutomation.CreateRoad_Programmatically(RoadSystem, ref nodeLocations); + } + } +#endif } \ No newline at end of file diff --git a/Materials/FedSigns/396/GSDFedSign-396-UpcomingRight.mat.meta b/Materials/FedSigns/396/GSDFedSign-396-UpcomingRight.mat.meta index ee8b88be..0572a5df 100644 --- a/Materials/FedSigns/396/GSDFedSign-396-UpcomingRight.mat.meta +++ b/Materials/FedSigns/396/GSDFedSign-396-UpcomingRight.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: 7e634a0d178014a4985691c0c1729f2b -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: 7e634a0d178014a4985691c0c1729f2b +NativeFormatImporter: + userData: diff --git a/Materials/GSDBrickRoad.mat b/Materials/GSDBrickRoad.mat index ba2166f9..1d2bf035 100755 --- a/Materials/GSDBrickRoad.mat +++ b/Materials/GSDBrickRoad.mat @@ -1,85 +1,85 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: GSDBrickRoad - m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _NORMALMAP - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 2800000, guid: 6d1117bfd13dc3d47928f1a50e1c3429, type: 3} - m_Scale: {x: 4, y: 2} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: 731bd619e50e2664a8c51a1c81c80b81, type: 3} - m_Scale: {x: 8, y: 2} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Mode: 0 - - _OcclusionStrength: 1 - - _OffsetY: 114.62686 - - _Parallax: 0.02 - - _Shininess: 0.3706869 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _SpecColor: {r: 0.22794116, g: 0.22794116, b: 0.22794116, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: GSDBrickRoad + m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 6d1117bfd13dc3d47928f1a50e1c3429, type: 3} + m_Scale: {x: 4, y: 2} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 731bd619e50e2664a8c51a1c81c80b81, type: 3} + m_Scale: {x: 8, y: 2} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OffsetY: 114.62686 + - _Parallax: 0.02 + - _Shininess: 0.3706869 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _SpecColor: {r: 0.22794116, g: 0.22794116, b: 0.22794116, a: 1} diff --git a/Materials/GSDCobblestoneRoad.mat b/Materials/GSDCobblestoneRoad.mat index bbf73178..cf424fd7 100755 --- a/Materials/GSDCobblestoneRoad.mat +++ b/Materials/GSDCobblestoneRoad.mat @@ -1,85 +1,85 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: GSDCobblestoneRoad - m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _NORMALMAP - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 2800000, guid: 0987da75586fbce49935373875402ade, type: 3} - m_Scale: {x: 4, y: 2} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 8, y: 2} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: 7bc8533c591d19c449434823291665e7, type: 3} - m_Scale: {x: 8, y: 2} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Mode: 0 - - _OcclusionStrength: 1 - - _OffsetY: 114.62686 - - _Parallax: 0.02 - - _Shininess: 0.30878767 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _SpecColor: {r: 0.30147058, g: 0.30147058, b: 0.30147058, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: GSDCobblestoneRoad + m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 0987da75586fbce49935373875402ade, type: 3} + m_Scale: {x: 4, y: 2} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 8, y: 2} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 7bc8533c591d19c449434823291665e7, type: 3} + m_Scale: {x: 8, y: 2} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OffsetY: 114.62686 + - _Parallax: 0.02 + - _Shininess: 0.30878767 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _SpecColor: {r: 0.30147058, g: 0.30147058, b: 0.30147058, a: 1} diff --git a/Materials/GSDDirtRoad.mat b/Materials/GSDDirtRoad.mat index e178a33c..7fb7c38d 100755 --- a/Materials/GSDDirtRoad.mat +++ b/Materials/GSDDirtRoad.mat @@ -1,85 +1,85 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: GSDDirtRoad - m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _NORMALMAP - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 2800000, guid: dabdc29a42c7052479d3a018cabd5781, type: 3} - m_Scale: {x: 8, y: 4} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 0.5} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: 1dae68b77da49b24bab737ff948674a8, type: 3} - m_Scale: {x: 1, y: 0.5} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Mode: 0 - - _OcclusionStrength: 1 - - _OffsetY: 114.62686 - - _Parallax: 0.02 - - _Shininess: 1 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _SpecColor: {r: 0, g: 0, b: 0, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: GSDDirtRoad + m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: dabdc29a42c7052479d3a018cabd5781, type: 3} + m_Scale: {x: 8, y: 4} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 0.5} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 1dae68b77da49b24bab737ff948674a8, type: 3} + m_Scale: {x: 1, y: 0.5} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OffsetY: 114.62686 + - _Parallax: 0.02 + - _Shininess: 1 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _SpecColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Materials/GSDRoad1.mat b/Materials/GSDRoad1.mat index e1c5ddf6..23c013f4 100644 --- a/Materials/GSDRoad1.mat +++ b/Materials/GSDRoad1.mat @@ -1,90 +1,90 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: GSDRoad1 - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _EMISSION _NORMALMAP - m_LightmapFlags: 1 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 2800000, guid: 72077a6207982e24bbeb90ce49ba6bab, type: 3} - m_Scale: {x: 8, y: 4} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: 46ae3471803bb3d4fb909806703ecca1, type: 3} - m_Scale: {x: 4, y: 2} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _OffsetY: 114.62686 - - _Parallax: 0.02 - - _ShadowIntensity: 0.6 - - _Shininess: 0.4232378 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _SpecColor: {r: 0.125, g: 0.125, b: 0.125, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: GSDRoad1 + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION _NORMALMAP + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 72077a6207982e24bbeb90ce49ba6bab, type: 3} + m_Scale: {x: 8, y: 4} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 46ae3471803bb3d4fb909806703ecca1, type: 3} + m_Scale: {x: 4, y: 2} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OffsetY: 114.62686 + - _Parallax: 0.02 + - _ShadowIntensity: 0.6 + - _Shininess: 0.4232378 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _SpecColor: {r: 0.125, g: 0.125, b: 0.125, a: 1} diff --git a/Materials/GSDShoulder1.mat b/Materials/GSDShoulder1.mat index ece3bdb4..75ca514d 100644 --- a/Materials/GSDShoulder1.mat +++ b/Materials/GSDShoulder1.mat @@ -1,89 +1,89 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: GSDShoulder1 - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _NORMALMAP - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 2800000, guid: 72077a6207982e24bbeb90ce49ba6bab, type: 3} - m_Scale: {x: 8, y: 4} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: 46ae3471803bb3d4fb909806703ecca1, type: 3} - m_Scale: {x: 4, y: 2} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _OffsetY: 114.62686 - - _Parallax: 0.02 - - _Shininess: 0.4232378 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _SpecColor: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: GSDShoulder1 + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 72077a6207982e24bbeb90ce49ba6bab, type: 3} + m_Scale: {x: 8, y: 4} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 46ae3471803bb3d4fb909806703ecca1, type: 3} + m_Scale: {x: 4, y: 2} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OffsetY: 114.62686 + - _Parallax: 0.02 + - _Shininess: 0.4232378 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7238806, g: 0.7238806, b: 0.7238806, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _SpecColor: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 1} diff --git a/Materials/Markers/GSDRoadConn-YellowSingle-4L.mat.meta b/Materials/Markers/GSDRoadConn-YellowSingle-4L.mat.meta index e6387a14..e96b3dc6 100644 --- a/Materials/Markers/GSDRoadConn-YellowSingle-4L.mat.meta +++ b/Materials/Markers/GSDRoadConn-YellowSingle-4L.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: cee5809aae9eae14897b330ad5c62859 -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: cee5809aae9eae14897b330ad5c62859 +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDRoadConn-YellowSingle-6L-2L.mat.meta b/Materials/Markers/GSDRoadConn-YellowSingle-6L-2L.mat.meta index cdc441cb..bf0245a1 100644 --- a/Materials/Markers/GSDRoadConn-YellowSingle-6L-2L.mat.meta +++ b/Materials/Markers/GSDRoadConn-YellowSingle-6L-2L.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: 62e911e02e72d714bbf3b7080277a926 -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: 62e911e02e72d714bbf3b7080277a926 +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDRoadConn-YellowSingle-6L-4L.mat.meta b/Materials/Markers/GSDRoadConn-YellowSingle-6L-4L.mat.meta index 7a299fec..884b1805 100644 --- a/Materials/Markers/GSDRoadConn-YellowSingle-6L-4L.mat.meta +++ b/Materials/Markers/GSDRoadConn-YellowSingle-6L-4L.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: d420715e7bf2ecb4591868fcbf3625fd -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: d420715e7bf2ecb4591868fcbf3625fd +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDRoadDetailOverlay1.mat b/Materials/Markers/GSDRoadDetailOverlay1.mat index 60fd855a..5415b432 100644 --- a/Materials/Markers/GSDRoadDetailOverlay1.mat +++ b/Materials/Markers/GSDRoadDetailOverlay1.mat @@ -1,149 +1,149 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: GSDRoadDetailOverlay1 - m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BackTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _BumpMap: - m_Texture: {fileID: 2800000, guid: de5bb1e0fee7e6a428dd7f8cfda0ecd1, type: 3} - m_Scale: {x: 4, y: 4} - m_Offset: {x: 0, y: 0} - - _Cube: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _Decal: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _Detail: - m_Texture: {fileID: 2800000, guid: 74abfab6bf577c64d863cca0004d26eb, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DownTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _FrontTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _GlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _LeftTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 2800000, guid: f2345b5490e2c1747a03a872a8396fea, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 2800000, guid: 74abfab6bf577c64d863cca0004d26eb, type: 3} - m_Scale: {x: 4, y: 4} - m_Offset: {x: 0, y: 0} - - _ReflMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _RightTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SparkleTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ToonShade: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _UpTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DecalColoring: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _EdgeLength: 10 - - _FrezFalloff: 4 - - _FrezPow: 0 - - _Gloss: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _LineWidth: 0.1 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Outline: 0.005 - - _Parallax: 0.01619403 - - _Reflection: 0 - - _ShadowIntensity: 0.314 - - _Shininess: 0.081 - - _SmoothnessTextureChannel: 0 - - _Sparkle: 0.01 - - _SpecularHighlights: 1 - - _SquashAmount: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.1254902, g: 0.1254902, b: 0.1254902, a: 1} - - _Emission: {r: 0, g: 0, b: 0, a: 0} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _GridColor: {r: 0, g: 0, b: 0, a: 0} - - _HighlightColor: {r: 1, g: 1, b: 1, a: 1} - - _LineColor: {r: 1, g: 1, b: 1, a: 1} - - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} - - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} - - _Scale: {r: 1, g: 1, b: 1, a: 1} - - _SpecColor: {r: 0.5019608, g: 0.5019608, b: 0.5019608, a: 1} - - _SpecularColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: GSDRoadDetailOverlay1 + m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BackTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 2800000, guid: de5bb1e0fee7e6a428dd7f8cfda0ecd1, type: 3} + m_Scale: {x: 4, y: 4} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Decal: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Detail: + m_Texture: {fileID: 2800000, guid: 74abfab6bf577c64d863cca0004d26eb, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DownTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FrontTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _LeftTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: f2345b5490e2c1747a03a872a8396fea, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 2800000, guid: 74abfab6bf577c64d863cca0004d26eb, type: 3} + m_Scale: {x: 4, y: 4} + m_Offset: {x: 0, y: 0} + - _ReflMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RightTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SparkleTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ToonShade: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _UpTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DecalColoring: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _EdgeLength: 10 + - _FrezFalloff: 4 + - _FrezPow: 0 + - _Gloss: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _LineWidth: 0.1 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Outline: 0.005 + - _Parallax: 0.01619403 + - _Reflection: 0 + - _ShadowIntensity: 0.314 + - _Shininess: 0.081 + - _SmoothnessTextureChannel: 0 + - _Sparkle: 0.01 + - _SpecularHighlights: 1 + - _SquashAmount: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.1254902, g: 0.1254902, b: 0.1254902, a: 1} + - _Emission: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _GridColor: {r: 0, g: 0, b: 0, a: 0} + - _HighlightColor: {r: 1, g: 1, b: 1, a: 1} + - _LineColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectColor: {r: 1, g: 1, b: 1, a: 0.5} + - _Scale: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.5019608, g: 0.5019608, b: 0.5019608, a: 1} + - _SpecularColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} diff --git a/Materials/Markers/GSDWhiteYellowPassBoth.mat.meta b/Materials/Markers/GSDWhiteYellowPassBoth.mat.meta index 5d619bfa..3fcb869e 100644 --- a/Materials/Markers/GSDWhiteYellowPassBoth.mat.meta +++ b/Materials/Markers/GSDWhiteYellowPassBoth.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: bcff6ab61bcba654fb81c02debf6eace -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: bcff6ab61bcba654fb81c02debf6eace +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDWhiteYellowSingle-4L.mat.meta b/Materials/Markers/GSDWhiteYellowSingle-4L.mat.meta index 69486e7b..bf14592b 100644 --- a/Materials/Markers/GSDWhiteYellowSingle-4L.mat.meta +++ b/Materials/Markers/GSDWhiteYellowSingle-4L.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: 6ad3e8571f530f54cb288d4dd37c83ee -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: 6ad3e8571f530f54cb288d4dd37c83ee +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDWhiteYellowSingle-6L.mat.meta b/Materials/Markers/GSDWhiteYellowSingle-6L.mat.meta index c91e7cce..1d7fda0f 100644 --- a/Materials/Markers/GSDWhiteYellowSingle-6L.mat.meta +++ b/Materials/Markers/GSDWhiteYellowSingle-6L.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: 5f13feb25f9804746946d789793171b7 -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: 5f13feb25f9804746946d789793171b7 +NativeFormatImporter: + userData: diff --git a/Materials/Markers/GSDWhiteYellowSingle.mat.meta b/Materials/Markers/GSDWhiteYellowSingle.mat.meta index ad06e264..3ac85ade 100644 --- a/Materials/Markers/GSDWhiteYellowSingle.mat.meta +++ b/Materials/Markers/GSDWhiteYellowSingle.mat.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 -guid: 63d6ccd2648203b46b40c8ac86a52d22 -NativeFormatImporter: - userData: +fileFormatVersion: 2 +guid: 63d6ccd2648203b46b40c8ac86a52d22 +NativeFormatImporter: + userData: diff --git a/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab b/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab index fe33bd7a..adfc0a0d 100644 --- a/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab +++ b/Mesh/RoadObj/Signs/GSDSignStopAllway.prefab @@ -1,98 +1,98 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &100000 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 6 - m_Component: - - component: {fileID: 400000} - - component: {fileID: 3300000} - - component: {fileID: 2300000} - - component: {fileID: 65751558033613452} - m_Layer: 0 - m_Name: GSDSignStopAllway - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &400000 -Transform: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 100000} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!23 &2300000 -MeshRenderer: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 100000} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RenderingLayerMask: 4294967295 - m_Materials: - - {fileID: 2100000, guid: e0addf608cbdb0b4e8934e96292b76bf, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &3300000 -MeshFilter: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 100000} - m_Mesh: {fileID: 4300000, guid: ecdab1c0bef00a840a3bfb7169a9371e, type: 3} ---- !u!1001 &100100000 -Prefab: - m_ObjectHideFlags: 1 - serializedVersion: 2 - m_Modification: - m_TransformParent: {fileID: 0} - m_Modifications: [] - m_RemovedComponents: [] - m_SourcePrefab: {fileID: 0} - m_RootGameObject: {fileID: 100000} - m_IsPrefabAsset: 1 ---- !u!65 &65751558033613452 -BoxCollider: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 100000} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 0.7500003, y: 2.2499998, z: 0.031000352} - m_Center: {x: -0.00000020861626, y: 1.1250001, z: -0.00049950834} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &100000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 400000} + - component: {fileID: 3300000} + - component: {fileID: 2300000} + - component: {fileID: 65751558033613452} + m_Layer: 0 + m_Name: GSDSignStopAllway + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &400000 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &2300000 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: e0addf608cbdb0b4e8934e96292b76bf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &3300000 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Mesh: {fileID: 4300000, guid: ecdab1c0bef00a840a3bfb7169a9371e, type: 3} +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 0} + m_RootGameObject: {fileID: 100000} + m_IsPrefabAsset: 1 +--- !u!65 &65751558033613452 +BoxCollider: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 0.7500003, y: 2.2499998, z: 0.031000352} + m_Center: {x: -0.00000020861626, y: 1.1250001, z: -0.00049950834} diff --git a/README.md b/README.md index 5e452df9..c07da01b 100755 --- a/README.md +++ b/README.md @@ -1,62 +1,62 @@ -# RoadArchitect -[![GitHub release](https://img.shields.io/github/release/embeddedt/RoadArchitect.svg)]() -[![Github All Releases](https://img.shields.io/github/downloads/embeddedt/RoadArchitect/total.svg)]() -[![GitHub contributors](https://img.shields.io/github/contributors/embeddedt/RoadArchitect.svg)]() -[![Join the chat at https://gitter.im/NewRoadArchitect/community](https://badges.gitter.im/NewRoadArchitect/community.svg)](https://gitter.im/NewRoadArchitect/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -Road Architect for Unity. Road architect is a professional quality road system creator featuring dynamic intersections, bridges and many other road objects. - -Road Architect is currently being developed with Unity 2018.2.0f1. If interested in contributing please open an issue or pull request. - -- Currently, I recommend downloading the main git repository by either using `git clone https://github.com/embeddedt/RoadArchitect.git` or downloading a ZIP from GitHub. -- The resulting folder should be copied to the root of your Assets directory and may need to be renamed to RoadArchitect (instead of RoadArchitect-master). -- The previously recommended way to install Road Architect was to use the unity package on the releases page, but I have not yet made a release since forking from the original RoadArchitect in October 2018. -- https://github.com/embeddedt/RoadArchitect/releases -- Documentation https://github.com/embeddedt/RoadArchitect/wiki/Documentation - - Note: The Road Architect menu is located under the "Window" menu. - -## Videos -- Overview: https://www.youtube.com/watch?v=AUwud3XklJ8 -- 2.5 minutes: https://www.youtube.com/watch?v=DZWYfgDNSoo -- Road Architect Tutorial #1: Road Creation: http://youtu.be/IR4lwbnuPVQ -- Road Architect Tutorial #2: Bridges: http://youtu.be/Dq4c2Q0wlAs -- Road Architect Tutorial #3: Intersections: http://youtu.be/05Pg7U1FHyg -- Road Architect Tutorial #4: Extrusion & Edge Objects: http://youtu.be/jQT15NlWIV4 -- Road Architect Tutorial #5: Splatmap Creation: http://youtu.be/qy71HXR4VBg -- Tutorial playlist: https://www.youtube.com/playlist?list=PLnPqLrVfSAEIk_7Ug6IkknZCSW2GlR74g - -**NOTE:** Unless stated otherwise, all screenshots were made using Unity 2018.2.2f1 Personal. They utilize free trees and grass from the Unity Asset Store, RoadArchitect, and the Unity Post-Processing Stack v1. No paid products were used in the production of these screenshots. - -## Intersections -![Newer intersection screenshot](ManualImages/Extra/newscreenshot1.PNG) -- **Dynamic** - Procedurally generated based upon lanes, road width and angle of attack. -- **Turn lanes** - Complete left and right optional turn lanes. -- **Traffic lights** - Fully functioning and heavily detailed traffic light system including left on yield and right turn lane only lights. -- **Assets** - Includes several assets such as traffic light poles, street lights, traffic lights, stop signs and more. Most include rigid body versions for dynamic environments. - -## Bridges -![Bridges](ManualImages/Extra/arch_bridge.PNG) -- **Bridge wizard** - Allows for instant creation of professional quality bridges such as causeway, arch, suspension and more. All bridge creation aspects are generated instantly allowing quick iteration. -- **Customization** - Custom extrusion allows for mix and match of bridge parts. Over 50 bridge parts included. -- **Details** - Many different types of railing, bases, center dividers included. -- **Curvature** - Curvature of bridges supported including arch and suspension bridges. - -## Railing and extrusions -![Railing](ManualImages/Extra/wbeam.PNG) -- **Railing** - 12+ Railing types included such as K-Rails and W Beams. -- **Center dividers** - Many center divider options including the most popular configurations such as K-Rails with blinders or street lights. All aspects of mesh extrusion are performed instantly allowing quick iteration. -- **Collision barriers** - Water barrels and other collision barriers come with prefabricated rigid or static body configurations. -- **Custom extrusion** - Extrude any custom mesh along the spline with almost limitless customization. - -## Assets -NOTE: This screenshot has no other assets besides RoadArchitect. -![Assets](ManualImages/Extra/SS3-640.jpg) -- **Road assets** - Several road assets are included such as street lights, double lights, stop signs and more. All aspects of road asset placement are done instantly, allowing for quick iterations. -- **Custom assets** - Place any custom mesh along the spline with an extreme amount of customization options. -- **Signs** - 300+ U.S. federal and state road signs are pre-built and available for use. -- **Future assets** - Assets will be added and freely available as time progresses. - -## Quality -![Quality](ManualImages/Extra/quality_road.PNG) -- **Speed** - All mesh extrusion, bridge extrusion and road asset placement actions are instantaneous. Optimized road generation results in an average 100ms per (2km road + 1 intersection). Multithreaded support. -- **Quality** - Most road textures at least 1024x1024 resolution. Most materials include normal and specular maps. Most assets created to federal or state specification. +# RoadArchitect +[![GitHub release](https://img.shields.io/github/release/embeddedt/RoadArchitect.svg)]() +[![Github All Releases](https://img.shields.io/github/downloads/embeddedt/RoadArchitect/total.svg)]() +[![GitHub contributors](https://img.shields.io/github/contributors/embeddedt/RoadArchitect.svg)]() +[![Join the chat at https://gitter.im/NewRoadArchitect/community](https://badges.gitter.im/NewRoadArchitect/community.svg)](https://gitter.im/NewRoadArchitect/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Road Architect for Unity. Road architect is a professional quality road system creator featuring dynamic intersections, bridges and many other road objects. + +Road Architect is currently being developed with Unity 2018.3.1f1. If interested in contributing please open an issue or pull request. + +- Currently, I recommend downloading the main git repository by either using `git clone https://github.com/FritzsHero/RoadArchitect.git` or using Embeddedt's Repo: `git clone https://github.com/embeddedt/RoadArchitect.git` downloading a ZIP from GitHub. +- The resulting folder should be copied to the root of your Assets directory and may need to be renamed to RoadArchitect (instead of RoadArchitect-master). +- The previously recommended way to install Road Architect was to use the unity package on the releases page, but I have not yet made a release since forking from the original RoadArchitect in October 2018. +- https://github.com/embeddedt/RoadArchitect/releases +- Documentation https://github.com/embeddedt/RoadArchitect/wiki/Documentation + - Note: The Road Architect menu is located under the "Window" menu. + +## Videos +- Overview: https://www.youtube.com/watch?v=AUwud3XklJ8 +- 2.5 minutes: https://www.youtube.com/watch?v=DZWYfgDNSoo +- Road Architect Tutorial #1: Road Creation: http://youtu.be/IR4lwbnuPVQ +- Road Architect Tutorial #2: Bridges: http://youtu.be/Dq4c2Q0wlAs +- Road Architect Tutorial #3: Intersections: http://youtu.be/05Pg7U1FHyg +- Road Architect Tutorial #4: Extrusion & Edge Objects: http://youtu.be/jQT15NlWIV4 +- Road Architect Tutorial #5: Splatmap Creation: http://youtu.be/qy71HXR4VBg +- Tutorial playlist: https://www.youtube.com/playlist?list=PLnPqLrVfSAEIk_7Ug6IkknZCSW2GlR74g + +**NOTE:** Unless stated otherwise, all screenshots were made using Unity 2018.2.2f1 Personal. They utilize free trees and grass from the Unity Asset Store, RoadArchitect, and the Unity Post-Processing Stack v1. No paid products were used in the production of these screenshots. + +## Intersections +![Newer intersection screenshot](ManualImages/Extra/newscreenshot1.PNG) +- **Dynamic** - Procedurally generated based upon lanes, road width and angle of attack. +- **Turn lanes** - Complete left and right optional turn lanes. +- **Traffic lights** - Fully functioning and heavily detailed traffic light system including left on yield and right turn lane only lights. +- **Assets** - Includes several assets such as traffic light poles, street lights, traffic lights, stop signs and more. Most include rigid body versions for dynamic environments. + +## Bridges +![Bridges](ManualImages/Extra/arch_bridge.PNG) +- **Bridge wizard** - Allows for instant creation of professional quality bridges such as causeway, arch, suspension and more. All bridge creation aspects are generated instantly allowing quick iteration. +- **Customization** - Custom extrusion allows for mix and match of bridge parts. Over 50 bridge parts included. +- **Details** - Many different types of railing, bases, center dividers included. +- **Curvature** - Curvature of bridges supported including arch and suspension bridges. + +## Railing and extrusions +![Railing](ManualImages/Extra/wbeam.PNG) +- **Railing** - 12+ Railing types included such as K-Rails and W Beams. +- **Center dividers** - Many center divider options including the most popular configurations such as K-Rails with blinders or street lights. All aspects of mesh extrusion are performed instantly allowing quick iteration. +- **Collision barriers** - Water barrels and other collision barriers come with prefabricated rigid or static body configurations. +- **Custom extrusion** - Extrude any custom mesh along the spline with almost limitless customization. + +## Assets +NOTE: This screenshot has no other assets besides RoadArchitect. +![Assets](ManualImages/Extra/SS3-640.jpg) +- **Road assets** - Several road assets are included such as street lights, double lights, stop signs and more. All aspects of road asset placement are done instantly, allowing for quick iterations. +- **Custom assets** - Place any custom mesh along the spline with an extreme amount of customization options. +- **Signs** - 300+ U.S. federal and state road signs are pre-built and available for use. +- **Future assets** - Assets will be added and freely available as time progresses. + +## Quality +![Quality](ManualImages/Extra/quality_road.PNG) +- **Speed** - All mesh extrusion, bridge extrusion and road asset placement actions are instantaneous. Optimized road generation results in an average 100ms per (2km road + 1 intersection). Multithreaded support. +- **Quality** - Most road textures at least 1024x1024 resolution. Most materials include normal and specular maps. Most assets created to federal or state specification. diff --git a/Readme.txt b/Readme.txt index 54ffeba3..a62f133b 100755 --- a/Readme.txt +++ b/Readme.txt @@ -1,5 +1,5 @@ -Road Architect Readme - -For issues, bugs and related please visit https://github.com/embeddedt/RoadArchitect - -This project is licensed under the terms of the MIT license. See https://github.com/embeddedt/RoadArchitect/blob/master/LICENSE for more details. +Road Architect Readme + +For issues, bugs and related please visit https://github.com/embeddedt/RoadArchitect + +This project is licensed under the terms of the MIT license. See https://github.com/embeddedt/RoadArchitect/blob/master/LICENSE for more details. diff --git a/RoadArchitectManual.htm b/RoadArchitectManual.htm index ddeef70c..1e2fdba3 100755 --- a/RoadArchitectManual.htm +++ b/RoadArchitectManual.htm @@ -1,1097 +1,1097 @@ - - - - - - Road Architect Manual - MicroGSD - - - - - - - - -
-
- -
- - -
-
-
-
-
- -
Road Architect Offline Manual
- - - -
- -
-
I. Quick overview
-
-Road Architect's primary game objects: -
    -
  • "Road Architect System" (RoadArchitectSystem.cs) - this script component is treated as the master GameObject for organization purposes. Located at the root level of the hierarchy.
  • -
  • "Road Object" (GSDRoad.cs) - this script component is attached to each road created. Contains 42+ options including road width, lane count and terrain options. Located as a child of a Road Architect System GameObject.
  • -
  • "Road Node" (GSDSplineN.cs) - this script component is attached to each road node on a road. Contains 100+ options and is the primary place in which bridges, edge objects and more are created. Located as a child of a Spline GameObject, which is a child of a Road GameObject.
  • -
  • "Intersection Object" (GSDRoadIntersection.cs) - this script component is attached to each intersection object. Contains dozens of intersection options. Located as a child of the "Intersections" GameObject, which is a child of a Road Architect System GameObject.
  • -
  • "Splatmap Creator" (GSDTerrain.cs) - this script component is attached to each terrain in the scene. Contains 8 options for creating and exporting splat maps. Located on each Terrain GameObject.
  • -
-
-
- -
-
II. Quick start guides
-
-
a. Building a road
- -
    -
  • Create a Road Architect System GameObject via the Road Architect file menu.
  • -
  • Select the newly created Road Architect System GameObject and click "Add road" to add a road (located in the Road Architect System's inspector window).
  • -
  • While a road object is selected:
  • -
- -
- CTRL - + - LEFT-CLICK - = Add road nodes on the terrain while holding ctrl and left-clicking on the terrain location. -
- -
- SHIFT - + - LEFT-CLICK - = Insertion mode: Insert road nodes on the terrain while holding shift and left-clicking on the terrain location. -
- - -
b. Building an intersection
- -
    -
  • Drag a node on top of another node. Can be from the same road or different roads. To create a 3-way intersection, utilize an end node (a road's first or last node) to create the intersection. Note: You can't create an intersection out of consecutive nodes of the same road.
  • -
- -
c. Building a bridge
- -
    -
  • Select the road node where the bridge is to start. - -
      -
    • -
      - -
      -
    • -
    - -
  • - -
  • At the top of the node's inspector window, check "Bridge start". -
      -
    • -
      - - - -
      -
    • -
    -
  • - -
  • Select the road node where the bridge is to end. -
      -
    • -
      - -
      -
    • -
    -
  • - -
  • At the top of the node's inspector window, check "Bridge end". -
      -
    • -
      - - - -
      -
    • -
    -
  • - -
  • Select the bridge start node. -
      -
    • -
      - -
      -
    • -
    -
  • - -
  • Click "Open Wizard" (the blue button) in the inspector panel. This will open the creation wizard. -
      -
    • -
      - -
      -
    • -
    -
  • - -
  • Make sure "Completed Bridges" is selected in the creation wizard drop-down. - -
      -
    • -
      - -
      -
    • -
    - -
  • -
  • Single-click on which bridge type to add. Adjust the bridge start and end nodes' heights for desired effect.
  • -
- - -
d. Using the Wizard
-
    -
  • Select the node in which you wish to add an extruded, repeated object or singular object.
  • -
  • Switch back to the node where you want the bridge to start. Click "Open Wizard" (the blue button). This will open the creation wizard.
  • -
  • Select "Extrusion Objects" or "Edge Objects" from the the creation wizard drop-down.
  • -
  • Experiment with the drop-down and its options to explore all of the included assets
  • -
-
-
- - -
-
III. Quick tips
-
-
    -
  • Look at the example scenes to see entire road layouts with bridges and more.
  • -
  • Nodes are the only GameObject to add bridges, railings, signs and similar items. In other words: To add any non-road item you must do so from a Node.
  • -
  • To add nodes, you must have a road selected. Ctrl-left-click to add a node to the end of the road. Shift-left-click to insert a node anywhere along the spline.
  • -
  • Creating a custom extrusion and edge objects is performed by clicking the "Create a custom extrusion object" and "Create a custom edge object" in a Node's inspector window.
  • -
  • Confused? Watch the tutorial videos. Still confused? Email support@microgsd.com and you will received a response within 48 hours.
  • -
-
-
- -
-
IV. Road Architect System GameObject
-
- - -
- RoadArchitectSystem UI image - -
Add road: Adds a road to the system. After clicking this button, the new road will automatically be selected as the active GameObject.
-
Multithreading: Enables or disables multithreading during road generation.
-
Save mesh assets: Enables or disables saving of meshes as unity assets.
-
Update all roads: Updates all roads in the scene. This may take a while depending on the number of roads in the scene.
-
View next intersection: Changes the sceneview to the next valid intersection. Hotkey "K" works while the Road Architect System GameObject is selected.
-
View next bridge: Changes the sceneview to the next valid bridge. Hotkey "L" works while the Road Architect System GameObject is selected.
-
-
-
- -
-
V. Road GameObject
-
- - - -
a. Road options:
-
RoadObject1 UI image
- -
-
Gizmos: Enable or disable most gizmos for this road. Disable mesh collider gizmos via the unity menu if necessary or desired.
-
Lanes: Select the number of lanes for this road.
-
Lane width: Modify the width per lane, in meters.
-
Road width: Displays the road width without considering shoulders, in meters.
-
Shoulders enabled: Enables or disables shoulders.
-
Shoulders width: Modify the width of shoulders, in meters.
-
Road definition: The meter spacing between mesh triangles on the road and shoulder.
-
Use default materials: When enabled will use default materials for the road system, allowing certain aspects of generation to automatically determine the correct materials to utilize.
-
Max grade enforced: When enabled enforces a maximum grade on a per node basis.
-
Max road grade: The maximum road grade allowed on a per node basis.
-
Multithreading: When enabled allows for multi-threaded road generation.
-
Save mesh assets: When enabled saves all generated meshes as .asset files.
-
Reset to default icon = Reset to default value.
-
- - - - -
b. Terrain options:
-
RoadObject2 UI image
-
-
Terrain subtraction: This value, in meters, will be subtracted from the terrain match height to prevent z-fighting.
-
Spline magnitude limit: Limits the magnitude of the spline nodes. Lower limit is better for typical roads with node separation of around 100 to 300 meters. Higher limits will allow for less tension when using very spread out nodes.
-
Height Modification: Enables or disables height matching for the terrain.
-
Active detail removal: Enables or disables active detail removal. Memory intensive on large terrains with large amounts of details. Recommended to not use this option and instead remove details and trees via splat maps with other addons.
-
Active tree removal: Enables or disables active tree removal. Memory intensive on large terrains with large amounts of trees. Recommended to not use this option and instead remove details and trees via splat maps with other addons.
-
Heights match width: The distance to the left and right of the road in which terrain heights will be matched to the road.
-
- -
-
Details clear width: The distance between the road and detail, width wise, in which details will be removed.
-
Details clear height: The distance between the road and detail, height wise, in which details will be removed.
-
Tree clear width: The distance between the road and tree, width wise, in which trees will be removed.
-
Tree clear height: The distance between the road and tree, height wise, in which trees will be removed.
-
Store terrain history separate from scene: If enabled, stores the terrain history immediately on disk after use, saving memory while in editor.
-
Terrain history size: Shows the size, in kilobytes, of the terrain history in memory or on disk.
-
Reset to default icon = Reset to default value.
-
- - - - -
c. Road and shoulder splitting:
-
RoadObject3 UI image
-
-
Typically auto-split will be the best choice for performance and other reasons.
-
Choosing split options will split the road/shoulder up into pieces mirroring the road segments between nodes.
-
Splitting makes mesh collider bound calculations more efficient and fast. Splitting also allows for more detailed and flexible road texturing options such as passing sections, other different road lines per section, road debris and more.
-
- -
-
Which splitting option to choose?
-
Recommended option: auto-split enabled for roads and shoulders.
-
Choose no splitting if you desire a single material set for this entire road and your game experiences no collision processing slowdowns from one large mesh collider. This option will create less game objects than automatic and manual splitting.
-
Choose automatic road and shoulder splitting if you desire multiple materials (such as yellow double lines for certain sections and white dotted for others) for this road and or your game experiences collision processing slowdowns from one large mesh collider.
-
Choose manual road and shoulder splitting if you desire the same as automatic splitting and desire more freedom over the process. This option will result in less GameObjects and larger mesh colliders when compared to automatic splitting.
- -
Manual splitting information:
-
Choosing manual splitting will force the user to select individual nodes to cut instead of the cuts being performed automatically. This option is recommended if bigger mesh colliders do not cause a slowdown in performance, as it lowers the overall GameObject count.
-
Manual splitting will not split up the mesh colliders like automatic cuts, so the colliders may get large & complex and cost more CPU to process collisions. If this option is chosen, please verify your game's collision processing speed and if you run into long collision processing times split more road sections.
- -
Example usages of manual splitting:
-
Example hill: Goal is to have double yellow no passing lines on a two lane road but only while the road is near or on the hill. - Pick nodes on either sides of the hill and mark both as road cut. Everything between these two nodes will be its own section - allowing you to apply double yellow no passing lines for just the hill.
-
Example mountains: In the mountains, the road is curvy and the grade is high. - There's a flat straight spot that you want to allow passing in, by marking the road with white dotted passing lines. - At the beginning of the flat straight section, mark the node as road cut. Now at the end of the flat straight section, mark this node as road cut. - This will create a road section between the two nodes, allowing you to apply white dotted passing lines for just the flat straight section. -
-
Reset to default icon = Reset to default value.
-
- - - - -
d. Editor camera:
-
RoadObject4 UI image
-
-
Use this section to travel along the road while in the editor sceneview.
-
Camera meters/sec is the speed at which the camera moves along the road.
-
Auto rotate will automatically rotate the camera to look forward at the current road's tangent. Note: You can still zoom in and out with the camera with this option selected.
-
Note: Materials act differently in the editor scene view compared to actual gameplay. Try the game camera if the materials are z fighting and having other issues.
-
Reset to default icon = Reset to default value.
-
- - - - -
e. Road materials:
-
RoadObject5 UI image
-
-
These default materials will be applied by default to their respective generated meshes. If using split roads and or shoulders, you can specific specific materials to use on them (on the mesh renderers of the cuts) and they will be used instead of the default materials listed above.
-
Road base material is UV mapped on a world vector basis for seamless tiles.
-
Road marker material is UV mapped to fit roads. Use these materials to place road lines and other road texture details. Note: if using road cuts, these are the materials which will be placed by default at the initial generation.
-
Shoulder base material is UV mapped on a world vector basis for seamless tiles.
-
Shoulder marker material is UV mapped on a world vector basis for seamless tiles. For intended use with transparent shadow receiving shaders. Marker materials are applied, optionally, on shoulder cuts.
-
Physical material for road will be used on all road colliders. The physical material for shoulder will be used on all shoulder colliders. If using road and or shoulder cuts, you can specify unique physics materials which will be used instead of the default physics materials.
-
Apply above materials button will clear all saved materials on the roads and all road and shoulder meshes will use the materials listed above.
-
Reset to default icon = Reset to default value.
-
- - - - -
f. Miscellaneous:
-
RoadObject6 UI image
-
-
Reset terrain history Resetting the terrain history will make the road system "forget" all terrain height,detail and tree history.
-
WARNING: Only reset the terrain history if you have changed terrain resolution data such as heightmap or detail resolutions. A rare event may occur when editing and compiling this addon's scripts that a terrain history reset may be necessary. Treat this reset as a last resort.
-
-
-
- -
-
VI. Node GameObject
- - - -
a. Node basic options:
-
Node1 UI image
-
-
Gizmos: Enable or disable most gizmos for this node. Disable mesh collider gizmos via the unity menu if necessary or desired.
-
Save group: Allows the saving of a group of items for easy replication.
-
Open wizard: Opens the creation wizard, allowing the user to easily create prefabricated bridges, systems, railing, signs and more.
- -
Add custom extrusion object: Adds a custom extrusion object to the node.
-
Add custom edge object: Adds a custom edge object to the node.
- -
Statistics: Displays general statistics about the node.
-
- -
a. Extrusion objects:
-
- - - - -
i. General options:
-
Node1SMM1 UI image
-
- - - -
Name: The name of the extrusion object.
-
Prefab: The prefab or FBX file to repeat along the spline.
-
Prefab start cap: The start cap of the prefab. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Prefab end cap: The end cap of the prefab. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Material override: If enabled, instead of using the prefab's material, the extrusion object will use the override materials listed below.
-
Override mat #1: The first override material.
-
Override mat #2: The second override material.
-
Extrusion axis: The axis in which the prefab is extruded, either the X-axis or Z-axis. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Start param: The start parameter of the extrusion object. Corresponds to the parameter of the spline.
-
End param: The end parameter of the extrusion object. Corresponds to the parameter of the spline.
-
Trim start: Trims the start of the extrusion object by one length of the extrusion object.
-
Trim end: Trims the end of the extrusion object by one length of the extrusion object.
-
Static: Marks the created object as static.
-
Match ground: If enabled, makes the extrusion object hug the terrain, road or whichever object is directly beneath the extrusion object.
-
- - -
- - -
Vertex min/max: This value is the threshold in which the start and end vertices are detected on the base prefab. For example, a value of 0.002f (or 2mm) will retrieve the outermost values along the extrusion axis and then reflect inward 2mm and mark all detected vertices and start and end vertices. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Vertex matching: This value is the allowable error rate when attempting to match mirrored vertices. For example, a value of 0.005f (or 5mm) will allow an error of 5mm in determining matching vertices. Please watch all extrusion object tutorial videos for more comprehensive information.
- -
UV repeat axis: Determines which axis the UV will repeat. This option is typically used in conjunction with the match road definition option.
-
Match road definition: If enabled, attempts to match the length of the object to the road definition value. This option should only be used for objects without any middle vertices.
-
Flip Y rotation: Flips the Y rotation of the extrusion object by 180 degrees.
- -
- - -
-
Extrude icon = Indicates this is an extrusion object.
-
Refresh icon = Manually updates the object.
-
-
Copy icon = Duplicates the extrusion object.
-
Delete icon = Deletes the extrusion object.
-
-
- -
Save icon = Allows saving of this extrusion object via a save dialog. This saved item can then be loaded onto other nodes via the creation wizard.
- -
Reset to default icon = Reset to default value.
-
- - - - -
ii. Vertical and horizontal curve options:
-
Node1SMM2 UI image
-
-
Vertical raise magnitude: The magnitude of vertical rise given to the extrusion object. This magnitude is interpolated along the extrusion length as the value of the Vertical Curve. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Horizontal offset magnitude: The magnitude of horizontal offset given to the extrusion object. This magnitude is interpolated along the extrusion length as the value of the Horizontal Curve. Please watch all extrusion object tutorial videos for more comprehensive information.
-
Reset to default icon = Reset to default value.
-
- - - - -
iii. Vertical cutoff options:
-
Node1SMM31 UI image
-
Node1SMM32 UI image
-
-
Vertical cutoff: Vertical cutoff options allow for suspension bridge cables and arch bridges. The vertical cutoff options are not utilized for any other purpose.
-
Match spline height: Attempts to match the spline's height. If the cut direction toggle is enabled, the match spline height is applied to the base. If the cut direction toggle is disabled, the match spline height is applied to the top.
-
Cut direction toggle: Toggles the direction of the cut, either top or bottom. For example, a suspension bridge will need to be "cut" at the top and an arch bridge will need to be "cut" in the opposite direction.
- -
Height cut offset: Offsets the base cut level. For example, this setting will affect a suspension bridge cable's bottom area and will affect an arch bridge's top area.
-
Opposite dir cut: If enabled, flips the mesh before cutting.
-
Mesh cut offset: The vertical height cut offset which is applied to the cut ends of the mesh. Allows fine tuning of the cuts. For example, sometimes your suspension bridge cables may stick through the top of the main cable and might need fine tuned.
-
- - - - - -
iv. Start & end object options:
-
Node1SMM4 UI image
-
-
Push endings down: If enables, pushes the endings of the extrusion object down into the ground. Creates realistic effects with KRails, WBeams and other types of railing.
-
Override down value: If enabled, overrides the down value with the below option.
-
Downward movement: The override down value.
- -
Match objects to ends: If enabled, attempts to place the start/end extra objects with the proper end placement.
-
Force origins to ground: If enabled, attempts to force the extra objects to hug the ground.
- -
Start object: Allows placement of an extra object at the start of the extrusion. Excellent for sand barrels, warning signs or attenuators.
-
Start quick select: A drop-down which features quick selection of extra objects.
-
Start prefab: The prefab used to generate the start object.
-
Start position offset: Adds a positional offset to the start object.
-
Start rotation offset: Adds a rotational offset to the start object.
- -
End object: Allows placement of an extra object at the end of the extrusion. Excellent for sand barrels, warning signs or attenuators..
-
End quick select: A drop-down which features quick selection of extra objects.
-
End prefab: The prefab used to generate the end object.
-
End position offset: Adds a positional offset to the end object.
-
End rotation offset: Adds a rotational offset to the end object.
-
- - - - -
v. Collision options:
-
Node1SMM51 UI image
-
Node1SMM52 UI image
-
-
Collision type drop-down: Select the collision type.
-
None: Disables all collision on this extrusion object.
-
Simple mesh triangle: Uses a dynamically created simple mesh triangle as the collider for the extrusion object.
-
Simple mesh trapezoid: Uses a dynamically created simple mesh trapezoid as the collider for the extrusion object.
-
Base Mesh collision: Uses the extrusion object's mesh filter as the collider for the extrusion object.
-
Box collision: When using the straight line option for bridges, a box collider can be used as the collider.
- -
Convex: Corresponds to the convex option on mesh colliders.
-
Trigger: Corresponds to the trigger option on mesh colliders.
-
Automatic simple:
-
Enabled: If simple triangle or trapezoid is selected and this option is enabled, the mesh collider dimensions will automatically created.
-
Disabled: If disabled and simple triangle or trapezoid is selected, allows the user to customize the dimensions of the dynamically created mesh collider.
-
- - - - -
vi. Rotation and deprecated:
-
Node1SMM6 UI image
-
-
Custom rotation: Rotates the base prefab before extrusion takes place.
-
Directional extrusion: A deprecated option, extrudes the objects by different methods.
-
Reset to default icon = Reset to default value.
-
- -
- - -
b. Edge objects:
-
- - - - -
i. General options:
-
Node1EOM1Multi UI image
-
Node1EOM1Single UI image
-
-
Name: The name of the edge object instance.
-
Edge object: The prefab or FBX file representing this edge object.
-
Material override: If enabled, instead of using the prefab's material, the edge object will use the override materials listed below.
-
Override mat #1: The first override material.
-
Override mat #2: The second override material.
- -
Combine meshes: If enabled, combines all edge objects into one mesh.
-
Combined mesh collider: If enabled, uses a mesh collider for the combined mesh.
- -
Single object only: If enabled, only creates a single edge object.
-
Single location: If a single edge object, then use this value to place the single edge object along the spline.
- -
Static: Marks the created edge object(s) as static.
-
Match ground height: If enabled, the edge object(s) hug the ground.
-
Dist between objects: The distance between each edge object.
-
Match road definition: Attempts to match the road definition in terms of distance between objects. For example, if the road definition is 5 meters, the distance between objects will be 5 meters while attempting to start at a road definition segment.
-
Position fine tuning: Fine tunes the start distance on a scale of 0 meters to the road definition meters.
-
Start param: The start location of the edge objects.
-
End param: The end location of the edge objects.
- -
- - -
-
Extrude icon = Indicates this is an edge object(s).
-
Refresh icon = Manually updates the edge object(s).
-
-
Copy icon = Duplicates the edge object(s).
-
Delete icon = Deletes the edge object(s).
-
-
- -
Save icon = Allows saving of this edge object(s) via a save dialog. This saved item can then be loaded onto other nodes via the creation wizard.
- -
Reset to default icon = Reset to default value.
-
- - - - -
ii. Vertical, horizontal and rotation options:
-
Node1EOM2 UI image
-
-
Vertical raise magnitude: The magnitude of vertical rise given to the edge object. This magnitude is interpolated along the edge object repeat length as the value of the Vertical Curve. Please watch all edge object tutorial videos for more comprehensive information.
-
Select horizontal preset: Offers horizontal offset magnitude presets such as road edges and shoulder edges for easy placement of railing and signs.
-
Horizontal offset magnitude: The magnitude of horizontal offset given to the edge object. This magnitude is interpolated along the edge object repeat length as the value of the Horizontal Curve. Please watch all edge object tutorial videos for more comprehensive information.
-
Auto-rotate incoming: Automatically rotates the object 180 degrees around the y-axis if placed on the left side of the road (negative horizontal offset magnitude).
-
Custom rotation: Rotates the base prefab before edge object repetition takes place.
-
Reset to default icon = Reset to default value.
-
- -
-
- -
-
VII. Intersection GameObject
- - - -
a. Intersection options:
-
Intersection1 UI image
-
-
Auto-update: Enables or disables auto updating of this intersection when changing options.
-
Gizmo: Enables or disables most gizmo drawing on all objects related to this intersection.
-
Intersection turn lane options:
-
No turn lanes: Creates an intersection with no turn lanes.
-
Left turn lane only: Creates an intersection with a left turn lane.
-
Both turn lanes: Creates an intersection with left turn and right turn lanes.
- -
Left yield on green: If checked, replaces the standard 3-light left turn light with a five-light yield on green left turn signal structure and sign.
-
Street lights: If checked, attaches street lights to each intersection pole. Point lights optional and can be manipulated in the next option segment.
-
Gray color: If checked, sets the traffic light pole base materials to gray galvanized steel. If unchecked the material used is black metal paint.
-
Normal pole alignment: Recommended to keep this option on unless abnormal twisting of light objects is occurring. Turn this option off if the roads immediately surrounding your intersection are curved at extreme angles and cause irregular twisting of the traffic light objects. Turning this option off will attempt to align the poles perpendicular to the adjacent relevant road without any part existing over the main intersection bounds.
-
Point lights: Enabled means that point lights for the traffic lights (and street lights, if enabled) will be turned on. This is accessible via script \"bLightsEnabled\"
-
If street pole lights enabled: Street light range, intensity and color: These settings directly correlate to the standard point light settings.
-
Traffic light scale sensitivity: Increasing this value will increase the scaling sensitivity relative to the size of the intersection. Higher scaling value = bigger traffic lights at further distances. Default value is 170.
-
Grade correction: If using extreme road grades immediately surrounding the intersection, terrain height matching errors may occur at the point of road expansion leading to the intersection.
-
Raise this value if you see terrain poking through the road at the road expansion areas.
-
Lower this value if you are not using road mesh colliders and notice dips at the expansion points.
-
Default value is 0.375 meters, which is the maximum value for a linear range of 0% to 20% grade.
-
Recommended to keep grades and angles small leading up to intersections.
-
Reset to default icon = Reset to default value.
- -
- - - - -
b. Intersection materials:
-
Intersection2 UI image
-
-
Center marker materials: Center marker materials require transparent shaders. Covers the center area of the intersection. Displayed in order #1 on bottom to #4 on top. Combine with transparent shaders which accept shadows to allow for easy marking. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
-
Exterior fitted marker materials: Fitted marker materials require transparent shaders. Covers the exterior area of the intersection with the UV's stretched to match at a 1:1 ratio. Should be use for intersection markings and any visual effects like dirt. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
-
Exterior tiled marker materials: Covers the exterior area of the intersection with the UV's tiled matching world coordinates. Tiled and used for road pavement textures. UV coordinates will match up seamlessly with road pavement. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
- -
Lanes marker materials: Covers individual lane sections in the intersection. Used for high-definition line marking. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
-
Lane section 0: Left side of the intersection where oncoming traffic travels. Use lane texture which matches the number of lanes used on the road system, with a white left line and a yellow right line.
-
Lane section 1: Left turn lane. Use a single lane texture with a yellow left line and a white right line.
-
Lane section 2: Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line.
-
Lane section 3: Right turn lane. Use a single lane texture with a white right line.
-
Reset to default icon = Reset to default value.
-
Delete icon = Deletes the edge object(s).
-
-
- -
-
VIII. Exporting a splatmap
-
- - -
- Splatmap UI image - -
Match resolutions: Select from a pre-populated list of resolutions. This resolution corresponds to the image size of the generated splatmap.
-
Splat image width & height: Corresponds to the image resolution of the generated splatmap.
-
Splat foreground: Changes the foreground color which represents the road(s) in the splatmap.
-
Splat background: Changes the background color which represents the non road covered areas in the splatmap.
-
Splat width: Changes the width of the road splat. Example: If you wanted a splatmap width of 60 meters surrounding the road, set the value to 60.
-
Skip bridges: Disables or enables the splat generation of bridge sections.
-
Skip tunnels: Disables or enables the splat generation of tunnel sections.
-
Splat a single road: Enables the selection of a single specific road to splat.
-
Generate splatmap: Creates the splatmap and prompts where to save the image.
-
Reset to default icon = Reset to default value.
-
-
-
- -
-
IX. Exporting meshes
-
- - -
-
To export any mesh, utilize the main menu toolbar at "Road Architect" -> "Export".
-
Utilizes "Exporters by Hrafnkell Freyr Hlooversson" from Unity3D wiki: http://wiki.unity3d.com/index.php?title=ObjExporter.
-
-
-
- - -
-
X. Frequently asked questions ( FAQ / F.A.Q. )
-
- - -
- -
Why does the information message "Mesh has been leaked X times message" appear in the console occasionally? 02/02/2014
-
All meshes are getting properly marked for garbage collection but due to the way Unity Editor handles mesh creation and nullification, it may not happen in a predictable fashion. This message is not harmful and you can safely ignore it: The message informs of proper cleanup of a leaked mesh during editor mode and it has zero effect on gameplay modes.
- -
Some of my roads turn too sharp or bunch up inexplicably. 02/02/2014
-
Try manipulating the "Spline Magnitude Limit" listed in the terrain options of the "Road Object".
- -
What builds are supported? 02/02/2014
-
Windows, Web, MAC, Linux. Other builds probably work but we don't know. Email support@microgsd.com if you run into any problems.
- -
Sometimes my 3-way intersection looks wrong, what do I do? 02/25/2014
-
Try manually updating the intersection by clicking on the "Update Intersection" button while the intersection gameobject is selected in the hierarchy. If the problem persists, please contact us at support@microgsd.com
- -
Why did my terrain history get reset or altered? 02/25/2014
-
If the terrain history is saved on the disk, the saving scheme uses the scene name, the road name and then the road system name. Don't name your scenes the same name.
- -
Sometimes when using the road grade enforcement the grade between nodes is higher than the limit, why? 02/25/2014
-
If you adjust the height of nodes along the spline there is a small chance that the limitation will be exceeded from the adjustment node to the next node. To avoid unintentional rolling changes to the entire road it is advised to manually examine the next node and adjust it's height next.
- -
My intersection looks messed up, what can I do to fix it? 02/26/2014
-
Try clicking "Update intersection" in the inspector window while having the intersection selected in the hierarchy. If the problem persists, please contact us at support@microgsd.com
-
-
-
- -
-
-
-
-
- -
- - + + + + + + Road Architect Manual - MicroGSD + + + + + + + + +
+
+ +
+ + +
+
+
+
+
+ +
Road Architect Offline Manual
+ + + +
+ +
+
I. Quick overview
+
+Road Architect's primary game objects: +
    +
  • "Road Architect System" (RoadArchitectSystem.cs) - this script component is treated as the master GameObject for organization purposes. Located at the root level of the hierarchy.
  • +
  • "Road Object" (GSDRoad.cs) - this script component is attached to each road created. Contains 42+ options including road width, lane count and terrain options. Located as a child of a Road Architect System GameObject.
  • +
  • "Road Node" (GSDSplineN.cs) - this script component is attached to each road node on a road. Contains 100+ options and is the primary place in which bridges, edge objects and more are created. Located as a child of a Spline GameObject, which is a child of a Road GameObject.
  • +
  • "Intersection Object" (GSDRoadIntersection.cs) - this script component is attached to each intersection object. Contains dozens of intersection options. Located as a child of the "Intersections" GameObject, which is a child of a Road Architect System GameObject.
  • +
  • "Splatmap Creator" (GSDTerrain.cs) - this script component is attached to each terrain in the scene. Contains 8 options for creating and exporting splat maps. Located on each Terrain GameObject.
  • +
+
+
+ +
+
II. Quick start guides
+
+
a. Building a road
+ +
    +
  • Create a Road Architect System GameObject via the Road Architect file menu.
  • +
  • Select the newly created Road Architect System GameObject and click "Add road" to add a road (located in the Road Architect System's inspector window).
  • +
  • While a road object is selected:
  • +
+ +
+ CTRL + + + LEFT-CLICK + = Add road nodes on the terrain while holding ctrl and left-clicking on the terrain location. +
+ +
+ SHIFT + + + LEFT-CLICK + = Insertion mode: Insert road nodes on the terrain while holding shift and left-clicking on the terrain location. +
+ + +
b. Building an intersection
+ +
    +
  • Drag a node on top of another node. Can be from the same road or different roads. To create a 3-way intersection, utilize an end node (a road's first or last node) to create the intersection. Note: You can't create an intersection out of consecutive nodes of the same road.
  • +
+ +
c. Building a bridge
+ +
    +
  • Select the road node where the bridge is to start. + +
      +
    • +
      + +
      +
    • +
    + +
  • + +
  • At the top of the node's inspector window, check "Bridge start". +
      +
    • +
      + + + +
      +
    • +
    +
  • + +
  • Select the road node where the bridge is to end. +
      +
    • +
      + +
      +
    • +
    +
  • + +
  • At the top of the node's inspector window, check "Bridge end". +
      +
    • +
      + + + +
      +
    • +
    +
  • + +
  • Select the bridge start node. +
      +
    • +
      + +
      +
    • +
    +
  • + +
  • Click "Open Wizard" (the blue button) in the inspector panel. This will open the creation wizard. +
      +
    • +
      + +
      +
    • +
    +
  • + +
  • Make sure "Completed Bridges" is selected in the creation wizard drop-down. + +
      +
    • +
      + +
      +
    • +
    + +
  • +
  • Single-click on which bridge type to add. Adjust the bridge start and end nodes' heights for desired effect.
  • +
+ + +
d. Using the Wizard
+
    +
  • Select the node in which you wish to add an extruded, repeated object or singular object.
  • +
  • Switch back to the node where you want the bridge to start. Click "Open Wizard" (the blue button). This will open the creation wizard.
  • +
  • Select "Extrusion Objects" or "Edge Objects" from the the creation wizard drop-down.
  • +
  • Experiment with the drop-down and its options to explore all of the included assets
  • +
+
+
+ + +
+
III. Quick tips
+
+
    +
  • Look at the example scenes to see entire road layouts with bridges and more.
  • +
  • Nodes are the only GameObject to add bridges, railings, signs and similar items. In other words: To add any non-road item you must do so from a Node.
  • +
  • To add nodes, you must have a road selected. Ctrl-left-click to add a node to the end of the road. Shift-left-click to insert a node anywhere along the spline.
  • +
  • Creating a custom extrusion and edge objects is performed by clicking the "Create a custom extrusion object" and "Create a custom edge object" in a Node's inspector window.
  • +
  • Confused? Watch the tutorial videos. Still confused? Email support@microgsd.com and you will received a response within 48 hours.
  • +
+
+
+ +
+
IV. Road Architect System GameObject
+
+ + +
+ RoadArchitectSystem UI image + +
Add road: Adds a road to the system. After clicking this button, the new road will automatically be selected as the active GameObject.
+
Multithreading: Enables or disables multithreading during road generation.
+
Save mesh assets: Enables or disables saving of meshes as unity assets.
+
Update all roads: Updates all roads in the scene. This may take a while depending on the number of roads in the scene.
+
View next intersection: Changes the sceneview to the next valid intersection. Hotkey "K" works while the Road Architect System GameObject is selected.
+
View next bridge: Changes the sceneview to the next valid bridge. Hotkey "L" works while the Road Architect System GameObject is selected.
+
+
+
+ +
+
V. Road GameObject
+
+ + + +
a. Road options:
+
RoadObject1 UI image
+ +
+
Gizmos: Enable or disable most gizmos for this road. Disable mesh collider gizmos via the unity menu if necessary or desired.
+
Lanes: Select the number of lanes for this road.
+
Lane width: Modify the width per lane, in meters.
+
Road width: Displays the road width without considering shoulders, in meters.
+
Shoulders enabled: Enables or disables shoulders.
+
Shoulders width: Modify the width of shoulders, in meters.
+
Road definition: The meter spacing between mesh triangles on the road and shoulder.
+
Use default materials: When enabled will use default materials for the road system, allowing certain aspects of generation to automatically determine the correct materials to utilize.
+
Max grade enforced: When enabled enforces a maximum grade on a per node basis.
+
Max road grade: The maximum road grade allowed on a per node basis.
+
Multithreading: When enabled allows for multi-threaded road generation.
+
Save mesh assets: When enabled saves all generated meshes as .asset files.
+
Reset to default icon = Reset to default value.
+
+ + + + +
b. Terrain options:
+
RoadObject2 UI image
+
+
Terrain subtraction: This value, in meters, will be subtracted from the terrain match height to prevent z-fighting.
+
Spline magnitude limit: Limits the magnitude of the spline nodes. Lower limit is better for typical roads with node separation of around 100 to 300 meters. Higher limits will allow for less tension when using very spread out nodes.
+
Height Modification: Enables or disables height matching for the terrain.
+
Active detail removal: Enables or disables active detail removal. Memory intensive on large terrains with large amounts of details. Recommended to not use this option and instead remove details and trees via splat maps with other addons.
+
Active tree removal: Enables or disables active tree removal. Memory intensive on large terrains with large amounts of trees. Recommended to not use this option and instead remove details and trees via splat maps with other addons.
+
Heights match width: The distance to the left and right of the road in which terrain heights will be matched to the road.
+
+ +
+
Details clear width: The distance between the road and detail, width wise, in which details will be removed.
+
Details clear height: The distance between the road and detail, height wise, in which details will be removed.
+
Tree clear width: The distance between the road and tree, width wise, in which trees will be removed.
+
Tree clear height: The distance between the road and tree, height wise, in which trees will be removed.
+
Store terrain history separate from scene: If enabled, stores the terrain history immediately on disk after use, saving memory while in editor.
+
Terrain history size: Shows the size, in kilobytes, of the terrain history in memory or on disk.
+
Reset to default icon = Reset to default value.
+
+ + + + +
c. Road and shoulder splitting:
+
RoadObject3 UI image
+
+
Typically auto-split will be the best choice for performance and other reasons.
+
Choosing split options will split the road/shoulder up into pieces mirroring the road segments between nodes.
+
Splitting makes mesh collider bound calculations more efficient and fast. Splitting also allows for more detailed and flexible road texturing options such as passing sections, other different road lines per section, road debris and more.
+
+ +
+
Which splitting option to choose?
+
Recommended option: auto-split enabled for roads and shoulders.
+
Choose no splitting if you desire a single material set for this entire road and your game experiences no collision processing slowdowns from one large mesh collider. This option will create less game objects than automatic and manual splitting.
+
Choose automatic road and shoulder splitting if you desire multiple materials (such as yellow double lines for certain sections and white dotted for others) for this road and or your game experiences collision processing slowdowns from one large mesh collider.
+
Choose manual road and shoulder splitting if you desire the same as automatic splitting and desire more freedom over the process. This option will result in less GameObjects and larger mesh colliders when compared to automatic splitting.
+ +
Manual splitting information:
+
Choosing manual splitting will force the user to select individual nodes to cut instead of the cuts being performed automatically. This option is recommended if bigger mesh colliders do not cause a slowdown in performance, as it lowers the overall GameObject count.
+
Manual splitting will not split up the mesh colliders like automatic cuts, so the colliders may get large & complex and cost more CPU to process collisions. If this option is chosen, please verify your game's collision processing speed and if you run into long collision processing times split more road sections.
+ +
Example usages of manual splitting:
+
Example hill: Goal is to have double yellow no passing lines on a two lane road but only while the road is near or on the hill. + Pick nodes on either sides of the hill and mark both as road cut. Everything between these two nodes will be its own section + allowing you to apply double yellow no passing lines for just the hill.
+
Example mountains: In the mountains, the road is curvy and the grade is high. + There's a flat straight spot that you want to allow passing in, by marking the road with white dotted passing lines. + At the beginning of the flat straight section, mark the node as road cut. Now at the end of the flat straight section, mark this node as road cut. + This will create a road section between the two nodes, allowing you to apply white dotted passing lines for just the flat straight section. +
+
Reset to default icon = Reset to default value.
+
+ + + + +
d. Editor camera:
+
RoadObject4 UI image
+
+
Use this section to travel along the road while in the editor sceneview.
+
Camera meters/sec is the speed at which the camera moves along the road.
+
Auto rotate will automatically rotate the camera to look forward at the current road's tangent. Note: You can still zoom in and out with the camera with this option selected.
+
Note: Materials act differently in the editor scene view compared to actual gameplay. Try the game camera if the materials are z fighting and having other issues.
+
Reset to default icon = Reset to default value.
+
+ + + + +
e. Road materials:
+
RoadObject5 UI image
+
+
These default materials will be applied by default to their respective generated meshes. If using split roads and or shoulders, you can specific specific materials to use on them (on the mesh renderers of the cuts) and they will be used instead of the default materials listed above.
+
Road base material is UV mapped on a world vector basis for seamless tiles.
+
Road marker material is UV mapped to fit roads. Use these materials to place road lines and other road texture details. Note: if using road cuts, these are the materials which will be placed by default at the initial generation.
+
Shoulder base material is UV mapped on a world vector basis for seamless tiles.
+
Shoulder marker material is UV mapped on a world vector basis for seamless tiles. For intended use with transparent shadow receiving shaders. Marker materials are applied, optionally, on shoulder cuts.
+
Physical material for road will be used on all road colliders. The physical material for shoulder will be used on all shoulder colliders. If using road and or shoulder cuts, you can specify unique physics materials which will be used instead of the default physics materials.
+
Apply above materials button will clear all saved materials on the roads and all road and shoulder meshes will use the materials listed above.
+
Reset to default icon = Reset to default value.
+
+ + + + +
f. Miscellaneous:
+
RoadObject6 UI image
+
+
Reset terrain history Resetting the terrain history will make the road system "forget" all terrain height,detail and tree history.
+
WARNING: Only reset the terrain history if you have changed terrain resolution data such as heightmap or detail resolutions. A rare event may occur when editing and compiling this addon's scripts that a terrain history reset may be necessary. Treat this reset as a last resort.
+
+
+
+ +
+
VI. Node GameObject
+ + + +
a. Node basic options:
+
Node1 UI image
+
+
Gizmos: Enable or disable most gizmos for this node. Disable mesh collider gizmos via the unity menu if necessary or desired.
+
Save group: Allows the saving of a group of items for easy replication.
+
Open wizard: Opens the creation wizard, allowing the user to easily create prefabricated bridges, systems, railing, signs and more.
+ +
Add custom extrusion object: Adds a custom extrusion object to the node.
+
Add custom edge object: Adds a custom edge object to the node.
+ +
Statistics: Displays general statistics about the node.
+
+ +
a. Extrusion objects:
+
+ + + + +
i. General options:
+
Node1SMM1 UI image
+
+ + + +
Name: The name of the extrusion object.
+
Prefab: The prefab or FBX file to repeat along the spline.
+
Prefab start cap: The start cap of the prefab. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Prefab end cap: The end cap of the prefab. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Material override: If enabled, instead of using the prefab's material, the extrusion object will use the override materials listed below.
+
Override mat #1: The first override material.
+
Override mat #2: The second override material.
+
Extrusion axis: The axis in which the prefab is extruded, either the X-axis or Z-axis. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Start param: The start parameter of the extrusion object. Corresponds to the parameter of the spline.
+
End param: The end parameter of the extrusion object. Corresponds to the parameter of the spline.
+
Trim start: Trims the start of the extrusion object by one length of the extrusion object.
+
Trim end: Trims the end of the extrusion object by one length of the extrusion object.
+
Static: Marks the created object as static.
+
Match ground: If enabled, makes the extrusion object hug the terrain, road or whichever object is directly beneath the extrusion object.
+
+ + +
+ + +
Vertex min/max: This value is the threshold in which the start and end vertices are detected on the base prefab. For example, a value of 0.002f (or 2mm) will retrieve the outermost values along the extrusion axis and then reflect inward 2mm and mark all detected vertices and start and end vertices. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Vertex matching: This value is the allowable error rate when attempting to match mirrored vertices. For example, a value of 0.005f (or 5mm) will allow an error of 5mm in determining matching vertices. Please watch all extrusion object tutorial videos for more comprehensive information.
+ +
UV repeat axis: Determines which axis the UV will repeat. This option is typically used in conjunction with the match road definition option.
+
Match road definition: If enabled, attempts to match the length of the object to the road definition value. This option should only be used for objects without any middle vertices.
+
Flip Y rotation: Flips the Y rotation of the extrusion object by 180 degrees.
+ +
+ + +
+
Extrude icon = Indicates this is an extrusion object.
+
Refresh icon = Manually updates the object.
+
+
Copy icon = Duplicates the extrusion object.
+
Delete icon = Deletes the extrusion object.
+
+
+ +
Save icon = Allows saving of this extrusion object via a save dialog. This saved item can then be loaded onto other nodes via the creation wizard.
+ +
Reset to default icon = Reset to default value.
+
+ + + + +
ii. Vertical and horizontal curve options:
+
Node1SMM2 UI image
+
+
Vertical raise magnitude: The magnitude of vertical rise given to the extrusion object. This magnitude is interpolated along the extrusion length as the value of the Vertical Curve. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Horizontal offset magnitude: The magnitude of horizontal offset given to the extrusion object. This magnitude is interpolated along the extrusion length as the value of the Horizontal Curve. Please watch all extrusion object tutorial videos for more comprehensive information.
+
Reset to default icon = Reset to default value.
+
+ + + + +
iii. Vertical cutoff options:
+
Node1SMM31 UI image
+
Node1SMM32 UI image
+
+
Vertical cutoff: Vertical cutoff options allow for suspension bridge cables and arch bridges. The vertical cutoff options are not utilized for any other purpose.
+
Match spline height: Attempts to match the spline's height. If the cut direction toggle is enabled, the match spline height is applied to the base. If the cut direction toggle is disabled, the match spline height is applied to the top.
+
Cut direction toggle: Toggles the direction of the cut, either top or bottom. For example, a suspension bridge will need to be "cut" at the top and an arch bridge will need to be "cut" in the opposite direction.
+ +
Height cut offset: Offsets the base cut level. For example, this setting will affect a suspension bridge cable's bottom area and will affect an arch bridge's top area.
+
Opposite dir cut: If enabled, flips the mesh before cutting.
+
Mesh cut offset: The vertical height cut offset which is applied to the cut ends of the mesh. Allows fine tuning of the cuts. For example, sometimes your suspension bridge cables may stick through the top of the main cable and might need fine tuned.
+
+ + + + + +
iv. Start & end object options:
+
Node1SMM4 UI image
+
+
Push endings down: If enables, pushes the endings of the extrusion object down into the ground. Creates realistic effects with KRails, WBeams and other types of railing.
+
Override down value: If enabled, overrides the down value with the below option.
+
Downward movement: The override down value.
+ +
Match objects to ends: If enabled, attempts to place the start/end extra objects with the proper end placement.
+
Force origins to ground: If enabled, attempts to force the extra objects to hug the ground.
+ +
Start object: Allows placement of an extra object at the start of the extrusion. Excellent for sand barrels, warning signs or attenuators.
+
Start quick select: A drop-down which features quick selection of extra objects.
+
Start prefab: The prefab used to generate the start object.
+
Start position offset: Adds a positional offset to the start object.
+
Start rotation offset: Adds a rotational offset to the start object.
+ +
End object: Allows placement of an extra object at the end of the extrusion. Excellent for sand barrels, warning signs or attenuators..
+
End quick select: A drop-down which features quick selection of extra objects.
+
End prefab: The prefab used to generate the end object.
+
End position offset: Adds a positional offset to the end object.
+
End rotation offset: Adds a rotational offset to the end object.
+
+ + + + +
v. Collision options:
+
Node1SMM51 UI image
+
Node1SMM52 UI image
+
+
Collision type drop-down: Select the collision type.
+
None: Disables all collision on this extrusion object.
+
Simple mesh triangle: Uses a dynamically created simple mesh triangle as the collider for the extrusion object.
+
Simple mesh trapezoid: Uses a dynamically created simple mesh trapezoid as the collider for the extrusion object.
+
Base Mesh collision: Uses the extrusion object's mesh filter as the collider for the extrusion object.
+
Box collision: When using the straight line option for bridges, a box collider can be used as the collider.
+ +
Convex: Corresponds to the convex option on mesh colliders.
+
Trigger: Corresponds to the trigger option on mesh colliders.
+
Automatic simple:
+
Enabled: If simple triangle or trapezoid is selected and this option is enabled, the mesh collider dimensions will automatically created.
+
Disabled: If disabled and simple triangle or trapezoid is selected, allows the user to customize the dimensions of the dynamically created mesh collider.
+
+ + + + +
vi. Rotation and deprecated:
+
Node1SMM6 UI image
+
+
Custom rotation: Rotates the base prefab before extrusion takes place.
+
Directional extrusion: A deprecated option, extrudes the objects by different methods.
+
Reset to default icon = Reset to default value.
+
+ +
+ + +
b. Edge objects:
+
+ + + + +
i. General options:
+
Node1EOM1Multi UI image
+
Node1EOM1Single UI image
+
+
Name: The name of the edge object instance.
+
Edge object: The prefab or FBX file representing this edge object.
+
Material override: If enabled, instead of using the prefab's material, the edge object will use the override materials listed below.
+
Override mat #1: The first override material.
+
Override mat #2: The second override material.
+ +
Combine meshes: If enabled, combines all edge objects into one mesh.
+
Combined mesh collider: If enabled, uses a mesh collider for the combined mesh.
+ +
Single object only: If enabled, only creates a single edge object.
+
Single location: If a single edge object, then use this value to place the single edge object along the spline.
+ +
Static: Marks the created edge object(s) as static.
+
Match ground height: If enabled, the edge object(s) hug the ground.
+
Dist between objects: The distance between each edge object.
+
Match road definition: Attempts to match the road definition in terms of distance between objects. For example, if the road definition is 5 meters, the distance between objects will be 5 meters while attempting to start at a road definition segment.
+
Position fine tuning: Fine tunes the start distance on a scale of 0 meters to the road definition meters.
+
Start param: The start location of the edge objects.
+
End param: The end location of the edge objects.
+ +
+ + +
+
Extrude icon = Indicates this is an edge object(s).
+
Refresh icon = Manually updates the edge object(s).
+
+
Copy icon = Duplicates the edge object(s).
+
Delete icon = Deletes the edge object(s).
+
+
+ +
Save icon = Allows saving of this edge object(s) via a save dialog. This saved item can then be loaded onto other nodes via the creation wizard.
+ +
Reset to default icon = Reset to default value.
+
+ + + + +
ii. Vertical, horizontal and rotation options:
+
Node1EOM2 UI image
+
+
Vertical raise magnitude: The magnitude of vertical rise given to the edge object. This magnitude is interpolated along the edge object repeat length as the value of the Vertical Curve. Please watch all edge object tutorial videos for more comprehensive information.
+
Select horizontal preset: Offers horizontal offset magnitude presets such as road edges and shoulder edges for easy placement of railing and signs.
+
Horizontal offset magnitude: The magnitude of horizontal offset given to the edge object. This magnitude is interpolated along the edge object repeat length as the value of the Horizontal Curve. Please watch all edge object tutorial videos for more comprehensive information.
+
Auto-rotate incoming: Automatically rotates the object 180 degrees around the y-axis if placed on the left side of the road (negative horizontal offset magnitude).
+
Custom rotation: Rotates the base prefab before edge object repetition takes place.
+
Reset to default icon = Reset to default value.
+
+ +
+
+ +
+
VII. Intersection GameObject
+ + + +
a. Intersection options:
+
Intersection1 UI image
+
+
Auto-update: Enables or disables auto updating of this intersection when changing options.
+
Gizmo: Enables or disables most gizmo drawing on all objects related to this intersection.
+
Intersection turn lane options:
+
No turn lanes: Creates an intersection with no turn lanes.
+
Left turn lane only: Creates an intersection with a left turn lane.
+
Both turn lanes: Creates an intersection with left turn and right turn lanes.
+ +
Left yield on green: If checked, replaces the standard 3-light left turn light with a five-light yield on green left turn signal structure and sign.
+
Street lights: If checked, attaches street lights to each intersection pole. Point lights optional and can be manipulated in the next option segment.
+
Gray color: If checked, sets the traffic light pole base materials to gray galvanized steel. If unchecked the material used is black metal paint.
+
Normal pole alignment: Recommended to keep this option on unless abnormal twisting of light objects is occurring. Turn this option off if the roads immediately surrounding your intersection are curved at extreme angles and cause irregular twisting of the traffic light objects. Turning this option off will attempt to align the poles perpendicular to the adjacent relevant road without any part existing over the main intersection bounds.
+
Point lights: Enabled means that point lights for the traffic lights (and street lights, if enabled) will be turned on. This is accessible via script \"bLightsEnabled\"
+
If street pole lights enabled: Street light range, intensity and color: These settings directly correlate to the standard point light settings.
+
Traffic light scale sensitivity: Increasing this value will increase the scaling sensitivity relative to the size of the intersection. Higher scaling value = bigger traffic lights at further distances. Default value is 170.
+
Grade correction: If using extreme road grades immediately surrounding the intersection, terrain height matching errors may occur at the point of road expansion leading to the intersection.
+
Raise this value if you see terrain poking through the road at the road expansion areas.
+
Lower this value if you are not using road mesh colliders and notice dips at the expansion points.
+
Default value is 0.375 meters, which is the maximum value for a linear range of 0% to 20% grade.
+
Recommended to keep grades and angles small leading up to intersections.
+
Reset to default icon = Reset to default value.
+ +
+ + + + +
b. Intersection materials:
+
Intersection2 UI image
+
+
Center marker materials: Center marker materials require transparent shaders. Covers the center area of the intersection. Displayed in order #1 on bottom to #4 on top. Combine with transparent shaders which accept shadows to allow for easy marking. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
+
Exterior fitted marker materials: Fitted marker materials require transparent shaders. Covers the exterior area of the intersection with the UV's stretched to match at a 1:1 ratio. Should be use for intersection markings and any visual effects like dirt. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
+
Exterior tiled marker materials: Covers the exterior area of the intersection with the UV's tiled matching world coordinates. Tiled and used for road pavement textures. UV coordinates will match up seamlessly with road pavement. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
+ +
Lanes marker materials: Covers individual lane sections in the intersection. Used for high-definition line marking. Each material added is rendered on top of the previous. Combine with transparent shaders which accept shadows to allow for easy marking.
+
Lane section 0: Left side of the intersection where oncoming traffic travels. Use lane texture which matches the number of lanes used on the road system, with a white left line and a yellow right line.
+
Lane section 1: Left turn lane. Use a single lane texture with a yellow left line and a white right line.
+
Lane section 2: Right outgoing traffic lane. Use lane texture which matches the number of lanes used on the road system with a white right line.
+
Lane section 3: Right turn lane. Use a single lane texture with a white right line.
+
Reset to default icon = Reset to default value.
+
Delete icon = Deletes the edge object(s).
+
+
+ +
+
VIII. Exporting a splatmap
+
+ + +
+ Splatmap UI image + +
Match resolutions: Select from a pre-populated list of resolutions. This resolution corresponds to the image size of the generated splatmap.
+
Splat image width & height: Corresponds to the image resolution of the generated splatmap.
+
Splat foreground: Changes the foreground color which represents the road(s) in the splatmap.
+
Splat background: Changes the background color which represents the non road covered areas in the splatmap.
+
Splat width: Changes the width of the road splat. Example: If you wanted a splatmap width of 60 meters surrounding the road, set the value to 60.
+
Skip bridges: Disables or enables the splat generation of bridge sections.
+
Skip tunnels: Disables or enables the splat generation of tunnel sections.
+
Splat a single road: Enables the selection of a single specific road to splat.
+
Generate splatmap: Creates the splatmap and prompts where to save the image.
+
Reset to default icon = Reset to default value.
+
+
+
+ +
+
IX. Exporting meshes
+
+ + +
+
To export any mesh, utilize the main menu toolbar at "Road Architect" -> "Export".
+
Utilizes "Exporters by Hrafnkell Freyr Hlooversson" from Unity3D wiki: http://wiki.unity3d.com/index.php?title=ObjExporter.
+
+
+
+ + +
+
X. Frequently asked questions ( FAQ / F.A.Q. )
+
+ + +
+ +
Why does the information message "Mesh has been leaked X times message" appear in the console occasionally? 02/02/2014
+
All meshes are getting properly marked for garbage collection but due to the way Unity Editor handles mesh creation and nullification, it may not happen in a predictable fashion. This message is not harmful and you can safely ignore it: The message informs of proper cleanup of a leaked mesh during editor mode and it has zero effect on gameplay modes.
+ +
Some of my roads turn too sharp or bunch up inexplicably. 02/02/2014
+
Try manipulating the "Spline Magnitude Limit" listed in the terrain options of the "Road Object".
+ +
What builds are supported? 02/02/2014
+
Windows, Web, MAC, Linux. Other builds probably work but we don't know. Email support@microgsd.com if you run into any problems.
+ +
Sometimes my 3-way intersection looks wrong, what do I do? 02/25/2014
+
Try manually updating the intersection by clicking on the "Update Intersection" button while the intersection gameobject is selected in the hierarchy. If the problem persists, please contact us at support@microgsd.com
+ +
Why did my terrain history get reset or altered? 02/25/2014
+
If the terrain history is saved on the disk, the saving scheme uses the scene name, the road name and then the road system name. Don't name your scenes the same name.
+ +
Sometimes when using the road grade enforcement the grade between nodes is higher than the limit, why? 02/25/2014
+
If you adjust the height of nodes along the spline there is a small chance that the limitation will be exceeded from the adjustment node to the next node. To avoid unintentional rolling changes to the entire road it is advised to manually examine the next node and adjust it's height next.
+ +
My intersection looks messed up, what can I do to fix it? 02/26/2014
+
Try clicking "Update intersection" in the inspector window while having the intersection selected in the hierarchy. If the problem persists, please contact us at support@microgsd.com
+
+
+
+ +
+
+
+
+
+ +
+ + diff --git a/Shaders.meta b/Shaders.meta new file mode 100644 index 00000000..82252e63 --- /dev/null +++ b/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a6054d734a7c18a4c9608df817d3251f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Spline/GSDSplineC.cs b/Spline/GSDSplineC.cs index 892e34bf..12f214d3 100755 --- a/Spline/GSDSplineC.cs +++ b/Spline/GSDSplineC.cs @@ -1,2127 +1,2412 @@ -#region "Imports" -using UnityEngine; -using System.Collections.Generic; -using GSD; -#endregion -public class GSDSplineC : MonoBehaviour -{ - //#if UNITY_EDITOR - public List mNodes = new List(); - public GameObject mSplineRoot; - public GSDRoad tRoad; - public float distance = -1f; - public Vector3[] CachedPoints; - private const float CachedPointsSeperation = 1f; - - //Editor preview splines for add and insert: - public GSDSplineF PreviewSpline; - public GSDSplineI PreviewSplineInsert; - - //Nav data - public float RoadWidth; - public int Lanes; - public List id_connected; - public int id = 0; - public string UID; //Unique ID - public List> BridgeParams; - public List> TunnelParams; - public List> HeightHistory; - public int[] RoadDefKeysArray; - public float[] RoadDefValuesArray; - public double EditorOnly_LastNode_TimeSinceStartup = -1f; - - //Vars for intersections: - const float MetersToCheck_NoTurnLane = 75f; - const float MetersToCheck_NoTurnLaneSQ = 5625f; - const float MetersToCheck_TurnLane = 125f; - const float MetersToCheck_TurnLaneSQ = 15625f; - const float MetersToCheck_BothTurnLane = 125f; - const float MetersToCheck_BothTurnLaneSQ = 15625f; - const bool bUseSQ = true; - - //Road connections and 3-way intersections: - public bool bSpecialStartControlNode = false; - public bool bSpecialEndControlNode = false; - public bool bSpecialEndNode_IsStart_Delay = false; - public bool bSpecialEndNode_IsEnd_Delay = false; - public float SpecialEndNodeDelay_Start = 10f; - public float SpecialEndNodeDelay_Start_Result = 10f; - public float SpecialEndNodeDelay_End = 10f; - public float SpecialEndNodeDelay_End_Result = 10f; - public GSDSplineC SpecialEndNode_Start_OtherSpline = null; - public GSDSplineC SpecialEndNode_End_OtherSpline = null; - - public Vector2 RoadV0 = default(Vector2); - public Vector2 RoadV1 = default(Vector2); - public Vector2 RoadV2 = default(Vector2); - public Vector2 RoadV3 = default(Vector2); -#if UNITY_EDITOR - #region "Setup" - public void Setup_Trigger() - { -#if UNITY_EDITOR - if (!tRoad) - { - if (mSplineRoot != null) - { - tRoad = mSplineRoot.transform.parent.transform.gameObject.GetComponent(); - } - } - if (tRoad) - { - tRoad.UpdateRoad(); - } -#endif - } - public void Setup() - { -#if UNITY_EDITOR - //Don't setup if playing: - // if(!Application.isEditor || (Application.isEditor && UnityEditor.EditorApplication.isPlaying)){ return; } - - //Setup unique ID: - SetupUniqueIdentifier(); - - //Set spline root: - mSplineRoot = transform.gameObject; - - //Create spline nodes: - GSDSplineN[] tNodesRaw = mSplineRoot.GetComponentsInChildren(); - List tList = new List(); - int tNodesRawLength = tNodesRaw.Length; - if (tNodesRawLength == 0) { return; } - for (int i = 0; i < tNodesRawLength; i++) - { - if (tNodesRaw[i] != null) - { - tNodesRaw[i].pos = tNodesRaw[i].transform.position; - tList.Add(tNodesRaw[i]); - } - } - tList.Sort(CompareListByName); - //tList.Sort(delegate(GSDSplin i1, Item i2) { return i1.name.CompareTo(i2.name); }); - tNodesRaw = tList.ToArray(); - tList = null; - Setup_Nodes(ref tNodesRaw); - - //Setup spline length, if more than 1 node: - if (GetNodeCount() > 1) - { - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("SplineSetupLength"); } - Setup_SplineLength(); - // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } - } - else if (GetNodeCount() == 1) - { - mNodes[0].tTime = 0f; - } - -#if UNITY_EDITOR - //Setup preview spline: - if (PreviewSpline == null) - { - PreviewSpline = mSplineRoot.AddComponent(); - PreviewSpline.GSDSpline = this; - } - //Setup preview spline for insertion mode: - if (PreviewSplineInsert == null) - { - PreviewSplineInsert = mSplineRoot.AddComponent(); - PreviewSplineInsert.GSDSpline = this; - } -#endif - - int mNodesCount = mNodes.Count; - GSDSplineN tNode = null; - Vector3[] pVects = new Vector3[mNodesCount + 1]; - for (int i = 0; i < mNodesCount; i++) - { - tNode = mNodes[i]; - tNode.idOnSpline = i; - tNode.bIsEndPoint = false; - pVects[i] = tNode.pos; - } - pVects[pVects.Length - 1] = new Vector3(0f, 0f, 0f); -#if UNITY_EDITOR - PreviewSpline.Setup(ref pVects); -#endif - - RenameNodes(); - - //Setup bridge params: - if (BridgeParams != null) - { - BridgeParams.Clear(); - } - BridgeParams = new List>(); - KeyValuePair KVP; - - //Setup tunnel params: - if (TunnelParams != null) - { - TunnelParams.Clear(); - } - TunnelParams = new List>(); - - if (mNodesCount > 1) - { - if (bSpecialStartControlNode) - { - mNodes[1].bIsEndPoint = true; - } - else - { - mNodes[0].bIsEndPoint = true; - } - if (bSpecialEndControlNode) - { - mNodes[mNodesCount - 2].bIsEndPoint = true; - } - else - { - mNodes[mNodesCount - 1].bIsEndPoint = true; - } - } - else if (mNodesCount == 1) - { - mNodes[0].bIsEndPoint = true; - distance = 1; - } - - float fStart = -1f; - float fEnd = -1f; - if (mNodesCount > 1) - { - for (int i = 0; i < mNodesCount; i++) - { - tNode = mNodes[i]; - - //Bridges: - fStart = -1f; - fEnd = -1f; - if (tNode.bIsBridgeStart && !tNode.bIsTunnelStart) - { - fStart = tNode.tTime; - for (int j = i; j < mNodesCount; j++) - { - if (mNodes[j].bIsBridgeEnd) - { - fEnd = mNodes[j].tTime; - break; - } - } - if (fEnd > 0f || GSDRootUtil.IsApproximately(fEnd, 0f, 0.0001f)) - { - KVP = new KeyValuePair(fStart, fEnd); - BridgeParams.Add(KVP); - } - } - - //Tunnels: - fStart = -1f; - fEnd = -1f; - if (!tNode.bIsBridgeStart && tNode.bIsTunnelStart) - { - fStart = tNode.tTime; - for (int j = i; j < mNodesCount; j++) - { - if (mNodes[j].bIsTunnelEnd) - { - fEnd = mNodes[j].tTime; - break; - } - } - - if (fEnd > 0f || GSDRootUtil.IsApproximately(fEnd, 0f, 0.0001f)) - { - KVP = new KeyValuePair(fStart, fEnd); - TunnelParams.Add(KVP); - } - } - - tNode.SetGradePercent(mNodesCount); - // tNode.bIsEndPoint = false; - tNode.tangent = GetSplineValue(mNodes[i].tTime, true); - if (i < (mNodesCount - 1)) - { - tNode.NextTime = mNodes[i + 1].tTime; - tNode.NextTan = mNodes[i + 1].tangent; - } - } - } - else if (mNodesCount == 1) - { - mNodes[0].tangent = default(Vector3); - } - - //Get bounds of road system: - float[] tMaxEffects = new float[3]; - tMaxEffects[0] = tRoad.opt_MatchHeightsDistance; - tMaxEffects[1] = tRoad.opt_ClearDetailsDistance; - tMaxEffects[2] = tRoad.opt_ClearTreesDistance; - float MaxEffectDistance = Mathf.Max(tMaxEffects) * 2f; //Add min/max clear diff to bound checks - int mCount1 = GetNodeCount(); - float[] tMinMaxX = new float[mCount1]; - float[] tMinMaxZ = new float[mCount1]; - // Vector3 tVect1 = default(Vector3); - for (int i = 0; i < mCount1; i++) - { - tMinMaxX[i] = mNodes[i].pos.x; - tMinMaxZ[i] = mNodes[i].pos.z; - } - float MinX = Mathf.Min(tMinMaxX) - MaxEffectDistance; - float MaxX = Mathf.Max(tMinMaxX) + MaxEffectDistance; - float MinZ = Mathf.Min(tMinMaxZ) - MaxEffectDistance; - float MaxZ = Mathf.Max(tMinMaxZ) + MaxEffectDistance; - RoadV0 = new Vector3(MinX, MinZ); - RoadV1 = new Vector3(MaxX, MinZ); - RoadV2 = new Vector3(MaxX, MaxZ); - RoadV3 = new Vector3(MinX, MaxZ); -#endif - } - - private void SetupUniqueIdentifier() - { - if (UID == null || UID.Length < 4) - { - UID = System.Guid.NewGuid().ToString(); - } - } - - private void RenameNodes() - { - int mNodesCount = mNodes.Count; - for (int i = 0; i < mNodesCount; i++) - { - GSDSplineN tNode = mNodes[i]; - tNode.name = "Node" + tNode.idOnSpline; - tNode.transform.gameObject.name = tNode.name; - tNode.EditorDisplayString = tRoad.transform.name + "-" + tNode.name; - } - } - - private int CompareListByName(GSDSplineN i1, GSDSplineN i2) - { - return i1.idOnSpline.CompareTo(i2.idOnSpline); - } - - private void Setup_Nodes(ref GSDSplineN[] tNodesRaw) - { - //Process nodes: - int i = 0; - List tNodes = new List(); - int tNodesRawLength = tNodesRaw.Length; - for (i = 0; i < tNodesRawLength; i++) - { - if (!tNodesRaw[i].bDestroyed) - { - tNodes.Add(tNodesRaw[i]); - } - } - - mNodes.Clear(); - mNodes = new List(); - GSDSplineN tNode; - float step; - Quaternion rot; - bool bClosed = false; - step = (bClosed) ? 1f / ((float)tNodes.Count) : 1f / ((float)(tNodes.Count - 1)); - int tNodesCount = tNodes.Count; - for (i = 0; i < tNodesCount; i++) - { - tNode = tNodes[i]; - - rot = Quaternion.identity; - if (i != tNodes.Count - 1) - { - if ((tNodes[i + 1].transform.position - tNode.transform.position) == Vector3.zero) - { - rot = Quaternion.identity; - } - else - { - rot = Quaternion.LookRotation(tNodes[i + 1].transform.position - tNode.transform.position, transform.up); - } - } - else if (bClosed) - { - rot = Quaternion.LookRotation(tNodes[0].transform.position - tNode.transform.position, transform.up); - } - else - { - rot = Quaternion.identity; - } - - tNode.Setup(tNode.transform.position, rot, new Vector2(0f, 1f), step * ((float)i), tNode.transform.gameObject.name); - tNode.SetupUniqueIdentifier(); - mNodes.Add(tNode); - } - - tNodes = null; - tNodesRaw = null; - } - - private void Setup_SplineLength() - { - int mNodeCount = mNodes.Count; - - //First lets get the general distance, node to node: - mNodes[0].tTime = 0f; - mNodes[mNodeCount - 1].tTime = 1f; - Vector3 tVect1 = new Vector3(0f, 0f, 0f); - Vector3 tVect2 = new Vector3(0f, 0f, 0f); - float mDistance = 0f; - float mDistance_NoMod = 0f; - for (int j = 0; j < mNodeCount; j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - mDistance += Vector3.Distance(tVect1, tVect2); - } - tVect1 = tVect2; - } - mDistance_NoMod = mDistance; - mDistance = mDistance * 1.05f; - float step = 0.5f / mDistance; - - //Get a slightly more accurate portrayal of the time: - float tTime = 0f; - for (int j = 0; j < (mNodeCount - 1); j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); - mNodes[j].tTime = tTime; - } - tVect1 = tVect2; - } - - //Using general distance and calculated step, get an accurate distance: - float tDistance = 0f; - Vector3 prevPos = mNodes[0].pos; - Vector3 cPos = new Vector3(0f, 0f, 0f); - // float hDistance = 0f; - GSDSplineN tNode; - - prevPos = GetSplineValue(0f); - for (float i = 0f; i < 1f; i += step) - { - cPos = GetSplineValue(i); - // if(float.IsNaN(cPos.x)){ - // int xsagfdsdgsd = 0; - // } - tDistance += Vector3.Distance(cPos, prevPos); - prevPos = cPos; - } - - distance = tDistance; - - //Now get fine distance between nodes: - - // float tNanCheck = 0f; - float newTotalDistance = 0f; - step = 0.5f / distance; - GSDSplineN PrevNode = null; - GSDSplineN ThisNode = null; - prevPos = GetSplineValue(0f, false); - for (int j = 1; j < (mNodeCount - 1); j++) - { - PrevNode = mNodes[j - 1]; - ThisNode = mNodes[j]; - - if (j == 1) - { - prevPos = GetSplineValue(PrevNode.tTime); - } - tDistance = 0.00001f; - for (float i = PrevNode.tTime; i < ThisNode.tTime; i += step) - { - cPos = GetSplineValue(i); - if (!float.IsNaN(cPos.x)) - { - if (float.IsNaN(prevPos.x)) - { - prevPos = cPos; - } - tDistance += Vector3.Distance(cPos, prevPos); - prevPos = cPos; - } - } - ThisNode.tempSegmentTime = (tDistance / distance); - newTotalDistance += tDistance; - ThisNode.tDist = newTotalDistance; - } - - - mNodes[0].tDist = 0f; - PrevNode = mNodes[mNodeCount - 2]; - ThisNode = mNodes[mNodeCount - 1]; - tDistance = 0.00001f; - for (float i = PrevNode.tTime; i < ThisNode.tTime; i += step) - { - cPos = GetSplineValue(i, false); - if (!float.IsNaN(cPos.x)) - { - if (float.IsNaN(prevPos.x)) - { - prevPos = cPos; - } - tDistance += Vector3.Distance(cPos, prevPos); - prevPos = cPos; - } - } - ThisNode.tempSegmentTime = (tDistance / distance); - newTotalDistance += tDistance; - ThisNode.tDist = newTotalDistance; - distance = newTotalDistance; - - - tTime = 0f; - for (int j = 1; j < (mNodeCount - 1); j++) - { - tNode = mNodes[j]; - tTime += tNode.tempSegmentTime; - tNode.OldTime = tNode.tTime; - tNode.tTime = tTime; - tNode.tangent = GetSplineValue_SkipOpt(tNode.tTime, true); - tNode.transform.rotation = Quaternion.LookRotation(tNode.tangent); - } - mNodes[0].tangent = GetSplineValue_SkipOpt(0f, true); - mNodes[mNodeCount - 1].tangent = GetSplineValue_SkipOpt(1f, true); - - - mNodes[0].tDist = 0f; - - step = distance / CachedPointsSeperation; - int ArrayCount = (int)Mathf.Floor(step) + 2; - CachedPoints = null; - CachedPoints = new Vector3[ArrayCount]; - step = CachedPointsSeperation / distance; - for (int j = 1; j < (ArrayCount - 1); j++) - { - CachedPoints[j] = GetSplineValue(step * j); - } - CachedPoints[0] = mNodes[0].pos; - CachedPoints[ArrayCount - 1] = mNodes[mNodeCount - 1].pos; - - RoadDefCalcs(); - } - #endregion -#endif - #region "Road definition cache and translation" - private void RoadDefCalcs() - { - // float tNanCheck = 0f; - float tMod = Mathf.Lerp(0.05f, 0.2f, distance / 9000f); - float step = tMod / distance; - Vector3 cPos = GetSplineValue(0f); - Vector3 prevPos = cPos; - float tempDistanceModMax = tRoad.opt_RoadDefinition - step; - float tempDistanceMod = 0f; - float tempTotalDistance = 0f; - float tempDistanceHolder = 0f; - if (RoadDefKeysArray != null) { RoadDefKeysArray = null; } - if (RoadDefValuesArray != null) { RoadDefValuesArray = null; } - - List RoadDefKeys = new List(); - List RoadDefValues = new List(); - - RoadDefKeys.Add(0); - RoadDefValues.Add(0f); - - for (float i = 0f; i < 1f; i += step) - { - cPos = GetSplineValue(i); - tempDistanceHolder = Vector3.Distance(cPos, prevPos); - tempTotalDistance += tempDistanceHolder; - tempDistanceMod += tempDistanceHolder; - if (tempDistanceMod > tempDistanceModMax) - { - tempDistanceMod = 0f; - RoadDefKeys.Add(TranslateParamToInt(i)); - RoadDefValues.Add(tempTotalDistance); - } - prevPos = cPos; - } - - RoadDefKeysArray = RoadDefKeys.ToArray(); - RoadDefValuesArray = RoadDefValues.ToArray(); - } - - public int TranslateParamToInt(float f) - { - return Mathf.Clamp((int)(f * 10000000f), 0, 10000000); - } - public float TranslateInverseParamToFloat(int f) - { - return Mathf.Clamp(((float)(float)f / 10000000f), 0f, 1f); - } - - private void GetClosestRoadDefKeys(float tX, out int lo, out int hi, out int loIndex, out int hiIndex) - { - int x = TranslateParamToInt(tX); - lo = -1; - hi = RoadDefKeysArray.Length - 1; - - int mid = -1; - - while ((hi - lo) > 1) - { - mid = Mathf.RoundToInt((lo + hi) / 2); - if (RoadDefKeysArray[mid] <= x) - { - lo = mid; - } - else - { - hi = mid; - } - } - - if (RoadDefKeysArray[lo] == x) - { - hi = lo; - } - // if(hi > RoadDefKeysArray.Length-1){ hi = RoadDefKeysArray.Length-1; } - - loIndex = lo; - hiIndex = hi; - lo = RoadDefKeysArray[lo]; - hi = RoadDefKeysArray[hi]; - } - - public int GetClosestRoadDefIndex(float tX, bool bRoundUp = false, bool bRoundDown = false) - { - int lo, hi, loIndex, hiIndex; - - GetClosestRoadDefKeys(tX, out lo, out hi, out loIndex, out hiIndex); - - int x = TranslateParamToInt(tX); - - if (bRoundUp) { return hiIndex; } - if (bRoundDown) { return loIndex; } - - if ((x - lo) > (hi - x)) - { - return hiIndex; - } - else - { - return loIndex; - } - } - - private void GetClosestRoadDefValues(float tX, out float loF, out float hiF, out int loIndex, out int hiIndex) - { - int lo = -1; - int hi = RoadDefValuesArray.Length - 1; - int mid = -1; - - while ((hi - lo) > 1) - { - mid = Mathf.RoundToInt((lo + hi) / 2); - if (RoadDefValuesArray[mid] < tX || GSDRootUtil.IsApproximately(RoadDefValuesArray[mid], tX, 0.02f)) - { - lo = mid; - } - else - { - hi = mid; - } - } - - if (GSDRootUtil.IsApproximately(RoadDefValuesArray[lo], tX, 0.02f)) - { - hi = lo; - } - - loIndex = lo; - hiIndex = hi; - loF = RoadDefValuesArray[lo]; - hiF = RoadDefValuesArray[hi]; - } - - public int GetClosestRoadDefValuesIndex(float tX, bool bRoundUp = false, bool bRoundDown = false) - { - float lo, hi; - int loIndex, hiIndex; - - GetClosestRoadDefValues(tX, out lo, out hi, out loIndex, out hiIndex); - - if (bRoundUp) { return hiIndex; } - if (bRoundDown) { return loIndex; } - - if ((tX - lo) > (hi - tX)) - { - return hiIndex; - } - else - { - return loIndex; - } - } - - public float TranslateDistBasedToParam(float mDist) - { - int tIndex = GetClosestRoadDefValuesIndex(mDist, false, false); - float tKey = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex]); - int tCount = RoadDefKeysArray.Length; - float kDist = RoadDefValuesArray[tIndex]; - - if (tIndex < (tCount - 1)) - { - if (mDist > kDist) - { - float NextValue = RoadDefValuesArray[tIndex + 1]; - float tDiff1 = (mDist - kDist) / (NextValue - kDist); - tKey += (tDiff1 * (TranslateInverseParamToFloat(RoadDefKeysArray[tIndex + 1]) - tKey)); - } - } - if (tIndex > 0) - { - if (mDist < kDist) - { - float PrevValue = RoadDefValuesArray[tIndex - 1]; - float tDiff1 = (mDist - PrevValue) / (kDist - PrevValue); - tKey -= (tDiff1 * (tKey - TranslateInverseParamToFloat(RoadDefKeysArray[tIndex - 1]))); - } - } - - return tKey; - } - - public float TranslateParamToDist(float param) - { - int tIndex = GetClosestRoadDefIndex(param, false, false); - float tKey = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex]); - int tCount = RoadDefKeysArray.Length; - float kDist = RoadDefValuesArray[tIndex]; - float xDiff = kDist; - - if (tIndex < (tCount - 1)) - { - if (param > tKey) - { - float NextValue = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex + 1]); - float tDiff1 = (param - tKey) / (NextValue - tKey); - xDiff += (tDiff1 * (RoadDefValuesArray[tIndex + 1] - kDist)); - } - } - if (tIndex > 0) - { - if (param < tKey) - { - float PrevValue = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex - 1]); - float tDiff1 = 1f - ((param - PrevValue) / (tKey - PrevValue)); - xDiff -= (tDiff1 * (kDist - RoadDefValuesArray[tIndex - 1])); - } - } - - return xDiff; - } - #endregion - - #region "Hermite math" - /// - /// Gets the spline value. - /// - /// - /// The relevant param (0-1) of the spline. - /// - /// - /// True for is tangent, false (default) for vector3 position. - /// - public Vector3 GetSplineValue(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - //GSDRootUtil.IsApproximately(f,1f,0.00001f) - for (i = 0; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime > f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - public void GetSplineValue_Both(float f, out Vector3 tVect1, out Vector3 tVect2) - { - int i; - int idx = -1; - int mCount = GetNodeCount(); - - if (f < 0f) { f = 0f; } - if (f > 1f) { f = 1f; } - - if (mCount == 0) - { - tVect1 = default(Vector3); - tVect2 = default(Vector3); - return; - } - if (mCount == 1) - { - if (mNodes[0]) - { - tVect1 = mNodes[0].pos; - tVect2 = default(Vector3); - } - else - { - tVect1 = default(Vector3); - tVect2 = default(Vector3); - } - return; - } - - // if(GSDRootUtil.IsApproximately(f,1f,0.0001f)){ - // tVect1 = mNodes[mNodes.Count-1].pos; - // tVect2 = mNodes[mNodes.Count-1].tangent; - // return; - // } - // else if(GSDRootUtil.IsApproximately(f,0f,0.0001f)){ - // tVect1 = mNodes[0].pos; - // tVect2 = mNodes[0].tangent; - // return; - // } - - for (i = 1; i < mCount; i++) - { - if (i == mCount - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime > f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - - tVect1 = GetHermiteInternal(idx, param, false); - tVect2 = GetHermiteInternal(idx, param, true); - } - - public Vector3 GetSplineValue_SkipOpt(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - for (i = 1; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime > f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // if(b && GSDRootUtil.IsApproximately(f,1f,0.00001f)){ - // idx = mNodes.Count-2; - // } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - public float GetClosestParam(Vector3 tVect, bool b20cmPrecision = false, bool b1MeterPrecision = false) - { - return GetClosestParam_Do(ref tVect, b20cmPrecision, b1MeterPrecision); - } - private float GetClosestParam_Do(ref Vector3 tVect, bool b20cmPrecision, bool b1MeterPrecision) - { - float Step1 = CachedPointsSeperation / distance; //5m to 1m - float Step2 = Step1 * 0.2f; //20 cm - float Step3 = Step2 * 0.4f; //8 cm - float Step4 = Step3 * 0.25f; //2 cm - float tMin = 0f; - float tMax = 1f; - float BestValue = -1f; - float MaxStretch = 0.9f; - Vector3 BestVect_p = new Vector3(0f, 0f, 0f); - Vector3 BestVect_n = new Vector3(0f, 0f, 0f); - - if (mNodes.Count == 0) { return 0f; } - if (mNodes.Count == 1) { return 1f; } - - //Step 1: 1m - BestValue = GetClosestPoint_Helper(ref tVect, Step1, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n, true); - if (b1MeterPrecision) { return BestValue; } - //Step 2: 20cm - tMin = BestValue - (Step1 * MaxStretch); - tMax = BestValue + (Step1 * MaxStretch); - BestValue = GetClosestPoint_Helper(ref tVect, Step2, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); - if (b20cmPrecision) { return BestValue; } - //Step 3: 8cm - tMin = BestValue - (Step2 * MaxStretch); - tMax = BestValue + (Step2 * MaxStretch); - BestValue = GetClosestPoint_Helper(ref tVect, Step3, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); - - //Step 4: 2cm - tMin = BestValue - (Step3 * MaxStretch); - tMax = BestValue + (Step3 * MaxStretch); - BestValue = GetClosestPoint_Helper(ref tVect, Step4, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); - - return BestValue; - } - - private float GetClosestPoint_Helper(ref Vector3 tVect, float tStep, float BestValue, float tMin, float tMax, ref Vector3 BestVect_p, ref Vector3 BestVect_n, bool bMeterCache = false) - { - float mDistance = 5000f; - float tDistance = 0f; - Vector3 cVect = new Vector3(0f, 0f, 0f); - Vector3 pVect = new Vector3(0f, 0f, 0f); - bool bFirstLoopHappened = false; - bool bSetBestValue = false; - - //Get lean for tmin/tmax: - if (GetClosetPoint_MinMaxDirection(ref tVect, ref BestVect_p, ref BestVect_n)) - { - tMax = BestValue; - } - else - { - tMin = BestValue; - } - - tMin = Mathf.Clamp(tMin, 0f, 1f); - tMax = Mathf.Clamp(tMax, 0f, 1f); - - if (bMeterCache) - { - int CachedIndex = -1; - int Step1 = 10; - - int CachedPointsLength = CachedPoints.Length; - for (int j = 0; j < CachedPointsLength; j += Step1) - { - cVect = CachedPoints[j]; - tDistance = Vector3.Distance(tVect, cVect); - if (tDistance < mDistance) - { - mDistance = tDistance; - CachedIndex = j; - } - } - - int jStart = (CachedIndex - Step1); - if (jStart < 50) { jStart = 0; } - int jEnd = (CachedIndex + Step1); - if (jEnd > (CachedPointsLength)) { jEnd = CachedPointsLength; } - for (int j = jStart; j < jEnd; j++) - { - cVect = CachedPoints[j]; - if (bSetBestValue) { BestVect_n = cVect; bSetBestValue = false; } - tDistance = Vector3.Distance(tVect, cVect); - if (tDistance < mDistance) - { - mDistance = tDistance; - if (!bFirstLoopHappened) - { - BestVect_p = cVect; - } - else - { - BestVect_p = pVect; - } - CachedIndex = j; - bSetBestValue = true; - bFirstLoopHappened = true; - } - pVect = cVect; - } - - BestValue = (CachedIndex / distance); - - } - else - { - for (float i = tMin; i <= tMax; i += tStep) - { - cVect = GetSplineValue(i); - if (bSetBestValue) { BestVect_n = cVect; bSetBestValue = false; } - tDistance = Vector3.Distance(tVect, cVect); - if (tDistance < mDistance) - { - mDistance = tDistance; - BestValue = i; - if (!bFirstLoopHappened) - { - BestVect_p = cVect; - } - else - { - BestVect_p = pVect; - } - - bSetBestValue = true; - bFirstLoopHappened = true; - } - pVect = cVect; - } - } - - if (bSetBestValue) - { - BestVect_n = cVect; - } - - //Debug.Log ("returning: " + BestValue + " tmin:" + tMin + " tmax:" + tMax); - return BestValue; - } - - //Returns true for tmin lean: - private bool GetClosetPoint_MinMaxDirection(ref Vector3 tVect, ref Vector3 BestVect_p, ref Vector3 BestVect_n) - { - float Distance1 = Vector3.Distance(tVect, BestVect_p); - float Distance2 = Vector3.Distance(tVect, BestVect_n); - - if (Distance1 < Distance2) - { - //tMin lean - return true; - } - else - { - //tMax lean - return false; - } - } - - private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) - { - double t2, t3; - float BL0, BL1, BL2, BL3, tension; - - if (!bTangent) - { - t2 = t * t; - t3 = t2 * t; - } - else - { - t2 = t * t; - t = t * 2.0; - t2 = t2 * 3.0; - t3 = 0; //Necessary for compiler error. - } - - //Vectors: - Vector3 P0 = mNodes[NGI(i, NI[0])].pos; - Vector3 P1 = mNodes[NGI(i, NI[1])].pos; - Vector3 P2 = mNodes[NGI(i, NI[2])].pos; - Vector3 P3 = mNodes[NGI(i, NI[3])].pos; - - //Tension: - tension = 0.5f; - - - - //Tangents: - Vector3 xVect1 = (P1 - P2) * tension; - Vector3 xVect2 = (P3 - P0) * tension; - float tMaxMag = tRoad.opt_MagnitudeThreshold; - - if (Vector3.Distance(P1, P3) > tMaxMag) - { - if (xVect1.magnitude > tMaxMag) { xVect1 = Vector3.ClampMagnitude(xVect1, tMaxMag); } - if (xVect2.magnitude > tMaxMag) { xVect2 = Vector3.ClampMagnitude(xVect2, tMaxMag); } - } - else if (Vector3.Distance(P0, P2) > tMaxMag) - { - if (xVect1.magnitude > tMaxMag) { xVect1 = Vector3.ClampMagnitude(xVect1, tMaxMag); } - if (xVect2.magnitude > tMaxMag) { xVect2 = Vector3.ClampMagnitude(xVect2, tMaxMag); } - } - - - if (!bTangent) - { - BL0 = (float)(CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); - BL1 = (float)(CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); - BL2 = (float)(CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); - BL3 = (float)(CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); - } - else - { - BL0 = (float)(CM[0] * t2 + CM[1] * t + CM[2]); - BL1 = (float)(CM[4] * t2 + CM[5] * t + CM[6]); - BL2 = (float)(CM[8] * t2 + CM[9] * t + CM[10]); - BL3 = (float)(CM[12] * t2 + CM[13] * t + CM[14]); - } - - Vector3 tVect = BL0 * P0 + BL1 * P1 + BL2 * xVect1 + BL3 * xVect2; - - if (!bTangent) { if (tVect.y < 0f) { tVect.y = 0f; } } - - return tVect; - } - - private static readonly double[] CM = new double[] { - 2.0, -3.0, 0.0, 1.0, - -2.0, 3.0, 0.0, 0.0, - 1.0, -2.0, 1.0, 0.0, - 1.0, -1.0, 0.0, 0.0 - }; - private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; - - private int NGI(int i, int o) - { - int NGITI = i + o; - // if(bClosed){ - // return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; - // }else{ - return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); - // } - } - #endregion - - #region "Gizmos" - // private const bool bGizmoDraw = true; - private float GizmoDrawMeters = 1f; - void OnDrawGizmosSelected() - { - // if(!bGizmoDraw){ return; } - if (mNodes == null || mNodes.Count < 2) { return; } - if (transform == null) { return; } - float DistanceFromCam = Vector3.SqrMagnitude(Camera.current.transform.position - mNodes[0].transform.position); - - if (DistanceFromCam > 16777216f) - { - return; - } - else if (DistanceFromCam > 4194304f) - { - GizmoDrawMeters = 16f; - } - else if (DistanceFromCam > 1048576f) - { - GizmoDrawMeters = 8f; - } - else if (DistanceFromCam > 262144f) - { - GizmoDrawMeters = 4f; - } - else if (DistanceFromCam > 65536) - { - GizmoDrawMeters = 1f; - } - else if (DistanceFromCam > 16384f) - { - GizmoDrawMeters = 0.5f; - } - else - { - GizmoDrawMeters = 0.1f; - } - - Vector3 prevPos = mNodes[0].pos; - Vector3 tempVect = new Vector3(0f, 0f, 0f); - float step = GizmoDrawMeters / distance; - step = Mathf.Clamp(step, 0f, 1f); - Gizmos.color = new Color(1f, 0f, 0f, 1f); - float i = 0f; - Vector3 cPos; - float tCheck = 0f; - Vector3 camPos = Camera.current.transform.position; - for (i = 0f; i <= 1f; i += step) - { - tCheck += step; - cPos = GetSplineValue(i); - - if (tCheck > 0.1f) - { - DistanceFromCam = Vector3.SqrMagnitude(camPos - cPos); - if (DistanceFromCam > 16777216f) - { - return; - } - else if (DistanceFromCam > 4194304f) - { - GizmoDrawMeters = 16f; - } - else if (DistanceFromCam > 1048576f) - { - GizmoDrawMeters = 10f; - } - else if (DistanceFromCam > 262144f) - { - GizmoDrawMeters = 4f; - } - else if (DistanceFromCam > 65536) - { - GizmoDrawMeters = 1f; - } - else if (DistanceFromCam > 16384f) - { - GizmoDrawMeters = 0.5f; - } - else - { - GizmoDrawMeters = 0.1f; - } - step = GizmoDrawMeters / distance; - step = Mathf.Clamp(step, 0f, 1f); - tCheck = 0f; - } - - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - prevPos = cPos; - if ((i + step) > 1f) - { - cPos = GetSplineValue(1f); - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - } - - } - } - #endregion - - #region "Intersections" - public bool IsNearIntersection(ref Vector3 tPos, ref float nResult) - { - int mCount = GetNodeCount(); - GSDSplineN tNode; - float MetersToCheck = 75f * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); - float tDist; - for (int i = 0; i < mCount; i++) - { - tNode = mNodes[i]; - if (tNode.bIsIntersection) - { - tNode.GSDRI.Height = tNode.pos.y; - - if (bUseSQ) - { - tDist = Vector3.SqrMagnitude(tPos - tNode.pos); - } - // else{ - // tDist = Vector3.Distance(tPos,tNode.pos); - // } - - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_NoTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_NoTurnLane; - // } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_TurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_TurnLane; - // } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_BothTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_BothTurnLane; - // } - } - - MetersToCheck *= 0.8f; - if (tRoad.opt_Lanes == 4) - { - MetersToCheck *= 1.25f; - } - else if (tRoad.opt_Lanes == 6) - { - MetersToCheck *= 1.35f; - } - - if (tDist <= MetersToCheck) - { - nResult = tNode.pos.y; - return true; - } - } - } - nResult = tPos.y; - return false; - } - - public float IntersectionStrength(ref Vector3 tPos, ref float nResult, ref GSDRoadIntersection tInter, ref bool bIsPast, ref float p, ref GSDSplineN fNode) - { - int mCount = GetNodeCount(); - float tDist; - GSDSplineN tNode; - - float MetersToCheck = 75f * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); - - for (int i = 0; i < mCount; i++) - { - tNode = mNodes[i]; - if (tNode.bIsIntersection) - { - tNode.GSDRI.Height = tNode.pos.y; - GSDSplineN xNode; - if (bUseSQ) - { - tDist = Vector3.SqrMagnitude(tPos - tNode.pos); - } - // else{ - // tDist = Vector3.Distance(tPos,tNode.pos); - // } - - if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_NoTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_NoTurnLane; - // } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_TurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_TurnLane; - // } - } - else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) - { - if (bUseSQ) - { - MetersToCheck = MetersToCheck_BothTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); ; - } - // else{ - // MetersToCheck = MetersToCheck_BothTurnLane; - // } - } - if (tRoad.opt_Lanes == 4) - { - MetersToCheck *= 1.25f; - } - else if (tRoad.opt_Lanes == 6) - { - MetersToCheck *= 1.35f; - } - - if (tDist <= MetersToCheck) - { - if (tNode.GSDRI.bSameSpline) - { - if (tNode.GSDRI.Node1.UID != tNode.UID) - { - xNode = tNode.GSDRI.Node1; - } - else - { - xNode = tNode.GSDRI.Node2; - } - - float P1 = tNode.tTime - p; if (P1 < 0f) { P1 *= -1f; } - float P2 = xNode.tTime - p; if (P2 < 0f) { P2 *= -1f; } - - if (P1 > P2) - { - if (p > xNode.tTime) - { - bIsPast = true; - } - else - { - bIsPast = false; - } - fNode = xNode; - } - else - { - if (p > tNode.tTime) - { - bIsPast = true; - } - else - { - bIsPast = false; - } - fNode = tNode; - } - } - else - { - if (p > tNode.tTime) - { - bIsPast = true; - } - else - { - bIsPast = false; - } - fNode = tNode; - } - - - if (bUseSQ) - { - tDist = Mathf.Sqrt(tDist); - MetersToCheck = Mathf.Sqrt(MetersToCheck); - } - - tInter = tNode.GSDRI; - nResult = tNode.pos.y + 0.1f; - tDist = 1f - (tDist / MetersToCheck); - tDist = Mathf.Pow(tDist, 3f) * 5f; - if (tDist > 1f) tDist = 1f; - if (tDist < 0f) tDist = 0f; - return tDist; - } - } - } - nResult = tPos.y; - return 0f; - } - - public float IntersectionStrength_Next(Vector3 tPos) - { - float nResult = 0f; - GSDRoadIntersection tInter = null; - bool bIsPast = false; - float p = 0f; - GSDSplineN fNode = null; - return IntersectionStrength(ref tPos, ref nResult, ref tInter, ref bIsPast, ref p, ref fNode); - } - - public bool IntersectionIsPast(ref float p, ref GSDSplineN oNode) - { - // int mCount = GetNodeCount(); - // bool bIsPast; - // GSDSplineN tNode = null; - // for(int i=0;i P2){ - // if(p > tNode.GSDRI.Node2.tTime){ - // bIsPast = true; - // }else{ - // bIsPast = false; - // } - // }else{ - // if(p > tNode.GSDRI.Node1.tTime){ - // bIsPast = true; - // }else{ - // bIsPast = false; - // } - // } - // return bIsPast; - // } - // } - // return false; - - - if (p < oNode.tTime) - { - return false; - } - else - { - return true; - } - } - - void DestroyIntersection(GSDSplineN tNode) - { - if (tNode != null) - { - if (tNode.bIsEndPoint) - { - if (tNode.idOnSpline == 1 && tNode.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) - { - Object.DestroyImmediate(tNode.GSDSpline.mNodes[0].transform.gameObject); - tNode.GSDSpline.bSpecialStartControlNode = false; - } - else if (tNode.idOnSpline == tNode.GSDSpline.GetNodeCount() - 2 && tNode.GSDSpline.mNodes[tNode.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) - { - Object.DestroyImmediate(tNode.GSDSpline.mNodes[tNode.GSDSpline.GetNodeCount() - 1].transform.gameObject); - tNode.GSDSpline.bSpecialEndControlNode = false; - } - - } - tNode.bIsIntersection = false; - tNode.bSpecialIntersection = false; - } - if (tNode.Intersection_OtherNode != null) - { - if (tNode.Intersection_OtherNode.bIsEndPoint) - { - if (tNode.Intersection_OtherNode.idOnSpline == 1 && tNode.Intersection_OtherNode.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) - { - Object.DestroyImmediate(tNode.Intersection_OtherNode.GSDSpline.mNodes[0].transform.gameObject); - tNode.Intersection_OtherNode.GSDSpline.bSpecialStartControlNode = false; - } - else if (tNode.Intersection_OtherNode.idOnSpline == tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 2 && tNode.Intersection_OtherNode.GSDSpline.mNodes[tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) - { - Object.DestroyImmediate(tNode.Intersection_OtherNode.GSDSpline.mNodes[tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 1].transform.gameObject); - tNode.Intersection_OtherNode.GSDSpline.bSpecialEndControlNode = false; - } - } - tNode.Intersection_OtherNode.bIsIntersection = false; - tNode.Intersection_OtherNode.bSpecialIntersection = false; - } - - if (tNode != null && tNode.Intersection_OtherNode != null) - { - if (tNode.GSDSpline != tNode.Intersection_OtherNode.GSDSpline) - { - if (tNode != null) { tNode.GSDSpline.tRoad.bUpdateSpline = true; } - if (tNode.Intersection_OtherNode != null) { tNode.Intersection_OtherNode.GSDSpline.tRoad.bUpdateSpline = true; } - } - else - { - tNode.GSDSpline.tRoad.bUpdateSpline = true; - } - } - else if (tNode != null) - { - tNode.GSDSpline.tRoad.bUpdateSpline = true; - } - } - #endregion - - #region "Bridges" - public bool IsInBridge(float p) - { - KeyValuePair KVP; - if (BridgeParams == null) { return false; } - int cCount = BridgeParams.Count; - if (cCount < 1) { return false; } - for (int i = 0; i < cCount; i++) - { - KVP = BridgeParams[i]; - if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) - { - return true; - } - if (p > KVP.Key && p < KVP.Value) - { - return true; - } - } - return false; - } - - public float BridgeUpComing(float p) - { - float tDist = 20f / distance; - float OrigP = p; - p += tDist; - KeyValuePair KVP; - if (BridgeParams == null) { return 1f; } - int cCount = BridgeParams.Count; - if (cCount < 1) { return 1f; } - for (int i = 0; i < cCount; i++) - { - KVP = BridgeParams[i]; - - if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) - { - return ((KVP.Key - OrigP) / tDist); - } - if (p > KVP.Key && p < KVP.Value) - { - return ((KVP.Key - OrigP) / tDist); - } - } - return 1f; - } - - public bool IsInBridgeTerrain(float p) - { - KeyValuePair KVP; - if (BridgeParams == null) { return false; } - int cCount = BridgeParams.Count; - if (cCount < 1) { return false; } - for (int i = 0; i < cCount; i++) - { - KVP = BridgeParams[i]; - if (GSDRootUtil.IsApproximately(KVP.Key + (10f / distance), p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value - (10f / distance), p, 0.0001f)) - { - return true; - } - if (p > (KVP.Key + (10f / distance)) && p < (KVP.Value - (10f / distance))) - { - return true; - } - } - return false; - } - - public float GetBridgeEnd(float p) - { - KeyValuePair KVP; - if (BridgeParams == null) { return -1f; } - int cCount = BridgeParams.Count; - if (cCount < 1) { return -1f; } - for (int i = 0; i < cCount; i++) - { - KVP = BridgeParams[i]; - if (p >= KVP.Key && p <= KVP.Value) - { - return KVP.Value; - } - } - return -1f; - } - #endregion - - #region "Tunnels" - public bool IsInTunnel(float p) - { - KeyValuePair KVP; - if (TunnelParams == null) { return false; } - int cCount = TunnelParams.Count; - if (cCount < 1) { return false; } - for (int i = 0; i < cCount; i++) - { - KVP = TunnelParams[i]; - if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) - { - return true; - } - if (p > KVP.Key && p < KVP.Value) - { - return true; - } - } - return false; - } - - public float TunnelUpComing(float p) - { - float tDist = 20f / distance; - float OrigP = p; - p += tDist; - KeyValuePair KVP; - if (TunnelParams == null) { return 1f; } - int cCount = TunnelParams.Count; - if (cCount < 1) { return 1f; } - for (int i = 0; i < cCount; i++) - { - KVP = TunnelParams[i]; - - if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) - { - return ((KVP.Key - OrigP) / tDist); - } - if (p > KVP.Key && p < KVP.Value) - { - return ((KVP.Key - OrigP) / tDist); - } - } - return 1f; - } - - public bool IsInTunnelTerrain(float p) - { - KeyValuePair KVP; - if (TunnelParams == null) { return false; } - int cCount = TunnelParams.Count; - if (cCount < 1) { return false; } - for (int i = 0; i < cCount; i++) - { - KVP = TunnelParams[i]; - if (GSDRootUtil.IsApproximately(KVP.Key + (10f / distance), p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value - (10f / distance), p, 0.0001f)) - { - return true; - } - if (p > (KVP.Key + (10f / distance)) && p < (KVP.Value - (10f / distance))) - { - return true; - } - } - return false; - } - - public float GetTunnelEnd(float p) - { - KeyValuePair KVP; - if (TunnelParams == null) { return -1f; } - int cCount = TunnelParams.Count; - if (cCount < 1) { return -1f; } - for (int i = 0; i < cCount; i++) - { - KVP = TunnelParams[i]; - if (p >= KVP.Key && p <= KVP.Value) - { - return KVP.Value; - } - } - return -1f; - } - #endregion -#if UNITY_EDITOR - #region "Road connections" - public void ActivateEndNodeConnection(GSDSplineN tNode1, GSDSplineN tNode2) - { - ActivateEndNodeConnection_Do(tNode1, tNode2); - } - private void ActivateEndNodeConnection_Do(GSDSplineN tNode1, GSDSplineN tNode2) - { - GSDSplineC xSpline = tNode2.GSDSpline; - int xCount = xSpline.GetNodeCount(); - int mCount = GetNodeCount(); - //Don't allow connection with less than 3 nodes: - if (mCount < 3 || xCount < 3) - { -#if UNITY_EDITOR - UnityEditor.EditorUtility.DisplayDialog("Cannot connect roads", "Roads must have at least 3 nodes to be connected.", "ok"); -#endif - return; - } - - Vector3 tNode1_ExtraPos = default(Vector3); - Vector3 tNode2_ExtraPos = default(Vector3); - - bool bFirstNode_Start = false; - // bool bFirstNode_End = false; - if (tNode1.idOnSpline == 0) - { - bFirstNode_Start = true; - tNode2_ExtraPos = mNodes[1].transform.position; - } - else - { - // bFirstNode_End = true; - tNode2_ExtraPos = mNodes[mCount - 2].transform.position; - } - - bool bSecondNode_Start = false; - // bool bSecondNode_End = false; - if (tNode2.idOnSpline == 0) - { - bSecondNode_Start = true; - tNode1_ExtraPos = xSpline.mNodes[1].transform.position; - } - else - { - // bSecondNode_End = true; - tNode1_ExtraPos = xSpline.mNodes[xCount - 2].transform.position; - } - - GSDSplineN NodeCreated1 = null; - GSDSplineN NodeCreated2 = null; - - if (bFirstNode_Start) - { - bSpecialStartControlNode = true; - if (mNodes[0].bSpecialEndNode) - { - mNodes[0].transform.position = tNode1_ExtraPos; - mNodes[0].pos = tNode1_ExtraPos; - NodeCreated1 = mNodes[0]; - } - else - { - NodeCreated1 = GSD.Roads.GSDConstruction.InsertNode(tRoad, true, tNode1_ExtraPos, false, 0, true); - } - } - else - { - bSpecialEndControlNode = true; - GSDSplineN zNode1 = xSpline.GetLastNode_All(); - if (zNode1 != null && zNode1.bSpecialEndNode) - { - zNode1.transform.position = tNode1_ExtraPos; - zNode1.pos = tNode1_ExtraPos; - NodeCreated1 = GetLastNode_All(); - } - else - { - NodeCreated1 = GSD.Roads.GSDConstruction.CreateNode(tRoad, true, tNode1_ExtraPos); - } - - } - - if (bSecondNode_Start) - { - xSpline.bSpecialStartControlNode = true; - if (xSpline.mNodes[0].bSpecialEndNode) - { - xSpline.mNodes[0].transform.position = tNode2_ExtraPos; - xSpline.mNodes[0].pos = tNode2_ExtraPos; - NodeCreated2 = xSpline.mNodes[0]; - } - else - { - NodeCreated2 = GSD.Roads.GSDConstruction.InsertNode(xSpline.tRoad, true, tNode2_ExtraPos, false, 0, true); - } - - } - else - { - xSpline.bSpecialEndControlNode = true; - GSDSplineN zNode2 = xSpline.GetLastNode_All(); - if (zNode2 != null && zNode2.bSpecialEndNode) - { - zNode2.transform.position = tNode2_ExtraPos; - zNode2.pos = tNode2_ExtraPos; - NodeCreated2 = xSpline.GetLastNode_All(); - } - else - { - NodeCreated2 = GSD.Roads.GSDConstruction.CreateNode(xSpline.tRoad, true, tNode2_ExtraPos); - } - - } - - NodeCreated1.bSpecialEndNode_IsStart = bFirstNode_Start; - NodeCreated2.bSpecialEndNode_IsStart = bSecondNode_Start; - NodeCreated1.bSpecialEndNode_IsEnd = !bFirstNode_Start; - NodeCreated2.bSpecialEndNode_IsEnd = !bSecondNode_Start; - NodeCreated1.SpecialNodeCounterpart = NodeCreated2; - NodeCreated2.SpecialNodeCounterpart = NodeCreated1; - - float lWidth1 = tNode1.GSDSpline.tRoad.opt_LaneWidth; - float lWidth2 = tNode2.GSDSpline.tRoad.opt_LaneWidth; - float xWidth = Mathf.Max(lWidth1, lWidth2); - - float tDelay = 0f; - if (tNode1.GSDSpline.tRoad.opt_Lanes > tNode2.GSDSpline.tRoad.opt_Lanes) - { - tNode2.bSpecialRoadConnPrimary = true; - NodeCreated2.bSpecialRoadConnPrimary = true; - if (tNode2.GSDSpline.tRoad.opt_Lanes == 4) { xWidth *= 2f; } - tDelay = (tNode1.GSDSpline.tRoad.opt_Lanes - tNode2.GSDSpline.tRoad.opt_Lanes) * xWidth; - if (tDelay < 10f) { tDelay = 10f; } - if (bSecondNode_Start) - { - tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = true; - tNode2.GSDSpline.SpecialEndNodeDelay_Start = tDelay; - tNode2.GSDSpline.SpecialEndNodeDelay_Start_Result = tNode1.GSDSpline.tRoad.RoadWidth(); - tNode2.GSDSpline.SpecialEndNode_Start_OtherSpline = tNode1.GSDSpline; - } - else - { - tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = true; - tNode2.GSDSpline.SpecialEndNodeDelay_End = tDelay; - tNode2.GSDSpline.SpecialEndNodeDelay_End_Result = tNode1.GSDSpline.tRoad.RoadWidth(); - tNode2.GSDSpline.SpecialEndNode_End_OtherSpline = tNode1.GSDSpline; - } - } - else if (tNode2.GSDSpline.tRoad.opt_Lanes > tNode1.GSDSpline.tRoad.opt_Lanes) - { - tNode1.bSpecialRoadConnPrimary = true; - NodeCreated1.bSpecialRoadConnPrimary = true; - if (tNode1.GSDSpline.tRoad.opt_Lanes == 4) { xWidth *= 2f; } - tDelay = (tNode2.GSDSpline.tRoad.opt_Lanes - tNode1.GSDSpline.tRoad.opt_Lanes) * xWidth; - if (tDelay < 10f) { tDelay = 10f; } - if (bFirstNode_Start) - { - tNode1.GSDSpline.bSpecialEndNode_IsStart_Delay = true; - tNode1.GSDSpline.SpecialEndNodeDelay_Start = tDelay; - tNode1.GSDSpline.SpecialEndNodeDelay_Start_Result = tNode2.GSDSpline.tRoad.RoadWidth(); - tNode1.GSDSpline.SpecialEndNode_Start_OtherSpline = tNode2.GSDSpline; - } - else - { - tNode1.GSDSpline.bSpecialEndNode_IsEnd_Delay = true; - tNode1.GSDSpline.SpecialEndNodeDelay_End = tDelay; - tNode1.GSDSpline.SpecialEndNodeDelay_End_Result = tNode2.GSDSpline.tRoad.RoadWidth(); - tNode1.GSDSpline.SpecialEndNode_End_OtherSpline = tNode2.GSDSpline; - } - } - else - { - tNode1.bSpecialRoadConnPrimary = true; - NodeCreated1.bSpecialRoadConnPrimary = true; - tDelay = 0f; - tNode1.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; - tNode1.GSDSpline.bSpecialEndNode_IsStart_Delay = false; - tNode1.GSDSpline.SpecialEndNodeDelay_End = tDelay; - tNode1.GSDSpline.SpecialEndNodeDelay_End_Result = tNode2.GSDSpline.tRoad.RoadWidth(); - tNode1.GSDSpline.SpecialEndNode_End_OtherSpline = tNode2.GSDSpline; - tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; - tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = false; - tNode2.GSDSpline.SpecialEndNodeDelay_End = tDelay; - tNode2.GSDSpline.SpecialEndNodeDelay_End_Result = tNode1.GSDSpline.tRoad.RoadWidth(); - tNode2.GSDSpline.SpecialEndNode_End_OtherSpline = tNode1.GSDSpline; - } - - tNode1.SpecialNodeCounterpart = NodeCreated1; - tNode2.SpecialNodeCounterpart = NodeCreated2; - NodeCreated1.SpecialNodeCounterpart_Master = tNode1; - NodeCreated2.SpecialNodeCounterpart_Master = tNode2; - - - NodeCreated1.ToggleHideFlags(true); - NodeCreated2.ToggleHideFlags(true); - - GSDSplineN[] OrigNodes = new GSDSplineN[2]; - OrigNodes[0] = tNode1; - OrigNodes[1] = tNode2; - tNode1.OriginalConnectionNodes = OrigNodes; - tNode2.OriginalConnectionNodes = OrigNodes; - - // tNode1.GSDSpline.Setup_Trigger(); - // if(tNode1.GSDSpline != tNode2.GSDSpline){ - // tNode2.GSDSpline.Setup_Trigger(); - // } - - if (tNode1 != null && tNode2 != null) - { - if (tNode1.GSDSpline != tNode2.GSDSpline) - { - tNode1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[1]; - tNode1.GSDSpline.tRoad.PiggyBacks[0] = tNode2.GSDSpline; - } - tNode1.GSDSpline.tRoad.EditorUpdateMe = true; - } - PreviewSpline.bGizmoDraw = false; - xSpline.PreviewSpline.bGizmoDraw = false; - UnityEditor.SceneView.RepaintAll(); - } - #endregion -#endif - #region "General Util" - public int GetNodeCount() - { - return mNodes.Count; - } - - public int GetNodeCountNonNull() - { - int mCount = GetNodeCount(); - int tCount = 0; - for (int i = 0; i < mCount; i++) - { - if (mNodes[i] != null) - { - tCount += 1; - if (mNodes[i].bIsIntersection && mNodes[i].GSDRI == null) - { - DestroyIntersection(mNodes[i]); - } - } - } - return tCount; - } - - public bool CheckInvalidNodeCount() - { - int mCount = GetNodeCount(); - int tCount = 0; - for (int i = 0; i < mCount; i++) - { - if (mNodes[i] != null) - { - tCount += 1; - if (mNodes[i].bIsIntersection && mNodes[i].GSDRI == null) - { - DestroyIntersection(mNodes[i]); - } - } - else - { - - } - } - if (tCount != mCount) - { - return true; - } - else - { - return false; - } - } - - public GSDSplineN GetCurrentNode(float p) - { - int mCount = GetNodeCount(); - GSDSplineN tNode = null; - for (int i = 0; i < mCount; i++) - { - tNode = mNodes[i]; - if (tNode.tTime > p) - { - tNode = mNodes[i - 1]; - return tNode; - } - } - return tNode; - } - - public GSDSplineN GetLastLegitimateNode() - { - int mCount = GetNodeCount(); - GSDSplineN tNode = null; - for (int i = (mCount - 1); i >= 0; i--) - { - tNode = mNodes[i]; - if (tNode.IsLegitimate()) - { - return tNode; - } - } - return null; - } - - public GSDSplineN GetLastNode_All() - { - int mCount = GetNodeCount(); - int StartIndex = (mCount - 1); - GSDSplineN tNode = null; - - int i = StartIndex; - while (i >= 0) - { - if (i <= (mNodes.Count - 1)) - { - tNode = mNodes[i]; - if (tNode != null) - { - return tNode; - } - } - i -= 1; - } - return null; - } - - public GSDSplineN GetPrevLegitimateNode(int tIndex) - { - try - { - GSDSplineN tNode = null; - for (int i = (tIndex - 1); i >= 0; i--) - { - tNode = mNodes[i]; - if (tNode.IsLegitimateGrade()) - { - return tNode; - } - } - return null; - } - catch - { - return null; - } - } - - public GSDSplineN GetNextLegitimateNode(int tIndex) - { - GSDSplineN tNode = null; - int mCount = GetNodeCount(); - for (int i = (tIndex + 1); i < mCount; i++) - { - tNode = mNodes[i]; - if (tNode.IsLegitimateGrade()) - { - return tNode; - } - } - return null; - } -#if UNITY_EDITOR - public void ClearAllRoadCuts() - { - int mCount = GetNodeCount(); - for (int i = 0; i < mCount; i++) - { - mNodes[i].ClearCuts(); - } - } -#endif - - public void ResetNavigationData() - { - id_connected = null; - id_connected = new List(); - } - #endregion - - //#endif - - #region "Start" - void Start() - { -#if UNITY_EDITOR - //CachedPoints = null; -#else - this.enabled = false; -#endif - } - #endregion +#region "Imports" +using UnityEngine; +using System.Collections.Generic; +using GSD; +#endregion + + +public class GSDSplineC : MonoBehaviour +{ + //#if UNITY_EDITOR + public List mNodes = new List(); + public GameObject mSplineRoot; + public GSDRoad tRoad; + public float distance = -1f; + public Vector3[] CachedPoints; + private const float CachedPointsSeperation = 1f; + + //Editor preview splines for add and insert: + public GSDSplineF PreviewSpline; + public GSDSplineI PreviewSplineInsert; + + + #region Nav data Vars + public float RoadWidth; + public int Lanes; + public List id_connected; + public int id = 0; + public string UID; //Unique ID + public List> BridgeParams; + public List> TunnelParams; + public List> HeightHistory; + public int[] RoadDefKeysArray; + public float[] RoadDefValuesArray; + public double EditorOnly_LastNode_TimeSinceStartup = -1f; + #endregion + + + #region Vars for intersections: + const float MetersToCheck_NoTurnLane = 75f; + const float MetersToCheck_NoTurnLaneSQ = 5625f; + const float MetersToCheck_TurnLane = 125f; + const float MetersToCheck_TurnLaneSQ = 15625f; + const float MetersToCheck_BothTurnLane = 125f; + const float MetersToCheck_BothTurnLaneSQ = 15625f; + const bool bUseSQ = true; + #endregion + + + #region Road connections and 3-way intersections: + public bool bSpecialStartControlNode = false; + public bool bSpecialEndControlNode = false; + public bool bSpecialEndNode_IsStart_Delay = false; + public bool bSpecialEndNode_IsEnd_Delay = false; + public float SpecialEndNodeDelay_Start = 10f; + public float SpecialEndNodeDelay_Start_Result = 10f; + public float SpecialEndNodeDelay_End = 10f; + public float SpecialEndNodeDelay_End_Result = 10f; + public GSDSplineC SpecialEndNode_Start_OtherSpline = null; + public GSDSplineC SpecialEndNode_End_OtherSpline = null; + #endregion + + + public Vector2 RoadV0 = default(Vector2); + public Vector2 RoadV1 = default(Vector2); + public Vector2 RoadV2 = default(Vector2); + public Vector2 RoadV3 = default(Vector2); + + +#if UNITY_EDITOR + #region "Setup" + public void Setup_Trigger() + { +#if UNITY_EDITOR + if (!tRoad) + { + if (mSplineRoot != null) + { + tRoad = mSplineRoot.transform.parent.transform.gameObject.GetComponent(); + } + } + if (tRoad) + { + tRoad.UpdateRoad(); + } +#endif + } + + + public void Setup() + { +#if UNITY_EDITOR + //Don't setup if playing: + // if(!Application.isEditor || (Application.isEditor && UnityEditor.EditorApplication.isPlaying)){ return; } + + //Setup unique ID: + SetupUniqueIdentifier(); + + //Set spline root: + mSplineRoot = transform.gameObject; + + //Create spline nodes: + GSDSplineN[] tNodesRaw = mSplineRoot.GetComponentsInChildren(); + List tList = new List(); + int tNodesRawLength = tNodesRaw.Length; + if (tNodesRawLength == 0) + { + return; + } + for (int i = 0; i < tNodesRawLength; i++) + { + if (tNodesRaw[i] != null) + { + tNodesRaw[i].pos = tNodesRaw[i].transform.position; + tList.Add(tNodesRaw[i]); + } + } + tList.Sort(CompareListByName); + //tList.Sort(delegate(GSDSplin i1, Item i2) { return i1.name.CompareTo(i2.name); }); + tNodesRaw = tList.ToArray(); + tList = null; + Setup_Nodes(ref tNodesRaw); + + //Setup spline length, if more than 1 node: + if (GetNodeCount() > 1) + { + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.BeginSample("SplineSetupLength"); } + Setup_SplineLength(); + // if(tRoad.bProfiling){ UnityEngine.Profiling.Profiler.EndSample(); } + } + else if (GetNodeCount() == 1) + { + mNodes[0].tTime = 0f; + } + + +#if UNITY_EDITOR + //Setup preview spline: + if (PreviewSpline == null) + { + PreviewSpline = mSplineRoot.AddComponent(); + PreviewSpline.GSDSpline = this; + } + //Setup preview spline for insertion mode: + if (PreviewSplineInsert == null) + { + PreviewSplineInsert = mSplineRoot.AddComponent(); + PreviewSplineInsert.GSDSpline = this; + } +#endif + + + int mNodesCount = mNodes.Count; + GSDSplineN tNode = null; + Vector3[] pVects = new Vector3[mNodesCount + 1]; + for (int i = 0; i < mNodesCount; i++) + { + tNode = mNodes[i]; + tNode.idOnSpline = i; + tNode.bIsEndPoint = false; + pVects[i] = tNode.pos; + } + pVects[pVects.Length - 1] = new Vector3(0f, 0f, 0f); +#if UNITY_EDITOR + PreviewSpline.Setup(ref pVects); +#endif + + + RenameNodes(); + + + #region Setup bridge params: + if (BridgeParams != null) + { + BridgeParams.Clear(); + } + BridgeParams = new List>(); + KeyValuePair KVP; + #endregion + + + //Setup tunnel params: + if (TunnelParams != null) + { + TunnelParams.Clear(); + } + TunnelParams = new List>(); + + if (mNodesCount > 1) + { + if (bSpecialStartControlNode) + { + mNodes[1].bIsEndPoint = true; + } + else + { + mNodes[0].bIsEndPoint = true; + } + if (bSpecialEndControlNode) + { + mNodes[mNodesCount - 2].bIsEndPoint = true; + } + else + { + mNodes[mNodesCount - 1].bIsEndPoint = true; + } + } + else if (mNodesCount == 1) + { + mNodes[0].bIsEndPoint = true; + distance = 1; + } + + float fStart = -1f; + float fEnd = -1f; + if (mNodesCount > 1) + { + for (int i = 0; i < mNodesCount; i++) + { + tNode = mNodes[i]; + + //Bridges: + fStart = -1f; + fEnd = -1f; + if (tNode.bIsBridgeStart && !tNode.bIsTunnelStart) + { + fStart = tNode.tTime; + for (int j = i; j < mNodesCount; j++) + { + if (mNodes[j].bIsBridgeEnd) + { + fEnd = mNodes[j].tTime; + break; + } + } + if (fEnd > 0f || GSDRootUtil.IsApproximately(fEnd, 0f, 0.0001f)) + { + KVP = new KeyValuePair(fStart, fEnd); + BridgeParams.Add(KVP); + } + } + + //Tunnels: + fStart = -1f; + fEnd = -1f; + if (!tNode.bIsBridgeStart && tNode.bIsTunnelStart) + { + fStart = tNode.tTime; + for (int j = i; j < mNodesCount; j++) + { + if (mNodes[j].bIsTunnelEnd) + { + fEnd = mNodes[j].tTime; + break; + } + } + + if (fEnd > 0f || GSDRootUtil.IsApproximately(fEnd, 0f, 0.0001f)) + { + KVP = new KeyValuePair(fStart, fEnd); + TunnelParams.Add(KVP); + } + } + + tNode.SetGradePercent(mNodesCount); + // tNode.bIsEndPoint = false; + tNode.tangent = GetSplineValue(mNodes[i].tTime, true); + if (i < (mNodesCount - 1)) + { + tNode.NextTime = mNodes[i + 1].tTime; + tNode.NextTan = mNodes[i + 1].tangent; + } + } + } + else if (mNodesCount == 1) + { + mNodes[0].tangent = default(Vector3); + } + + //Get bounds of road system: + float[] tMaxEffects = new float[3]; + tMaxEffects[0] = tRoad.opt_MatchHeightsDistance; + tMaxEffects[1] = tRoad.opt_ClearDetailsDistance; + tMaxEffects[2] = tRoad.opt_ClearTreesDistance; + float MaxEffectDistance = Mathf.Max(tMaxEffects) * 2f; //Add min/max clear diff to bound checks + int mCount1 = GetNodeCount(); + float[] tMinMaxX = new float[mCount1]; + float[] tMinMaxZ = new float[mCount1]; + // Vector3 tVect1 = default(Vector3); + for (int i = 0; i < mCount1; i++) + { + tMinMaxX[i] = mNodes[i].pos.x; + tMinMaxZ[i] = mNodes[i].pos.z; + } + float MinX = Mathf.Min(tMinMaxX) - MaxEffectDistance; + float MaxX = Mathf.Max(tMinMaxX) + MaxEffectDistance; + float MinZ = Mathf.Min(tMinMaxZ) - MaxEffectDistance; + float MaxZ = Mathf.Max(tMinMaxZ) + MaxEffectDistance; + RoadV0 = new Vector3(MinX, MinZ); + RoadV1 = new Vector3(MaxX, MinZ); + RoadV2 = new Vector3(MaxX, MaxZ); + RoadV3 = new Vector3(MinX, MaxZ); +#endif + } + + + private void SetupUniqueIdentifier() + { + if (UID == null || UID.Length < 4) + { + UID = System.Guid.NewGuid().ToString(); + } + } + + + /// + /// Renames the Nodes to their id on the Spline + /// + private void RenameNodes() + { + int mNodesCount = mNodes.Count; + for (int i = 0; i < mNodesCount; i++) + { + GSDSplineN tNode = mNodes[i]; + tNode.name = "Node" + tNode.idOnSpline; + tNode.transform.gameObject.name = tNode.name; + tNode.EditorDisplayString = tRoad.transform.name + "-" + tNode.name; + } + } + + + private int CompareListByName(GSDSplineN i1, GSDSplineN i2) + { + return i1.idOnSpline.CompareTo(i2.idOnSpline); + } + + + private void Setup_Nodes(ref GSDSplineN[] tNodesRaw) + { + //Process nodes: + int i = 0; + List tNodes = new List(); + int tNodesRawLength = tNodesRaw.Length; + for (i = 0; i < tNodesRawLength; i++) + { + if (!tNodesRaw[i].bDestroyed) + { + tNodes.Add(tNodesRaw[i]); + } + } + + mNodes.Clear(); + mNodes = new List(); + GSDSplineN tNode; + float step; + Quaternion rot; + bool bClosed = false; + step = (bClosed) ? 1f / ((float) tNodes.Count) : 1f / ((float) (tNodes.Count - 1)); + int tNodesCount = tNodes.Count; + for (i = 0; i < tNodesCount; i++) + { + tNode = tNodes[i]; + + rot = Quaternion.identity; + if (i != tNodes.Count - 1) + { + if ((tNodes[i + 1].transform.position - tNode.transform.position) == Vector3.zero) + { + rot = Quaternion.identity; + } + else + { + rot = Quaternion.LookRotation(tNodes[i + 1].transform.position - tNode.transform.position, transform.up); + } + } + else if (bClosed) + { + rot = Quaternion.LookRotation(tNodes[0].transform.position - tNode.transform.position, transform.up); + } + else + { + rot = Quaternion.identity; + } + + tNode.Setup(tNode.transform.position, rot, new Vector2(0f, 1f), step * ((float) i), tNode.transform.gameObject.name); + tNode.SetupUniqueIdentifier(); + mNodes.Add(tNode); + } + + tNodes = null; + tNodesRaw = null; + } + + + private void Setup_SplineLength() + { + int mNodeCount = mNodes.Count; + + //First lets get the general distance, node to node: + mNodes[0].tTime = 0f; + mNodes[mNodeCount - 1].tTime = 1f; + Vector3 tVect1 = new Vector3(0f, 0f, 0f); + Vector3 tVect2 = new Vector3(0f, 0f, 0f); + float mDistance = 0f; + float mDistance_NoMod = 0f; + for (int j = 0; j < mNodeCount; j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + mDistance += Vector3.Distance(tVect1, tVect2); + } + tVect1 = tVect2; + } + mDistance_NoMod = mDistance; + mDistance = mDistance * 1.05f; + float step = 0.5f / mDistance; + + //Get a slightly more accurate portrayal of the time: + float tTime = 0f; + for (int j = 0; j < (mNodeCount - 1); j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); + mNodes[j].tTime = tTime; + } + tVect1 = tVect2; + } + + //Using general distance and calculated step, get an accurate distance: + float tDistance = 0f; + Vector3 prevPos = mNodes[0].pos; + Vector3 cPos = new Vector3(0f, 0f, 0f); + // float hDistance = 0f; + GSDSplineN tNode; + + prevPos = GetSplineValue(0f); + for (float i = 0f; i < 1f; i += step) + { + cPos = GetSplineValue(i); + // if(float.IsNaN(cPos.x)){ + // int xsagfdsdgsd = 0; + // } + tDistance += Vector3.Distance(cPos, prevPos); + prevPos = cPos; + } + + distance = tDistance; + + //Now get fine distance between nodes: + + // float tNanCheck = 0f; + float newTotalDistance = 0f; + step = 0.5f / distance; + GSDSplineN PrevNode = null; + GSDSplineN ThisNode = null; + prevPos = GetSplineValue(0f, false); + for (int j = 1; j < (mNodeCount - 1); j++) + { + PrevNode = mNodes[j - 1]; + ThisNode = mNodes[j]; + + if (j == 1) + { + prevPos = GetSplineValue(PrevNode.tTime); + } + tDistance = 0.00001f; + for (float i = PrevNode.tTime; i < ThisNode.tTime; i += step) + { + cPos = GetSplineValue(i); + if (!float.IsNaN(cPos.x)) + { + if (float.IsNaN(prevPos.x)) + { + prevPos = cPos; + } + tDistance += Vector3.Distance(cPos, prevPos); + prevPos = cPos; + } + } + ThisNode.tempSegmentTime = (tDistance / distance); + newTotalDistance += tDistance; + ThisNode.tDist = newTotalDistance; + } + + + mNodes[0].tDist = 0f; + PrevNode = mNodes[mNodeCount - 2]; + ThisNode = mNodes[mNodeCount - 1]; + tDistance = 0.00001f; + for (float i = PrevNode.tTime; i < ThisNode.tTime; i += step) + { + cPos = GetSplineValue(i, false); + if (!float.IsNaN(cPos.x)) + { + if (float.IsNaN(prevPos.x)) + { + prevPos = cPos; + } + tDistance += Vector3.Distance(cPos, prevPos); + prevPos = cPos; + } + } + ThisNode.tempSegmentTime = (tDistance / distance); + newTotalDistance += tDistance; + ThisNode.tDist = newTotalDistance; + distance = newTotalDistance; + + + tTime = 0f; + for (int j = 1; j < (mNodeCount - 1); j++) + { + tNode = mNodes[j]; + tTime += tNode.tempSegmentTime; + tNode.OldTime = tNode.tTime; + tNode.tTime = tTime; + tNode.tangent = GetSplineValue_SkipOpt(tNode.tTime, true); + tNode.transform.rotation = Quaternion.LookRotation(tNode.tangent); + } + mNodes[0].tangent = GetSplineValue_SkipOpt(0f, true); + mNodes[mNodeCount - 1].tangent = GetSplineValue_SkipOpt(1f, true); + + + mNodes[0].tDist = 0f; + + step = distance / CachedPointsSeperation; + int ArrayCount = (int) Mathf.Floor(step) + 2; + CachedPoints = null; + CachedPoints = new Vector3[ArrayCount]; + step = CachedPointsSeperation / distance; + for (int j = 1; j < (ArrayCount - 1); j++) + { + CachedPoints[j] = GetSplineValue(step * j); + } + CachedPoints[0] = mNodes[0].pos; + CachedPoints[ArrayCount - 1] = mNodes[mNodeCount - 1].pos; + + RoadDefCalcs(); + } + #endregion +#endif + + + #region "Road definition cache and translation" + private void RoadDefCalcs() + { + // float tNanCheck = 0f; + float tMod = Mathf.Lerp(0.05f, 0.2f, distance / 9000f); + float step = tMod / distance; + Vector3 cPos = GetSplineValue(0f); + Vector3 prevPos = cPos; + float tempDistanceModMax = tRoad.opt_RoadDefinition - step; + float tempDistanceMod = 0f; + float tempTotalDistance = 0f; + float tempDistanceHolder = 0f; + if (RoadDefKeysArray != null) + { + RoadDefKeysArray = null; + } + if (RoadDefValuesArray != null) + { + RoadDefValuesArray = null; + } + + List RoadDefKeys = new List(); + List RoadDefValues = new List(); + + RoadDefKeys.Add(0); + RoadDefValues.Add(0f); + + for (float index = 0f; index < 1f; index += step) + { + cPos = GetSplineValue(index); + tempDistanceHolder = Vector3.Distance(cPos, prevPos); + tempTotalDistance += tempDistanceHolder; + tempDistanceMod += tempDistanceHolder; + if (tempDistanceMod > tempDistanceModMax) + { + tempDistanceMod = 0f; + RoadDefKeys.Add(TranslateParamToInt(index)); + RoadDefValues.Add(tempTotalDistance); + } + prevPos = cPos; + } + + RoadDefKeysArray = RoadDefKeys.ToArray(); + RoadDefValuesArray = RoadDefValues.ToArray(); + } + + + public int TranslateParamToInt(float f) + { + return Mathf.Clamp((int) (f * 10000000f), 0, 10000000); + } + + + public float TranslateInverseParamToFloat(int f) + { + return Mathf.Clamp(((float) (float) f / 10000000f), 0f, 1f); + } + + + private void GetClosestRoadDefKeys(float tX, out int lo, out int hi, out int loIndex, out int hiIndex) + { + int x = TranslateParamToInt(tX); + lo = -1; + hi = RoadDefKeysArray.Length - 1; + + int mid = -1; + + while ((hi - lo) > 1) + { + mid = Mathf.RoundToInt((lo + hi) / 2); + if (RoadDefKeysArray[mid] <= x) + { + lo = mid; + } + else + { + hi = mid; + } + } + + if (RoadDefKeysArray[lo] == x) + { + hi = lo; + } + // if(hi > RoadDefKeysArray.Length-1){ hi = RoadDefKeysArray.Length-1; } + + loIndex = lo; + hiIndex = hi; + lo = RoadDefKeysArray[lo]; + hi = RoadDefKeysArray[hi]; + } + + + public int GetClosestRoadDefIndex(float tX, bool bRoundUp = false, bool bRoundDown = false) + { + int lo, hi, loIndex, hiIndex; + + GetClosestRoadDefKeys(tX, out lo, out hi, out loIndex, out hiIndex); + + int x = TranslateParamToInt(tX); + + if (bRoundUp) + { + return hiIndex; + } + if (bRoundDown) + { + return loIndex; + } + + if ((x - lo) > (hi - x)) + { + return hiIndex; + } + else + { + return loIndex; + } + } + + + private void GetClosestRoadDefValues(float tX, out float loF, out float hiF, out int loIndex, out int hiIndex) + { + int lo = -1; + int hi = RoadDefValuesArray.Length - 1; + int mid = -1; + + while ((hi - lo) > 1) + { + mid = Mathf.RoundToInt((lo + hi) / 2); + if (RoadDefValuesArray[mid] < tX || GSDRootUtil.IsApproximately(RoadDefValuesArray[mid], tX, 0.02f)) + { + lo = mid; + } + else + { + hi = mid; + } + } + + if (GSDRootUtil.IsApproximately(RoadDefValuesArray[lo], tX, 0.02f)) + { + hi = lo; + } + + loIndex = lo; + hiIndex = hi; + loF = RoadDefValuesArray[lo]; + hiF = RoadDefValuesArray[hi]; + } + + + public int GetClosestRoadDefValuesIndex(float tX, bool bRoundUp = false, bool bRoundDown = false) + { + float lo, hi; + int loIndex, hiIndex; + + GetClosestRoadDefValues(tX, out lo, out hi, out loIndex, out hiIndex); + + if (bRoundUp) + { + return hiIndex; + } + if (bRoundDown) + { + return loIndex; + } + + if ((tX - lo) > (hi - tX)) + { + return hiIndex; + } + else + { + return loIndex; + } + } + + + public float TranslateDistBasedToParam(float mDist) + { + int tIndex = GetClosestRoadDefValuesIndex(mDist, false, false); + float tKey = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex]); + int tCount = RoadDefKeysArray.Length; + float kDist = RoadDefValuesArray[tIndex]; + + if (tIndex < (tCount - 1)) + { + if (mDist > kDist) + { + float NextValue = RoadDefValuesArray[tIndex + 1]; + float tDiff1 = (mDist - kDist) / (NextValue - kDist); + tKey += (tDiff1 * (TranslateInverseParamToFloat(RoadDefKeysArray[tIndex + 1]) - tKey)); + } + } + if (tIndex > 0) + { + if (mDist < kDist) + { + float PrevValue = RoadDefValuesArray[tIndex - 1]; + float tDiff1 = (mDist - PrevValue) / (kDist - PrevValue); + tKey -= (tDiff1 * (tKey - TranslateInverseParamToFloat(RoadDefKeysArray[tIndex - 1]))); + } + } + + return tKey; + } + + + public float TranslateParamToDist(float param) + { + int tIndex = GetClosestRoadDefIndex(param, false, false); + float tKey = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex]); + int tCount = RoadDefKeysArray.Length; + float kDist = RoadDefValuesArray[tIndex]; + float xDiff = kDist; + + if (tIndex < (tCount - 1)) + { + if (param > tKey) + { + float NextValue = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex + 1]); + float tDiff1 = (param - tKey) / (NextValue - tKey); + xDiff += (tDiff1 * (RoadDefValuesArray[tIndex + 1] - kDist)); + } + } + if (tIndex > 0) + { + if (param < tKey) + { + float PrevValue = TranslateInverseParamToFloat(RoadDefKeysArray[tIndex - 1]); + float tDiff1 = 1f - ((param - PrevValue) / (tKey - PrevValue)); + xDiff -= (tDiff1 * (kDist - RoadDefValuesArray[tIndex - 1])); + } + } + + return xDiff; + } + #endregion + + + #region "Hermite math" + /// + /// Gets the spline value. + /// + /// + /// The relevant param (0-1) of the spline. + /// + /// + /// True for is tangent, false (default) for vector3 position. + /// + public Vector3 GetSplineValue(float _value, bool _isTangent = false) // float _value, formerly f; Renamed boolb to reflect its use according to the summary of this function + { + int index; // index, formerly i + int idx = -1; + + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + // FH 03.02.19 // This Code was outcommented, but it takes care about values above and below 0f and 1f and clamping them. + // This Fixes the Bug with 1f -> -0.0001f as descripted by embeddedt/RoadArchitect/issues/4 + if (GSDRootUtil.IsApproximately(_value, 0f, 0.00001f)) + { + if (_isTangent) + { + return mNodes[0].tangent; + } + else + { + return mNodes[0].pos; + } + } + else + if (GSDRootUtil.IsApproximately(_value, 1f, 0.00001f) || _value > 1f) + { + if (_isTangent) + { + return mNodes[mNodes.Count - 1].tangent; + } + else + { + return mNodes[mNodes.Count - 1].pos; + } + } + else + { + GSDRootUtil.IsApproximately(_value, 1f, 0.00001f); + // FH 03.02.19 // End of the former outcommented Code + + for (index = 0; index < mNodes.Count; index++) + { + if (index == mNodes.Count - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime > _value) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + } // // FH 03.02.19 // also former outcommented Code, see above + + float param = (_value - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, _isTangent); + } + + + public void GetSplineValue_Both(float _value, out Vector3 tVect1, out Vector3 tVect2) // former VarNames: f = _value + { + int index; + int idx = -1; + int mCount = GetNodeCount(); + + if (_value < 0f) + { + _value = 0f; + } + if (_value > 1f) + { + _value = 1f; + } + + + if (mCount == 0) + { + tVect1 = default(Vector3); + tVect2 = default(Vector3); + return; + } + + if (mCount == 1) + { + if (mNodes[0]) + { + tVect1 = mNodes[0].pos; + tVect2 = default(Vector3); + } + else + { + tVect1 = default(Vector3); + tVect2 = default(Vector3); + } + return; + } + + + // FH 03.02.19 // This Code was outcommented, but it takes care about values above and below 0f and 1f and clamping them. + // This code needs to be reevealuated if this isn't taken care of by the function above this one. GetSplineValue() + // Right now, I would say that it is not really a part of embeddedt/RoadArchitect/issues/4 + if (GSDRootUtil.IsApproximately(_value, 1f, 0.0001f)) + { + tVect1 = mNodes[mNodes.Count - 1].pos; + tVect2 = mNodes[mNodes.Count - 1].tangent; + return; + } + else if (GSDRootUtil.IsApproximately(_value, 0f, 0.0001f)) + { + tVect1 = mNodes[0].pos; + tVect2 = mNodes[0].tangent; + return; + } + // FH 10.02.19 // Do Note: This does prevent EdgeObjects from being placed before or after 0f/1f on the Spline, but also causes the EdgeObject to be placed at the same Position at the End of the Spline. + // FH 03.02.19 // End of the former outcommented Code + + for (index = 1; index < mCount; index++) + { + if (index == mCount - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime > _value) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + + float param = (_value - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + + tVect1 = GetHermiteInternal(idx, param, false); + tVect2 = GetHermiteInternal(idx, param, true); + } + + + public Vector3 GetSplineValue_SkipOpt(float f, bool b = false) + { + int index; + int idx = -1; + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + + // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ + // if(b){ + // return mNodes[0].tangent; + // }else{ + // return mNodes[0].pos; + // } + // }else + // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ + // if(b){ + // return mNodes[mNodes.Count-1].tangent; + // }else{ + // return mNodes[mNodes.Count-1].pos; + // } + // }else{ + for (index = 1; index < mNodes.Count; index++) + { + if (index == mNodes.Count - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime > f) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + // if(b && GSDRootUtil.IsApproximately(f,1f,0.00001f)){ + // idx = mNodes.Count-2; + // } + // } + + float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, b); + } + + + public float GetClosestParam(Vector3 tVect, bool b20cmPrecision = false, bool b1MeterPrecision = false) + { + return GetClosestParam_Do(ref tVect, b20cmPrecision, b1MeterPrecision); + } + + + private float GetClosestParam_Do(ref Vector3 tVect, bool b20cmPrecision, bool b1MeterPrecision) + { + float Step1 = CachedPointsSeperation / distance; //5m to 1m + float Step2 = Step1 * 0.2f; //20 cm + float Step3 = Step2 * 0.4f; //8 cm + float Step4 = Step3 * 0.25f; //2 cm + + + float tMin = 0f; + float tMax = 1f; + + // Why is Best value set to -1f? at init + float BestValue = -1f; + float MaxStretch = 0.9f; + Vector3 BestVect_p = new Vector3(0f, 0f, 0f); + Vector3 BestVect_n = new Vector3(0f, 0f, 0f); + + if (mNodes.Count == 0) + { + return 0f; + } + if (mNodes.Count == 1) + { + return 1f; + } + + //Step 1: 1m + BestValue = GetClosestPoint_Helper(ref tVect, Step1, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n, true); + if (b1MeterPrecision) + { + return BestValue; + } + + //Step 2: 20cm + tMin = BestValue - (Step1 * MaxStretch); + tMax = BestValue + (Step1 * MaxStretch); + BestValue = GetClosestPoint_Helper(ref tVect, Step2, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); + if (b20cmPrecision) + { + return BestValue; + } + + //Step 3: 8cm + tMin = BestValue - (Step2 * MaxStretch); + tMax = BestValue + (Step2 * MaxStretch); + BestValue = GetClosestPoint_Helper(ref tVect, Step3, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); + + //Step 4: 2cm + tMin = BestValue - (Step3 * MaxStretch); + tMax = BestValue + (Step3 * MaxStretch); + BestValue = GetClosestPoint_Helper(ref tVect, Step4, BestValue, tMin, tMax, ref BestVect_p, ref BestVect_n); + + return BestValue; + } + + + private float GetClosestPoint_Helper(ref Vector3 tVect, float tStep, float BestValue, float tMin, float tMax, ref Vector3 BestVect_p, ref Vector3 BestVect_n, bool bMeterCache = false) + { + float mDistance = 5000f; + float tDistance = 0f; + Vector3 cVect = new Vector3(0f, 0f, 0f); + Vector3 pVect = new Vector3(0f, 0f, 0f); + bool bFirstLoopHappened = false; + bool bSetBestValue = false; + + //Get lean for tmin/tmax: + if (GetClosetPoint_MinMaxDirection(ref tVect, ref BestVect_p, ref BestVect_n)) + { + tMax = BestValue; + } + else + { + tMin = BestValue; + } + + tMin = Mathf.Clamp(tMin, 0f, 1f); + tMax = Mathf.Clamp(tMax, 0f, 1f); + + if (bMeterCache) + { + int CachedIndex = -1; + int Step1 = 10; + + int CachedPointsLength = CachedPoints.Length; + for (int j = 0; j < CachedPointsLength; j += Step1) + { + cVect = CachedPoints[j]; + tDistance = Vector3.Distance(tVect, cVect); + if (tDistance < mDistance) + { + mDistance = tDistance; + CachedIndex = j; + } + } + + int jStart = (CachedIndex - Step1); + if (jStart < 50) + { + jStart = 0; + } + int jEnd = (CachedIndex + Step1); + if (jEnd > (CachedPointsLength)) + { + jEnd = CachedPointsLength; + } + for (int j = jStart; j < jEnd; j++) + { + cVect = CachedPoints[j]; + if (bSetBestValue) + { + BestVect_n = cVect; + bSetBestValue = false; + } + tDistance = Vector3.Distance(tVect, cVect); + if (tDistance < mDistance) + { + mDistance = tDistance; + if (!bFirstLoopHappened) + { + BestVect_p = cVect; + } + else + { + BestVect_p = pVect; + } + CachedIndex = j; + bSetBestValue = true; + bFirstLoopHappened = true; + } + pVect = cVect; + } + + BestValue = (CachedIndex / distance); + + } + else + { + for (float index = tMin; index <= tMax; index += tStep) + { + cVect = GetSplineValue(index); + if (bSetBestValue) + { + BestVect_n = cVect; + bSetBestValue = false; + } + tDistance = Vector3.Distance(tVect, cVect); + if (tDistance < mDistance) + { + mDistance = tDistance; + BestValue = index; + if (!bFirstLoopHappened) + { + BestVect_p = cVect; + } + else + { + BestVect_p = pVect; + } + + bSetBestValue = true; + bFirstLoopHappened = true; + } + pVect = cVect; + } + } + + if (bSetBestValue) + { + BestVect_n = cVect; + } + + //Debug.Log ("returning: " + BestValue + " tmin:" + tMin + " tmax:" + tMax); + return BestValue; + } + + + //Returns true for tmin lean: + private bool GetClosetPoint_MinMaxDirection(ref Vector3 tVect, ref Vector3 BestVect_p, ref Vector3 BestVect_n) + { + float Distance1 = Vector3.Distance(tVect, BestVect_p); + float Distance2 = Vector3.Distance(tVect, BestVect_n); + + if (Distance1 < Distance2) + { + //tMin lean + return true; + } + else + { + //tMax lean + return false; + } + } + + + private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) + { + double t2, t3; + float BL0, BL1, BL2, BL3, tension; + + if (!bTangent) + { + t2 = t * t; + t3 = t2 * t; + } + else + { + t2 = t * t; + t = t * 2.0; + t2 = t2 * 3.0; + t3 = 0; //Necessary for compiler error. + } + + //Vectors: + Vector3 P0 = mNodes[NGI(i, NI[0])].pos; + Vector3 P1 = mNodes[NGI(i, NI[1])].pos; + Vector3 P2 = mNodes[NGI(i, NI[2])].pos; + Vector3 P3 = mNodes[NGI(i, NI[3])].pos; + + //Tension: + tension = 0.5f; + + + + //Tangents: + Vector3 xVect1 = (P1 - P2) * tension; + Vector3 xVect2 = (P3 - P0) * tension; + float tMaxMag = tRoad.opt_MagnitudeThreshold; + + if (Vector3.Distance(P1, P3) > tMaxMag) + { + if (xVect1.magnitude > tMaxMag) + { + xVect1 = Vector3.ClampMagnitude(xVect1, tMaxMag); + } + if (xVect2.magnitude > tMaxMag) + { + xVect2 = Vector3.ClampMagnitude(xVect2, tMaxMag); + } + } + else if (Vector3.Distance(P0, P2) > tMaxMag) + { + if (xVect1.magnitude > tMaxMag) + { + xVect1 = Vector3.ClampMagnitude(xVect1, tMaxMag); + } + if (xVect2.magnitude > tMaxMag) + { + xVect2 = Vector3.ClampMagnitude(xVect2, tMaxMag); + } + } + + + if (!bTangent) + { + BL0 = (float) (CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); + BL1 = (float) (CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); + BL2 = (float) (CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); + BL3 = (float) (CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); + } + else + { + BL0 = (float) (CM[0] * t2 + CM[1] * t + CM[2]); + BL1 = (float) (CM[4] * t2 + CM[5] * t + CM[6]); + BL2 = (float) (CM[8] * t2 + CM[9] * t + CM[10]); + BL3 = (float) (CM[12] * t2 + CM[13] * t + CM[14]); + } + + Vector3 tVect = BL0 * P0 + BL1 * P1 + BL2 * xVect1 + BL3 * xVect2; + + if (!bTangent) + { + if (tVect.y < 0f) + { + tVect.y = 0f; + } + } + + return tVect; + } + + + private static readonly double[] CM = new double[] { + 2.0, -3.0, 0.0, 1.0, + -2.0, 3.0, 0.0, 0.0, + 1.0, -2.0, 1.0, 0.0, + 1.0, -1.0, 0.0, 0.0 + }; + + + private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; + + + private int NGI(int i, int o) + { + int NGITI = i + o; + // if(bClosed){ + // return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; + // }else{ + return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); + // } + } + #endregion + + + #region "Gizmos" + // private const bool bGizmoDraw = true; + private float GizmoDrawMeters = 1f; + + + void OnDrawGizmosSelected() + { + // if(!bGizmoDraw){ return; } + if (mNodes == null || mNodes.Count < 2) + { + return; + } + if (transform == null) + { + return; + } + float DistanceFromCam = Vector3.SqrMagnitude(Camera.current.transform.position - mNodes[0].transform.position); + + if (DistanceFromCam > 16777216f) + { + return; + } + else if (DistanceFromCam > 4194304f) + { + GizmoDrawMeters = 16f; + } + else if (DistanceFromCam > 1048576f) + { + GizmoDrawMeters = 8f; + } + else if (DistanceFromCam > 262144f) + { + GizmoDrawMeters = 4f; + } + else if (DistanceFromCam > 65536) + { + GizmoDrawMeters = 1f; + } + else if (DistanceFromCam > 16384f) + { + GizmoDrawMeters = 0.5f; + } + else + { + GizmoDrawMeters = 0.1f; + } + + Vector3 prevPos = mNodes[0].pos; + Vector3 tempVect = new Vector3(0f, 0f, 0f); + float step = GizmoDrawMeters / distance; + step = Mathf.Clamp(step, 0f, 1f); + Gizmos.color = new Color(1f, 0f, 0f, 1f); + float index = 0f; + Vector3 cPos; + float tCheck = 0f; + Vector3 camPos = Camera.current.transform.position; + for (index = 0f; index <= 1f; index += step) + { + tCheck += step; + cPos = GetSplineValue(index); + + if (tCheck > 0.1f) + { + DistanceFromCam = Vector3.SqrMagnitude(camPos - cPos); + if (DistanceFromCam > 16777216f) + { + return; + } + else if (DistanceFromCam > 4194304f) + { + GizmoDrawMeters = 16f; + } + else if (DistanceFromCam > 1048576f) + { + GizmoDrawMeters = 10f; + } + else if (DistanceFromCam > 262144f) + { + GizmoDrawMeters = 4f; + } + else if (DistanceFromCam > 65536) + { + GizmoDrawMeters = 1f; + } + else if (DistanceFromCam > 16384f) + { + GizmoDrawMeters = 0.5f; + } + else + { + GizmoDrawMeters = 0.1f; + } + step = GizmoDrawMeters / distance; + step = Mathf.Clamp(step, 0f, 1f); + tCheck = 0f; + } + + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + prevPos = cPos; + if ((index + step) > 1f) + { + cPos = GetSplineValue(1f); + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + } + + } + } + #endregion + + + #region "Intersections" + public bool IsNearIntersection(ref Vector3 tPos, ref float nResult) + { + int mCount = GetNodeCount(); + GSDSplineN tNode; + float MetersToCheck = 75f * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + float tDist; + for (int index = 0; index < mCount; index++) + { + tNode = mNodes[index]; + if (tNode.bIsIntersection) + { + tNode.GSDRI.Height = tNode.pos.y; + + if (bUseSQ) + { + tDist = Vector3.SqrMagnitude(tPos - tNode.pos); + } + // else{ + // tDist = Vector3.Distance(tPos,tNode.pos); + // } + + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_NoTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + } + // else{ + // MetersToCheck = MetersToCheck_NoTurnLane; + // } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_TurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + ; + } + // else{ + // MetersToCheck = MetersToCheck_TurnLane; + // } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_BothTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + ; + } + // else{ + // MetersToCheck = MetersToCheck_BothTurnLane; + // } + } + + MetersToCheck *= 0.8f; + if (tRoad.opt_Lanes == 4) + { + MetersToCheck *= 1.25f; + } + else if (tRoad.opt_Lanes == 6) + { + MetersToCheck *= 1.35f; + } + + if (tDist <= MetersToCheck) + { + nResult = tNode.pos.y; + return true; + } + } + } + nResult = tPos.y; + return false; + } + + + public float IntersectionStrength(ref Vector3 tPos, ref float nResult, ref GSDRoadIntersection tInter, ref bool bIsPast, ref float p, ref GSDSplineN fNode) + { + int mCount = GetNodeCount(); + float tDist; + GSDSplineN tNode; + + float MetersToCheck = 75f * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + + for (int index = 0; index < mCount; index++) + { + tNode = mNodes[index]; + if (tNode.bIsIntersection) + { + tNode.GSDRI.Height = tNode.pos.y; + GSDSplineN xNode; + if (bUseSQ) + { + tDist = Vector3.SqrMagnitude(tPos - tNode.pos); + } + // else{ + // tDist = Vector3.Distance(tPos,tNode.pos); + // } + + if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.NoTurnLane) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_NoTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + ; + } + // else{ + // MetersToCheck = MetersToCheck_NoTurnLane; + // } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.TurnLane) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_TurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + ; + } + // else{ + // MetersToCheck = MetersToCheck_TurnLane; + // } + } + else if (tNode.GSDRI.rType == GSDRoadIntersection.RoadTypeEnum.BothTurnLanes) + { + if (bUseSQ) + { + MetersToCheck = MetersToCheck_BothTurnLaneSQ * ((tRoad.opt_LaneWidth / 5f) * (tRoad.opt_LaneWidth / 5f)); + ; + } + // else{ + // MetersToCheck = MetersToCheck_BothTurnLane; + // } + } + if (tRoad.opt_Lanes == 4) + { + MetersToCheck *= 1.25f; + } + else if (tRoad.opt_Lanes == 6) + { + MetersToCheck *= 1.35f; + } + + if (tDist <= MetersToCheck) + { + if (tNode.GSDRI.bSameSpline) + { + if (tNode.GSDRI.Node1.UID != tNode.UID) + { + xNode = tNode.GSDRI.Node1; + } + else + { + xNode = tNode.GSDRI.Node2; + } + + float P1 = tNode.tTime - p; + if (P1 < 0f) + { P1 *= -1f; } + float P2 = xNode.tTime - p; + if (P2 < 0f) + { P2 *= -1f; } + + if (P1 > P2) + { + if (p > xNode.tTime) + { + bIsPast = true; + } + else + { + bIsPast = false; + } + fNode = xNode; + } + else + { + if (p > tNode.tTime) + { + bIsPast = true; + } + else + { + bIsPast = false; + } + fNode = tNode; + } + } + else + { + if (p > tNode.tTime) + { + bIsPast = true; + } + else + { + bIsPast = false; + } + fNode = tNode; + } + + + if (bUseSQ) + { + tDist = Mathf.Sqrt(tDist); + MetersToCheck = Mathf.Sqrt(MetersToCheck); + } + + tInter = tNode.GSDRI; + nResult = tNode.pos.y + 0.1f; + tDist = 1f - (tDist / MetersToCheck); + tDist = Mathf.Pow(tDist, 3f) * 5f; + if (tDist > 1f) + tDist = 1f; + if (tDist < 0f) + tDist = 0f; + return tDist; + } + } + } + nResult = tPos.y; + return 0f; + } + + + public float IntersectionStrength_Next(Vector3 tPos) + { + float nResult = 0f; + GSDRoadIntersection tInter = null; + bool bIsPast = false; + float p = 0f; + GSDSplineN fNode = null; + return IntersectionStrength(ref tPos, ref nResult, ref tInter, ref bIsPast, ref p, ref fNode); + } + + + public bool IntersectionIsPast(ref float p, ref GSDSplineN oNode) + { + // int mCount = GetNodeCount(); + // bool bIsPast; + // GSDSplineN tNode = null; + // for(int i=0;i P2){ + // if(p > tNode.GSDRI.Node2.tTime){ + // bIsPast = true; + // }else{ + // bIsPast = false; + // } + // }else{ + // if(p > tNode.GSDRI.Node1.tTime){ + // bIsPast = true; + // }else{ + // bIsPast = false; + // } + // } + // return bIsPast; + // } + // } + // return false; + + + if (p < oNode.tTime) + { + return false; + } + else + { + return true; + } + } + + + void DestroyIntersection(GSDSplineN tNode) + { + if (tNode != null) + { + if (tNode.bIsEndPoint) + { + if (tNode.idOnSpline == 1 && tNode.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) + { + Object.DestroyImmediate(tNode.GSDSpline.mNodes[0].transform.gameObject); + tNode.GSDSpline.bSpecialStartControlNode = false; + } + else if (tNode.idOnSpline == tNode.GSDSpline.GetNodeCount() - 2 && tNode.GSDSpline.mNodes[tNode.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) + { + Object.DestroyImmediate(tNode.GSDSpline.mNodes[tNode.GSDSpline.GetNodeCount() - 1].transform.gameObject); + tNode.GSDSpline.bSpecialEndControlNode = false; + } + + } + tNode.bIsIntersection = false; + tNode.bSpecialIntersection = false; + } + if (tNode.Intersection_OtherNode != null) + { + if (tNode.Intersection_OtherNode.bIsEndPoint) + { + if (tNode.Intersection_OtherNode.idOnSpline == 1 && tNode.Intersection_OtherNode.GSDSpline.mNodes[0].bSpecialEndNode_IsStart) + { + Object.DestroyImmediate(tNode.Intersection_OtherNode.GSDSpline.mNodes[0].transform.gameObject); + tNode.Intersection_OtherNode.GSDSpline.bSpecialStartControlNode = false; + } + else if (tNode.Intersection_OtherNode.idOnSpline == tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 2 && tNode.Intersection_OtherNode.GSDSpline.mNodes[tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 1].bSpecialEndNode_IsEnd) + { + Object.DestroyImmediate(tNode.Intersection_OtherNode.GSDSpline.mNodes[tNode.Intersection_OtherNode.GSDSpline.GetNodeCount() - 1].transform.gameObject); + tNode.Intersection_OtherNode.GSDSpline.bSpecialEndControlNode = false; + } + } + tNode.Intersection_OtherNode.bIsIntersection = false; + tNode.Intersection_OtherNode.bSpecialIntersection = false; + } + + if (tNode != null && tNode.Intersection_OtherNode != null) + { + if (tNode.GSDSpline != tNode.Intersection_OtherNode.GSDSpline) + { + if (tNode != null) + { tNode.GSDSpline.tRoad.bUpdateSpline = true; } + if (tNode.Intersection_OtherNode != null) + { tNode.Intersection_OtherNode.GSDSpline.tRoad.bUpdateSpline = true; } + } + else + { + tNode.GSDSpline.tRoad.bUpdateSpline = true; + } + } + else if (tNode != null) + { + tNode.GSDSpline.tRoad.bUpdateSpline = true; + } + } + #endregion + + + #region "Bridges" + public bool IsInBridge(float p) + { + KeyValuePair KVP; + if (BridgeParams == null) + { + return false; + } + int cCount = BridgeParams.Count; + if (cCount < 1) + { + return false; + } + for (int index = 0; index < cCount; index++) + { + KVP = BridgeParams[index]; + if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) + { + return true; + } + if (p > KVP.Key && p < KVP.Value) + { + return true; + } + } + return false; + } + + + public float BridgeUpComing(float p) + { + float tDist = 20f / distance; + float OrigP = p; + p += tDist; + KeyValuePair KVP; + if (BridgeParams == null) + { + return 1f; + } + int cCount = BridgeParams.Count; + if (cCount < 1) + { + return 1f; + } + for (int index = 0; index < cCount; index++) + { + KVP = BridgeParams[index]; + + if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) + { + return ((KVP.Key - OrigP) / tDist); + } + if (p > KVP.Key && p < KVP.Value) + { + return ((KVP.Key - OrigP) / tDist); + } + } + return 1f; + } + + + public bool IsInBridgeTerrain(float p) + { + KeyValuePair KVP; + if (BridgeParams == null) + { + return false; + } + int cCount = BridgeParams.Count; + if (cCount < 1) + { + return false; + } + for (int index = 0; index < cCount; index++) + { + KVP = BridgeParams[index]; + if (GSDRootUtil.IsApproximately(KVP.Key + (10f / distance), p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value - (10f / distance), p, 0.0001f)) + { + return true; + } + if (p > (KVP.Key + (10f / distance)) && p < (KVP.Value - (10f / distance))) + { + return true; + } + } + return false; + } + + + public float GetBridgeEnd(float p) + { + KeyValuePair KVP; + if (BridgeParams == null) + { + return -1f; + } + int cCount = BridgeParams.Count; + if (cCount < 1) + { + return -1f; + } + for (int index = 0; index < cCount; index++) + { + KVP = BridgeParams[index]; + if (p >= KVP.Key && p <= KVP.Value) + { + return KVP.Value; + } + } + return -1f; + } + #endregion + + + #region "Tunnels" + public bool IsInTunnel(float p) + { + KeyValuePair KVP; + if (TunnelParams == null) + { + return false; + } + int cCount = TunnelParams.Count; + if (cCount < 1) + { + return false; + } + for (int index = 0; index < cCount; index++) + { + KVP = TunnelParams[index]; + if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) + { + return true; + } + if (p > KVP.Key && p < KVP.Value) + { + return true; + } + } + return false; + } + + + public float TunnelUpComing(float p) + { + float tDist = 20f / distance; + float OrigP = p; + p += tDist; + KeyValuePair KVP; + if (TunnelParams == null) + { + return 1f; + } + int cCount = TunnelParams.Count; + if (cCount < 1) + { + return 1f; + } + for (int index = 0; index < cCount; index++) + { + KVP = TunnelParams[index]; + + if (GSDRootUtil.IsApproximately(KVP.Key, p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value, p, 0.0001f)) + { + return ((KVP.Key - OrigP) / tDist); + } + if (p > KVP.Key && p < KVP.Value) + { + return ((KVP.Key - OrigP) / tDist); + } + } + return 1f; + } + + + public bool IsInTunnelTerrain(float p) + { + KeyValuePair KVP; + if (TunnelParams == null) + { + return false; + } + int cCount = TunnelParams.Count; + if (cCount < 1) + { + return false; + } + for (int index = 0; index < cCount; index++) + { + KVP = TunnelParams[index]; + if (GSDRootUtil.IsApproximately(KVP.Key + (10f / distance), p, 0.0001f) || GSDRootUtil.IsApproximately(KVP.Value - (10f / distance), p, 0.0001f)) + { + return true; + } + if (p > (KVP.Key + (10f / distance)) && p < (KVP.Value - (10f / distance))) + { + return true; + } + } + return false; + } + + + public float GetTunnelEnd(float p) + { + KeyValuePair KVP; + if (TunnelParams == null) + { + return -1f; + } + int cCount = TunnelParams.Count; + if (cCount < 1) + { + return -1f; + } + for (int index = 0; index < cCount; index++) + { + KVP = TunnelParams[index]; + if (p >= KVP.Key && p <= KVP.Value) + { + return KVP.Value; + } + } + return -1f; + } + #endregion + + +#if UNITY_EDITOR + #region "Road connections" + public void ActivateEndNodeConnection(GSDSplineN tNode1, GSDSplineN tNode2) + { + ActivateEndNodeConnection_Do(tNode1, tNode2); + } + + + private void ActivateEndNodeConnection_Do(GSDSplineN tNode1, GSDSplineN tNode2) + { + GSDSplineC xSpline = tNode2.GSDSpline; + int xCount = xSpline.GetNodeCount(); + int mCount = GetNodeCount(); + //Don't allow connection with less than 3 nodes: + if (mCount < 3 || xCount < 3) + { +#if UNITY_EDITOR + UnityEditor.EditorUtility.DisplayDialog("Cannot connect roads", "Roads must have at least 3 nodes to be connected.", "ok"); +#endif + return; + } + + Vector3 tNode1_ExtraPos = default(Vector3); + Vector3 tNode2_ExtraPos = default(Vector3); + + bool bFirstNode_Start = false; + // bool bFirstNode_End = false; + if (tNode1.idOnSpline == 0) + { + bFirstNode_Start = true; + tNode2_ExtraPos = mNodes[1].transform.position; + } + else + { + // bFirstNode_End = true; + tNode2_ExtraPos = mNodes[mCount - 2].transform.position; + } + + bool bSecondNode_Start = false; + // bool bSecondNode_End = false; + if (tNode2.idOnSpline == 0) + { + bSecondNode_Start = true; + tNode1_ExtraPos = xSpline.mNodes[1].transform.position; + } + else + { + // bSecondNode_End = true; + tNode1_ExtraPos = xSpline.mNodes[xCount - 2].transform.position; + } + + GSDSplineN NodeCreated1 = null; + GSDSplineN NodeCreated2 = null; + + if (bFirstNode_Start) + { + bSpecialStartControlNode = true; + if (mNodes[0].bSpecialEndNode) + { + mNodes[0].transform.position = tNode1_ExtraPos; + mNodes[0].pos = tNode1_ExtraPos; + NodeCreated1 = mNodes[0]; + } + else + { + NodeCreated1 = GSD.Roads.GSDConstruction.InsertNode(tRoad, true, tNode1_ExtraPos, false, 0, true); + } + } + else + { + bSpecialEndControlNode = true; + GSDSplineN zNode1 = xSpline.GetLastNode_All(); + if (zNode1 != null && zNode1.bSpecialEndNode) + { + zNode1.transform.position = tNode1_ExtraPos; + zNode1.pos = tNode1_ExtraPos; + NodeCreated1 = GetLastNode_All(); + } + else + { + NodeCreated1 = GSD.Roads.GSDConstruction.CreateNode(tRoad, true, tNode1_ExtraPos); + } + + } + + if (bSecondNode_Start) + { + xSpline.bSpecialStartControlNode = true; + if (xSpline.mNodes[0].bSpecialEndNode) + { + xSpline.mNodes[0].transform.position = tNode2_ExtraPos; + xSpline.mNodes[0].pos = tNode2_ExtraPos; + NodeCreated2 = xSpline.mNodes[0]; + } + else + { + NodeCreated2 = GSD.Roads.GSDConstruction.InsertNode(xSpline.tRoad, true, tNode2_ExtraPos, false, 0, true); + } + + } + else + { + xSpline.bSpecialEndControlNode = true; + GSDSplineN zNode2 = xSpline.GetLastNode_All(); + if (zNode2 != null && zNode2.bSpecialEndNode) + { + zNode2.transform.position = tNode2_ExtraPos; + zNode2.pos = tNode2_ExtraPos; + NodeCreated2 = xSpline.GetLastNode_All(); + } + else + { + NodeCreated2 = GSD.Roads.GSDConstruction.CreateNode(xSpline.tRoad, true, tNode2_ExtraPos); + } + + } + + NodeCreated1.bSpecialEndNode_IsStart = bFirstNode_Start; + NodeCreated2.bSpecialEndNode_IsStart = bSecondNode_Start; + NodeCreated1.bSpecialEndNode_IsEnd = !bFirstNode_Start; + NodeCreated2.bSpecialEndNode_IsEnd = !bSecondNode_Start; + NodeCreated1.SpecialNodeCounterpart = NodeCreated2; + NodeCreated2.SpecialNodeCounterpart = NodeCreated1; + + float lWidth1 = tNode1.GSDSpline.tRoad.opt_LaneWidth; + float lWidth2 = tNode2.GSDSpline.tRoad.opt_LaneWidth; + float xWidth = Mathf.Max(lWidth1, lWidth2); + + float tDelay = 0f; + if (tNode1.GSDSpline.tRoad.opt_Lanes > tNode2.GSDSpline.tRoad.opt_Lanes) + { + tNode2.bSpecialRoadConnPrimary = true; + NodeCreated2.bSpecialRoadConnPrimary = true; + if (tNode2.GSDSpline.tRoad.opt_Lanes == 4) + { + xWidth *= 2f; + } + tDelay = (tNode1.GSDSpline.tRoad.opt_Lanes - tNode2.GSDSpline.tRoad.opt_Lanes) * xWidth; + if (tDelay < 10f) + { + tDelay = 10f; + } + if (bSecondNode_Start) + { + tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = true; + tNode2.GSDSpline.SpecialEndNodeDelay_Start = tDelay; + tNode2.GSDSpline.SpecialEndNodeDelay_Start_Result = tNode1.GSDSpline.tRoad.RoadWidth(); + tNode2.GSDSpline.SpecialEndNode_Start_OtherSpline = tNode1.GSDSpline; + } + else + { + tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = true; + tNode2.GSDSpline.SpecialEndNodeDelay_End = tDelay; + tNode2.GSDSpline.SpecialEndNodeDelay_End_Result = tNode1.GSDSpline.tRoad.RoadWidth(); + tNode2.GSDSpline.SpecialEndNode_End_OtherSpline = tNode1.GSDSpline; + } + } + else if (tNode2.GSDSpline.tRoad.opt_Lanes > tNode1.GSDSpline.tRoad.opt_Lanes) + { + tNode1.bSpecialRoadConnPrimary = true; + NodeCreated1.bSpecialRoadConnPrimary = true; + if (tNode1.GSDSpline.tRoad.opt_Lanes == 4) + { xWidth *= 2f; } + tDelay = (tNode2.GSDSpline.tRoad.opt_Lanes - tNode1.GSDSpline.tRoad.opt_Lanes) * xWidth; + if (tDelay < 10f) + { + tDelay = 10f; + } + if (bFirstNode_Start) + { + tNode1.GSDSpline.bSpecialEndNode_IsStart_Delay = true; + tNode1.GSDSpline.SpecialEndNodeDelay_Start = tDelay; + tNode1.GSDSpline.SpecialEndNodeDelay_Start_Result = tNode2.GSDSpline.tRoad.RoadWidth(); + tNode1.GSDSpline.SpecialEndNode_Start_OtherSpline = tNode2.GSDSpline; + } + else + { + tNode1.GSDSpline.bSpecialEndNode_IsEnd_Delay = true; + tNode1.GSDSpline.SpecialEndNodeDelay_End = tDelay; + tNode1.GSDSpline.SpecialEndNodeDelay_End_Result = tNode2.GSDSpline.tRoad.RoadWidth(); + tNode1.GSDSpline.SpecialEndNode_End_OtherSpline = tNode2.GSDSpline; + } + } + else + { + tNode1.bSpecialRoadConnPrimary = true; + NodeCreated1.bSpecialRoadConnPrimary = true; + tDelay = 0f; + tNode1.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; + tNode1.GSDSpline.bSpecialEndNode_IsStart_Delay = false; + tNode1.GSDSpline.SpecialEndNodeDelay_End = tDelay; + tNode1.GSDSpline.SpecialEndNodeDelay_End_Result = tNode2.GSDSpline.tRoad.RoadWidth(); + tNode1.GSDSpline.SpecialEndNode_End_OtherSpline = tNode2.GSDSpline; + tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; + tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = false; + tNode2.GSDSpline.SpecialEndNodeDelay_End = tDelay; + tNode2.GSDSpline.SpecialEndNodeDelay_End_Result = tNode1.GSDSpline.tRoad.RoadWidth(); + tNode2.GSDSpline.SpecialEndNode_End_OtherSpline = tNode1.GSDSpline; + } + + tNode1.SpecialNodeCounterpart = NodeCreated1; + tNode2.SpecialNodeCounterpart = NodeCreated2; + NodeCreated1.SpecialNodeCounterpart_Master = tNode1; + NodeCreated2.SpecialNodeCounterpart_Master = tNode2; + + + NodeCreated1.ToggleHideFlags(true); + NodeCreated2.ToggleHideFlags(true); + + GSDSplineN[] OrigNodes = new GSDSplineN[2]; + OrigNodes[0] = tNode1; + OrigNodes[1] = tNode2; + tNode1.OriginalConnectionNodes = OrigNodes; + tNode2.OriginalConnectionNodes = OrigNodes; + + // tNode1.GSDSpline.Setup_Trigger(); + // if(tNode1.GSDSpline != tNode2.GSDSpline){ + // tNode2.GSDSpline.Setup_Trigger(); + // } + + if (tNode1 != null && tNode2 != null) + { + if (tNode1.GSDSpline != tNode2.GSDSpline) + { + tNode1.GSDSpline.tRoad.PiggyBacks = new GSDSplineC[1]; + tNode1.GSDSpline.tRoad.PiggyBacks[0] = tNode2.GSDSpline; + } + tNode1.GSDSpline.tRoad.EditorUpdateMe = true; + } + PreviewSpline.bGizmoDraw = false; + xSpline.PreviewSpline.bGizmoDraw = false; + UnityEditor.SceneView.RepaintAll(); + } + #endregion +#endif + + #region "General Util" + public int GetNodeCount() + { + return mNodes.Count; + } + + + public int GetNodeCountNonNull() + { + int mCount = GetNodeCount(); + int tCount = 0; + for (int index = 0; index < mCount; index++) + { + if (mNodes[index] != null) + { + tCount += 1; + if (mNodes[index].bIsIntersection && mNodes[index].GSDRI == null) + { + DestroyIntersection(mNodes[index]); + } + } + } + return tCount; + } + + + public bool CheckInvalidNodeCount() + { + int mCount = GetNodeCount(); + int tCount = 0; + for (int index = 0; index < mCount; index++) + { + if (mNodes[index] != null) + { + tCount += 1; + if (mNodes[index].bIsIntersection && mNodes[index].GSDRI == null) + { + DestroyIntersection(mNodes[index]); + } + } + else + { + + } + } + if (tCount != mCount) + { + return true; + } + else + { + return false; + } + } + + + public GSDSplineN GetCurrentNode(float p) + { + int mCount = GetNodeCount(); + GSDSplineN tNode = null; + for (int index = 0; index < mCount; index++) + { + tNode = mNodes[index]; + if (tNode.tTime > p) + { + tNode = mNodes[index - 1]; + return tNode; + } + } + return tNode; + } + + + public GSDSplineN GetLastLegitimateNode() + { + int mCount = GetNodeCount(); + GSDSplineN tNode = null; + for (int index = (mCount - 1); index >= 0; index--) + { + tNode = mNodes[index]; + if (tNode.IsLegitimate()) + { + return tNode; + } + } + return null; + } + + + public GSDSplineN GetLastNode_All() + { + int mCount = GetNodeCount(); + int StartIndex = (mCount - 1); + GSDSplineN tNode = null; + + int i = StartIndex; + while (i >= 0) + { + if (i <= (mNodes.Count - 1)) + { + tNode = mNodes[i]; + if (tNode != null) + { + return tNode; + } + } + i -= 1; + } + return null; + } + + + public GSDSplineN GetPrevLegitimateNode(int tIndex) + { + try + { + GSDSplineN tNode = null; + for (int index = (tIndex - 1); index >= 0; index--) + { + tNode = mNodes[index]; + if (tNode.IsLegitimateGrade()) + { + return tNode; + } + } + return null; + } + catch + { + return null; + } + } + + + public GSDSplineN GetNextLegitimateNode(int tIndex) + { + GSDSplineN tNode = null; + int mCount = GetNodeCount(); + for (int index = (tIndex + 1); index < mCount; index++) + { + tNode = mNodes[index]; + if (tNode.IsLegitimateGrade()) + { + return tNode; + } + } + return null; + } + + +#if UNITY_EDITOR + public void ClearAllRoadCuts() + { + int mCount = GetNodeCount(); + for (int index = 0; index < mCount; index++) + { + mNodes[index].ClearCuts(); + } + } +#endif + + + public void ResetNavigationData() + { + id_connected = null; + id_connected = new List(); + } + #endregion + + + //#endif + + + #region "Start" + void Start() + { +#if UNITY_EDITOR + //CachedPoints = null; +#else + this.enabled = false; +#endif + } + #endregion } \ No newline at end of file diff --git a/Spline/GSDSplineF.cs b/Spline/GSDSplineF.cs index 91544c32..25bb6f44 100755 --- a/Spline/GSDSplineF.cs +++ b/Spline/GSDSplineF.cs @@ -1,413 +1,497 @@ -#region "Imports" -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -using GSD; -#endif -#endregion -public class GSDSplineF : MonoBehaviour -{ -#if UNITY_EDITOR - - public class GSDSplineFN - { - public Vector3 pos; - public Quaternion rot; - public Vector3 tangent; - public Vector2 EaseIO; - public float tTime = 0f; - public float OldTime = 0f; - - public string name = "Node-1"; - - public bool tempTime = false; - - public float tempSegmentTime = 0f; - public float tempMinDistance = 5000f; - public float tempMinTime = 0f; - - public int idOnSpline; - public GSDSplineC GSDSpline; - public bool bDestroyed = false; - public bool bPreviewNode = false; - - - - public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) - { - pos = _p; - rot = _q; - EaseIO = _io; - tTime = _tTime; - name = _name; - } - } - - public int tCount = 0; - public List mNodes = new List(); - public bool bClosed = false; - public float distance = -1f; - public Vector3 MousePos = new Vector3(0f, 0f, 0f); - public GSDSplineC GSDSpline; - - #region "Gizmos" - public bool bGizmoDraw = false; - private float GizmoDrawMeters = 1f; - void OnDrawGizmos() - { - if (!bGizmoDraw) { return; } - if (mNodes == null || mNodes.Count < 2) { return; } - //Debug.Log ("lawl2"); - mNodes[mNodes.Count - 1].pos = MousePos; - //Debug.Log ("lawl23"); - //Setup_SplineLength(); - - float DistanceFromCam = Vector3.Distance(Camera.current.transform.position, mNodes[0].pos); - - if (DistanceFromCam > 2048) - { - return; - } - else if (DistanceFromCam > 1024) - { - GizmoDrawMeters = 32f; - } - else if (DistanceFromCam > 512) - { - GizmoDrawMeters = 16f; - } - else if (DistanceFromCam > 256) - { - GizmoDrawMeters = 8f; - } - else if (DistanceFromCam > 128) - { - GizmoDrawMeters = 2f; - } - else if (DistanceFromCam > 64) - { - GizmoDrawMeters = 0.5f; - } - else - { - GizmoDrawMeters = 0.1f; - } - - Vector3 prevPos = mNodes[0].pos; - Vector3 tempVect = new Vector3(0f, 0f, 0f); - //GizmoDrawMeters = 40f; - float step = GizmoDrawMeters / distance; - step = Mathf.Clamp(step, 0f, 1f); - Gizmos.color = new Color(0f, 0f, 1f, 1f); - float i = 0f; - Vector3 cPos; - - float startI = 0f; - if (mNodes.Count > 4) - { - startI = mNodes[mNodes.Count - 4].tTime; - } - - prevPos = GetSplineValue(startI); - for (i = startI; i <= 1f; i += step) - { - cPos = GetSplineValue(i); - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - prevPos = cPos; - if ((i + step) > 1f) - { - cPos = GetSplineValue(1f); - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - } - } - } - #endregion - - #region "Setup" - public void Setup(ref Vector3[] tVects) - { - //Create spline nodes: - Setup_Nodes(ref tVects); - - //Setup spline length, if more than 1 node: - if (GetNodeCount() > 1) - { - Setup_SplineLength(); - } - - tCount = mNodes.Count; - } - - private void Setup_Nodes(ref Vector3[] tVects) - { - //Process nodes: - int i = 0; - if (mNodes != null) { mNodes.Clear(); mNodes = null; } - mNodes = new List(); - GSDSplineFN tNode; - for (i = 0; i < tVects.Length; i++) - { - tNode = new GSDSplineFN(); - tNode.pos = tVects[i]; - mNodes.Add(tNode); - } - - float step; - Quaternion rot; - step = (bClosed) ? 1f / mNodes.Count : 1f / (mNodes.Count - 1); - for (i = 0; i < mNodes.Count; i++) - { - tNode = mNodes[i]; - - rot = Quaternion.identity; - if (i != mNodes.Count - 1) - { - if (mNodes[i + 1].pos - tNode.pos == Vector3.zero) - { - rot = Quaternion.identity; - } - else - { - rot = Quaternion.LookRotation(mNodes[i + 1].pos - tNode.pos, transform.up); - } - - //rot = Quaternion.LookRotation(mNodes[i+1].pos - tNode.pos, transform.up); - } - else if (bClosed) - { - rot = Quaternion.LookRotation(mNodes[0].pos - tNode.pos, transform.up); - } - else - { - rot = Quaternion.identity; - } - - tNode.Setup(tNode.pos, rot, new Vector2(0, 1), step * i, "pNode"); - } - tNode = null; - tVects = null; - } - - private void Setup_SplineLength() - { - //First lets get the general distance, node to node: - mNodes[0].tTime = 0f; - mNodes[mNodes.Count - 1].tTime = 1f; - Vector3 tVect1 = new Vector3(0f, 0f, 0f); - Vector3 tVect2 = new Vector3(0f, 0f, 0f); - float mDistance = 0f; - float mDistance_NoMod = 0f; - for (int j = 0; j < mNodes.Count; j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - mDistance += Vector3.Distance(tVect1, tVect2); - } - tVect1 = tVect2; - } - mDistance_NoMod = mDistance; - mDistance = mDistance * 1.05f; - // float step = 0.1f / mDistance; - - //Get a slightly more accurate portrayal of the time: - float tTime = 0f; - for (int j = 0; j < (mNodes.Count - 1); j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); - mNodes[j].tTime = tTime; - } - tVect1 = tVect2; - } - distance = mDistance_NoMod; - } - #endregion - - #region "Hermite math" - /// - /// Gets the spline value. - /// - /// - /// The relevant param (0-1) of the spline. - /// - /// - /// True for is tangent, false (default) for vector3 position. - /// - public Vector3 GetSplineValue(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - for (i = 1; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime >= f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - public Vector3 GetSplineValue_SkipOpt(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - for (i = 1; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime >= f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) - { - double t2, t3; - float BL0, BL1, BL2, BL3, tension; - - if (!bTangent) - { - t2 = t * t; - t3 = t2 * t; - } - else - { - t2 = t * t; - t = t * 2.0; - t2 = t2 * 3.0; - t3 = 0; //Necessary for compiler error. - } - - //Vectors: - Vector3 P0 = mNodes[NGI(i, NI[0])].pos; - Vector3 P1 = mNodes[NGI(i, NI[1])].pos; - Vector3 P2 = mNodes[NGI(i, NI[2])].pos; - Vector3 P3 = mNodes[NGI(i, NI[3])].pos; - - //Tension: - tension = 0.5f; // 0.5 equivale a catmull-rom - - //Tangents: - P2 = (P1 - P2) * tension; - P3 = (P3 - P0) * tension; - - if (!bTangent) - { - BL0 = (float)(CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); - BL1 = (float)(CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); - BL2 = (float)(CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); - BL3 = (float)(CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); - } - else - { - BL0 = (float)(CM[0] * t2 + CM[1] * t + CM[2]); - BL1 = (float)(CM[4] * t2 + CM[5] * t + CM[6]); - BL2 = (float)(CM[8] * t2 + CM[9] * t + CM[10]); - BL3 = (float)(CM[12] * t2 + CM[13] * t + CM[14]); - } - - return BL0 * P0 + BL1 * P1 + BL2 * P2 + BL3 * P3; - } - - private static readonly double[] CM = new double[] { - 2.0, -3.0, 0.0, 1.0, - -2.0, 3.0, 0.0, 0.0, - 1.0, -2.0, 1.0, 0.0, - 1.0, -1.0, 0.0, 0.0 - }; - private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; - - private int NGI(int i, int o) - { - int NGITI = i + o; - if (bClosed) - { - return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; - } - else - { - return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); - } - } - #endregion - - public int GetNodeCount() - { - return mNodes.Count; - } - -#endif - - #region "Start" - void Start() - { -#if UNITY_EDITOR - //Do nothing. -#else - this.enabled = false; -#endif - } - #endregion +#region "Imports" +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +using GSD; +#endif +#endregion + + +public class GSDSplineF : MonoBehaviour +{ +#if UNITY_EDITOR + + public class GSDSplineFN + { + public Vector3 pos; + public Quaternion rot; + public Vector3 tangent; + public Vector2 EaseIO; + public float tTime = 0f; + public float OldTime = 0f; + + public string name = "Node-1"; + + public bool tempTime = false; + + public float tempSegmentTime = 0f; + public float tempMinDistance = 5000f; + public float tempMinTime = 0f; + + public int idOnSpline; + public GSDSplineC GSDSpline; + public bool bDestroyed = false; + public bool bPreviewNode = false; + + + + public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) + { + pos = _p; + rot = _q; + EaseIO = _io; + tTime = _tTime; + name = _name; + } + } + + + public int tCount = 0; + public List mNodes = new List(); + public bool bClosed = false; + public float distance = -1f; + public Vector3 MousePos = new Vector3(0f, 0f, 0f); + public GSDSplineC GSDSpline; + + + #region "Gizmos" + public bool bGizmoDraw = false; + private float GizmoDrawMeters = 1f; + + + void OnDrawGizmos() + { + if (!bGizmoDraw) + { + return; + } + if (mNodes == null || mNodes.Count < 2) + { + return; + } + + //Debug.Log ("lawl2"); + mNodes[mNodes.Count - 1].pos = MousePos; + //Debug.Log ("lawl23"); + //Setup_SplineLength(); + + float DistanceFromCam = Vector3.Distance(Camera.current.transform.position, mNodes[0].pos); + + if (DistanceFromCam > 2048) + { + return; + } + else if (DistanceFromCam > 1024) + { + GizmoDrawMeters = 32f; + } + else if (DistanceFromCam > 512) + { + GizmoDrawMeters = 16f; + } + else if (DistanceFromCam > 256) + { + GizmoDrawMeters = 8f; + } + else if (DistanceFromCam > 128) + { + GizmoDrawMeters = 2f; + } + else if (DistanceFromCam > 64) + { + GizmoDrawMeters = 0.5f; + } + else + { + GizmoDrawMeters = 0.1f; + } + + + Vector3 prevPos = mNodes[0].pos; + Vector3 tempVect = new Vector3(0f, 0f, 0f); + //GizmoDrawMeters = 40f; + float step = GizmoDrawMeters / distance; + step = Mathf.Clamp(step, 0f, 1f); + Gizmos.color = new Color(0f, 0f, 1f, 1f); + float index = 0f; + Vector3 cPos; + + float startI = 0f; + if (mNodes.Count > 4) + { + startI = mNodes[mNodes.Count - 4].tTime; + } + + prevPos = GetSplineValue(startI); + for (index = startI; index <= 1f; index += step) + { + cPos = GetSplineValue(index); + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + prevPos = cPos; + if ((index + step) > 1f) + { + cPos = GetSplineValue(1f); + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + } + } + } + #endregion + + + #region "Setup" + public void Setup(ref Vector3[] tVects) + { + //Create spline nodes: + Setup_Nodes(ref tVects); + + //Setup spline length, if more than 1 node: + if (GetNodeCount() > 1) + { + Setup_SplineLength(); + } + + tCount = mNodes.Count; + } + + + private void Setup_Nodes(ref Vector3[] tVects) + { + //Process nodes: + int index = 0; + if (mNodes != null) + { + mNodes.Clear(); + mNodes = null; + } + + mNodes = new List(); + GSDSplineFN tNode; + for (index = 0; index < tVects.Length; index++) + { + tNode = new GSDSplineFN(); + tNode.pos = tVects[index]; + mNodes.Add(tNode); + } + + float step; + Quaternion rot; + step = (bClosed) ? 1f / mNodes.Count : 1f / (mNodes.Count - 1); + for (index = 0; index < mNodes.Count; index++) + { + tNode = mNodes[index]; + + rot = Quaternion.identity; + if (index != mNodes.Count - 1) + { + if (mNodes[index + 1].pos - tNode.pos == Vector3.zero) + { + rot = Quaternion.identity; + } + else + { + rot = Quaternion.LookRotation(mNodes[index + 1].pos - tNode.pos, transform.up); + } + + //rot = Quaternion.LookRotation(mNodes[i+1].pos - tNode.pos, transform.up); + } + else if (bClosed) + { + rot = Quaternion.LookRotation(mNodes[0].pos - tNode.pos, transform.up); + } + else + { + rot = Quaternion.identity; + } + + tNode.Setup(tNode.pos, rot, new Vector2(0, 1), step * index, "pNode"); + } + tNode = null; + tVects = null; + } + + + /// + /// I think this is the general Length of the Spline? + /// + private void Setup_SplineLength() + { + //First lets get the general distance, node to node: + mNodes[0].tTime = 0f; + mNodes[mNodes.Count - 1].tTime = 1f; + Vector3 tVect1 = new Vector3(0f, 0f, 0f); + Vector3 tVect2 = new Vector3(0f, 0f, 0f); + float mDistance = 0f; + float mDistance_NoMod = 0f; + for (int j = 0; j < mNodes.Count; j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + mDistance += Vector3.Distance(tVect1, tVect2); + } + tVect1 = tVect2; + } + mDistance_NoMod = mDistance; + mDistance = mDistance * 1.05f; + // float step = 0.1f / mDistance; + + //Get a slightly more accurate portrayal of the time: + float tTime = 0f; + for (int j = 0; j < (mNodes.Count - 1); j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); + mNodes[j].tTime = tTime; + } + tVect1 = tVect2; + } + distance = mDistance_NoMod; + } + #endregion + + + #region "Hermite math" + /// + /// Gets the spline value. + /// + /// + /// The relevant param (0-1) of the spline. + /// + /// + /// True for is tangent, false (default) for vector3 position. + /// + public Vector3 GetSplineValue(float _value, bool _isTangent = false) // FH 03.02.19 // f is now _value // b is now_isTangent + { + int index; + int idx = -1; + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + + /* + if (GSDRootUtil.IsApproximately(_value, 0f, 0.00001f)) + { + if (_isTangent) + { + return mNodes[0].tangent; + } + else + { + return mNodes[0].pos; + } + } + else + if (GSDRootUtil.IsApproximately(_value, 1f, 0.00001f) || f > 1f) + { + if (_isTangent) + { + return mNodes[mNodes.Count - 1].tangent; + } + else + { + return mNodes[mNodes.Count - 1].pos; + } + } + else + { + */ + + + for (index = 1; index < mNodes.Count; index++) + { + if (index == mNodes.Count - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime >= _value) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + // } + + float param = (_value - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, _isTangent); + } + + + public Vector3 GetSplineValue_SkipOpt(float f, bool b = false) + { + int i; + int idx = -1; + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + + /* + if (GSDRootUtil.IsApproximately(f, 0f, 0.00001f)) + { + if (b) + { + return mNodes[0].tangent; + } + else + { + return mNodes[0].pos; + } + } + else + if (GSDRootUtil.IsApproximately(f, 1f, 0.00001f) || f > 1f) + { + if (b) + { + return mNodes[mNodes.Count - 1].tangent; + } + else + { + return mNodes[mNodes.Count - 1].pos; + } + } + else + { + */ + + + for (i = 1; i < mNodes.Count; i++) + { + if (i == mNodes.Count - 1) + { + idx = i - 1; + break; + } + if (mNodes[i].tTime >= f) + { + idx = i - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + // } + + float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, b); + } + + + private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) + { + double t2, t3; + float BL0, BL1, BL2, BL3, tension; + + if (!bTangent) + { + t2 = t * t; + t3 = t2 * t; + } + else + { + t2 = t * t; + t = t * 2.0; + t2 = t2 * 3.0; + t3 = 0; //Necessary for compiler error. + } + + //Vectors: + Vector3 P0 = mNodes[NGI(i, NI[0])].pos; + Vector3 P1 = mNodes[NGI(i, NI[1])].pos; + Vector3 P2 = mNodes[NGI(i, NI[2])].pos; + Vector3 P3 = mNodes[NGI(i, NI[3])].pos; + + //Tension: + tension = 0.5f; // 0.5 equivale a catmull-rom + + //Tangents: + P2 = (P1 - P2) * tension; + P3 = (P3 - P0) * tension; + + if (!bTangent) + { + BL0 = (float) (CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); + BL1 = (float) (CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); + BL2 = (float) (CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); + BL3 = (float) (CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); + } + else + { + BL0 = (float) (CM[0] * t2 + CM[1] * t + CM[2]); + BL1 = (float) (CM[4] * t2 + CM[5] * t + CM[6]); + BL2 = (float) (CM[8] * t2 + CM[9] * t + CM[10]); + BL3 = (float) (CM[12] * t2 + CM[13] * t + CM[14]); + } + + return BL0 * P0 + BL1 * P1 + BL2 * P2 + BL3 * P3; + } + + + private static readonly double[] CM = new double[] { + 2.0, -3.0, 0.0, 1.0, + -2.0, 3.0, 0.0, 0.0, + 1.0, -2.0, 1.0, 0.0, + 1.0, -1.0, 0.0, 0.0 + }; + + + private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; + + + private int NGI(int i, int o) + { + int NGITI = i + o; + if (bClosed) + { + return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; + } + else + { + return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); + } + } + #endregion + + + public int GetNodeCount() + { + return mNodes.Count; + } + + +#endif + + #region "Start" + void Start() + { +#if UNITY_EDITOR + //Do nothing. +#else + this.enabled = false; +#endif + } + #endregion } \ No newline at end of file diff --git a/Spline/GSDSplineI.cs b/Spline/GSDSplineI.cs index d4a847a7..8347ea6d 100755 --- a/Spline/GSDSplineI.cs +++ b/Spline/GSDSplineI.cs @@ -1,436 +1,503 @@ -#region "Imports" -using UnityEngine; -#if UNITY_EDITOR -using System.Collections.Generic; -using GSD; -#endif -#endregion -public class GSDSplineI : MonoBehaviour -{ -#if UNITY_EDITOR - public class GSDSplineIN - { - public Vector3 pos; - public Quaternion rot; - public Vector3 tangent; - public Vector2 EaseIO; - public float tTime = 0f; - public float OldTime = 0f; - - public string name = "Node-1"; - - public bool tempTime = false; - - public float tempSegmentTime = 0f; - public float tempMinDistance = 5000f; - public float tempMinTime = 0f; - - public int idOnSpline; - public GSDSplineC GSDSpline; - public bool bDestroyed = false; - public bool bPreviewNode = false; - - public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) - { - pos = _p; - rot = _q; - EaseIO = _io; - tTime = _tTime; - name = _name; - } - } - - public int tCount = 0; - public List mNodes = new List(); - public bool bClosed = false; - public float distance = -1f; - public Vector3 MousePos = new Vector3(0f, 0f, 0f); - public GSDSplineC GSDSpline; - public GSDSplineIN ActionNode; - - public void DetermineInsertNodes() - { - int iCount = GSDSpline.mNodes.Count; - if (iCount < 2) { return; } - GSDSplineIN tNode; - GSDSplineN xNode; - mNodes.Clear(); - float tParam = GSDSpline.GetClosestParam(MousePos, false, true); - bool bEndInsert = false; - bool bZeroInsert = false; - int iStart = 0; - if (Mathf.Approximately(tParam, 0f)) - { - bZeroInsert = true; - iStart = 0; - } - else if (Mathf.Approximately(tParam, 1f)) - { - bEndInsert = true; - } - - for (int i = 0; i < iCount; i++) - { - xNode = GSDSpline.mNodes[i]; - tNode = new GSDSplineIN(); - tNode.pos = xNode.pos; - tNode.idOnSpline = xNode.idOnSpline; - tNode.tTime = xNode.tTime; - if (!bZeroInsert && !bEndInsert) - { - if (tParam > tNode.tTime) - { - iStart = tNode.idOnSpline + 1; - } - } - mNodes.Add(tNode); - } - - mNodes.Sort(CompareListByName); - int cCount = mNodes.Count; - if (bEndInsert) - { - iStart = cCount; - } - else - { - for (int i = iStart; i < cCount; i++) - { - mNodes[i].idOnSpline += 1; - } - } - tNode = new GSDSplineIN(); - tNode.pos = MousePos; - tNode.idOnSpline = iStart; - tNode.tTime = tParam; - tNode.bPreviewNode = true; - if (bEndInsert) - { - mNodes.Add(tNode); - } - else - { - mNodes.Insert(iStart, tNode); - } - Setup_SplineLength(); - ActionNode = tNode; - } - - private int CompareListByName(GSDSplineIN i1, GSDSplineIN i2) - { - return i1.idOnSpline.CompareTo(i2.idOnSpline); - } - - public void UpdateActionNode() - { - if (ActionNode != null) - { - ActionNode.pos = MousePos; - } - DetermineInsertNodes(); - } - - #region "Gizmos" - public bool bGizmoDraw = false; - private float GizmoDrawMeters = 1f; - void OnDrawGizmos() - { - if (!bGizmoDraw) { return; } - if (ActionNode == null) { return; } - if (mNodes == null || mNodes.Count < 2) { return; } - //Debug.Log ("lawl2"); - //mNodes[mNodes.Count-1].pos = MousePos; - //Debug.Log ("lawl23"); - //Setup_SplineLength(); - - float DistanceFromCam = Vector3.Distance(Camera.current.transform.position, mNodes[0].pos); - - if (DistanceFromCam > 2048) - { - return; - } - else if (DistanceFromCam > 1024) - { - GizmoDrawMeters = 32f; - } - else if (DistanceFromCam > 512) - { - GizmoDrawMeters = 16f; - } - else if (DistanceFromCam > 256) - { - GizmoDrawMeters = 8f; - } - else if (DistanceFromCam > 128) - { - GizmoDrawMeters = 2f; - } - else if (DistanceFromCam > 64) - { - GizmoDrawMeters = 0.5f; - } - else - { - GizmoDrawMeters = 0.1f; - } - GizmoDrawMeters = 0.1f; - - Vector3 prevPos = mNodes[0].pos; - Vector3 tempVect = new Vector3(0f, 0f, 0f); - //GizmoDrawMeters = 40f; - float step = GizmoDrawMeters / distance; - step = Mathf.Clamp(step, 0f, 1f); - Gizmos.color = new Color(0f, 0f, 1f, 1f); - float i = 0f; - Vector3 cPos; - - float startI = 0f; - float endI = 1f; - if (ActionNode.idOnSpline > 3) - { - startI = mNodes[ActionNode.idOnSpline - 2].tTime; - } - if (ActionNode.idOnSpline < (mNodes.Count - 3)) - { - endI = mNodes[ActionNode.idOnSpline + 2].tTime; - } - - prevPos = GetSplineValue(startI); - for (i = startI; i <= endI; i += step) - { - cPos = GetSplineValue(i); - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - prevPos = cPos; - if ((i + step) > 1f) - { - cPos = GetSplineValue(1f); - Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); - } - } - } - #endregion - - #region "Setup" - private void Setup_SplineLength() - { - //First lets get the general distance, node to node: - mNodes[0].tTime = 0f; - mNodes[mNodes.Count - 1].tTime = 1f; - Vector3 tVect1 = new Vector3(0f, 0f, 0f); - Vector3 tVect2 = new Vector3(0f, 0f, 0f); - float mDistance = 0f; - float mDistance_NoMod = 0f; - for (int j = 0; j < mNodes.Count; j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - mDistance += Vector3.Distance(tVect1, tVect2); - } - tVect1 = tVect2; - } - mDistance_NoMod = mDistance; - mDistance = mDistance * 1.05f; - // float step = 0.1f / mDistance; - - //Get a slightly more accurate portrayal of the time: - float tTime = 0f; - for (int j = 0; j < (mNodes.Count - 1); j++) - { - tVect2 = mNodes[j].pos; - if (j > 0) - { - tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); - mNodes[j].tTime = tTime; - } - tVect1 = tVect2; - } - distance = mDistance_NoMod; - } - #endregion - - #region "Hermite math" - /// - /// Gets the spline value. - /// - /// - /// The relevant param (0-1) of the spline. - /// - /// - /// True for is tangent, false (default) for vector3 position. - /// - public Vector3 GetSplineValue(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - for (i = 1; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime >= f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - public Vector3 GetSplineValue_SkipOpt(float f, bool b = false) - { - int i; - int idx = -1; - - if (mNodes.Count == 0) { return default(Vector3); } - if (mNodes.Count == 1) { return mNodes[0].pos; } - - // if(GSDRootUtil.IsApproximately(f,0f,0.00001f)){ - // if(b){ - // return mNodes[0].tangent; - // }else{ - // return mNodes[0].pos; - // } - // }else - // if(GSDRootUtil.IsApproximately(f,1f,0.00001f) || f > 1f){ - // if(b){ - // return mNodes[mNodes.Count-1].tangent; - // }else{ - // return mNodes[mNodes.Count-1].pos; - // } - // }else{ - for (i = 1; i < mNodes.Count; i++) - { - if (i == mNodes.Count - 1) - { - idx = i - 1; - break; - } - if (mNodes[i].tTime >= f) - { - idx = i - 1; - break; - } - } - if (idx < 0) { idx = 0; } - // } - - float param = (f - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); - param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); - return GetHermiteInternal(idx, param, b); - } - - private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) - { - double t2, t3; - float BL0, BL1, BL2, BL3, tension; - - if (!bTangent) - { - t2 = t * t; - t3 = t2 * t; - } - else - { - t2 = t * t; - t = t * 2.0; - t2 = t2 * 3.0; - t3 = 0; //Necessary for compiler error. - } - - //Vectors: - Vector3 P0 = mNodes[NGI(i, NI[0])].pos; - Vector3 P1 = mNodes[NGI(i, NI[1])].pos; - Vector3 P2 = mNodes[NGI(i, NI[2])].pos; - Vector3 P3 = mNodes[NGI(i, NI[3])].pos; - - //Tension: - tension = 0.5f; // 0.5 equivale a catmull-rom - - //Tangents: - P2 = (P1 - P2) * tension; - P3 = (P3 - P0) * tension; - - if (!bTangent) - { - BL0 = (float)(CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); - BL1 = (float)(CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); - BL2 = (float)(CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); - BL3 = (float)(CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); - } - else - { - BL0 = (float)(CM[0] * t2 + CM[1] * t + CM[2]); - BL1 = (float)(CM[4] * t2 + CM[5] * t + CM[6]); - BL2 = (float)(CM[8] * t2 + CM[9] * t + CM[10]); - BL3 = (float)(CM[12] * t2 + CM[13] * t + CM[14]); - } - - return BL0 * P0 + BL1 * P1 + BL2 * P2 + BL3 * P3; - } - - private static readonly double[] CM = new double[] { - 2.0, -3.0, 0.0, 1.0, - -2.0, 3.0, 0.0, 0.0, - 1.0, -2.0, 1.0, 0.0, - 1.0, -1.0, 0.0, 0.0 - }; - private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; - - private int NGI(int i, int o) - { - int NGITI = i + o; - if (bClosed) - { - return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; - } - else - { - return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); - } - } - #endregion - - public int GetNodeCount() - { - return mNodes.Count; - } - -#endif - - #region "Start" - void Start() - { -#if UNITY_EDITOR - //Do nothing. -#else - this.enabled = false; -#endif - } - #endregion +#region "Imports" +using UnityEngine; +#if UNITY_EDITOR +using System.Collections.Generic; +using GSD; +#endif +#endregion + + +public class GSDSplineI : MonoBehaviour +{ +#if UNITY_EDITOR + public class GSDSplineIN + { + public Vector3 pos; + public Quaternion rot; + public Vector3 tangent; + public Vector2 EaseIO; + public float tTime = 0f; + public float OldTime = 0f; + + public string name = "Node-1"; + + public bool tempTime = false; + + public float tempSegmentTime = 0f; + public float tempMinDistance = 5000f; + public float tempMinTime = 0f; + + public int idOnSpline; + public GSDSplineC GSDSpline; + public bool bDestroyed = false; + public bool bPreviewNode = false; + + + public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) + { + pos = _p; + rot = _q; + EaseIO = _io; + tTime = _tTime; + name = _name; + } + } + + + public int tCount = 0; + public List mNodes = new List(); + public bool bClosed = false; + public float distance = -1f; + public Vector3 MousePos = new Vector3(0f, 0f, 0f); + public GSDSplineC GSDSpline; + public GSDSplineIN ActionNode; + + + public void DetermineInsertNodes() + { + int iCount = GSDSpline.mNodes.Count; + if (iCount < 2) + { + return; + } + GSDSplineIN tNode; + GSDSplineN xNode; + mNodes.Clear(); + float tParam = GSDSpline.GetClosestParam(MousePos, false, true); + bool bEndInsert = false; + bool bZeroInsert = false; + int iStart = 0; + if (Mathf.Approximately(tParam, 0f)) + { + bZeroInsert = true; + iStart = 0; + } + else if (Mathf.Approximately(tParam, 1f)) + { + bEndInsert = true; + } + + for (int index = 0; index < iCount; index++) + { + xNode = GSDSpline.mNodes[index]; + tNode = new GSDSplineIN(); + tNode.pos = xNode.pos; + tNode.idOnSpline = xNode.idOnSpline; + tNode.tTime = xNode.tTime; + if (!bZeroInsert && !bEndInsert) + { + if (tParam > tNode.tTime) + { + iStart = tNode.idOnSpline + 1; + } + } + mNodes.Add(tNode); + } + + mNodes.Sort(CompareListByName); + int cCount = mNodes.Count; + if (bEndInsert) + { + iStart = cCount; + } + else + { + for (int index = iStart; index < cCount; index++) + { + mNodes[index].idOnSpline += 1; + } + } + tNode = new GSDSplineIN(); + tNode.pos = MousePos; + tNode.idOnSpline = iStart; + tNode.tTime = tParam; + tNode.bPreviewNode = true; + if (bEndInsert) + { + mNodes.Add(tNode); + } + else + { + mNodes.Insert(iStart, tNode); + } + Setup_SplineLength(); + ActionNode = tNode; + } + + + private int CompareListByName(GSDSplineIN i1, GSDSplineIN i2) + { + return i1.idOnSpline.CompareTo(i2.idOnSpline); + } + + + public void UpdateActionNode() + { + if (ActionNode != null) + { + ActionNode.pos = MousePos; + } + DetermineInsertNodes(); + } + + + #region "Gizmos" + public bool bGizmoDraw = false; + private float GizmoDrawMeters = 1f; + + + void OnDrawGizmos() + { + if (!bGizmoDraw) + { + return; + } + if (ActionNode == null) + { + return; + } + if (mNodes == null || mNodes.Count < 2) + { + return; + } + //Debug.Log ("lawl2"); + //mNodes[mNodes.Count-1].pos = MousePos; + //Debug.Log ("lawl23"); + //Setup_SplineLength(); + + float DistanceFromCam = Vector3.Distance(Camera.current.transform.position, mNodes[0].pos); + + if (DistanceFromCam > 2048) + { + return; + } + else if (DistanceFromCam > 1024) + { + GizmoDrawMeters = 32f; + } + else if (DistanceFromCam > 512) + { + GizmoDrawMeters = 16f; + } + else if (DistanceFromCam > 256) + { + GizmoDrawMeters = 8f; + } + else if (DistanceFromCam > 128) + { + GizmoDrawMeters = 2f; + } + else if (DistanceFromCam > 64) + { + GizmoDrawMeters = 0.5f; + } + else + { + GizmoDrawMeters = 0.1f; + } + GizmoDrawMeters = 0.1f; + + Vector3 prevPos = mNodes[0].pos; + Vector3 tempVect = new Vector3(0f, 0f, 0f); + //GizmoDrawMeters = 40f; + float step = GizmoDrawMeters / distance; + step = Mathf.Clamp(step, 0f, 1f); + Gizmos.color = new Color(0f, 0f, 1f, 1f); + float i = 0f; + Vector3 cPos; + + float startI = 0f; + float endI = 1f; + if (ActionNode.idOnSpline > 3) + { + startI = mNodes[ActionNode.idOnSpline - 2].tTime; + } + if (ActionNode.idOnSpline < (mNodes.Count - 3)) + { + endI = mNodes[ActionNode.idOnSpline + 2].tTime; + } + + prevPos = GetSplineValue(startI); + for (i = startI; i <= endI; i += step) + { + cPos = GetSplineValue(i); + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + prevPos = cPos; + if ((i + step) > 1f) + { + cPos = GetSplineValue(1f); + Gizmos.DrawLine(prevPos + tempVect, cPos + tempVect); + } + } + } + #endregion + + + #region "Setup" + private void Setup_SplineLength() + { + //First lets get the general distance, node to node: + mNodes[0].tTime = 0f; + mNodes[mNodes.Count - 1].tTime = 1f; + Vector3 tVect1 = new Vector3(0f, 0f, 0f); + Vector3 tVect2 = new Vector3(0f, 0f, 0f); + float mDistance = 0f; + float mDistance_NoMod = 0f; + for (int j = 0; j < mNodes.Count; j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + mDistance += Vector3.Distance(tVect1, tVect2); + } + tVect1 = tVect2; + } + mDistance_NoMod = mDistance; + mDistance = mDistance * 1.05f; + // float step = 0.1f / mDistance; + + //Get a slightly more accurate portrayal of the time: + float tTime = 0f; + for (int j = 0; j < (mNodes.Count - 1); j++) + { + tVect2 = mNodes[j].pos; + if (j > 0) + { + tTime += (Vector3.Distance(tVect1, tVect2) / mDistance_NoMod); + mNodes[j].tTime = tTime; + } + tVect1 = tVect2; + } + distance = mDistance_NoMod; + } + #endregion + + + #region "Hermite math" + /// + /// Gets the spline value. + /// + /// + /// The relevant param (0-1) of the spline. + /// + /// + /// True for is tangent, false (default) for vector3 position. + /// + public Vector3 GetSplineValue(float _value, bool _isTangent = false) // FH 03.02.19 // formerly varNames: f = _value; b = _isTangent + { + int index; + int idx = -1; + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + + // FH 03.02.19 // Do note, that someone outcommented stuff here, for whatever Reason, but why? + /* + if (GSDRootUtil.IsApproximately(_value, 0f, 0.00001f)) + { + if (_isTangent) + { + return mNodes[0].tangent; + } + else + { + return mNodes[0].pos; + } + } + else + if (GSDRootUtil.IsApproximately(_value, 1f, 0.00001f) || _value > 1f) + { + if (_isTangent) + { + return mNodes[mNodes.Count - 1].tangent; + } + else + { + return mNodes[mNodes.Count - 1].pos; + } + } + else + { + */ + // FH 03.02.19 // Do note, that someone outcommented stuff here, for whatever Reason, but why? + + + for (index = 1; index < mNodes.Count; index++) + { + if (index == mNodes.Count - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime >= _value) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + //} // FH 03.02.19 // Do note, that someone outcommented stuff here, for whatever Reason, but why? + + float param = (_value - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, _isTangent); +} + + +public Vector3 GetSplineValue_SkipOpt(float _value, bool _isTangent = false) // FH 03.02.19 // former VarNames: f = _value; b = _isTangent +{ + int index; + int idx = -1; + + if (mNodes.Count == 0) + { + return default(Vector3); + } + if (mNodes.Count == 1) + { + return mNodes[0].pos; + } + + // if(GSDRootUtil.IsApproximately(_value,0f,0.00001f)){ + // if(_isTangent){ + // return mNodes[0].tangent; + // }else{ + // return mNodes[0].pos; + // } + // }else + // if(GSDRootUtil.IsApproximately(_value,1f,0.00001f) || _value > 1f){ + // if(_isTangent){ + // return mNodes[mNodes.Count-1].tangent; + // }else{ + // return mNodes[mNodes.Count-1].pos; + // } + // }else{ + for (index = 1; index < mNodes.Count; index++) + { + if (index == mNodes.Count - 1) + { + idx = index - 1; + break; + } + if (mNodes[index].tTime >= _value) + { + idx = index - 1; + break; + } + } + if (idx < 0) + { + idx = 0; + } + // } + + float param = (_value - mNodes[idx].tTime) / (mNodes[idx + 1].tTime - mNodes[idx].tTime); + param = GSDRootUtil.Ease(param, mNodes[idx].EaseIO.x, mNodes[idx].EaseIO.y); + return GetHermiteInternal(idx, param, _isTangent); +} + + +private Vector3 GetHermiteInternal(int i, double t, bool bTangent = false) +{ + double t2, t3; + float BL0, BL1, BL2, BL3, tension; + + if (!bTangent) + { + t2 = t * t; + t3 = t2 * t; + } + else + { + t2 = t * t; + t = t * 2.0; + t2 = t2 * 3.0; + t3 = 0; //Necessary for compiler error. + } + + //Vectors: + Vector3 P0 = mNodes[NGI(i, NI[0])].pos; + Vector3 P1 = mNodes[NGI(i, NI[1])].pos; + Vector3 P2 = mNodes[NGI(i, NI[2])].pos; + Vector3 P3 = mNodes[NGI(i, NI[3])].pos; + + //Tension: + tension = 0.5f; // 0.5 equivale a catmull-rom + + //Tangents: + P2 = (P1 - P2) * tension; + P3 = (P3 - P0) * tension; + + if (!bTangent) + { + BL0 = (float) (CM[0] * t3 + CM[1] * t2 + CM[2] * t + CM[3]); + BL1 = (float) (CM[4] * t3 + CM[5] * t2 + CM[6] * t + CM[7]); + BL2 = (float) (CM[8] * t3 + CM[9] * t2 + CM[10] * t + CM[11]); + BL3 = (float) (CM[12] * t3 + CM[13] * t2 + CM[14] * t + CM[15]); + } + else + { + BL0 = (float) (CM[0] * t2 + CM[1] * t + CM[2]); + BL1 = (float) (CM[4] * t2 + CM[5] * t + CM[6]); + BL2 = (float) (CM[8] * t2 + CM[9] * t + CM[10]); + BL3 = (float) (CM[12] * t2 + CM[13] * t + CM[14]); + } + + return BL0 * P0 + BL1 * P1 + BL2 * P2 + BL3 * P3; +} + + +private static readonly double[] CM = new double[] { + 2.0, -3.0, 0.0, 1.0, + -2.0, 3.0, 0.0, 0.0, + 1.0, -2.0, 1.0, 0.0, + 1.0, -1.0, 0.0, 0.0 + }; + + +private static readonly int[] NI = new int[] { 0, 1, -1, 2 }; + + +private int NGI(int i, int o) +{ + int NGITI = i + o; + if (bClosed) + { + return (NGITI % mNodes.Count + mNodes.Count) % mNodes.Count; + } + else + { + return Mathf.Clamp(NGITI, 0, mNodes.Count - 1); + } +} +#endregion + + +public int GetNodeCount() +{ + return mNodes.Count; +} +#endif + + +#region "Start" +void Start() +{ +#if UNITY_EDITOR + //Do nothing. +#else + this.enabled = false; +#endif +} + #endregion } \ No newline at end of file diff --git a/Spline/GSDSplineN.cs b/Spline/GSDSplineN.cs index 066e109e..8577d617 100755 --- a/Spline/GSDSplineN.cs +++ b/Spline/GSDSplineN.cs @@ -1,1578 +1,1817 @@ -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using GSD.Roads.Splination; -using GSD.Roads.EdgeObjects; -using GSD; - -public class GSDSplineN : MonoBehaviour -{ - - - public Vector3 pos; - public Quaternion rot; - public Vector3 tangent; - public Vector2 EaseIO; - public float tDist = 0f; - public float tTime = 0f; - public float NextTime = 1f; - public Vector3 NextTan = default(Vector3); - public float OldTime = 0f; - public float SegmentDist = 0f; - public string EditorDisplayString = ""; - - public string tName = "Node-1"; - - public bool tempTime = false; - public float tempSegmentTime = 0f; - public float tempMinDistance = 5000f; - public float tempMinTime = 0f; - public bool bSpecialEndNode = false; - public GSDSplineN SpecialNodeCounterpart = null; - public GSDSplineN SpecialNodeCounterpart_Master = null; - public GSDSplineN SpecialNodeCounterpart_Old = null; - public GSDSplineN[] OriginalConnectionNodes = null; - - public bool bSpecialEndNode_IsStart = false; - public bool bSpecialEndNode_IsEnd = false; - public bool bSpecialIntersection = false; - public bool bSpecialRoadConnPrimary = false; - public bool bSpecialRoadConnPrimary_Old = false; - public bool bRoadCut = false; - public float MinSplination = 0f; - public float MaxSplination = 1f; - public bool bQuitGUI = false; - - public int idOnSpline = -1; - public GSDSplineC GSDSpline; - public bool bDestroyed = false; - public string UID; //Unique ID - public GSDSplineN Intersection_OtherNode; -#if UNITY_EDITOR - //Editor only: - public bool bEditorSelected = false; - public string GradeToNext; - public string GradeToPrev; - public float GradeToNextValue; - public float GradeToPrevValue; - public float bInitialRoadHeight = -1f; -#endif - //Navigation: - public bool bNeverIntersect = false; - public bool bIsIntersection = false; - public bool bIsEndPoint = false; - public bool bIsMainPoint = false; - public int id = 0; - public int id_intersection_othernode = 0; - public List id_connected; - public List node_connected; - public bool bDeleteMe = false; - public float tempDistance = 0f; - public int ExtraFCost = 0; - public int gValue, hValue, fValue; - public bool bIgnore = false; - public bool opt_GizmosEnabled = true; - - //Tunnels: - public bool bIsTunnel = false; - public bool bIsTunnelStart = false; - public bool bIsTunnelEnd = false; - public bool bIsTunnelMatched = false; - public GSDSplineN TunnelCounterpartNode = null; - - //Bridges: - public bool bIsBridge = false; - public bool bIsBridgeStart = false; - public bool bIsBridgeEnd = false; - public bool bIsBridgeMatched = false; - public GSDSplineN BridgeCounterpartNode = null; - - public GSDRoadIntersection GSDRI = null; -#if UNITY_EDITOR - public GSD.Roads.GSDIntersections.iConstructionMaker iConstruction; - - #region "Edge Objects" - public List EdgeObjects; - - public void SetupEdgeObjects(bool bCollect = true) - { - if (EdgeObjects == null) { EdgeObjects = new List(); } - int eCount = EdgeObjects.Count; - EdgeObjectMaker EOM = null; - for (int i = 0; i < eCount; i++) - { - EOM = EdgeObjects[i]; - EOM.tNode = this; - EOM.Setup(bCollect); - } - } - - public EdgeObjectMaker AddEdgeObject() - { - EdgeObjectMaker EOM = new EdgeObjectMaker(); - EOM.tNode = this; - EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - EOM.StartPos = GSDSpline.GetSplineValue(EOM.StartTime); - EOM.EndPos = GSDSpline.GetSplineValue(EOM.EndTime); - EdgeObjects.Add(EOM); - return EOM; - } - - public void EdgeObjectQuickAdd(string tName) - { - EdgeObjectMaker EOM = AddEdgeObject(); - EOM.LoadFromLibrary(tName, true); - EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - EOM.tNode = this; - EOM.Setup(); - } - - public void RemoveEdgeObject(int tIndex = -1, bool bSkipUpdate = false) - { - if (EdgeObjects == null) { return; } - if (EdgeObjects.Count == 0) { return; } - if (tIndex < 0) - { - if (EdgeObjects.Count > 0) - { - EdgeObjects[EdgeObjects.Count - 1].ClearEOM(); - EdgeObjects.RemoveAt(EdgeObjects.Count - 1); - } - } - else - { - if (EdgeObjects.Count > tIndex) - { - EdgeObjects[tIndex].ClearEOM(); - EdgeObjects.RemoveAt(tIndex); - } - } - if (!bSkipUpdate) - { - SetupEdgeObjects(); - } - } - - public void RemoveAllEdgeObjects(bool bSkipUpdate = false) - { - int SpamCheck = 0; - while (EdgeObjects.Count > 0 && SpamCheck < 1000) - { - RemoveEdgeObject(-1, bSkipUpdate); - SpamCheck += 1; - } - } - - public void CopyEdgeObject(int tIndex) - { - EdgeObjectMaker EOM = EdgeObjects[tIndex].Copy(); - EdgeObjects.Add(EOM); - SetupEdgeObjects(); - } - - public void EdgeObjectLoadFromLibrary(int i, string tName) - { - if (EdgeObjects == null) { EdgeObjects = new List(); } - int eCount = EdgeObjects.Count; - if (i > -1 && i < eCount) - { - EdgeObjectMaker EOM = EdgeObjects[i]; - EOM.LoadFromLibrary(tName); - EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - EOM.tNode = this; - EOM.Setup(); - } - } - - - public void DetectInvalidEdgeObjects() - { - int mCount = EdgeObjects.Count; - List InvalidList = new List(); - - for (int i = 0; i < mCount; i++) - { - if (EdgeObjects[i].EdgeObject == null) - { - InvalidList.Add(i); - } - } - - for (int i = (InvalidList.Count - 1); i >= 0; i--) - { - RemoveEdgeObject(InvalidList[i], true); - } - - SetupEdgeObjects(); - } - #endregion - - #region "Extruded objects" - public List SplinatedObjects; - - public void SetupSplinatedMeshes(bool bCollect = true) - { - if (SplinatedObjects == null) { SplinatedObjects = new List(); } - int eCount = SplinatedObjects.Count; - SplinatedMeshMaker SMM = null; - for (int i = 0; i < eCount; i++) - { - SMM = SplinatedObjects[i]; - SMM.Setup(true, bCollect); - } - } - - public int SplinatedMeshGetIndex(ref string UID) - { - if (SplinatedObjects == null) { SplinatedObjects = new List(); } - int eCount = SplinatedObjects.Count; - SplinatedMeshMaker SMM = null; - for (int i = 0; i < eCount; i++) - { - SMM = SplinatedObjects[i]; - if (string.CompareOrdinal(SMM.UID, UID) == 0) - { - return i; - } - } - return -1; - } - - public void SetupSplinatedMesh(int i, bool bGetStrings = false) - { - if (SplinatedObjects == null) { SplinatedObjects = new List(); } - int eCount = SplinatedObjects.Count; - if (i > -1 && i < eCount) - { - SplinatedMeshMaker SMM = SplinatedObjects[i]; - SMM.Setup(bGetStrings); - } - } - - public SplinatedMeshMaker AddSplinatedObject() - { - if (SplinatedObjects == null) { SplinatedObjects = new List(); } - SplinatedMeshMaker SMM = new SplinatedMeshMaker(); - SMM.Init(GSDSpline, this, transform); - SplinatedObjects.Add(SMM); - SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - SMM.StartPos = GSDSpline.GetSplineValue(SMM.StartTime); - SMM.EndPos = GSDSpline.GetSplineValue(SMM.EndTime); - return SMM; - } - - public void SplinatedObjectQuickAdd(string tName) - { - SplinatedMeshMaker SMM = AddSplinatedObject(); - SMM.LoadFromLibrary(tName, true); - SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - SMM.Setup(true); - } - - public void SplinatedObjectLoadFromLibrary(int i, string tName) - { - if (SplinatedObjects == null) { SplinatedObjects = new List(); } - int eCount = SplinatedObjects.Count; - if (i > -1 && i < eCount) - { - SplinatedMeshMaker SMM = SplinatedObjects[i]; - SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); - SMM.LoadFromLibrary(tName); - SMM.Setup(true); - } - } - - public void CopySplinatedObject(ref SplinatedMeshMaker tSMM) - { - SplinatedMeshMaker SMM = tSMM.Copy(); - SplinatedObjects.Add(SMM); - SetupSplinatedMeshes(); - } - - public void RemoveSplinatedObject(int tIndex = -1, bool bSkipUpdate = false) - { - if (SplinatedObjects == null) { return; } - if (SplinatedObjects.Count == 0) { return; } - SplinatedMeshMaker SMM = null; - if (tIndex < 0) - { - if (SplinatedObjects.Count > 0) - { - SMM = SplinatedObjects[SplinatedObjects.Count - 1]; - SMM.Kill(); - SplinatedObjects.RemoveAt(SplinatedObjects.Count - 1); - SMM = null; - } - } - else - { - if (SplinatedObjects.Count > tIndex) - { - SMM = SplinatedObjects[tIndex]; - SMM.Kill(); - SplinatedObjects.RemoveAt(tIndex); - SMM = null; - } - } - if (!bSkipUpdate) - { - SetupSplinatedMeshes(); - } - } - - public void RemoveAllSplinatedObjects(bool bSkipUpdate = false) - { - int SpamCheck = 0; - if (SplinatedObjects != null) - { - while (SplinatedObjects.Count > 0 && SpamCheck < 1000) - { - RemoveSplinatedObject(-1, bSkipUpdate); - SpamCheck += 1; - } - } - } - - public void DetectInvalidSplinatedObjects() - { - int mCount = SplinatedObjects.Count; - List InvalidList = new List(); - - for (int i = 0; i < mCount; i++) - { - if (SplinatedObjects[i].Output == null) - { - InvalidList.Add(i); - } - } - - for (int i = (InvalidList.Count - 1); i >= 0; i--) - { - RemoveSplinatedObject(InvalidList[i], true); - } - - SetupSplinatedMeshes(); - } - #endregion - - public void LoadWizardObjectsFromLibrary(string tFileName, bool _bIsDefault, bool _bIsBridge) - { - if (_bIsBridge) - { - RemoveAllSplinatedObjects(true); - RemoveAllEdgeObjects(true); - } - GSD.Roads.GSDRoadUtil.LoadNodeObjects(tFileName, this, _bIsDefault, _bIsBridge); - } - - public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) - { - if (!Application.isEditor) { return; } - pos = _p; - rot = _q; - EaseIO = _io; - tTime = _tTime; - name = _name; - if (EdgeObjects == null) { EdgeObjects = new List(); } - } - - public void SetupUniqueIdentifier() - { - if (UID == null || UID.Length < 4) - { - UID = System.Guid.NewGuid().ToString(); - } - } - - #region "Gizmos" - // private void TerrainDebugging(){ - // GSD.Roads.GSDRoadUtil.Construction3DTri tTri = null; - // Vector3 tHeightVec = new Vector3(0f,10f,0f); - // if(tTriList != null){ - // - // - //// bool bOddToggle = false; - //// for(int i=0;i 230){ break; } - //// if(i < 1330){ continue; } - //// if(i > 1510 || i > (tTriList.Count-10)){ break; } - //// tTri = tTriList[i]; - //// - //// if(bOddToggle){ - //// Gizmos.color = new Color(0f,1f,1f,1f); - //// }else{ - //// Gizmos.color = new Color(1f,1f,0f,1f); - //// } - //// - //// Gizmos.DrawLine(tTri.P1,tTri.P2); - //// Gizmos.DrawLine(tTri.P1,tTri.P3); - //// Gizmos.DrawLine(tTri.P2,tTri.P3); - ////// Gizmos.color = new Color(0f,1f,0f,1f); - ////// Gizmos.DrawLine(tTri.pMiddle,(tTri.normal*100f)+tTri.pMiddle); - //// - //// - //// - //// if(bOddToggle){ - //// Gizmos.color = new Color(0f,1f,1f,1f); - //// }else{ - //// Gizmos.color = new Color(1f,1f,0f,1f); - //// } - //// - //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P2+tHeightVec); - //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P3+tHeightVec); - //// Gizmos.DrawLine(tTri.P3+tHeightVec,tTri.P2+tHeightVec); - //// Gizmos.color = new Color(0f,1f,0f,1f); - //// Gizmos.DrawLine(tTri.pMiddle+tHeightVec,(tTri.normal*100f)+tTri.pMiddle+tHeightVec); - //// - ////// - //// - //// tTri = tTriList[i+1]; - //// if(bOddToggle){ - //// Gizmos.color = new Color(0f,1f,1f,1f); - //// }else{ - //// Gizmos.color = new Color(1f,1f,0f,1f); - //// } - //// - //// Gizmos.DrawLine(tTri.P1,tTri.P2); - //// Gizmos.DrawLine(tTri.P1,tTri.P3); - //// Gizmos.DrawLine(tTri.P2,tTri.P3); - //// - //// if(bOddToggle){ - //// Gizmos.color = new Color(0f,1f,1f,1f); - //// }else{ - //// Gizmos.color = new Color(1f,1f,0f,1f); - //// } - //// - //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P2+tHeightVec); - //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P3+tHeightVec); - //// Gizmos.DrawLine(tTri.P3+tHeightVec,tTri.P2+tHeightVec); - //// Gizmos.color = new Color(0f,1f,0f,1f); - //// Gizmos.DrawLine(tTri.pMiddle+tHeightVec,(tTri.normal*100f)+tTri.pMiddle+tHeightVec); - //// - //// - //// - //// bOddToggle = !bOddToggle; - ////// Gizmos.DrawCube(tRectList[i].pMiddle,new Vector3(1f,0.5f,1f)); - //// } - // - // - //// Gizmos.color = new Color(0f,1f,0f,1f); - //// Terrain tTerrain = GameObject.Find("Terrain").GetComponent(); - //// Vector3 HMVect = default(Vector3); - //// float tHeight = 0f; - //// for(int i=0;i tTriList; - public List tHMList; - public bool bGizmoDrawIntersectionHighlight = false; - - void OnDrawGizmos() - { - if (GSDSpline == null) { return; } - if (GSDSpline.tRoad == null) { return; } - if (!GSDSpline.tRoad.opt_GizmosEnabled) { return; } - if (bIgnore) { return; } - if (bIsIntersection) { return; } - if (bSpecialEndNode) { return; } - if (bSpecialEndNode_IsEnd || bSpecialEndNode_IsStart) { return; } - if (bGizmoDrawIntersectionHighlight && !bSpecialEndNode && bIsIntersection) - { - Gizmos.color = GSDSpline.tRoad.Color_NodeInter; - Gizmos.DrawCube(transform.position + new Vector3(0f, 2f, 0f), new Vector3(32f, 4f, 32f)); - return; - } - if (bSpecialRoadConnPrimary) - { - Gizmos.color = GSDSpline.tRoad.Color_NodeConnColor; - Gizmos.DrawCube(transform.position + new Vector3(0f, 7.5f, 0f), new Vector3(5f, 15f, 5f)); - } - else - { - Gizmos.color = GSDSpline.tRoad.Color_NodeDefaultColor; - Gizmos.DrawCube(transform.position + new Vector3(0f, 6f, 0f), new Vector3(2f, 11f, 2f)); - } - } - - void OnDrawGizmosSelected() - { - if (!GSDSpline.tRoad.opt_GizmosEnabled) { return; } - if (bIgnore) { return; } - if (bIsIntersection) { return; } - if (bSpecialEndNode) { return; } - if (bSpecialEndNode_IsEnd || bSpecialEndNode_IsStart) { return; } - if (bGizmoDrawIntersectionHighlight && !bSpecialEndNode && bIsIntersection) - { - Gizmos.color = new Color(0f, 1f, 0f, 0.6f); - Gizmos.DrawCube(transform.position + new Vector3(0f, 2f, 0f), new Vector3(32f, 4f, 32f)); - } - Gizmos.color = Color.yellow; - Gizmos.DrawCube(transform.position + new Vector3(0f, 6.25f, 0f), new Vector3(3.5f, 12.5f, 3.5f)); - } - #endregion - - #region "Grade" - public void SetGradePercent(int mCount) - { - Vector3 P1 = default(Vector3); - Vector3 P2 = default(Vector3); - float tDist; - float tGrade; - bool bIsNone = false; - - if (mCount < 2) - { - GradeToPrev = "NA"; - GradeToNext = "NA"; - GradeToNextValue = 0f; - GradeToPrevValue = 0f; - } - - // if(idOnSpline == 4){ - // int kasfdjsakf = 1; - // } - - if (!bIsEndPoint && !bSpecialEndNode && mCount > 1 && ((idOnSpline + 1) < GSDSpline.mNodes.Count)) - { - P1 = pos; - P2 = GSDSpline.mNodes[idOnSpline + 1].pos; - - if (bIsNone) - { - tGrade = 0f; - } - else - { - tDist = Vector2.Distance(new Vector2(P1.x, P1.z), new Vector2(P2.x, P2.z)); - tGrade = ((P2.y - P1.y) / tDist) * 100; - } - GradeToNextValue = tGrade; - GradeToNext = tGrade.ToString("0.##\\%"); - } - else - { - GradeToNext = "NA"; - GradeToNextValue = 0f; - } - - if (idOnSpline > 0 && !bSpecialEndNode && mCount > 1 && ((idOnSpline - 1) >= 0)) - { - P1 = pos; - P2 = GSDSpline.mNodes[idOnSpline - 1].pos; - - if (bIsNone) - { - tGrade = 0f; - } - else - { - tDist = Vector2.Distance(new Vector2(P1.x, P1.z), new Vector2(P2.x, P2.z)); - tGrade = ((P2.y - P1.y) / tDist) * 100; - } - GradeToPrevValue = tGrade; - GradeToPrev = tGrade.ToString("0.##\\%"); - } - else - { - GradeToPrev = "NA"; - GradeToPrevValue = 0f; - } - } - - public Vector3 FilterMaxGradeHeight(Vector3 tPos, out float MinY, out float MaxY) - { - Vector3 tVect = tPos; - tVect.y = pos.y; - float CurrentDistance = Vector2.Distance(new Vector2(pos.x, pos.z), new Vector2(tPos.x, tPos.z)); - // float CurrentDistance2 = Vector3.Distance(pos,tVect); - // float CurrentYDiff = tPos.y - pos.y; - // float CurrentGrade = CurrentYDiff/CurrentDistance; - //Get max/min grade height position for this currrent tDist distance: - MaxY = (GSDSpline.tRoad.opt_MaxGrade * CurrentDistance) + pos.y; - MinY = pos.y - (GSDSpline.tRoad.opt_MaxGrade * CurrentDistance); - - //(tPos.y-pos.y)/CurrentDistance - - - // float DifferenceFromMax = -1; - if (tPos.y > MaxY) - { - // DifferenceFromMax = tPos.y - MaximumY; - tPos.y = MaxY; - } - if (tPos.y < MinY) - { - // DifferenceFromMax = MinimumY - tPos.y; - tPos.y = MinY; - } - - return tPos; - } - - public void EnsureGradeValidity(int iStart = -1, bool bIsAddToEnd = false) - { - if (GSDSpline == null) { return; } - GSDSplineN PrevNode = null; - GSDSplineN NextNode = null; - - if (bIsAddToEnd && GSDSpline.GetNodeCount() > 0) - { - PrevNode = GSDSpline.mNodes[GSDSpline.GetNodeCount() - 1]; - } - else - { - if (iStart == -1) - { - PrevNode = GSDSpline.GetPrevLegitimateNode(idOnSpline); - } - else - { - PrevNode = GSDSpline.GetPrevLegitimateNode(iStart); - } - } - if (PrevNode == null) { return; } - Vector3 tVect = transform.position; - - float tMinY1 = 0f; - float tMinY2 = 0f; - float tMaxY1 = 0f; - float tMaxY2 = 0f; - if (PrevNode != null) - { - PrevNode.FilterMaxGradeHeight(tVect, out tMinY1, out tMaxY1); - } - if (NextNode != null) - { - NextNode.FilterMaxGradeHeight(tVect, out tMinY2, out tMaxY2); - } - - bool bPrevNodeGood = false; - bool bNextNodeGood = false; - - if (tVect.y > tMinY1 && tVect.y < tMaxY1) - { - bPrevNodeGood = true; - } - if (tVect.y > tMinY2 && tVect.y < tMaxY2) - { - bNextNodeGood = true; - } - - if (!bPrevNodeGood && !bNextNodeGood && PrevNode != null && NextNode != null) - { - float tMaxY3 = Mathf.Min(tMaxY1, tMaxY2); - float tMinY3 = Mathf.Max(tMinY1, tMinY2); - if (tVect.y < tMinY3) - { - tVect.y = tMinY3; - } - else if (tVect.y > tMaxY3) - { - tVect.y = tMaxY3; - } - } - else - { - if (!bPrevNodeGood && PrevNode != null) - { - if (tVect.y < tMinY1) - { - tVect.y = tMinY1; - } - else if (tVect.y > tMaxY1) - { - tVect.y = tMaxY1; - } - } - else if (!bNextNodeGood && NextNode != null) - { - if (tVect.y < tMinY2) - { - tVect.y = tMinY2; - } - else if (tVect.y > tMaxY2) - { - tVect.y = tMaxY2; - } - } - } - - transform.position = tVect; - } - #endregion - - #region "Util" - public void ResetNavigationData() - { - id_connected = null; - id_connected = new List(); - node_connected = null; - node_connected = new List(); - } - - public void BreakConnection() - { - GSDSplineN tNode2 = SpecialNodeCounterpart; - - if (bSpecialEndNode_IsStart) - { - GSDSpline.bSpecialStartControlNode = false; - GSDSpline.bSpecialEndNode_IsStart_Delay = false; - } - else if (bSpecialEndNode_IsEnd) - { - GSDSpline.bSpecialEndControlNode = false; - GSDSpline.bSpecialEndNode_IsEnd_Delay = false; - } - if (tNode2.bSpecialEndNode_IsStart) - { - tNode2.GSDSpline.bSpecialStartControlNode = false; - tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = false; - } - else if (tNode2.bSpecialEndNode_IsEnd) - { - tNode2.GSDSpline.bSpecialEndControlNode = false; - tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; - } - - SpecialNodeCounterpart = null; - bSpecialEndNode = false; - bSpecialEndNode_IsEnd = false; - bSpecialEndNode_IsStart = false; - bSpecialRoadConnPrimary = false; - tNode2.SpecialNodeCounterpart = null; - tNode2.bSpecialEndNode = false; - tNode2.bSpecialEndNode_IsEnd = false; - tNode2.bSpecialEndNode_IsStart = false; - tNode2.bSpecialRoadConnPrimary = false; - - tNode2.SpecialNodeCounterpart_Master.bSpecialRoadConnPrimary = false; - SpecialNodeCounterpart_Master.bSpecialRoadConnPrimary = false; - try - { - Object.DestroyImmediate(tNode2.transform.gameObject); - Object.DestroyImmediate(transform.gameObject); - } - catch (MissingReferenceException) - { - - } - } - - public void SetupSplinationLimits() - { - //Disallowed nodes: - if (!CanSplinate()) - { - MinSplination = tTime; - MaxSplination = tTime; - return; - } - - //Figure out min splination: - GSDSplineN tNode = null; - MinSplination = tTime; - for (int i = idOnSpline; i >= 0; i--) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.CanSplinate()) - { - MinSplination = tNode.tTime; - } - else - { - break; - } - } - - //Figure out max splination: - MaxSplination = tTime; - int mCount = GSDSpline.GetNodeCount(); - for (int i = idOnSpline; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.CanSplinate()) - { - MaxSplination = tNode.tTime; - } - else - { - break; - } - } - } - #endregion - - #region "Cut materials storage and setting" - public GameObject RoadCut_world = null; - public GameObject ShoulderCutR_world = null; - public GameObject ShoulderCutL_world = null; - public Material[] RoadCut_world_Mats; - public Material[] ShoulderCutR_world_Mats; - public Material[] ShoulderCutL_world_Mats; - - public GameObject RoadCut_marker = null; - public GameObject ShoulderCutR_marker = null; - public GameObject ShoulderCutL_marker = null; - public Material[] RoadCut_marker_Mats; - public Material[] ShoulderCutR_marker_Mats; - public Material[] ShoulderCutL_marker_Mats; - - public PhysicMaterial RoadCut_PhysicMat; - public PhysicMaterial ShoulderCutR_PhysicMat; - public PhysicMaterial ShoulderCutL_PhysicMat; - - /// - /// Stores the cut materials. For use in UpdateCuts(). See UpdateCuts() in this code file for further description of this system. - /// - public void StoreCuts() - { - //Buffers: - MeshRenderer MR = null; - MeshCollider MC = null; - - //World cuts first: - if (RoadCut_world != null) - { - MR = RoadCut_world.GetComponent(); - MC = RoadCut_world.GetComponent(); - if (MR != null) { RoadCut_world_Mats = MR.sharedMaterials; } - if (MC != null) { RoadCut_PhysicMat = MC.material; } - RoadCut_world = null;//Nullify reference only - } - if (ShoulderCutR_world != null) - { - MR = ShoulderCutR_world.GetComponent(); - MC = ShoulderCutR_world.GetComponent(); - if (MR != null) { ShoulderCutR_world_Mats = MR.sharedMaterials; } - if (MC != null) { ShoulderCutR_PhysicMat = MC.material; } - ShoulderCutR_world = null; - } - if (ShoulderCutL_world != null) - { - MR = ShoulderCutL_world.GetComponent(); - MC = ShoulderCutL_world.GetComponent(); - if (MR != null) { ShoulderCutL_world_Mats = MR.sharedMaterials; } - if (MC != null) { ShoulderCutL_PhysicMat = MC.material; } - ShoulderCutL_world = null; - } - //Markers: - if (RoadCut_marker != null) - { - MR = RoadCut_marker.GetComponent(); - if (MR != null) { RoadCut_marker_Mats = MR.sharedMaterials; } - RoadCut_marker = null; - } - if (ShoulderCutR_marker != null) - { - MR = ShoulderCutR_marker.GetComponent(); - if (MR != null) { ShoulderCutR_marker_Mats = MR.sharedMaterials; } - ShoulderCutR_marker = null; - } - if (ShoulderCutL_marker != null) - { - MR = ShoulderCutL_marker.GetComponent(); - if (MR != null) { ShoulderCutL_marker_Mats = MR.sharedMaterials; } - ShoulderCutL_marker = null; - } - } - /// - /// Updates the cut materials. Called upon creation of the cuts to set the newly cut materials to previously set materials. - /// For instance, if the user set a material on a road cut, and then regenerated the road, this function will apply the mats that the user applied. - /// - public void UpdateCuts() - { - //Buffers: - MeshRenderer MR = null; - MeshCollider MC = null; - - //World: - if (RoadCut_world_Mats != null && RoadCut_world_Mats.Length > 0 && RoadCut_world) - { - MR = RoadCut_world.GetComponent(); - if (!MR) { RoadCut_world.AddComponent(); } - if (MR != null) { MR.materials = RoadCut_world_Mats; } - } - if (RoadCut_PhysicMat != null && RoadCut_world) - { - MC = RoadCut_world.GetComponent(); - if (MC != null) { MC.material = RoadCut_PhysicMat; } - } - - if (ShoulderCutR_world_Mats != null && ShoulderCutR_world_Mats.Length > 0 && ShoulderCutR_world) - { - MR = ShoulderCutR_world.GetComponent(); - if (!MR) { ShoulderCutR_world.AddComponent(); } - if (MR != null) { MR.materials = ShoulderCutR_world_Mats; } - } - if (ShoulderCutR_PhysicMat != null && ShoulderCutR_world) - { - MC = ShoulderCutR_world.GetComponent(); - if (MC != null) { MC.material = ShoulderCutR_PhysicMat; } - } - - if (ShoulderCutL_world_Mats != null && ShoulderCutL_world_Mats.Length > 0 && ShoulderCutL_world) - { - MR = ShoulderCutL_world.GetComponent(); - if (!MR) { ShoulderCutL_world.AddComponent(); } - if (MR != null) { MR.materials = ShoulderCutL_world_Mats; } - } - if (ShoulderCutL_PhysicMat != null && ShoulderCutL_world) - { - MC = ShoulderCutL_world.GetComponent(); - if (MC != null) { MC.material = ShoulderCutL_PhysicMat; } - } - - //Markers: - if (RoadCut_marker_Mats != null && RoadCut_marker_Mats.Length > 0 && RoadCut_marker) - { - MR = RoadCut_marker.GetComponent(); - if (!MR) { RoadCut_marker.AddComponent(); } - if (MR != null) { MR.materials = RoadCut_marker_Mats; } - } - if (ShoulderCutR_marker_Mats != null && ShoulderCutR_marker_Mats.Length > 0 && ShoulderCutR_marker) - { - MR = ShoulderCutR_marker.GetComponent(); - if (!MR) { ShoulderCutR_marker.AddComponent(); } - if (MR != null) { MR.materials = ShoulderCutR_marker_Mats; } - } - if (ShoulderCutL_marker_Mats != null && ShoulderCutL_marker_Mats.Length > 0 && ShoulderCutL_marker) - { - MR = ShoulderCutL_marker.GetComponent(); - if (!MR) { ShoulderCutL_marker.AddComponent(); } - if (MR != null) { MR.materials = ShoulderCutL_marker_Mats; } - } - - if (RoadCut_marker != null) - { - MR = RoadCut_marker.GetComponent(); - if (MR == null || MR.sharedMaterial == null) - { - Object.DestroyImmediate(RoadCut_marker); - } - } - if (ShoulderCutR_marker != null) - { - MR = ShoulderCutR_marker.GetComponent(); - if (MR == null || MR.sharedMaterial == null) - { - Object.DestroyImmediate(ShoulderCutR_marker); - } - } - if (ShoulderCutL_marker != null) - { - MR = ShoulderCutL_marker.GetComponent(); - if (MR == null || MR.sharedMaterial == null) - { - Object.DestroyImmediate(ShoulderCutL_marker); - } - } - } - - /// - /// Clears the cut materials. Called when user hits button on road editor inspector gui. - /// - public void ClearCuts() - { - RoadCut_world_Mats = null; - ShoulderCutR_world_Mats = null; - ShoulderCutL_world_Mats = null; - RoadCut_marker_Mats = null; - ShoulderCutR_marker_Mats = null; - ShoulderCutL_marker_Mats = null; - RoadCut_PhysicMat = null; - ShoulderCutR_PhysicMat = null; - ShoulderCutL_PhysicMat = null; - } - #endregion - - #region "Bridges" - public void BridgeToggleStart() - { - //If switching to end, find associated bridge - if (bIsBridgeStart) - { - BridgeStart(); - } - else - { - BridgeDestroy(); - } - } - - public void BridgeToggleEnd() - { - //If switching to end, find associated bridge - if (bIsBridgeEnd) - { - int mCount = GSDSpline.GetNodeCount(); - GSDSplineN tNode = null; - for (int i = 1; i < (mCount - 1); i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.bIsBridgeStart && !tNode.bIsBridgeMatched) - { - tNode.BridgeToggleStart(); - if (tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode == this) { return; } - } - } - } - else - { - BridgeDestroy(); - } - } - - private void BridgeStart() - { - //Cycle through nodes until you find another end or another start (in this case, no creation, encountered another bridge): - int EndID = idOnSpline + 1; - int mCount = GSDSpline.GetNodeCount(); - if (bIsEndPoint) - { - //Attempted to make end point node a bridge node: - bIsBridgeStart = false; - return; - } - if (EndID >= mCount) - { - //Attempted to make last node a bridge node: - bIsBridgeStart = false; - return; - } - else if (idOnSpline == 0) - { - //Attempted to make first node a bridge node: - bIsBridgeStart = false; - return; - } - - bIsBridgeMatched = false; - BridgeCounterpartNode = null; - int StartI = idOnSpline + 1; - GSDSplineN tNode = null; - for (int i = StartI; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.bIsIntersection) - { - //Encountered intersection. End search. - return; - } - if (tNode.bIsBridgeStart) - { - //Encountered another bridge. Return: - return; - } - if (tNode.bIgnore) - { - continue; - } - if (tNode.bIsBridgeEnd) - { - bIsBridgeMatched = true; - tNode.bIsBridgeMatched = true; - BridgeCounterpartNode = tNode; - tNode.BridgeCounterpartNode = this; - GSDSpline.Setup_Trigger(); - return; - } - } - } - - private void BridgeDestroy() - { - if (BridgeCounterpartNode != null) - { - BridgeCounterpartNode.BridgeResetValues(); - } - BridgeResetValues(); - GSDSpline.Setup_Trigger(); - } - - public void BridgeResetValues() - { - bIsBridge = false; - bIsBridgeStart = false; - bIsBridgeEnd = false; - bIsBridgeMatched = false; - BridgeCounterpartNode = null; - } - - public bool CanBridgeStart() - { - if (bIsBridgeStart) { return true; } - if (bIsBridgeEnd) { return false; } - if (bIsEndPoint) { return false; } - - int mCount = GSDSpline.GetNodeCount(); - - if (idOnSpline > 0) - { - if (GSDSpline.mNodes[idOnSpline - 1].bIsBridgeStart) - { - return false; - } - } - - if (idOnSpline < (mCount - 1)) - { - if (GSDSpline.mNodes[idOnSpline + 1].bIsBridgeStart) - { - return false; - } - - if (GSDSpline.bSpecialEndControlNode) - { - if ((mCount - 3 > 0) && idOnSpline == mCount - 3) - { - return false; - } - } - else - { - if ((mCount - 2 > 0) && idOnSpline == mCount - 2) - { - return false; - } - } - } - - if (GSDSpline.IsInBridge(tTime)) - { - return false; - } - - return true; - } - - public bool CanBridgeEnd() - { - if (bIsBridgeEnd) { return true; } - if (bIsBridgeStart) { return false; } - if (bIsEndPoint) { return false; } - - int mCount = GSDSpline.GetNodeCount(); - - if (idOnSpline < (mCount - 1)) - { - if (GSDSpline.bSpecialStartControlNode) - { - if (idOnSpline == 2) - { - return false; - } - } - else - { - if (idOnSpline == 1) - { - return false; - } - } - } - - for (int i = idOnSpline; i >= 0; i--) - { - if (GSDSpline.mNodes[i].bIsBridgeStart) - { - if (!GSDSpline.mNodes[i].bIsBridgeMatched) - { - return true; - } - else - { - return false; - } - } - } - - return false; - } - #endregion - - #region "Tunnels" - public void TunnelToggleStart() - { - //If switching to end, find associated Tunnel - if (bIsTunnelStart) - { - TunnelStart(); - } - else - { - TunnelDestroy(); - } - } - - public void TunnelToggleEnd() - { - //If switching to end, find associated Tunnel - if (bIsTunnelEnd) - { - int mCount = GSDSpline.GetNodeCount(); - GSDSplineN tNode = null; - for (int i = 1; i < (mCount - 1); i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.bIsTunnelStart && !tNode.bIsTunnelMatched) - { - tNode.TunnelToggleStart(); - if (tNode.bIsTunnelMatched && tNode.TunnelCounterpartNode == this) { return; } - } - } - } - else - { - TunnelDestroy(); - } - } - - private void TunnelStart() - { - //Cycle through nodes until you find another end or another start (in this case, no creation, encountered another Tunnel): - int EndID = idOnSpline + 1; - int mCount = GSDSpline.GetNodeCount(); - if (bIsEndPoint) - { - //Attempted to make end point node a Tunnel node: - bIsTunnelStart = false; - return; - } - if (EndID >= mCount) - { - //Attempted to make last node a Tunnel node: - bIsTunnelStart = false; - return; - } - else if (idOnSpline == 0) - { - //Attempted to make first node a Tunnel node: - bIsTunnelStart = false; - return; - } - - bIsTunnelMatched = false; - TunnelCounterpartNode = null; - int StartI = idOnSpline + 1; - GSDSplineN tNode = null; - for (int i = StartI; i < mCount; i++) - { - tNode = GSDSpline.mNodes[i]; - if (tNode.bIsIntersection) - { - //Encountered intersection. End search. - return; - } - if (tNode.bIsTunnelStart) - { - //Encountered another Tunnel. Return: - return; - } - if (tNode.bIgnore) - { - continue; - } - if (tNode.bIsTunnelEnd) - { - bIsTunnelMatched = true; - tNode.bIsTunnelMatched = true; - TunnelCounterpartNode = tNode; - tNode.TunnelCounterpartNode = this; - GSDSpline.Setup_Trigger(); - return; - } - } - } - - private void TunnelDestroy() - { - if (TunnelCounterpartNode != null) - { - TunnelCounterpartNode.TunnelResetValues(); - } - TunnelResetValues(); - GSDSpline.Setup_Trigger(); - } - - public void TunnelResetValues() - { - bIsTunnel = false; - bIsTunnelStart = false; - bIsTunnelEnd = false; - bIsTunnelMatched = false; - TunnelCounterpartNode = null; - } - - public bool CanTunnelStart() - { - if (bIsTunnelStart) { return true; } - if (bIsTunnelEnd) { return false; } - if (bIsEndPoint) { return false; } - - int mCount = GSDSpline.GetNodeCount(); - - if (idOnSpline > 0) - { - if (GSDSpline.mNodes[idOnSpline - 1].bIsTunnelStart) - { - return false; - } - } - - if (idOnSpline < (mCount - 1)) - { - if (GSDSpline.mNodes[idOnSpline + 1].bIsTunnelStart) - { - return false; - } - - if (GSDSpline.bSpecialEndControlNode) - { - if ((mCount - 3 > 0) && idOnSpline == mCount - 3) - { - return false; - } - } - else - { - if ((mCount - 2 > 0) && idOnSpline == mCount - 2) - { - return false; - } - } - } - - if (GSDSpline.IsInTunnel(tTime)) - { - return false; - } - - return true; - } - - public bool CanTunnelEnd() - { - if (bIsTunnelEnd) { return true; } - if (bIsTunnelStart) { return false; } - if (bIsEndPoint) { return false; } - - int mCount = GSDSpline.GetNodeCount(); - - if (idOnSpline < (mCount - 1)) - { - if (GSDSpline.bSpecialStartControlNode) - { - if (idOnSpline == 2) - { - return false; - } - } - else - { - if (idOnSpline == 1) - { - return false; - } - } - } - - for (int i = idOnSpline; i >= 0; i--) - { - if (GSDSpline.mNodes[i].bIsTunnelStart) - { - if (!GSDSpline.mNodes[i].bIsTunnelMatched) - { - return true; - } - else - { - return false; - } - } - } - - return false; - } - #endregion - - #region "Is straight line to next node" - public bool IsStraight() - { - int id1 = idOnSpline - 1; - int id2 = idOnSpline + 1; - int id3 = idOnSpline + 2; - int mCount = GSDSpline.GetNodeCount(); - - if (id1 > -1 && id1 < mCount) - { - if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id1].pos)) - { - return false; - } - } - - if (id2 > -1 && id2 < mCount) - { - if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id2].pos)) - { - return false; - } - } - - if (id3 > -1 && id3 < mCount) - { - if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id3].pos)) - { - return false; - } - } - - return true; - } - - private static bool IsApproxTwoThirds(ref Vector3 V1, Vector3 V2) - { - int cCount = 0; - if (GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) - { - cCount += 1; - } - if (GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) - { - cCount += 1; - } - if (GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) - { - cCount += 1; - } - - if (cCount == 2) - { - return true; - } - else - { - return false; - } - } - #endregion -#endif - #region "Non-editor util" - public bool CanSplinate() - { - if (bSpecialEndNode) - {// || bIsBridge_PreNode || bIsBridge_PostNode){ - return false; - } - else - { - return true; - } - } - - public bool IsLegitimate() - { - if (bIsIntersection || bSpecialEndNode) - {// || bIsBridge_PreNode || bIsBridge_PostNode){ - return false; - } - else - { - return true; - } - } - public bool IsLegitimateGrade() - { - if (bSpecialEndNode) - {// || bIsBridge_PreNode || bIsBridge_PostNode){ - return false; - } - else - { - return true; - } - } - #endregion - - void Start() - { -#if UNITY_EDITOR - //Do nothing. -#else - this.enabled = false; -#endif - } - - public void ToggleHideFlags(bool bIsHidden) - { - if (bIsHidden) - { - this.hideFlags = HideFlags.HideInHierarchy; - transform.hideFlags = HideFlags.HideInHierarchy; - } - else - { - this.hideFlags = HideFlags.None; - transform.hideFlags = HideFlags.None; - } - } +#region Imports +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using GSD.Roads.Splination; +using GSD.Roads.EdgeObjects; +using GSD; +#endregion + + +public class GSDSplineN : MonoBehaviour +{ + public Vector3 pos; + public Quaternion rot; + public Vector3 tangent; + public Vector2 EaseIO; + public float tDist = 0f; + public float tTime = 0f; + public float NextTime = 1f; + public Vector3 NextTan = default(Vector3); + public float OldTime = 0f; + public float SegmentDist = 0f; + public string EditorDisplayString = ""; + + public string tName = "Node-1"; + + public bool tempTime = false; + public float tempSegmentTime = 0f; + public float tempMinDistance = 5000f; + public float tempMinTime = 0f; + public bool bSpecialEndNode = false; + public GSDSplineN SpecialNodeCounterpart = null; + public GSDSplineN SpecialNodeCounterpart_Master = null; + public GSDSplineN SpecialNodeCounterpart_Old = null; + public GSDSplineN[] OriginalConnectionNodes = null; + + public bool bSpecialEndNode_IsStart = false; + public bool bSpecialEndNode_IsEnd = false; + public bool bSpecialIntersection = false; + public bool bSpecialRoadConnPrimary = false; + public bool bSpecialRoadConnPrimary_Old = false; + public bool bRoadCut = false; + public float MinSplination = 0f; + public float MaxSplination = 1f; + public bool bQuitGUI = false; + + public int idOnSpline = -1; + public GSDSplineC GSDSpline; + public bool bDestroyed = false; + public string UID; //Unique ID + public GSDSplineN Intersection_OtherNode; +#if UNITY_EDITOR + //Editor only: + public bool bEditorSelected = false; + public string GradeToNext; + public string GradeToPrev; + public float GradeToNextValue; + public float GradeToPrevValue; + public float bInitialRoadHeight = -1f; +#endif + //Navigation: + public bool bNeverIntersect = false; + public bool bIsIntersection = false; + public bool bIsEndPoint = false; + public bool bIsMainPoint = false; + public int id = 0; + public int id_intersection_othernode = 0; + public List id_connected; + public List node_connected; + public bool bDeleteMe = false; + public float tempDistance = 0f; + public int ExtraFCost = 0; + public int gValue, hValue, fValue; + public bool bIgnore = false; + public bool opt_GizmosEnabled = true; + + + #region Tunnels: + public bool bIsTunnel = false; + public bool bIsTunnelStart = false; + public bool bIsTunnelEnd = false; + public bool bIsTunnelMatched = false; + public GSDSplineN TunnelCounterpartNode = null; + #endregion + + + //Bridges: + public bool bIsBridge = false; + public bool bIsBridgeStart = false; + public bool bIsBridgeEnd = false; + public bool bIsBridgeMatched = false; + public GSDSplineN BridgeCounterpartNode = null; + + public GSDRoadIntersection GSDRI = null; +#if UNITY_EDITOR + public GSD.Roads.GSDIntersections.iConstructionMaker iConstruction; + + + #region "Edge Objects" + public List EdgeObjects; + + + public void SetupEdgeObjects(bool bCollect = true) + { + if (EdgeObjects == null) + { + EdgeObjects = new List(); + } + int eCount = EdgeObjects.Count; + EdgeObjectMaker EOM = null; + for (int index = 0; index < eCount; index++) + { + EOM = EdgeObjects[index]; + EOM.tNode = this; + EOM.Setup(bCollect); + } + } + + + public EdgeObjectMaker AddEdgeObject() + { + EdgeObjectMaker EOM = new EdgeObjectMaker(); + EOM.tNode = this; + EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + EOM.StartPos = GSDSpline.GetSplineValue(EOM.StartTime); + EOM.EndPos = GSDSpline.GetSplineValue(EOM.EndTime); + EdgeObjects.Add(EOM); + return EOM; + } + + + public void EdgeObjectQuickAdd(string tName) + { + EdgeObjectMaker EOM = AddEdgeObject(); + EOM.LoadFromLibrary(tName, true); + EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + EOM.tNode = this; + EOM.Setup(); + } + + + public void RemoveEdgeObject(int tIndex = -1, bool bSkipUpdate = false) + { + if (EdgeObjects == null) + { + return; + } + if (EdgeObjects.Count == 0) + { + return; + } + if (tIndex < 0) + { + if (EdgeObjects.Count > 0) + { + EdgeObjects[EdgeObjects.Count - 1].ClearEOM(); + EdgeObjects.RemoveAt(EdgeObjects.Count - 1); + } + } + else + { + if (EdgeObjects.Count > tIndex) + { + EdgeObjects[tIndex].ClearEOM(); + EdgeObjects.RemoveAt(tIndex); + } + } + if (!bSkipUpdate) + { + SetupEdgeObjects(); + } + } + + + public void RemoveAllEdgeObjects(bool bSkipUpdate = false) + { + int SpamCheck = 0; + while (EdgeObjects.Count > 0 && SpamCheck < 1000) + { + RemoveEdgeObject(-1, bSkipUpdate); + SpamCheck += 1; + } + } + + + public void CopyEdgeObject(int tIndex) + { + EdgeObjectMaker EOM = EdgeObjects[tIndex].Copy(); + EdgeObjects.Add(EOM); + SetupEdgeObjects(); + } + + + public void EdgeObjectLoadFromLibrary(int i, string tName) + { + if (EdgeObjects == null) + { + EdgeObjects = new List(); + } + int eCount = EdgeObjects.Count; + if (i > -1 && i < eCount) + { + EdgeObjectMaker EOM = EdgeObjects[i]; + EOM.LoadFromLibrary(tName); + EOM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + EOM.tNode = this; + EOM.Setup(); + } + } + + + public void DetectInvalidEdgeObjects() + { + int mCount = EdgeObjects.Count; + List InvalidList = new List(); + + for (int index = 0; index < mCount; index++) + { + if (EdgeObjects[index].EdgeObject == null) + { + InvalidList.Add(index); + } + } + + for (int index = (InvalidList.Count - 1); index >= 0; index--) + { + RemoveEdgeObject(InvalidList[index], true); + } + + SetupEdgeObjects(); + } + #endregion + + + #region "Extruded objects" + public List SplinatedObjects; + + + public void SetupSplinatedMeshes(bool bCollect = true) + { + if (SplinatedObjects == null) + { + SplinatedObjects = new List(); + } + int eCount = SplinatedObjects.Count; + SplinatedMeshMaker SMM = null; + for (int index = 0; index < eCount; index++) + { + SMM = SplinatedObjects[index]; + SMM.Setup(true, bCollect); + } + } + + + public int SplinatedMeshGetIndex(ref string UID) + { + if (SplinatedObjects == null) + { + SplinatedObjects = new List(); + } + int eCount = SplinatedObjects.Count; + SplinatedMeshMaker SMM = null; + for (int index = 0; index < eCount; index++) + { + SMM = SplinatedObjects[index]; + if (string.CompareOrdinal(SMM.UID, UID) == 0) + { + return index; + } + } + return -1; + } + + + public void SetupSplinatedMesh(int i, bool bGetStrings = false) + { + if (SplinatedObjects == null) + { + SplinatedObjects = new List(); + } + int eCount = SplinatedObjects.Count; + if (i > -1 && i < eCount) + { + SplinatedMeshMaker SMM = SplinatedObjects[i]; + SMM.Setup(bGetStrings); + } + } + + + public SplinatedMeshMaker AddSplinatedObject() + { + if (SplinatedObjects == null) + { + SplinatedObjects = new List(); + } + SplinatedMeshMaker SMM = new SplinatedMeshMaker(); + SMM.Init(GSDSpline, this, transform); + SplinatedObjects.Add(SMM); + SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + SMM.StartPos = GSDSpline.GetSplineValue(SMM.StartTime); + SMM.EndPos = GSDSpline.GetSplineValue(SMM.EndTime); + return SMM; + } + + + public void SplinatedObjectQuickAdd(string tName) + { + SplinatedMeshMaker SMM = AddSplinatedObject(); + SMM.LoadFromLibrary(tName, true); + SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + SMM.Setup(true); + } + + + public void SplinatedObjectLoadFromLibrary(int i, string tName) + { + if (SplinatedObjects == null) + { + SplinatedObjects = new List(); + } + int eCount = SplinatedObjects.Count; + if (i > -1 && i < eCount) + { + SplinatedMeshMaker SMM = SplinatedObjects[i]; + SMM.SetDefaultTimes(bIsEndPoint, tTime, NextTime, idOnSpline, GSDSpline.distance); + SMM.LoadFromLibrary(tName); + SMM.Setup(true); + } + } + + + public void CopySplinatedObject(ref SplinatedMeshMaker tSMM) + { + SplinatedMeshMaker SMM = tSMM.Copy(); + SplinatedObjects.Add(SMM); + SetupSplinatedMeshes(); + } + + + public void RemoveSplinatedObject(int tIndex = -1, bool bSkipUpdate = false) + { + if (SplinatedObjects == null) + { + return; + } + if (SplinatedObjects.Count == 0) + { + return; + } + SplinatedMeshMaker SMM = null; + if (tIndex < 0) + { + if (SplinatedObjects.Count > 0) + { + SMM = SplinatedObjects[SplinatedObjects.Count - 1]; + SMM.Kill(); + SplinatedObjects.RemoveAt(SplinatedObjects.Count - 1); + SMM = null; + } + } + else + { + if (SplinatedObjects.Count > tIndex) + { + SMM = SplinatedObjects[tIndex]; + SMM.Kill(); + SplinatedObjects.RemoveAt(tIndex); + SMM = null; + } + } + if (!bSkipUpdate) + { + SetupSplinatedMeshes(); + } + } + + + public void RemoveAllSplinatedObjects(bool bSkipUpdate = false) + { + int SpamCheck = 0; + if (SplinatedObjects != null) + { + while (SplinatedObjects.Count > 0 && SpamCheck < 1000) + { + RemoveSplinatedObject(-1, bSkipUpdate); + SpamCheck += 1; + } + } + } + + + public void DetectInvalidSplinatedObjects() + { + int mCount = SplinatedObjects.Count; + List InvalidList = new List(); + + for (int index = 0; index < mCount; index++) + { + if (SplinatedObjects[index].Output == null) + { + InvalidList.Add(index); + } + } + + for (int index = (InvalidList.Count - 1); index >= 0; index--) + { + RemoveSplinatedObject(InvalidList[index], true); + } + + SetupSplinatedMeshes(); + } + #endregion + + + public void LoadWizardObjectsFromLibrary(string tFileName, bool _bIsDefault, bool _bIsBridge) + { + if (_bIsBridge) + { + RemoveAllSplinatedObjects(true); + RemoveAllEdgeObjects(true); + } + GSD.Roads.GSDRoadUtil.LoadNodeObjects(tFileName, this, _bIsDefault, _bIsBridge); + } + + + public void Setup(Vector3 _p, Quaternion _q, Vector2 _io, float _tTime, string _name) + { + if (!Application.isEditor) + { + return; + } + pos = _p; + rot = _q; + EaseIO = _io; + tTime = _tTime; + name = _name; + if (EdgeObjects == null) + { + EdgeObjects = new List(); + } + } + + + public void SetupUniqueIdentifier() + { + if (UID == null || UID.Length < 4) + { + UID = System.Guid.NewGuid().ToString(); + } + } + + + #region "Gizmos" + // private void TerrainDebugging(){ + // GSD.Roads.GSDRoadUtil.Construction3DTri tTri = null; + // Vector3 tHeightVec = new Vector3(0f,10f,0f); + // if(tTriList != null){ + // + // + //// bool bOddToggle = false; + //// for(int i=0;i 230){ break; } + //// if(i < 1330){ continue; } + //// if(i > 1510 || i > (tTriList.Count-10)){ break; } + //// tTri = tTriList[i]; + //// + //// if(bOddToggle){ + //// Gizmos.color = new Color(0f,1f,1f,1f); + //// }else{ + //// Gizmos.color = new Color(1f,1f,0f,1f); + //// } + //// + //// Gizmos.DrawLine(tTri.P1,tTri.P2); + //// Gizmos.DrawLine(tTri.P1,tTri.P3); + //// Gizmos.DrawLine(tTri.P2,tTri.P3); + ////// Gizmos.color = new Color(0f,1f,0f,1f); + ////// Gizmos.DrawLine(tTri.pMiddle,(tTri.normal*100f)+tTri.pMiddle); + //// + //// + //// + //// if(bOddToggle){ + //// Gizmos.color = new Color(0f,1f,1f,1f); + //// }else{ + //// Gizmos.color = new Color(1f,1f,0f,1f); + //// } + //// + //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P2+tHeightVec); + //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P3+tHeightVec); + //// Gizmos.DrawLine(tTri.P3+tHeightVec,tTri.P2+tHeightVec); + //// Gizmos.color = new Color(0f,1f,0f,1f); + //// Gizmos.DrawLine(tTri.pMiddle+tHeightVec,(tTri.normal*100f)+tTri.pMiddle+tHeightVec); + //// + ////// + //// + //// tTri = tTriList[i+1]; + //// if(bOddToggle){ + //// Gizmos.color = new Color(0f,1f,1f,1f); + //// }else{ + //// Gizmos.color = new Color(1f,1f,0f,1f); + //// } + //// + //// Gizmos.DrawLine(tTri.P1,tTri.P2); + //// Gizmos.DrawLine(tTri.P1,tTri.P3); + //// Gizmos.DrawLine(tTri.P2,tTri.P3); + //// + //// if(bOddToggle){ + //// Gizmos.color = new Color(0f,1f,1f,1f); + //// }else{ + //// Gizmos.color = new Color(1f,1f,0f,1f); + //// } + //// + //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P2+tHeightVec); + //// Gizmos.DrawLine(tTri.P1+tHeightVec,tTri.P3+tHeightVec); + //// Gizmos.DrawLine(tTri.P3+tHeightVec,tTri.P2+tHeightVec); + //// Gizmos.color = new Color(0f,1f,0f,1f); + //// Gizmos.DrawLine(tTri.pMiddle+tHeightVec,(tTri.normal*100f)+tTri.pMiddle+tHeightVec); + //// + //// + //// + //// bOddToggle = !bOddToggle; + ////// Gizmos.DrawCube(tRectList[i].pMiddle,new Vector3(1f,0.5f,1f)); + //// } + // + // + //// Gizmos.color = new Color(0f,1f,0f,1f); + //// Terrain tTerrain = GameObject.Find("Terrain").GetComponent(); + //// Vector3 HMVect = default(Vector3); + //// float tHeight = 0f; + //// for(int i=0;i tTriList; + public List tHMList; + public bool bGizmoDrawIntersectionHighlight = false; + + + void OnDrawGizmos() + { + if (GSDSpline == null) + { + return; + } + if (GSDSpline.tRoad == null) + { + return; + } + if (!GSDSpline.tRoad.opt_GizmosEnabled) + { + return; + } + if (bIgnore) + { + return; + } + if (bIsIntersection) + { + return; + } + if (bSpecialEndNode) + { + return; + } + if (bSpecialEndNode_IsEnd || bSpecialEndNode_IsStart) + { + return; + } + if (bGizmoDrawIntersectionHighlight && !bSpecialEndNode && bIsIntersection) + { + Gizmos.color = GSDSpline.tRoad.Color_NodeInter; + Gizmos.DrawCube(transform.position + new Vector3(0f, 2f, 0f), new Vector3(32f, 4f, 32f)); + return; + } + if (bSpecialRoadConnPrimary) + { + Gizmos.color = GSDSpline.tRoad.Color_NodeConnColor; + Gizmos.DrawCube(transform.position + new Vector3(0f, 7.5f, 0f), new Vector3(5f, 15f, 5f)); + } + else + { + Gizmos.color = GSDSpline.tRoad.Color_NodeDefaultColor; + Gizmos.DrawCube(transform.position + new Vector3(0f, 6f, 0f), new Vector3(2f, 11f, 2f)); + } + } + + + void OnDrawGizmosSelected() + { + if (!GSDSpline.tRoad.opt_GizmosEnabled) + { + return; + } + if (bIgnore) + { + return; + } + if (bIsIntersection) + { + return; + } + if (bSpecialEndNode) + { + return; + } + if (bSpecialEndNode_IsEnd || bSpecialEndNode_IsStart) + { + return; + } + if (bGizmoDrawIntersectionHighlight && !bSpecialEndNode && bIsIntersection) + { + Gizmos.color = new Color(0f, 1f, 0f, 0.6f); + Gizmos.DrawCube(transform.position + new Vector3(0f, 2f, 0f), new Vector3(32f, 4f, 32f)); + } + Gizmos.color = Color.yellow; + Gizmos.DrawCube(transform.position + new Vector3(0f, 6.25f, 0f), new Vector3(3.5f, 12.5f, 3.5f)); + } + #endregion + + + #region "Grade" + public void SetGradePercent(int mCount) + { + Vector3 P1 = default(Vector3); + Vector3 P2 = default(Vector3); + float tDist; + float tGrade; + bool bIsNone = false; + + if (mCount < 2) + { + GradeToPrev = "NA"; + GradeToNext = "NA"; + GradeToNextValue = 0f; + GradeToPrevValue = 0f; + } + + // if(idOnSpline == 4){ + // int kasfdjsakf = 1; + // } + + if (!bIsEndPoint && !bSpecialEndNode && mCount > 1 && ((idOnSpline + 1) < GSDSpline.mNodes.Count)) + { + P1 = pos; + P2 = GSDSpline.mNodes[idOnSpline + 1].pos; + + if (bIsNone) + { + tGrade = 0f; + } + else + { + tDist = Vector2.Distance(new Vector2(P1.x, P1.z), new Vector2(P2.x, P2.z)); + tGrade = ((P2.y - P1.y) / tDist) * 100; + } + GradeToNextValue = tGrade; + GradeToNext = tGrade.ToString("0.##\\%"); + } + else + { + GradeToNext = "NA"; + GradeToNextValue = 0f; + } + + if (idOnSpline > 0 && !bSpecialEndNode && mCount > 1 && ((idOnSpline - 1) >= 0)) + { + P1 = pos; + P2 = GSDSpline.mNodes[idOnSpline - 1].pos; + + if (bIsNone) + { + tGrade = 0f; + } + else + { + tDist = Vector2.Distance(new Vector2(P1.x, P1.z), new Vector2(P2.x, P2.z)); + tGrade = ((P2.y - P1.y) / tDist) * 100; + } + GradeToPrevValue = tGrade; + GradeToPrev = tGrade.ToString("0.##\\%"); + } + else + { + GradeToPrev = "NA"; + GradeToPrevValue = 0f; + } + } + + + public Vector3 FilterMaxGradeHeight(Vector3 tPos, out float MinY, out float MaxY) + { + Vector3 tVect = tPos; + tVect.y = pos.y; + float CurrentDistance = Vector2.Distance(new Vector2(pos.x, pos.z), new Vector2(tPos.x, tPos.z)); + // float CurrentDistance2 = Vector3.Distance(pos,tVect); + // float CurrentYDiff = tPos.y - pos.y; + // float CurrentGrade = CurrentYDiff/CurrentDistance; + //Get max/min grade height position for this currrent tDist distance: + MaxY = (GSDSpline.tRoad.opt_MaxGrade * CurrentDistance) + pos.y; + MinY = pos.y - (GSDSpline.tRoad.opt_MaxGrade * CurrentDistance); + + //(tPos.y-pos.y)/CurrentDistance + + + // float DifferenceFromMax = -1; + if (tPos.y > MaxY) + { + // DifferenceFromMax = tPos.y - MaximumY; + tPos.y = MaxY; + } + if (tPos.y < MinY) + { + // DifferenceFromMax = MinimumY - tPos.y; + tPos.y = MinY; + } + + return tPos; + } + + + public void EnsureGradeValidity(int iStart = -1, bool bIsAddToEnd = false) + { + if (GSDSpline == null) + { + return; + } + GSDSplineN PrevNode = null; + GSDSplineN NextNode = null; + + if (bIsAddToEnd && GSDSpline.GetNodeCount() > 0) + { + PrevNode = GSDSpline.mNodes[GSDSpline.GetNodeCount() - 1]; + } + else + { + if (iStart == -1) + { + PrevNode = GSDSpline.GetPrevLegitimateNode(idOnSpline); + } + else + { + PrevNode = GSDSpline.GetPrevLegitimateNode(iStart); + } + } + if (PrevNode == null) + { + return; + } + Vector3 tVect = transform.position; + + float tMinY1 = 0f; + float tMinY2 = 0f; + float tMaxY1 = 0f; + float tMaxY2 = 0f; + if (PrevNode != null) + { + PrevNode.FilterMaxGradeHeight(tVect, out tMinY1, out tMaxY1); + } + if (NextNode != null) + { + NextNode.FilterMaxGradeHeight(tVect, out tMinY2, out tMaxY2); + } + + bool bPrevNodeGood = false; + bool bNextNodeGood = false; + + if (tVect.y > tMinY1 && tVect.y < tMaxY1) + { + bPrevNodeGood = true; + } + if (tVect.y > tMinY2 && tVect.y < tMaxY2) + { + bNextNodeGood = true; + } + + if (!bPrevNodeGood && !bNextNodeGood && PrevNode != null && NextNode != null) + { + float tMaxY3 = Mathf.Min(tMaxY1, tMaxY2); + float tMinY3 = Mathf.Max(tMinY1, tMinY2); + if (tVect.y < tMinY3) + { + tVect.y = tMinY3; + } + else if (tVect.y > tMaxY3) + { + tVect.y = tMaxY3; + } + } + else + { + if (!bPrevNodeGood && PrevNode != null) + { + if (tVect.y < tMinY1) + { + tVect.y = tMinY1; + } + else if (tVect.y > tMaxY1) + { + tVect.y = tMaxY1; + } + } + else if (!bNextNodeGood && NextNode != null) + { + if (tVect.y < tMinY2) + { + tVect.y = tMinY2; + } + else if (tVect.y > tMaxY2) + { + tVect.y = tMaxY2; + } + } + } + + transform.position = tVect; + } + #endregion + + + #region "Util" + public void ResetNavigationData() + { + id_connected = null; + id_connected = new List(); + node_connected = null; + node_connected = new List(); + } + + + public void BreakConnection() + { + GSDSplineN tNode2 = SpecialNodeCounterpart; + + if (bSpecialEndNode_IsStart) + { + GSDSpline.bSpecialStartControlNode = false; + GSDSpline.bSpecialEndNode_IsStart_Delay = false; + } + else if (bSpecialEndNode_IsEnd) + { + GSDSpline.bSpecialEndControlNode = false; + GSDSpline.bSpecialEndNode_IsEnd_Delay = false; + } + if (tNode2.bSpecialEndNode_IsStart) + { + tNode2.GSDSpline.bSpecialStartControlNode = false; + tNode2.GSDSpline.bSpecialEndNode_IsStart_Delay = false; + } + else if (tNode2.bSpecialEndNode_IsEnd) + { + tNode2.GSDSpline.bSpecialEndControlNode = false; + tNode2.GSDSpline.bSpecialEndNode_IsEnd_Delay = false; + } + + SpecialNodeCounterpart = null; + bSpecialEndNode = false; + bSpecialEndNode_IsEnd = false; + bSpecialEndNode_IsStart = false; + bSpecialRoadConnPrimary = false; + tNode2.SpecialNodeCounterpart = null; + tNode2.bSpecialEndNode = false; + tNode2.bSpecialEndNode_IsEnd = false; + tNode2.bSpecialEndNode_IsStart = false; + tNode2.bSpecialRoadConnPrimary = false; + + tNode2.SpecialNodeCounterpart_Master.bSpecialRoadConnPrimary = false; + SpecialNodeCounterpart_Master.bSpecialRoadConnPrimary = false; + try + { + Object.DestroyImmediate(tNode2.transform.gameObject); + Object.DestroyImmediate(transform.gameObject); + } + catch (MissingReferenceException) + { + + } + } + + + public void SetupSplinationLimits() + { + //Disallowed nodes: + if (!CanSplinate()) + { + MinSplination = tTime; + MaxSplination = tTime; + return; + } + + //Figure out min splination: + GSDSplineN tNode = null; + MinSplination = tTime; + for (int index = idOnSpline; index >= 0; index--) + { + tNode = GSDSpline.mNodes[index]; + if (tNode.CanSplinate()) + { + MinSplination = tNode.tTime; + } + else + { + break; + } + } + + //Figure out max splination: + MaxSplination = tTime; + int mCount = GSDSpline.GetNodeCount(); + for (int index = idOnSpline; index < mCount; index++) + { + tNode = GSDSpline.mNodes[index]; + if (tNode.CanSplinate()) + { + MaxSplination = tNode.tTime; + } + else + { + break; + } + } + } + #endregion + + + #region "Cut materials storage and setting" + public GameObject RoadCut_world = null; + public GameObject ShoulderCutR_world = null; + public GameObject ShoulderCutL_world = null; + public Material[] RoadCut_world_Mats; + public Material[] ShoulderCutR_world_Mats; + public Material[] ShoulderCutL_world_Mats; + + public GameObject RoadCut_marker = null; + public GameObject ShoulderCutR_marker = null; + public GameObject ShoulderCutL_marker = null; + public Material[] RoadCut_marker_Mats; + public Material[] ShoulderCutR_marker_Mats; + public Material[] ShoulderCutL_marker_Mats; + + public PhysicMaterial RoadCut_PhysicMat; + public PhysicMaterial ShoulderCutR_PhysicMat; + public PhysicMaterial ShoulderCutL_PhysicMat; + + + /// + /// Stores the cut materials. For use in UpdateCuts(). See UpdateCuts() in this code file for further description of this system. + /// + public void StoreCuts() + { + //Buffers: + MeshRenderer MR = null; + MeshCollider MC = null; + + //World cuts first: + if (RoadCut_world != null) + { + MR = RoadCut_world.GetComponent(); + MC = RoadCut_world.GetComponent(); + if (MR != null) + { + RoadCut_world_Mats = MR.sharedMaterials; + } + if (MC != null) + { + RoadCut_PhysicMat = MC.material; + } + RoadCut_world = null;//Nullify reference only + } + if (ShoulderCutR_world != null) + { + MR = ShoulderCutR_world.GetComponent(); + MC = ShoulderCutR_world.GetComponent(); + if (MR != null) + { + ShoulderCutR_world_Mats = MR.sharedMaterials; + } + if (MC != null) + { + ShoulderCutR_PhysicMat = MC.material; + } + ShoulderCutR_world = null; + } + if (ShoulderCutL_world != null) + { + MR = ShoulderCutL_world.GetComponent(); + MC = ShoulderCutL_world.GetComponent(); + if (MR != null) + { + ShoulderCutL_world_Mats = MR.sharedMaterials; + } + if (MC != null) + { + ShoulderCutL_PhysicMat = MC.material; + } + ShoulderCutL_world = null; + } + //Markers: + if (RoadCut_marker != null) + { + MR = RoadCut_marker.GetComponent(); + if (MR != null) + { + RoadCut_marker_Mats = MR.sharedMaterials; + } + RoadCut_marker = null; + } + if (ShoulderCutR_marker != null) + { + MR = ShoulderCutR_marker.GetComponent(); + if (MR != null) + { + ShoulderCutR_marker_Mats = MR.sharedMaterials; + } + ShoulderCutR_marker = null; + } + if (ShoulderCutL_marker != null) + { + MR = ShoulderCutL_marker.GetComponent(); + if (MR != null) + { + ShoulderCutL_marker_Mats = MR.sharedMaterials; + } + ShoulderCutL_marker = null; + } + } + + + /// + /// Updates the cut materials. Called upon creation of the cuts to set the newly cut materials to previously set materials. + /// For instance, if the user set a material on a road cut, and then regenerated the road, this function will apply the mats that the user applied. + /// + public void UpdateCuts() + { + //Buffers: + MeshRenderer MR = null; + MeshCollider MC = null; + + //World: + if (RoadCut_world_Mats != null && RoadCut_world_Mats.Length > 0 && RoadCut_world) + { + MR = RoadCut_world.GetComponent(); + if (!MR) + { + RoadCut_world.AddComponent(); + } + if (MR != null) + { + MR.materials = RoadCut_world_Mats; + } + } + if (RoadCut_PhysicMat != null && RoadCut_world) + { + MC = RoadCut_world.GetComponent(); + if (MC != null) + { + MC.material = RoadCut_PhysicMat; + } + } + + if (ShoulderCutR_world_Mats != null && ShoulderCutR_world_Mats.Length > 0 && ShoulderCutR_world) + { + MR = ShoulderCutR_world.GetComponent(); + if (!MR) + { + ShoulderCutR_world.AddComponent(); + } + if (MR != null) + { + MR.materials = ShoulderCutR_world_Mats; + } + } + if (ShoulderCutR_PhysicMat != null && ShoulderCutR_world) + { + MC = ShoulderCutR_world.GetComponent(); + if (MC != null) + { + MC.material = ShoulderCutR_PhysicMat; + } + } + + if (ShoulderCutL_world_Mats != null && ShoulderCutL_world_Mats.Length > 0 && ShoulderCutL_world) + { + MR = ShoulderCutL_world.GetComponent(); + if (!MR) + { + ShoulderCutL_world.AddComponent(); + } + if (MR != null) + { + MR.materials = ShoulderCutL_world_Mats; + } + } + if (ShoulderCutL_PhysicMat != null && ShoulderCutL_world) + { + MC = ShoulderCutL_world.GetComponent(); + if (MC != null) + { + MC.material = ShoulderCutL_PhysicMat; + } + } + + //Markers: + if (RoadCut_marker_Mats != null && RoadCut_marker_Mats.Length > 0 && RoadCut_marker) + { + MR = RoadCut_marker.GetComponent(); + if (!MR) + { + RoadCut_marker.AddComponent(); + } + if (MR != null) + { + MR.materials = RoadCut_marker_Mats; + } + } + if (ShoulderCutR_marker_Mats != null && ShoulderCutR_marker_Mats.Length > 0 && ShoulderCutR_marker) + { + MR = ShoulderCutR_marker.GetComponent(); + if (!MR) + { + ShoulderCutR_marker.AddComponent(); + } + if (MR != null) + { + MR.materials = ShoulderCutR_marker_Mats; + } + } + if (ShoulderCutL_marker_Mats != null && ShoulderCutL_marker_Mats.Length > 0 && ShoulderCutL_marker) + { + MR = ShoulderCutL_marker.GetComponent(); + if (!MR) + { + ShoulderCutL_marker.AddComponent(); + } + if (MR != null) + { + MR.materials = ShoulderCutL_marker_Mats; + } + } + + if (RoadCut_marker != null) + { + MR = RoadCut_marker.GetComponent(); + if (MR == null || MR.sharedMaterial == null) + { + Object.DestroyImmediate(RoadCut_marker); + } + } + if (ShoulderCutR_marker != null) + { + MR = ShoulderCutR_marker.GetComponent(); + if (MR == null || MR.sharedMaterial == null) + { + Object.DestroyImmediate(ShoulderCutR_marker); + } + } + if (ShoulderCutL_marker != null) + { + MR = ShoulderCutL_marker.GetComponent(); + if (MR == null || MR.sharedMaterial == null) + { + Object.DestroyImmediate(ShoulderCutL_marker); + } + } + } + + + /// + /// Clears the cut materials. Called when user hits button on road editor inspector gui. + /// + public void ClearCuts() + { + RoadCut_world_Mats = null; + ShoulderCutR_world_Mats = null; + ShoulderCutL_world_Mats = null; + RoadCut_marker_Mats = null; + ShoulderCutR_marker_Mats = null; + ShoulderCutL_marker_Mats = null; + RoadCut_PhysicMat = null; + ShoulderCutR_PhysicMat = null; + ShoulderCutL_PhysicMat = null; + } + #endregion + + + #region "Bridges" + public void BridgeToggleStart() + { + //If switching to end, find associated bridge + if (bIsBridgeStart) + { + BridgeStart(); + } + else + { + BridgeDestroy(); + } + } + + + public void BridgeToggleEnd() + { + //If switching to end, find associated bridge + if (bIsBridgeEnd) + { + int mCount = GSDSpline.GetNodeCount(); + GSDSplineN tNode = null; + for (int i = 1; i < (mCount - 1); i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode.bIsBridgeStart && !tNode.bIsBridgeMatched) + { + tNode.BridgeToggleStart(); + if (tNode.bIsBridgeMatched && tNode.BridgeCounterpartNode == this) + { return; } + } + } + } + else + { + BridgeDestroy(); + } + } + + + private void BridgeStart() + { + //Cycle through nodes until you find another end or another start (in this case, no creation, encountered another bridge): + int EndID = idOnSpline + 1; + int mCount = GSDSpline.GetNodeCount(); + if (bIsEndPoint) + { + //Attempted to make end point node a bridge node: + bIsBridgeStart = false; + return; + } + if (EndID >= mCount) + { + //Attempted to make last node a bridge node: + bIsBridgeStart = false; + return; + } + else if (idOnSpline == 0) + { + //Attempted to make first node a bridge node: + bIsBridgeStart = false; + return; + } + + bIsBridgeMatched = false; + BridgeCounterpartNode = null; + int StartI = idOnSpline + 1; + GSDSplineN tNode = null; + for (int i = StartI; i < mCount; i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode.bIsIntersection) + { + //Encountered intersection. End search. + return; + } + if (tNode.bIsBridgeStart) + { + //Encountered another bridge. Return: + return; + } + if (tNode.bIgnore) + { + continue; + } + if (tNode.bIsBridgeEnd) + { + bIsBridgeMatched = true; + tNode.bIsBridgeMatched = true; + BridgeCounterpartNode = tNode; + tNode.BridgeCounterpartNode = this; + GSDSpline.Setup_Trigger(); + return; + } + } + } + + + private void BridgeDestroy() + { + if (BridgeCounterpartNode != null) + { + BridgeCounterpartNode.BridgeResetValues(); + } + BridgeResetValues(); + GSDSpline.Setup_Trigger(); + } + + + public void BridgeResetValues() + { + bIsBridge = false; + bIsBridgeStart = false; + bIsBridgeEnd = false; + bIsBridgeMatched = false; + BridgeCounterpartNode = null; + } + + + public bool CanBridgeStart() + { + if (bIsBridgeStart) + { + return true; + } + if (bIsBridgeEnd) + { + return false; + } + if (bIsEndPoint) + { + return false; + } + + int mCount = GSDSpline.GetNodeCount(); + + if (idOnSpline > 0) + { + if (GSDSpline.mNodes[idOnSpline - 1].bIsBridgeStart) + { + return false; + } + } + + if (idOnSpline < (mCount - 1)) + { + if (GSDSpline.mNodes[idOnSpline + 1].bIsBridgeStart) + { + return false; + } + + if (GSDSpline.bSpecialEndControlNode) + { + if ((mCount - 3 > 0) && idOnSpline == mCount - 3) + { + return false; + } + } + else + { + if ((mCount - 2 > 0) && idOnSpline == mCount - 2) + { + return false; + } + } + } + + if (GSDSpline.IsInBridge(tTime)) + { + return false; + } + + return true; + } + + + public bool CanBridgeEnd() + { + if (bIsBridgeEnd) + { return true; } + if (bIsBridgeStart) + { return false; } + if (bIsEndPoint) + { return false; } + + int mCount = GSDSpline.GetNodeCount(); + + if (idOnSpline < (mCount - 1)) + { + if (GSDSpline.bSpecialStartControlNode) + { + if (idOnSpline == 2) + { + return false; + } + } + else + { + if (idOnSpline == 1) + { + return false; + } + } + } + + for (int i = idOnSpline; i >= 0; i--) + { + if (GSDSpline.mNodes[i].bIsBridgeStart) + { + if (!GSDSpline.mNodes[i].bIsBridgeMatched) + { + return true; + } + else + { + return false; + } + } + } + + return false; + } + #endregion + + + #region "Tunnels" + public void TunnelToggleStart() + { + //If switching to end, find associated Tunnel + if (bIsTunnelStart) + { + TunnelStart(); + } + else + { + TunnelDestroy(); + } + } + + + public void TunnelToggleEnd() + { + //If switching to end, find associated Tunnel + if (bIsTunnelEnd) + { + int mCount = GSDSpline.GetNodeCount(); + GSDSplineN tNode = null; + for (int index = 1; index < (mCount - 1); index++) + { + tNode = GSDSpline.mNodes[index]; + if (tNode.bIsTunnelStart && !tNode.bIsTunnelMatched) + { + tNode.TunnelToggleStart(); + if (tNode.bIsTunnelMatched && tNode.TunnelCounterpartNode == this) + { + return; + } + } + } + } + else + { + TunnelDestroy(); + } + } + + + private void TunnelStart() + { + //Cycle through nodes until you find another end or another start (in this case, no creation, encountered another Tunnel): + int EndID = idOnSpline + 1; + int mCount = GSDSpline.GetNodeCount(); + if (bIsEndPoint) + { + //Attempted to make end point node a Tunnel node: + bIsTunnelStart = false; + return; + } + if (EndID >= mCount) + { + //Attempted to make last node a Tunnel node: + bIsTunnelStart = false; + return; + } + else if (idOnSpline == 0) + { + //Attempted to make first node a Tunnel node: + bIsTunnelStart = false; + return; + } + + bIsTunnelMatched = false; + TunnelCounterpartNode = null; + int StartI = idOnSpline + 1; + GSDSplineN tNode = null; + for (int i = StartI; i < mCount; i++) + { + tNode = GSDSpline.mNodes[i]; + if (tNode.bIsIntersection) + { + //Encountered intersection. End search. + return; + } + if (tNode.bIsTunnelStart) + { + //Encountered another Tunnel. Return: + return; + } + if (tNode.bIgnore) + { + continue; + } + if (tNode.bIsTunnelEnd) + { + bIsTunnelMatched = true; + tNode.bIsTunnelMatched = true; + TunnelCounterpartNode = tNode; + tNode.TunnelCounterpartNode = this; + GSDSpline.Setup_Trigger(); + return; + } + } + } + + + private void TunnelDestroy() + { + if (TunnelCounterpartNode != null) + { + TunnelCounterpartNode.TunnelResetValues(); + } + TunnelResetValues(); + GSDSpline.Setup_Trigger(); + } + + + public void TunnelResetValues() + { + bIsTunnel = false; + bIsTunnelStart = false; + bIsTunnelEnd = false; + bIsTunnelMatched = false; + TunnelCounterpartNode = null; + } + + + public bool CanTunnelStart() + { + if (bIsTunnelStart) + { return true; } + if (bIsTunnelEnd) + { return false; } + if (bIsEndPoint) + { return false; } + + int mCount = GSDSpline.GetNodeCount(); + + if (idOnSpline > 0) + { + if (GSDSpline.mNodes[idOnSpline - 1].bIsTunnelStart) + { + return false; + } + } + + if (idOnSpline < (mCount - 1)) + { + if (GSDSpline.mNodes[idOnSpline + 1].bIsTunnelStart) + { + return false; + } + + if (GSDSpline.bSpecialEndControlNode) + { + if ((mCount - 3 > 0) && idOnSpline == mCount - 3) + { + return false; + } + } + else + { + if ((mCount - 2 > 0) && idOnSpline == mCount - 2) + { + return false; + } + } + } + + if (GSDSpline.IsInTunnel(tTime)) + { + return false; + } + + return true; + } + + + public bool CanTunnelEnd() + { + if (bIsTunnelEnd) + { return true; } + if (bIsTunnelStart) + { return false; } + if (bIsEndPoint) + { return false; } + + int mCount = GSDSpline.GetNodeCount(); + + if (idOnSpline < (mCount - 1)) + { + if (GSDSpline.bSpecialStartControlNode) + { + if (idOnSpline == 2) + { + return false; + } + } + else + { + if (idOnSpline == 1) + { + return false; + } + } + } + + for (int i = idOnSpline; i >= 0; i--) + { + if (GSDSpline.mNodes[i].bIsTunnelStart) + { + if (!GSDSpline.mNodes[i].bIsTunnelMatched) + { + return true; + } + else + { + return false; + } + } + } + + return false; + } + #endregion + + + #region "Is straight line to next node" + public bool IsStraight() + { + int id1 = idOnSpline - 1; + int id2 = idOnSpline + 1; + int id3 = idOnSpline + 2; + int mCount = GSDSpline.GetNodeCount(); + + if (id1 > -1 && id1 < mCount) + { + if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id1].pos)) + { + return false; + } + } + + if (id2 > -1 && id2 < mCount) + { + if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id2].pos)) + { + return false; + } + } + + if (id3 > -1 && id3 < mCount) + { + if (!IsApproxTwoThirds(ref pos, GSDSpline.mNodes[id3].pos)) + { + return false; + } + } + + return true; + } + + + private static bool IsApproxTwoThirds(ref Vector3 V1, Vector3 V2) + { + int cCount = 0; + if (GSDRootUtil.IsApproximately(V1.x, V2.x, 0.02f)) + { + cCount += 1; + } + if (GSDRootUtil.IsApproximately(V1.y, V2.y, 0.02f)) + { + cCount += 1; + } + if (GSDRootUtil.IsApproximately(V1.z, V2.z, 0.02f)) + { + cCount += 1; + } + + if (cCount == 2) + { + return true; + } + else + { + return false; + } + } + #endregion +#endif + + + #region "Non-editor util" + public bool CanSplinate() + { + if (bSpecialEndNode) + {// || bIsBridge_PreNode || bIsBridge_PostNode){ + return false; + } + else + { + return true; + } + } + + + public bool IsLegitimate() + { + if (bIsIntersection || bSpecialEndNode) + {// || bIsBridge_PreNode || bIsBridge_PostNode){ + return false; + } + else + { + return true; + } + } + + + public bool IsLegitimateGrade() + { + if (bSpecialEndNode) + {// || bIsBridge_PreNode || bIsBridge_PostNode){ + return false; + } + else + { + return true; + } + } + #endregion + + + void Start() + { +#if UNITY_EDITOR + //Do nothing. +#else + this.enabled = false; +#endif + } + + + public void ToggleHideFlags(bool bIsHidden) + { + if (bIsHidden) + { + this.hideFlags = HideFlags.HideInHierarchy; + transform.hideFlags = HideFlags.HideInHierarchy; + } + else + { + this.hideFlags = HideFlags.None; + transform.hideFlags = HideFlags.None; + } + } } \ No newline at end of file diff --git a/Spline/GSDSplineRepair.cs b/Spline/GSDSplineRepair.cs index c7a1dbb2..bb67326f 100644 --- a/Spline/GSDSplineRepair.cs +++ b/Spline/GSDSplineRepair.cs @@ -1,12 +1,17 @@ -using System.Collections; +#region Imports +using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; +#endregion + + #if UNITY_EDITOR + + [ExecuteInEditMode] -public class GSDSplineRepair : MonoBehaviour -{ - +public class GSDSplineRepair : MonoBehaviour +{ public void RemoveLastNode() { GSDSplineC spline = GetComponent(); @@ -23,11 +28,11 @@ public override void OnInspectorGUI() { DrawDefaultInspector(); - GSDSplineRepair repair = (GSDSplineRepair)target; + GSDSplineRepair repair = (GSDSplineRepair) target; if (GUILayout.Button("Remove last node")) { repair.RemoveLastNode(); } } -} +} #endif \ No newline at end of file diff --git a/Traffic/traffic-readme.md b/Traffic/traffic-readme.md index d6b1f2cd..ad281e97 100755 --- a/Traffic/traffic-readme.md +++ b/Traffic/traffic-readme.md @@ -1,33 +1,33 @@ - -# Warning -Any code relating to the traffic system is in early alpha and not ready for production. Use at own risk. - -## Directory -This directory contains experimental traffic implementations not ready for production and contains the code for the traffic project. This will be contained within the Road Architect project due to its heavy integration with the Road Architect system, but should be able to be used on other implementations. - -https://github.com/embeddedt/RoadArchitect/projects/3 - -## State summary -The code is 4 years old and needs work before including in the repo. - -## Features of current implementation -- Hundreds of cars at once across many square km -- Uses forward cached bucket lookups of spline system to facilitate tracing. -- Except for the forward lookups on the spline, it works very similar to real-life lidar systems. -- Each agent (car) is capable of the following: - - Traveling from one node to another node. - - Evasion of objects in the road. - - Evasion of objects in non-road parts (shoulders) when already evading other objects. - - Stopping at intersections gracefully with other vehicles. - - Communicating with other agents on who should go first in situations (object in road). - - LOD like system which degrades CPU requirements per agent the further they are away from player (single player implementation only). - - Pull over to shoulder for arbitrary reasons (emergency etc). - -## Technical details -- Each car is their own agent, with vision cones/cylinders via ray casting ( https://docs.unity3d.com/ScriptReference/Physics.Raycast.html ) -- This system gracefully degrades if user is further away from vehicles. e.g. they go on "rails" without collision. -- There is caching on spline lookups on Road Architect explicitly written for the traffic system. "Buckets" are established to facilitate faster lookups. Line ~428 at https://github.com/embeddedt/RoadArchitect/blob/master/Spline/GSDSplineC.cs#L428 . This caching is handled internally by RA. - -## Active Issues -- System was written in early development of RA and needs updated heavily. Organizing and pruning old code is necessary before inclusion of the code files. -- System needs adapted to whatever best vehicle solution (preferably open-source). + +# Warning +Any code relating to the traffic system is in early alpha and not ready for production. Use at own risk. + +## Directory +This directory contains experimental traffic implementations not ready for production and contains the code for the traffic project. This will be contained within the Road Architect project due to its heavy integration with the Road Architect system, but should be able to be used on other implementations. + +https://github.com/embeddedt/RoadArchitect/projects/3 + +## State summary +The code is 4 years old and needs work before including in the repo. + +## Features of current implementation +- Hundreds of cars at once across many square km +- Uses forward cached bucket lookups of spline system to facilitate tracing. +- Except for the forward lookups on the spline, it works very similar to real-life lidar systems. +- Each agent (car) is capable of the following: + - Traveling from one node to another node. + - Evasion of objects in the road. + - Evasion of objects in non-road parts (shoulders) when already evading other objects. + - Stopping at intersections gracefully with other vehicles. + - Communicating with other agents on who should go first in situations (object in road). + - LOD like system which degrades CPU requirements per agent the further they are away from player (single player implementation only). + - Pull over to shoulder for arbitrary reasons (emergency etc). + +## Technical details +- Each car is their own agent, with vision cones/cylinders via ray casting ( https://docs.unity3d.com/ScriptReference/Physics.Raycast.html ) +- This system gracefully degrades if user is further away from vehicles. e.g. they go on "rails" without collision. +- There is caching on spline lookups on Road Architect explicitly written for the traffic system. "Buckets" are established to facilitate faster lookups. Line ~428 at https://github.com/embeddedt/RoadArchitect/blob/master/Spline/GSDSplineC.cs#L428 . This caching is handled internally by RA. + +## Active Issues +- System was written in early development of RA and needs updated heavily. Organizing and pruning old code is necessary before inclusion of the code files. +- System needs adapted to whatever best vehicle solution (preferably open-source). diff --git a/index.html.meta b/index.html.meta new file mode 100644 index 00000000..01cc7823 --- /dev/null +++ b/index.html.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e04a2aed7aae15746a7d8722c59f7ba6 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: