public override void OnInspectorGUI() { m_editorUtils.Initialize(); // Do not remove this! m_spawnerSettings = (SpawnerSettings)target; string message = m_editorUtils.GetTextValue("Intro");; EditorGUILayout.HelpBox(message, MessageType.Info, true); if (GUILayout.Button(m_editorUtils.GetContent("AddToScene"))) { m_spawnerSettings.CreateSpawner(); } GUILayout.Label(m_editorUtils.GetContent("SpawnRulePreview"), m_editorUtils.Styles.heading); GaiaResource resource = m_spawnerSettings.m_resources;// (GaiaResource)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_spawnerSettings.m_resourcesGUID), typeof(GaiaResource)); foreach (SpawnRule rule in m_spawnerSettings.m_spawnerRules) { m_editorUtils.LabelField("Name", new GUIContent(rule.m_name)); m_editorUtils.LabelField("Type", new GUIContent(rule.m_resourceType.ToString())); Texture2D resourceTexture = SpawnerEditor.GetSpawnRulePreviewTexture(rule, resource); if (resourceTexture != null) { m_editorUtils.Image(resourceTexture, 100, 100); } } }
/// <summary> /// Create the terrain defined by these settings - and apply the resources to it /// </summary> public void CreateTerrain(GaiaResource resources) { Terrain[,] world; //Update the resouces ny associating them with their assets resources.AssociateAssets(); //Update the session GaiaSessionManager sessionMgr = GaiaSessionManager.GetSessionManager(); if (sessionMgr != null && sessionMgr.IsLocked() != true) { //Update terrain settings in session sessionMgr.m_session.m_terrainWidth = m_tilesX * m_terrainSize; sessionMgr.m_session.m_terrainDepth = m_tilesZ * m_terrainSize; sessionMgr.m_session.m_terrainHeight = m_terrainHeight; //Add the defaults sessionMgr.AddDefaults(this); //Set the sea level - but only if it is zero - if not zero then its been deliberately set if (Gaia.GaiaUtils.Math_ApproximatelyEqual(sessionMgr.m_session.m_seaLevel, 0f)) { sessionMgr.SetSeaLevel(m_seaLevel); } //Grab the resources scriptable object sessionMgr.AddResource(resources); //Adjust them if they are different to the defaults resources.ChangeSeaLevel(sessionMgr.m_session.m_seaLevel); //Then add the operation sessionMgr.AddOperation(GetTerrainCreationOperation(resources)); } //Create the terrains array world = new Terrain[m_tilesX, m_tilesZ]; //And iterate through and create each terrain for (int x = 0; x < m_tilesX; x++) { for (int z = 0; z < m_tilesZ; z++) { CreateTile(x, z, ref world, resources); } } //Now join them together and remove their seams RemoveWorldSeams(ref world); }
public GaiaOperation GetTerrainCreationOperation(GaiaResource resources) { //Then add the operation GaiaOperation op = new GaiaOperation(); op.m_description = "Creating terrain"; op.m_generatedByID = m_defaultsID; op.m_generatedByName = this.name; op.m_generatedByType = this.GetType().ToString(); op.m_isActive = true; op.m_operationDateTime = DateTime.Now.ToString(); op.m_operationType = GaiaOperation.OperationType.CreateTerrain; #if UNITY_EDITOR op.m_operationDataJson = new string[2]; string ap = AssetDatabase.GetAssetPath(this); if (string.IsNullOrEmpty(ap)) { op.m_operationDataJson[0] = "GaiaDefaults.asset"; } else { op.m_operationDataJson[0] = AssetDatabase.GetAssetPath(this); } ap = AssetDatabase.GetAssetPath(resources); if (string.IsNullOrEmpty(ap)) { op.m_operationDataJson[1] = "GaiaResources.asset"; } else { op.m_operationDataJson[1] = AssetDatabase.GetAssetPath(resources); } #endif return(op); }
public GaiaOperation GetTerrainCreationOperation(GaiaResource resources) { // //Then add the operation // GaiaOperation op = new GaiaOperation(); // op.m_description = "Creating terrain"; // op.m_generatedByID = m_defaultsID; // op.m_generatedByName = this.name; // op.m_generatedByType = this.GetType().ToString(); // op.m_isActive = true; // op.m_operationDateTime = DateTime.Now.ToString(); // op.m_operationType = GaiaOperation.OperationType.CreateTerrain; //#if UNITY_EDITOR // op.m_operationDataJson = new string[2]; // string ap = AssetDatabase.GetAssetPath(this); // if (string.IsNullOrEmpty(ap)) // { // op.m_operationDataJson[0] = "GaiaDefaults.asset"; // } // else // { // op.m_operationDataJson[0] = AssetDatabase.GetAssetPath(this); // } // ap = AssetDatabase.GetAssetPath(resources); // if (string.IsNullOrEmpty(ap)) // { // op.m_operationDataJson[1] = "GaiaResources.asset"; // } // else // { // op.m_operationDataJson[1] = AssetDatabase.GetAssetPath(resources); // } //#endif //return op; return(null); }
/// <summary> /// Write the content of the object out as C#, and assign the content of the original object to it /// </summary> /// <param name="src">Object to dump</param> /// <param name="name">Name of the variable to dump it to</param> /// <param name="tabDepth">Number of prefix tabs to prepend to each line</param> /// <param name="prefixType">Show the type of the object when creating it</param> /// <param name="instantiate">Write code to instantiate the object</param> /// <returns></returns> private string DumpObject(object src, string name, int tabDepth, bool prefixType = true, bool instantiate = true) { if (src == null) { return(""); } StringBuilder retS = new StringBuilder(); FieldInfo[] fields = src.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); string tabs = ""; for (int td = 0; td < tabDepth; td++) { tabs += "\t"; } if (instantiate) { if (!prefixType) { if (src.GetType().BaseType == typeof(UnityEngine.ScriptableObject)) { retS.AppendLine(string.Format("{0}{2} = ScriptableObject.CreateInstance<{1}>();", tabs, src.GetType(), name)); } else if (src.GetType().BaseType == typeof(UnityEngine.MonoBehaviour)) { retS.AppendLine(string.Format("{0}{2} = {2}.AddComponent<{1}>();", tabs, src.GetType(), name)); } else { retS.AppendLine(string.Format("{0}{1} = new {2}();", tabs, name, src.GetType())); } } else { if (src.GetType().BaseType == typeof(UnityEngine.ScriptableObject)) { retS.AppendLine(string.Format("{0}{1} {2} = ScriptableObject.CreateInstance<{1}>();", tabs, src.GetType(), name)); } else if (src.GetType().BaseType == typeof(UnityEngine.MonoBehaviour)) { retS.AppendLine(string.Format("{0}GameObject go = new GameObject();", tabs)); retS.AppendLine(string.Format("{0}go.name = \"{1}\";", tabs, ((UnityEngine.MonoBehaviour)src).gameObject.name)); retS.AppendLine(string.Format("{0}{1} {2} = go.AddComponent<{1}>();", tabs, src.GetType(), name)); } else { retS.AppendLine(string.Format("{0}{1} {2} = new {1}();", tabs, src.GetType(), name)); } } } foreach (FieldInfo f in fields) { if (f.FieldType == typeof(System.String)) { retS.AppendLine(string.Format("{0}{1}.{2} = \"{3}\";", tabs, name, f.Name, f.GetValue(src))); } else if (f.FieldType == typeof(System.Single)) { retS.AppendLine(string.Format("{0}{1}.{2} = {3}f;", tabs, name, f.Name, f.GetValue(src))); } else if (f.FieldType == typeof(System.Double)) { retS.AppendLine(string.Format("{0}{1}.{2} = {3};", tabs, name, f.Name, f.GetValue(src))); } else if (f.FieldType == typeof(System.Int32) || f.FieldType == typeof(System.UInt32) || f.FieldType == typeof(System.Int64) || f.FieldType == typeof(System.UInt64)) { retS.AppendLine(string.Format("{0}{1}.{2} = {3};", tabs, name, f.Name, f.GetValue(src))); } else if (f.FieldType == typeof(System.Boolean)) { //Debug.Log(name + " " + f.Name + " " + f.FieldType + " " + f.GetValue(src).ToString()); if (f.GetValue(src).ToString() == "True") { retS.AppendLine(string.Format("{0}{1}.{2} = true;", tabs, name, f.Name)); } else { retS.AppendLine(string.Format("{0}{1}.{2} = false;", tabs, name, f.Name)); } } else if (f.FieldType == typeof(UnityEngine.Texture2D)) { if (((UnityEngine.Texture2D)f.GetValue(src)) != null) { retS.AppendLine(string.Format("{0}{1}.{2} = GetTexture2D(\"{3}\");", tabs, name, f.Name, AssetDatabase.GetAssetPath(((UnityEngine.Texture2D)f.GetValue(src)).GetInstanceID()))); } else { retS.AppendLine(string.Format("{0}{1}.{2} = null;", tabs, name, f.Name)); } } else if (f.FieldType == typeof(UnityEngine.AnimationCurve)) { if (((UnityEngine.AnimationCurve)f.GetValue(src)) != null) { UnityEngine.AnimationCurve curve = ((UnityEngine.AnimationCurve)f.GetValue(src)); retS.AppendLine(string.Format("{0}{1}.{2} = new UnityEngine.AnimationCurve();", tabs, name, f.Name)); foreach (Keyframe frame in curve.keys) { retS.AppendLine(string.Format("{0}{1}.{2}.AddKey({3}f,{4}f);", tabs, name, f.Name, frame.time, frame.value)); } } else { retS.AppendLine(string.Format("{0}{1}.{2} = null;", tabs, name, f.Name)); } } else if (f.FieldType == typeof(UnityEngine.Color)) { Color c = ((UnityEngine.Color)f.GetValue(src)); retS.AppendLine(string.Format("{0}{1}.{2} = new UnityEngine.Color({3}f,{4}f,{5}f,{6}f);", tabs, name, f.Name, c.r, c.b, c.g, c.a)); } else if (f.FieldType == typeof(UnityEngine.GameObject)) { if (((UnityEngine.GameObject)f.GetValue(src)) != null) { retS.AppendLine(string.Format("{0}{1}.{2} = GetGameObject(\"{3}\");", tabs, name, f.Name, AssetDatabase.GetAssetPath(((UnityEngine.GameObject)f.GetValue(src)).GetInstanceID()))); } else { retS.AppendLine(string.Format("{0}{1}.{2} = null;", tabs, name, f.Name)); } } else if (f.FieldType.IsEnum == true) { string enumValue = ""; foreach (var value in Enum.GetValues(f.FieldType)) { if ((int)value == (int)f.GetValue(src)) { enumValue = value.ToString(); } } retS.AppendLine(string.Format("{0}{1}.{2} = {3}.{4};", tabs, name, f.Name, f.FieldType.ToString().Replace("+", "."), enumValue)); } else if (f.FieldType == typeof(Gaia.SpawnRuleExtension[])) { retS.AppendLine(string.Format("{0}{1}.{2} = new {3}[{4}];", tabs, name, f.Name, f.FieldType.ToString().Replace("[]", ""), ((System.Array)f.GetValue(src)).GetLength(0))); for (int idx = 0; idx < ((System.Array)f.GetValue(src)).GetLength(0); idx++) { retS.AppendLine(string.Format("{0}\t{1}.{2}[{3}] = GetSpawnRuleExtension(\"{4}\");", tabs, name, f.Name, idx, AssetDatabase.GetAssetPath(((Gaia.SpawnRuleExtension)(((System.Array)f.GetValue(src)).GetValue(idx))).GetInstanceID()))); } } else if (f.FieldType == typeof(Gaia.ResourceProtoDNA)) { retS.AppendLine(string.Format("{0}{1}.{2} = new {3}();", tabs, name, f.Name, f.FieldType.ToString().Replace("[]", ""))); retS.Append(DumpObject(f.GetValue(src), string.Format("{0}.{1}", name, f.Name), tabDepth + 1, false, false)); } else if (f.FieldType == typeof(Gaia.XorshiftPlus)) { retS.AppendLine(string.Format("{0}{1}.{2} = new {3}();", tabs, name, f.Name, f.FieldType.ToString().Replace("[]", ""))); retS.Append(DumpObject(f.GetValue(src), string.Format("{0}.{1}", name, f.Name), tabDepth + 1, false, false)); } else if (f.FieldType == typeof(Gaia.GaiaResource)) { GaiaResource resource = ((Gaia.GaiaResource)f.GetValue(src)); if (resource != null) { retS.AppendLine(string.Format("{0}{1}.{2} = GetResource(\"{3}\",\"{4}\");", tabs, name, f.Name, FixFileName(m_publisherName) + "_" + FixFileName(m_extensionName) + "_" + FixFileName(resource.m_name) + ".asset", resource.m_resourcesID)); } else { retS.AppendLine(string.Format("{0}{1}.{2} = null;", tabs, name, f.Name)); } } else if (f.FieldType.IsGenericType == true) { string type = f.FieldType.ToString(); if (type.Contains("System.Collections.Generic.List")) { type = type.Substring(type.IndexOf("[") + 1); type = type.Substring(0, type.IndexOf("]")); retS.AppendLine(string.Format("{0}{1}.{2} = new List<{3}>();", tabs, name, f.Name, type)); int idx = 0; IEnumerator enumerator = ((ICollection)f.GetValue(src)).GetEnumerator(); while (enumerator.MoveNext()) { retS.AppendLine(string.Format("{0}{1}.{2}.Add(new {3}());", tabs, name, f.Name, type)); retS.Append(DumpObject(enumerator.Current, string.Format("{0}.{1}[{2}]", name, f.Name, idx++), tabDepth + 1, false, false)); } } else { retS.AppendLine(string.Format("{0}// ******* {1} {2} = {3};", tabs, name, f.FieldType, f.Name, f.GetValue(src))); } } else if (f.FieldType.BaseType == typeof(System.Array)) { retS.AppendLine(string.Format("{0}{1}.{2} = new {3}[{4}];", tabs, name, f.Name, f.FieldType.ToString().Replace("[]", ""), ((System.Array)f.GetValue(src)).GetLength(0))); for (int idx = 0; idx < ((System.Array)f.GetValue(src)).GetLength(0); idx++) { retS.Append(DumpObject(((System.Array)f.GetValue(src)).GetValue(idx), string.Format("{0}.{1}[{2}]", name, f.Name, idx), tabDepth + 1, false)); } } else if (f.FieldType == typeof(Gaia.HeightMap) || f.FieldType == typeof(Gaia.UnityHeightMap)) { //Dont export } else if (f.FieldType == typeof(UnityEngine.Transform)) { //Dont export } else if (f.FieldType == typeof(UnityEngine.LayerMask)) { //Dont export } else if (f.FieldType == typeof(System.Random)) { //Dont export } else if (f.FieldType == typeof(System.Collections.IEnumerator)) { //Dont export } else if (f.FieldType == typeof(UnityEngine.Bounds)) { //Dont export } else { retS.AppendLine(string.Format("{0}// ******* {1} {2} = {3};", tabs, name, f.FieldType, f.Name, f.GetValue(src))); } } return(retS.ToString()); }
/// <summary> /// Extract and save the resources file /// </summary> /// <param name="writer"></param> /// <param name="source"></param> private void SaveResources(StreamWriter writer, GaiaResource source) { if (writer == null) { Debug.LogError("Can not write resources, writer not supplied."); return; } if (source == null) { Debug.LogError("Can not write resources, resources not supplied."); return; } //Create extraction path string path = "Assets/GaiaExtensions/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path += m_extensionName + "/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path += Path.GetFileName(AssetDatabase.GetAssetPath(source.GetInstanceID())); GaiaResource resources = ScriptableObject.CreateInstance <Gaia.GaiaResource>(); AssetDatabase.CreateAsset(resources, path); resources.m_beachHeight = source.m_beachHeight; resources.m_name = source.m_name; resources.m_resourcesID = source.m_resourcesID; resources.m_seaLevel = source.m_seaLevel; resources.m_terrainHeight = source.m_terrainHeight; //Iterate through the prototypes SpawnCritera srcCrit, newCrit; ResourceProtoTexture srcTex, newTex; resources.m_texturePrototypes = new ResourceProtoTexture[source.m_texturePrototypes.GetLength(0)]; for (int resIdx = 0; resIdx < source.m_texturePrototypes.GetLength(0); resIdx++) { srcTex = source.m_texturePrototypes[resIdx]; newTex = new ResourceProtoTexture(); newTex.m_metalic = srcTex.m_metalic; newTex.m_name = srcTex.m_name; newTex.m_normal = srcTex.m_normal; newTex.m_offsetX = srcTex.m_offsetX; newTex.m_offsetY = srcTex.m_offsetY; newTex.m_sizeX = srcTex.m_sizeX; newTex.m_sizeY = srcTex.m_sizeY; newTex.m_smoothness = srcTex.m_smoothness; newTex.m_texture = srcTex.m_texture; newTex.m_spawnCriteria = new SpawnCritera[srcTex.m_spawnCriteria.GetLength(0)]; for (int critIdx = 0; critIdx < srcTex.m_spawnCriteria.GetLength(0); critIdx++) { srcCrit = srcTex.m_spawnCriteria[critIdx]; newCrit = new SpawnCritera(); newCrit.m_checkHeight = srcCrit.m_checkHeight; newCrit.m_checkProximity = srcCrit.m_checkProximity; newCrit.m_checkSlope = srcCrit.m_checkSlope; newCrit.m_checkTexture = srcCrit.m_checkTexture; newCrit.m_checkType = srcCrit.m_checkType; newCrit.m_heightFitness = srcCrit.m_heightFitness; newCrit.m_isActive = srcCrit.m_isActive; newCrit.m_matchingTextures = srcCrit.m_matchingTextures; newCrit.m_maxHeight = srcCrit.m_maxHeight; newTex.m_spawnCriteria[critIdx] = newCrit; } resources.m_texturePrototypes[resIdx] = newTex; } }
public override void OnInspectorGUI() { //Get our stamper m_stamper = (Stamper)target; //Init editor utils m_editorUtils.Initialize(); //Set up the box style if (m_boxStyle == null) { m_boxStyle = new GUIStyle(GUI.skin.box); m_boxStyle.normal.textColor = GUI.skin.label.normal.textColor; m_boxStyle.fontStyle = FontStyle.Bold; m_boxStyle.alignment = TextAnchor.UpperLeft; } //Setup the wrap style if (m_wrapStyle == null) { m_wrapStyle = new GUIStyle(GUI.skin.label); m_wrapStyle.wordWrap = true; } //Draw the intro m_editorUtils.DrawIntro("Stamper", "The stamper allows you to stamp features into your terrain. Click here to see a tutorial.", "http://www.procedural-worlds.com/gaia/tutorials/stamper-introduction/"); //Disable if spawning if (m_stamper.m_stampComplete != true && !m_stamper.m_cancelStamp) { GUI.enabled = false; } EditorGUI.BeginChangeCheck(); GUILayout.BeginVertical("Operations:", m_boxStyle); GUILayout.Space(20); Texture2D feature = (Texture2D)EditorGUILayout.ObjectField(GetLabel("Stamp Preview"), m_stamper.m_stampPreviewImage, typeof(Texture2D), false); GaiaResource resources = (GaiaResource)EditorGUILayout.ObjectField(GetLabel("Resources"), m_stamper.m_resources, typeof(GaiaResource), false); Gaia.GaiaConstants.FeatureOperation operation = (Gaia.GaiaConstants.FeatureOperation)EditorGUILayout.EnumPopup(GetLabel("Operation Type"), m_stamper.m_stampOperation); float stencilHeight = m_stamper.m_stencilHeight; if (operation == GaiaConstants.FeatureOperation.StencilHeight) { stencilHeight = EditorGUILayout.Slider(GetLabel("Stencil Height"), m_stamper.m_stencilHeight, -1000f, 1000f); } float blendStrength = m_stamper.m_blendStrength; if (operation == GaiaConstants.FeatureOperation.BlendHeight) { blendStrength = EditorGUILayout.Slider(GetLabel("Blend Strength"), m_stamper.m_blendStrength, 0f, 1f); } //GUILayout.Label(stamper.m_feature, GUILayout.Width(200f), GUILayout.Height(200f) ); AnimationCurve heightModifier = EditorGUILayout.CurveField(GetLabel("Transform Height"), m_stamper.m_heightModifier); int smoothIterations = m_stamper.m_smoothIterations = EditorGUILayout.IntSlider(GetLabel("Smooth Stamp"), m_stamper.m_smoothIterations, 0, 10); bool normaliseStamp = EditorGUILayout.Toggle(GetLabel("Normalise Stamp"), m_stamper.m_normaliseStamp); bool invertStamp = EditorGUILayout.Toggle(GetLabel("Invert Stamp"), m_stamper.m_invertStamp); GUILayout.EndVertical(); GUILayout.BeginVertical("Position, Rotate and Scale:", m_boxStyle); GUILayout.Space(20); //GUILayout.Label("Operation:", EditorStyles.boldLabel); float x = EditorGUILayout.Slider(GetLabel("Position X"), m_stamper.m_x, m_minX, m_maxX); float y = m_stamper.m_y; if (!m_stamper.m_stickBaseToGround) { y = EditorGUILayout.Slider(GetLabel("Position Y"), m_stamper.m_y, m_minY, m_maxY); } float z = EditorGUILayout.Slider(GetLabel("Position Z"), m_stamper.m_z, m_minZ, m_maxZ); float rotation = EditorGUILayout.Slider(GetLabel("Rotation"), m_stamper.m_rotation, -180f, 180f); float width = EditorGUILayout.Slider(GetLabel("Width"), m_stamper.m_width, 0.1f, 200f); float height = EditorGUILayout.Slider(GetLabel("Height"), m_stamper.m_height, 0.1f, 100f); float baseLevel = EditorGUILayout.Slider(GetLabel("Base Level"), m_stamper.m_baseLevel, 0f, 1f); bool stickBaseToGround = EditorGUILayout.Toggle(GetLabel("Ground Base"), m_stamper.m_stickBaseToGround); bool stampBase = EditorGUILayout.Toggle(GetLabel("Stamp Base"), m_stamper.m_drawStampBase); bool showBase = EditorGUILayout.Toggle(GetLabel("Show Base"), m_stamper.m_showBase); GUILayout.EndVertical(); GUILayout.BeginVertical("Masks:", m_boxStyle); GUILayout.Space(20); //GUILayout.Label("Masks:", EditorStyles.boldLabel); AnimationCurve distanceMask = EditorGUILayout.CurveField(GetLabel("Distance Mask"), m_stamper.m_distanceMask); Gaia.GaiaConstants.ImageFitnessFilterMode areaMaskMode = (Gaia.GaiaConstants.ImageFitnessFilterMode)EditorGUILayout.EnumPopup(GetLabel("Area Mask"), m_stamper.m_areaMaskMode); Texture2D imageMask = m_stamper.m_imageMask; bool imageMaskInvert = m_stamper.m_imageMaskInvert; bool imageMaskNormalise = m_stamper.m_imageMaskNormalise; bool imageMaskFlip = m_stamper.m_imageMaskFlip; float noiseMaskSeed = m_stamper.m_noiseMaskSeed; int noiseMaskOctaves = m_stamper.m_noiseMaskOctaves; float noiseMaskPersistence = m_stamper.m_noiseMaskPersistence; float noiseMaskFrequency = m_stamper.m_noiseMaskFrequency; float noiseMaskLacunarity = m_stamper.m_noiseMaskLacunarity; float noiseZoom = m_stamper.m_noiseZoom; int imageMaskSmoothIterations = m_stamper.m_imageMaskSmoothIterations; if (areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageAlphaChannel || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageBlueChannel || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageGreenChannel || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageGreyScale || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageRedChannel) { imageMask = (Texture2D)EditorGUILayout.ObjectField(GetLabel("Image Mask"), m_stamper.m_imageMask, typeof(Texture2D), false); } else if (areaMaskMode == GaiaConstants.ImageFitnessFilterMode.PerlinNoise || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.RidgedNoise || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.BillowNoise) { noiseMaskSeed = EditorGUILayout.Slider(GetLabel("Noise Seed"), noiseMaskSeed, 0f, 65000f); noiseMaskOctaves = EditorGUILayout.IntSlider(GetLabel("Octaves"), noiseMaskOctaves, 1, 12); noiseMaskPersistence = EditorGUILayout.Slider(GetLabel("Persistence"), noiseMaskPersistence, 0f, 1f); noiseMaskFrequency = EditorGUILayout.Slider(GetLabel("Frequency"), noiseMaskFrequency, 0f, 1f); noiseMaskLacunarity = EditorGUILayout.Slider(GetLabel("Lacunarity"), noiseMaskLacunarity, 1.5f, 3.5f); noiseZoom = EditorGUILayout.Slider(GetLabel("Zoom"), noiseZoom, 1f, 1000f); } if (areaMaskMode != GaiaConstants.ImageFitnessFilterMode.None) { imageMaskSmoothIterations = EditorGUILayout.IntSlider(GetLabel("Smooth Mask"), m_stamper.m_imageMaskSmoothIterations, 0, 20); imageMaskNormalise = EditorGUILayout.Toggle(GetLabel("Normalise Mask"), m_stamper.m_imageMaskNormalise); imageMaskInvert = EditorGUILayout.Toggle(GetLabel("Invert Mask"), m_stamper.m_imageMaskInvert); imageMaskFlip = EditorGUILayout.Toggle(GetLabel("Flip Mask"), m_stamper.m_imageMaskFlip); } GUILayout.EndVertical(); GUILayout.BeginVertical("Helpers:", m_boxStyle); GUILayout.Space(20); //GUILayout.Label("Helpers:", EditorStyles.boldLabel); if (m_stamper.m_resources != null) { EditorGUILayout.LabelField("Sea Level", m_stamper.m_resources.m_seaLevel.ToString() + " m"); } bool showSeaLevel = EditorGUILayout.Toggle(GetLabel("Show Sea Level"), m_stamper.m_showSeaLevel); //Color gizmoColour = EditorGUILayout.ColorField(GetLabel("Gizmo Colour"), m_stamper.m_gizmoColour); bool alwaysShow = EditorGUILayout.Toggle(GetLabel("Always Show Stamper"), m_stamper.m_alwaysShow); bool showRulers = m_stamper.m_showRulers = EditorGUILayout.Toggle(GetLabel("Show Rulers"), m_stamper.m_showRulers); bool showTerrainHelper = m_stamper.m_showTerrainHelper = EditorGUILayout.Toggle(GetLabel("Show Terrain Helper"), m_stamper.m_showTerrainHelper); GUILayout.EndVertical(); //Check for changes, make undo record, make changes and let editor know we are dirty if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_stamper, "Made changes"); //Check to see if we need to load a new stamp if (feature != null) { if (m_stamper.m_stampPreviewImage == null) { m_stamper.m_stampPreviewImage = feature; m_stamper.LoadStamp(); m_stamper.FitToTerrain(); baseLevel = m_stamper.m_baseLevel; width = m_stamper.m_width; height = m_stamper.m_height; rotation = m_stamper.m_rotation; x = m_stamper.m_x; y = m_stamper.m_y; z = m_stamper.m_z; } else if (m_stamper.m_stampPreviewImage.GetInstanceID() != feature.GetInstanceID()) { m_stamper.m_stampPreviewImage = feature; m_stamper.LoadStamp(); baseLevel = m_stamper.m_baseLevel; } } //And invert it if (m_stamper.m_invertStamp != invertStamp) { m_stamper.m_invertStamp = invertStamp; m_stamper.InvertStamp(); } //And normalise it if (m_stamper.m_normaliseStamp != normaliseStamp) { m_stamper.m_normaliseStamp = normaliseStamp; if (normaliseStamp) { m_stamper.NormaliseStamp(); } else { m_stamper.LoadStamp(); baseLevel = m_stamper.m_baseLevel; } } m_stamper.m_heightModifier = heightModifier; m_stamper.m_drawStampBase = stampBase; m_stamper.m_stampOperation = operation; m_stamper.m_blendStrength = blendStrength; m_stamper.m_stencilHeight = stencilHeight; m_stamper.m_distanceMask = distanceMask; m_stamper.m_smoothIterations = smoothIterations; m_stamper.m_resources = resources; m_stamper.m_x = x; m_stamper.m_y = y; m_stamper.m_z = z; m_stamper.m_width = width; m_stamper.m_height = height; m_stamper.m_rotation = rotation; m_stamper.m_stickBaseToGround = stickBaseToGround; m_stamper.m_alwaysShow = alwaysShow; m_stamper.m_showSeaLevel = showSeaLevel; m_stamper.m_baseLevel = baseLevel; m_stamper.m_showBase = showBase; m_stamper.m_showRulers = showRulers; m_stamper.m_showTerrainHelper = showTerrainHelper; m_stamper.m_areaMaskMode = areaMaskMode; m_stamper.m_imageMask = imageMask; m_stamper.m_imageMaskInvert = imageMaskInvert; m_stamper.m_imageMaskNormalise = imageMaskNormalise; m_stamper.m_imageMaskFlip = imageMaskFlip; m_stamper.m_imageMaskSmoothIterations = imageMaskSmoothIterations; m_stamper.m_noiseMaskSeed = noiseMaskSeed; m_stamper.m_noiseMaskOctaves = noiseMaskOctaves; m_stamper.m_noiseMaskPersistence = noiseMaskPersistence; m_stamper.m_noiseMaskFrequency = noiseMaskFrequency; m_stamper.m_noiseMaskLacunarity = noiseMaskLacunarity; m_stamper.m_noiseZoom = noiseZoom; //Update the stamp calcs m_stamper.UpdateStamp(); EditorUtility.SetDirty(m_stamper); } //Terrain control if (showTerrainHelper) { GUILayout.BeginVertical("Terrain Helper", m_boxStyle); GUILayout.Space(20); if (GUILayout.Button(GetLabel("Show Terrain Utilities"))) { var export = EditorWindow.GetWindow <GaiaTerrainExplorerEditor>(false, "Terrain Utilities"); export.Show(); } GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Flatten"))) { if (EditorUtility.DisplayDialog("Flatten Terrain tiles ?", "Are you sure you want to flatten all terrain tiles - this can not be undone ?", "Yes", "No")) { m_stamper.FlattenTerrain(); } } if (GUILayout.Button(GetLabel("Smooth"))) { if (EditorUtility.DisplayDialog("Smooth Terrain tiles ?", "Are you sure you want to smooth all terrain tiles - this can not be undone ?", "Yes", "No")) { m_stamper.SmoothTerrain(); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Clear Trees"))) { if (EditorUtility.DisplayDialog("Clear Terrain trees ?", "Are you sure you want to clear all terrain trees - this can not be undone ?", "Yes", "No")) { m_stamper.ClearTrees(); } } if (GUILayout.Button(GetLabel("Clear Details"))) { if (EditorUtility.DisplayDialog("Clear Terrain details ?", "Are you sure you want to clear all terrain details - this can not be undone ?", "Yes", "No")) { m_stamper.ClearDetails(); } } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); } //Regardless, re-enable the spawner controls GUI.enabled = true; //Display progress if (m_stamper.m_stampComplete != true && !m_stamper.m_cancelStamp) { GUILayout.BeginVertical("Stamp Controller", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Cancel"))) { m_stamper.CancelStamp(); } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); ProgressBar(string.Format("Progress ({0:0.0}%)", m_stamper.m_stampProgress * 100f), m_stamper.m_stampProgress); } else { //Stamp control GUILayout.BeginVertical("Stamp Controller", m_boxStyle); GUILayout.Space(20); if (!m_stamper.CanPreview()) { GUI.enabled = false; } GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Ground"))) { m_stamper.AlignToGround(); m_stamper.UpdateStamp(); } if (GUILayout.Button(GetLabel("Fit To Terrain"))) { m_stamper.FitToTerrain(); m_stamper.UpdateStamp(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Preview"))) { m_stamper.TogglePreview(); } GUI.enabled = true; if (m_stamper.m_stampPreviewImage == null) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Stamp"))) { //Check that they have a single selected terrain if (Gaia.TerrainHelper.GetActiveTerrainCount() != 1) { EditorUtility.DisplayDialog("OOPS!", "You must have only one active terrain in order to use a Spawner. Please either add a terrain, or deactivate all but one terrain.", "OK"); } else { //Check that the centre of the terrain is at 0,0,0, and offer to move bool isCentred = true; Bounds b = new Bounds(); Terrain terrain = Gaia.TerrainHelper.GetActiveTerrain(); Gaia.TerrainHelper.GetTerrainBounds(terrain, ref b); if ((b.center.x != 0f) || (b.min.y != 0f) || (b.center.z != 0f)) { isCentred = false; if (EditorUtility.DisplayDialog("OOPS!", "The terrain must be centered at 0,0,0 for stamping to work properly. Would you like GAIA to move it for you? You will need to reposition your stamp after this to adjust for the movement. You can move the terrain back to its original position after you have finished with the stamper.", "OK", "Cancel")) { terrain.transform.position = new Vector3(b.extents.x * -1f, 0f, b.extents.z * -1f); } } if (isCentred) { //Check that they are not using terrain based mask - this can give unexpected results if (areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture0 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture1 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture2 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture3 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture4 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture5 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture6 || areaMaskMode == GaiaConstants.ImageFitnessFilterMode.TerrainTexture7 ) { //Do an alert and fix if necessary if (!m_stamper.IsFitToTerrain()) { if (EditorUtility.DisplayDialog("WARNING!", "This feature requires your stamp to be Fit To Terrain in order to guarantee correct placement.", "Stamp Anyway", "Cancel")) { m_stamper.Stamp(); } } else { m_stamper.Stamp(); } } else { m_stamper.Stamp(); } } } } GUI.enabled = true; if (m_stamper.CanRedo()) { if (GUILayout.Button(GetLabel("Redo"))) { m_stamper.Redo(); } } else { if (!m_stamper.CanUndo()) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Undo"))) { m_stamper.Undo(); } } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); GUILayout.Space(5f); } }
/// <summary> /// Create a terrain tile based on these settings /// </summary> /// <param name="tx">X location</param> /// <param name="tz">Z location</param> /// <param name="world">The array managing it</param> private void CreateTile(int tx, int tz, ref Terrain[,] world, GaiaResource resources) { if (tx < 0 || tx >= m_tilesX) { Debug.LogError("X value out of bounds"); return; } if (tz < 0 || tz >= m_tilesZ) { Debug.LogError("Z value out of bounds"); return; } //Look for issues in the terrain settings and fix them GetAndFixDefaults(); //this will center terrain at origin Vector2 m_offset = new Vector2(-m_terrainSize * m_tilesX * 0.5f, -m_terrainSize * m_tilesZ * 0.5f); //create the terrains if they dont already exist if (world.Length < m_tilesX) { world = new Terrain[m_tilesX, m_tilesZ]; } //Create the terrain Terrain terrain; TerrainData terrainData = new TerrainData(); terrainData.name = string.Format("Terrain_{0}_{1}-{2:yyyyMMdd-HHmmss}", tx, tz, DateTime.Now); terrainData.alphamapResolution = m_controlTextureResolution; terrainData.baseMapResolution = m_baseMapSize; terrainData.SetDetailResolution(m_detailResolution, m_detailResolutionPerPatch); terrainData.heightmapResolution = m_heightmapResolution; //terrainData.physicsMaterial = m_physicsMaterial; terrainData.wavingGrassAmount = m_bending; terrainData.wavingGrassSpeed = m_size; terrainData.wavingGrassStrength = m_speed; terrainData.wavingGrassTint = m_grassTint; terrainData.size = new Vector3(m_terrainSize, m_terrainHeight, m_terrainSize); #if UNITY_EDITOR AssetDatabase.CreateAsset(terrainData, string.Format("Assets/{0}.asset", terrainData.name)); #endif terrain = Terrain.CreateTerrainGameObject(terrainData).GetComponent <Terrain>(); terrain.name = terrainData.name; terrain.transform.position = new Vector3(m_terrainSize * tx + m_offset.x, 0, m_terrainSize * tz + m_offset.y); terrain.basemapDistance = m_baseMapDist; #if UNITY_2019_1_OR_NEWER terrain.shadowCastingMode = m_shaodwCastingMode; #else terrain.castShadows = m_castShadows; #endif terrain.detailObjectDensity = m_detailDensity; terrain.detailObjectDistance = m_detailDistance; terrain.heightmapPixelError = m_pixelError; terrain.treeBillboardDistance = m_billboardStart; terrain.treeCrossFadeLength = m_fadeLength; terrain.treeDistance = m_treeDistance; terrain.treeMaximumFullLODCount = m_maxMeshTrees; #if UNITY_EDITOR GameObjectUtility.SetStaticEditorFlags(terrain.gameObject, StaticEditorFlags.BatchingStatic | StaticEditorFlags.NavigationStatic | StaticEditorFlags.OccludeeStatic | StaticEditorFlags.OccluderStatic | StaticEditorFlags.OffMeshLinkGeneration | StaticEditorFlags.ReflectionProbeStatic | StaticEditorFlags.LightmapStatic ); terrain.bakeLightProbesForTrees = false; #if UNITY_2018_3_OR_NEWER terrain.drawInstanced = true; #endif #endif GaiaConstants.EnvironmentRenderer rendererType = GaiaConstants.EnvironmentRenderer.BuiltIn; GaiaSettings gaiaSettings = GaiaUtils.GetGaiaSettings(); if (gaiaSettings != null) { rendererType = gaiaSettings.m_currentRenderer; #if !UNITY_2018_1_OR_NEWER rendererType = GaiaConstants.EnvironmentRenderer.BuiltIn; #endif } if (rendererType == GaiaConstants.EnvironmentRenderer.BuiltIn) { if (m_material != null) { #if UNITY_EDITOR GaiaPipelineUtils.SetupPipeline(rendererType, null, null, null, "Procedural Worlds/Simple Water", false); #endif } } else { terrain.materialType = Terrain.MaterialType.Custom; if (rendererType == GaiaConstants.EnvironmentRenderer.LightWeight2018x) { #if UNITY_EDITOR && UNITY_2018_3_OR_NEWER GaiaPipelineUtils.SetupPipeline(rendererType, "Procedural Worlds Lightweight Pipeline Profile", "Pipeline Terrain Material", "Lightweight Render Pipeline/Terrain/Lit", "Procedural Worlds/Simple Water LW", false); #else Debug.LogWarning("Lightweight Pipeline is only supposted in 2018.3 or newer"); #endif } else { #if UNITY_EDITOR && UNITY_2018_3_OR_NEWER GaiaPipelineUtils.SetupPipeline(rendererType, "Procedural Worlds HDRenderPipelineAsset", "Pipeline Terrain Material", "HDRP/TerrainLit", "Procedural Worlds/Simple Water HD", false); #else Debug.LogWarning("Lightweight Pipeline is only supposted in 2018.3 or newer"); #endif } } if (m_physicsMaterial != null) { TerrainCollider collider = terrain.GetComponent <TerrainCollider>(); if (collider != null) { collider.material = m_physicsMaterial; } else { Debug.LogWarning("Unable to assign physics material to terrain!"); } } //Assign prototypes if (resources != null) { resources.ApplyPrototypesToTerrain(terrain); } else { terrain.Flush(); } //Save the new tile world[tx, tz] = terrain; //Parent it to the environment GameObject gaiaObj = GameObject.Find("Gaia Environment"); if (gaiaObj == null) { gaiaObj = new GameObject("Gaia Environment"); } terrain.transform.parent = gaiaObj.transform; }
/// <summary> /// Create a terrain tile based on these settings /// </summary> /// <param name="tx">X location</param> /// <param name="tz">Z location</param> /// <param name="world">The array managing it</param> private void CreateTile(int tx, int tz, ref Terrain[,] world, GaiaResource resources) { if (tx < 0 || tx >= m_tilesX) { Debug.LogError("X value out of bounds"); return; } if (tz < 0 || tz >= m_tilesZ) { Debug.LogError("Z value out of bounds"); return; } //Look for issues in the terrain settings and fix them GetAndFixDefaults(); //this will center terrain at origin Vector2 m_offset = new Vector2(-m_terrainSize * m_tilesX * 0.5f, -m_terrainSize * m_tilesZ * 0.5f); //create the terrains if they dont already exist if (world.Length < m_tilesX) { world = new Terrain[m_tilesX, m_tilesZ]; } //Create the terrain Terrain terrain; TerrainData terrainData = new TerrainData(); terrainData.name = string.Format("Terrain_{0}_{1}-{2:yyyyMMdd-HHmmss}", tx, tz, DateTime.Now); terrainData.alphamapResolution = m_controlTextureResolution; terrainData.baseMapResolution = m_baseMapSize; terrainData.SetDetailResolution(m_detailResolution, m_detailResolutionPerPatch); terrainData.heightmapResolution = m_heightmapResolution; //terrainData.physicsMaterial = m_physicsMaterial; terrainData.wavingGrassAmount = m_bending; terrainData.wavingGrassSpeed = m_size; terrainData.wavingGrassStrength = m_speed; terrainData.wavingGrassTint = m_grassTint; terrainData.size = new Vector3(m_terrainSize, m_terrainHeight, m_terrainSize); #if UNITY_EDITOR AssetDatabase.CreateAsset(terrainData, string.Format("Assets/{0}.asset", terrainData.name)); #endif terrain = Terrain.CreateTerrainGameObject(terrainData).GetComponent <Terrain>(); terrain.name = terrainData.name; terrain.transform.position = new Vector3(m_terrainSize * tx + m_offset.x, 0, m_terrainSize * tz + m_offset.y); terrain.basemapDistance = m_baseMapDist; terrain.castShadows = m_castShadows; terrain.detailObjectDensity = m_detailDensity; terrain.detailObjectDistance = m_detailDistance; terrain.heightmapPixelError = m_pixelError; terrain.treeBillboardDistance = m_billboardStart; terrain.treeCrossFadeLength = m_fadeLength; terrain.treeDistance = m_treeDistance; terrain.treeMaximumFullLODCount = m_maxMeshTrees; if (m_material != null) { terrain.materialType = Terrain.MaterialType.Custom; terrain.materialTemplate = m_material; } if (m_physicsMaterial != null) { TerrainCollider collider = terrain.GetComponent <TerrainCollider>(); if (collider != null) { collider.material = m_physicsMaterial; } else { Debug.LogWarning("Unable to assign physics material to terrain!"); } } //Assign prototypes if (resources != null) { resources.ApplyPrototypesToTerrain(terrain); } else { terrain.Flush(); } //Save the new tile world[tx, tz] = terrain; //Parent it to the environment GameObject gaiaObj = GameObject.Find("Gaia Environment"); if (gaiaObj == null) { gaiaObj = new GameObject("Gaia Environment"); } terrain.transform.parent = gaiaObj.transform; }
public override void OnInspectorGUI() { //Get our resource m_resource = (GaiaResource)target; //Set up the box style if (m_boxStyle == null) { m_boxStyle = new GUIStyle(GUI.skin.box); m_boxStyle.normal.textColor = GUI.skin.label.normal.textColor; m_boxStyle.fontStyle = FontStyle.Bold; m_boxStyle.alignment = TextAnchor.UpperLeft; } //Setup the wrap style if (m_wrapStyle == null) { m_wrapStyle = new GUIStyle(GUI.skin.label); m_wrapStyle.wordWrap = true; } //Create a nice text intro GUILayout.BeginVertical("Gaia Resource", m_boxStyle); GUILayout.Space(20); //EditorGUILayout.LabelField("The resource manager allows you to manage the resources used by your terrain and spawner. To see what every setting does you can hover over it.\n\nGet From Terrain - Pick up resources and settings from the current terrain.\n\nUpdate DNA - Updates DNA for all resources and automatically calculate sizes.\n\nApply To Terrain - Apply terrain specific settings such as texture, detail and tree prototypes back into the terrain. Prefab this settings to save time creating your next terrain.", m_wrapStyle); EditorGUILayout.LabelField("These are the resources used by the Spawning & Stamping system. Create a terrain, add textures, details and trees, then press Get Resources From Terrain to load. To see how the settings influence the system you can hover over them.", m_wrapStyle); GUILayout.EndVertical(); float oldSeaLevel = m_resource.m_seaLevel; float oldHeight = m_resource.m_terrainHeight; EditorGUI.BeginChangeCheck(); DrawDefaultInspector(); DropAreaGUI(); GUILayout.BeginVertical("Resource Controller", m_boxStyle); GUILayout.Space(20); if (GUILayout.Button(GetLabel("Set Asset Associations"))) { if (EditorUtility.DisplayDialog("Set Asset Associations", "This will update your asset associations and can not be undone ! Here temporarily until hidden.", "Yes", "No")) { if (m_resource.SetAssetAssociations()) { EditorUtility.SetDirty(m_resource); } } } if (GUILayout.Button(GetLabel("Associate Assets"))) { if (EditorUtility.DisplayDialog("Associate Assets", "This will locate and associate the first resource found that matches your asset and can not be undone !", "Yes", "No")) { if (m_resource.AssociateAssets()) { EditorUtility.SetDirty(m_resource); } } } if (GUILayout.Button(GetLabel("Get Resources From Terrain"))) { if (EditorUtility.DisplayDialog("Get Resources from Terrain ?", "Are you sure you want to get / update your resource prototypes from the terrain ? This will update your settings and can not be undone !", "Yes", "No")) { m_resource.UpdatePrototypesFromTerrain(); EditorUtility.SetDirty(m_resource); } } if (GUILayout.Button(GetLabel("Replace Resources In Terrains"))) { if (EditorUtility.DisplayDialog("Replace Resources in ALL Terrains ?", "Are you sure you want to replace the resources in ALL terrains with these? This can not be undone !", "Yes", "No")) { m_resource.ApplyPrototypesToTerrain(); } } if (GUILayout.Button(GetLabel("Add Missing Resources To Terrains"))) { if (EditorUtility.DisplayDialog("Add Missing Resources to ALL Terrains ?", "Are you sure you want to add your missing resource prototypes to ALL terrains ? This can not be undone !", "Yes", "No")) { m_resource.AddMissingPrototypesToTerrain(); } } if (m_resource.m_texturePrototypes.GetLength(0) == 0) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Create Coverage Texture Spawner"))) { m_resource.CreateCoverageTextureSpawner(GetRangeFromTerrain(), GetTextureIncrementFromTerrain()); } GUI.enabled = true; if (m_resource.m_detailPrototypes.GetLength(0) == 0) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Create Clustered Grass Spawner"))) { m_resource.CreateClusteredDetailSpawner(GetRangeFromTerrain(), GetDetailIncrementFromTerrain()); } if (GUILayout.Button(GetLabel("Create Coverage Grass Spawner"))) { m_resource.CreateCoverageDetailSpawner(GetRangeFromTerrain(), GetDetailIncrementFromTerrain()); } GUI.enabled = true; if (m_resource.m_treePrototypes.GetLength(0) == 0) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Create Clustered Terrain Tree Spawner"))) { m_resource.CreateClusteredTreeSpawner(GetRangeFromTerrain()); } if (GUILayout.Button(GetLabel("Create Coverage Terrain Tree Spawner"))) { m_resource.CreateCoverageTreeSpawner(GetRangeFromTerrain()); } GUI.enabled = true; if (m_resource.m_gameObjectPrototypes.GetLength(0) == 0) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Create Clustered Prefab Spawner"))) { m_resource.CreateClusteredGameObjectSpawner(GetRangeFromTerrain()); } if (GUILayout.Button(GetLabel("Create Coverage Prefab Spawner"))) { m_resource.CreateCoverageGameObjectSpawner(GetRangeFromTerrain()); } GUI.enabled = true; if (GUILayout.Button(GetLabel("Visualise"))) { GameObject gaiaObj = GameObject.Find("Gaia"); if (gaiaObj == null) { gaiaObj = new GameObject("Gaia"); } GameObject visualiserObj = GameObject.Find("Visualiser"); if (visualiserObj == null) { visualiserObj = new GameObject("Visualiser"); visualiserObj.AddComponent <ResourceVisualiser>(); visualiserObj.transform.parent = gaiaObj.transform; } ResourceVisualiser visualiser = visualiserObj.GetComponent <ResourceVisualiser>(); visualiser.m_resources = m_resource; Selection.activeGameObject = visualiserObj; } GUILayout.Space(5f); GUILayout.EndVertical(); //Check for changes, make undo record, make changes and let editor know we are dirty if (EditorGUI.EndChangeCheck()) { if (oldHeight != m_resource.m_terrainHeight) { m_resource.ChangeHeight(oldHeight, m_resource.m_terrainHeight); } if (oldSeaLevel != m_resource.m_seaLevel) { m_resource.ChangeSeaLevel(oldSeaLevel, m_resource.m_seaLevel); } Undo.RecordObject(m_resource, "Made resource changes"); EditorUtility.SetDirty(m_resource); //Stop the save from going nuts if ((DateTime.Now - m_lastSaveDT).Seconds > 5) { m_lastSaveDT = DateTime.Now; AssetDatabase.SaveAssets(); } } }
/// <summary> /// Takes a spawner preset list and assembles arrays with the new prototypes in them. If a reference Terrain is passed in, the arrays will contain the existing prototypes on the terrain + only the additional stuff from the preset list, no duplicates. /// </summary> /// <param name="spawnerPresetList"></param> /// <param name="terrainLayers"></param> /// <param name="terrainDetails"></param> /// <param name="terrainTrees"></param> /// <param name="referenceTerrain"></param> public static void GetPrototypes(List <BiomeSpawnerListEntry> spawnerPresetList, ref TerrainLayer[] terrainLayers, ref DetailPrototype[] terrainDetails, ref TreePrototype[] terrainTrees, Terrain referenceTerrain = null) { //Early out when no spawner preset list if (spawnerPresetList == null || spawnerPresetList.Count == 0) { return; } //collect the splat prototypes in a GaiaSplatPrototype List first, then build a terrain layer array from that later List <GaiaSplatPrototype> presetSplatPrototypes = new List <GaiaSplatPrototype>(); List <DetailPrototype> presetTerrainDetails = new List <DetailPrototype>(); List <TreePrototype> presetTerrainTrees = new List <TreePrototype>(); //if there is a reference terrain, start by pre-filling those lists with the prototypes from the terrain if (referenceTerrain != null) { foreach (TerrainLayer layer in referenceTerrain.terrainData.terrainLayers) { presetSplatPrototypes.Add(new GaiaSplatPrototype(layer)); } foreach (DetailPrototype detailPrototype in referenceTerrain.terrainData.detailPrototypes) { presetTerrainDetails.Add(detailPrototype); } foreach (TreePrototype treePrototype in referenceTerrain.terrainData.treePrototypes) { presetTerrainTrees.Add(treePrototype); } } foreach (BiomeSpawnerListEntry preset in spawnerPresetList.Where(x => x.m_autoAssignPrototypes == true)) { if (preset == null) { //Skip entries missing information continue; } if (preset.m_spawnerSettings == null) { continue; } if (preset.m_spawnerSettings.m_resources == null) { continue; } GaiaResource resources = preset.m_spawnerSettings.m_resources; foreach (SpawnRule sr in preset.m_spawnerSettings.m_spawnerRules) { //skip if resource is not maintained properly (=null) if (sr.ResourceIsNull(preset.m_spawnerSettings)) { Debug.Log("Spawn Rule " + sr.m_name + " in " + preset.m_spawnerSettings.name + " has missing resources maintained. This rule might not work properly when spawning later."); continue; } switch (sr.m_resourceType) { case GaiaConstants.SpawnerResourceType.TerrainTexture: ResourceProtoTexture protoTexture = resources.m_texturePrototypes[sr.m_resourceIdx]; if (protoTexture != null) { GaiaSplatPrototype newSplat = new GaiaSplatPrototype(); newSplat.normalMap = protoTexture.m_normal; newSplat.normalScale = protoTexture.m_normalScale; newSplat.smoothness = protoTexture.m_smoothness; newSplat.metallic = protoTexture.m_metallic; newSplat.diffuseRemapMin = protoTexture.m_diffuseRemapMin; newSplat.diffuseRemapMax = protoTexture.m_diffuseRemapMax; newSplat.maskMapRemapMin = protoTexture.m_maskMapRemapMin; newSplat.maskMapRemapMax = protoTexture.m_maskMapRemapMax; newSplat.specularColor = protoTexture.m_specularColor; newSplat.tileOffset = new Vector2(protoTexture.m_offsetX, protoTexture.m_offsetY); newSplat.tileSize = new Vector2(protoTexture.m_sizeX, protoTexture.m_sizeY); newSplat.texture = protoTexture.m_texture; newSplat.maskMap = protoTexture.m_maskmap; //Only add as a new prototype if not a fully equal prototype already exists in the list if (!presetSplatPrototypes.Exists(x => x.texture == newSplat.texture && x.normalMap == newSplat.normalMap && x.tileOffset == newSplat.tileOffset && x.tileSize == newSplat.tileSize )) { presetSplatPrototypes.Add(newSplat); } } break; case GaiaConstants.SpawnerResourceType.TerrainDetail: ResourceProtoDetail protoDetail = resources.m_detailPrototypes[sr.m_resourceIdx]; if (protoDetail != null) { DetailPrototype newTerrainDetail = new DetailPrototype(); newTerrainDetail.renderMode = protoDetail.m_renderMode; newTerrainDetail.prototypeTexture = protoDetail.m_detailTexture; newTerrainDetail.prototype = protoDetail.m_detailProtoype; newTerrainDetail.dryColor = protoDetail.m_dryColour; newTerrainDetail.healthyColor = protoDetail.m_healthyColour; newTerrainDetail.maxHeight = protoDetail.m_maxHeight; newTerrainDetail.maxWidth = protoDetail.m_maxWidth; newTerrainDetail.minHeight = protoDetail.m_minHeight; newTerrainDetail.minWidth = protoDetail.m_minWidth; newTerrainDetail.noiseSpread = protoDetail.m_noiseSpread; if ((protoDetail.m_renderMode == DetailRenderMode.Grass && protoDetail.m_detailProtoype == null) || protoDetail.m_renderMode == DetailRenderMode.GrassBillboard) { if (!presetTerrainDetails.Exists(x => x.prototypeTexture == newTerrainDetail.prototypeTexture && x.prototype == newTerrainDetail.prototype && x.dryColor == newTerrainDetail.dryColor && x.healthyColor == newTerrainDetail.healthyColor && x.maxHeight == newTerrainDetail.maxHeight && x.maxWidth == newTerrainDetail.maxWidth && x.minHeight == newTerrainDetail.minHeight && x.minWidth == newTerrainDetail.minWidth && x.noiseSpread == newTerrainDetail.noiseSpread )) { presetTerrainDetails.Add(newTerrainDetail); } } else { if (!presetTerrainDetails.Exists(x => x.prototype == newTerrainDetail.prototype && x.prototype == newTerrainDetail.prototype && x.dryColor == newTerrainDetail.dryColor && x.healthyColor == newTerrainDetail.healthyColor && x.maxHeight == newTerrainDetail.maxHeight && x.maxWidth == newTerrainDetail.maxWidth && x.minHeight == newTerrainDetail.minHeight && x.minWidth == newTerrainDetail.minWidth && x.noiseSpread == newTerrainDetail.noiseSpread )) { presetTerrainDetails.Add(newTerrainDetail); } } } break; case GaiaConstants.SpawnerResourceType.TerrainTree: ResourceProtoTree protoTree = resources.m_treePrototypes[sr.m_resourceIdx]; if (protoTree != null) { TreePrototype newTree = new TreePrototype(); newTree.bendFactor = protoTree.m_bendFactor; newTree.prefab = protoTree.m_desktopPrefab; if (!presetTerrainTrees.Exists(x => x.bendFactor == newTree.bendFactor && x.prefab == newTree.prefab)) { presetTerrainTrees.Add(newTree); } } break; } } } //now look at the existing terrain layers on the terrain again, and add only the additional new Splat Prototypes as new layers - all the other ones must exist on the terrains already List <GaiaSplatPrototype> additionalSplatPrototypes = new List <GaiaSplatPrototype>(); List <DetailPrototype> additionalTerrainDetails = new List <DetailPrototype>(); List <TreePrototype> additionalTerrainTrees = new List <TreePrototype>(); //Do we have a refernece terrain? The only the splat prototypes with a higher index then what is currently present on the terrain already are relevant if (referenceTerrain != null) { for (int i = referenceTerrain.terrainData.terrainLayers.Length; i <= presetSplatPrototypes.Count - 1; i++) { additionalSplatPrototypes.Add(presetSplatPrototypes[i]); } for (int i = referenceTerrain.terrainData.detailPrototypes.Length; i <= presetTerrainDetails.Count - 1; i++) { additionalTerrainDetails.Add(presetTerrainDetails[i]); } for (int i = referenceTerrain.terrainData.treePrototypes.Length; i <= presetTerrainTrees.Count - 1; i++) { additionalTerrainTrees.Add(presetTerrainTrees[i]); } } else { //no reference terrain - we take preset prototypes collected before additionalSplatPrototypes = presetSplatPrototypes; additionalTerrainDetails = presetTerrainDetails; additionalTerrainTrees = presetTerrainTrees; } //convert Gaia Splat Prototypes into actual terrain layer files string layername = string.Format("Gaia_-{0:yyyyMMdd-HHmmss}", DateTime.Now); TerrainLayer[] additionalTerrainLayers = GaiaSplatPrototype.CreateTerrainLayers(layername, additionalSplatPrototypes.ToArray()); if (referenceTerrain != null) { //got a reference terrain? return the existing prototypes so they are not altered and attach the truly new ones terrainLayers = referenceTerrain.terrainData.terrainLayers; terrainLayers = terrainLayers.Concat(additionalTerrainLayers).ToArray(); terrainDetails = referenceTerrain.terrainData.detailPrototypes; terrainDetails = terrainDetails.Concat(additionalTerrainDetails.ToArray()).ToArray(); terrainTrees = referenceTerrain.terrainData.treePrototypes; terrainTrees = terrainTrees.Concat(additionalTerrainTrees.ToArray()).ToArray(); } else { //no reference terrain, just return all the new stuff directly terrainLayers = additionalTerrainLayers; terrainDetails = additionalTerrainDetails.ToArray(); terrainTrees = additionalTerrainTrees.ToArray(); } }