// Display loop for the inspector gui public override void OnInspectorGUI() { serializedObject.Update(); CustomTerrain terrain = (CustomTerrain)target; // `target` is linked to [1] "a link to class" // terrain.randomHeightRange = .. is possible, but we use serialization because otherwise editing // the code would reset the state and we're loosing whatever we setup in the inspect int height = terrain.terrainData.heightmapHeight; int width = terrain.terrainData.heightmapWidth; Rect r = EditorGUILayout.BeginVertical(); scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(r.width), GUILayout.Height(r.height)); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(resetTerrain); showRandom = EditorGUILayout.Foldout(showRandom, "Random"); // show foldout toggle if (showRandom) { GUILayout.Label("Set Heights Between Random Values", EditorStyles.boldLabel); EditorGUILayout.PropertyField(randomHeightRange); if (GUILayout.Button("Random Heights")) { terrain.RandomTerrain(); } } showLoadHeights = EditorGUILayout.Foldout(showLoadHeights, "Load Heights"); if (showLoadHeights) { GUILayout.Label("Load Heights From Texture", EditorStyles.boldLabel); EditorGUILayout.PropertyField(heightMapImage); EditorGUILayout.PropertyField(heightMapScale); if (GUILayout.Button("Load Texture")) { terrain.LoadTexture(); } } showPerlin = EditorGUILayout.Foldout(showPerlin, "Single Perlin Noise"); // show foldout toggle if (showPerlin) { EditorGUILayout.Slider(perlinXScale, 0, 0.1f, new GUIContent("X Scale")); EditorGUILayout.Slider(perlinYScale, 0, 0.1f, new GUIContent("Y Scale")); EditorGUILayout.IntSlider(perlinXOffset, 0, 10000, new GUIContent("Offset X")); EditorGUILayout.IntSlider(perlinYOffset, 0, 10000, new GUIContent("Offset Y")); EditorGUILayout.IntSlider(perlinOctaves, 1, 10, new GUIContent("Octaves")); EditorGUILayout.Slider(perlinPersistance, 0.1f, 10, new GUIContent("Persistance")); EditorGUILayout.Slider(perlinHeightScale, 0, 1, new GUIContent("Height Scale")); if (GUILayout.Button("Generate")) { terrain.Perlin(); } } showMultiplePerlin = EditorGUILayout.Foldout(showMultiplePerlin, "Multple Perlin Noise"); // show foldout toggle if (showMultiplePerlin) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); perlinParameterTable = GUITableLayout.DrawTable(perlinParameterTable, serializedObject.FindProperty("perlinParameters")); // why not the class attribute we mapped? GUILayout.Space(40); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewPerlin(); } if (GUILayout.Button("-")) { terrain.RemovePerlin(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply Multiple Perlin")) { terrain.MultiplePerlinTerrain(); } } showVoronoi = EditorGUILayout.Foldout(showVoronoi, "Voronoi"); if (showVoronoi) { EditorGUILayout.IntSlider(voronoiPeaks, 1, 10, new GUIContent("Peak Count")); EditorGUILayout.Slider(voronoiFallOff, 0, 10, new GUIContent("Falloff")); EditorGUILayout.Slider(voronoiDropOff, 0, 10, new GUIContent("Dropoff")); EditorGUILayout.Slider(voronoiMinHeight, 0, 1, new GUIContent("Min Height")); EditorGUILayout.Slider(voronoiMaxHeight, 0, 1, new GUIContent("Max Height")); EditorGUILayout.PropertyField(voronoiType); if (GUILayout.Button("Voronoi")) { terrain.Voronoi(); } } showMPD = EditorGUILayout.Foldout(showMPD, "Midpoint Displacement"); if (showMPD) { EditorGUILayout.PropertyField(mpdMinHeight); EditorGUILayout.PropertyField(mpdMaxHeight); EditorGUILayout.PropertyField(mpdDampenerPower); EditorGUILayout.PropertyField(mpdRoughness); if (GUILayout.Button("MPD")) { terrain.MidPointDisplacement(); } } showSplatMaps = EditorGUILayout.Foldout(showSplatMaps, "Splat Maps"); if (showSplatMaps) { /* * EditorGUILayout.Slider(splatOffset, 0, 0.1f, new GUIContent("Offset")); * EditorGUILayout.Slider(splatScaleX, 0.001f, 1, new GUIContent("Noise X Scale")); * EditorGUILayout.Slider(splatScaleY, 0.001f, 1, new GUIContent("Noise Y Scale")); * EditorGUILayout.Slider(splatScale, 0, 1, new GUIContent("Noise Scaler"));*/ splatMapTable = GUITableLayout.DrawTable(splatMapTable, serializedObject.FindProperty("splatHeights")); // why not the class attribute we mapped? GUILayout.Space(40); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewSplatHeight(); } if (GUILayout.Button("-")) { terrain.RemoveSplatHeight(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply SplatMaps")) { terrain.SplatMaps(); } } showVegetation = EditorGUILayout.Foldout(showVegetation, "Vegetation"); if (showVegetation) { EditorGUILayout.IntSlider(vegTreesMax, 1, 10000, new GUIContent("Maxium Trees")); EditorGUILayout.IntSlider(vegTreesSpacing, 1, 20, new GUIContent("Trees Spacing")); vegetationTable = GUITableLayout.DrawTable(vegetationTable, serializedObject.FindProperty("vegetation")); // why not the class attribute we mapped? GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewVegetation(); } if (GUILayout.Button("-")) { terrain.RemoveVegetation(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply Vegetation")) { terrain.ApplyVegetation(); } } showSmooth = EditorGUILayout.Foldout(showSmooth, "Smooth"); if (showSmooth) { EditorGUILayout.IntSlider(smoothAmount, 1, 10, new GUIContent("Smooth amount")); if (GUILayout.Button("Smooth")) { terrain.SmoothN(); } } if (GUILayout.Button("Reset Terrain")) { terrain.ResetTerrain(); } showHeightMap = EditorGUILayout.Foldout(showHeightMap, "HeightMap"); if (showHeightMap) { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Label(hmTexture, GUILayout.Width(height), GUILayout.Height(width)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Refresh")) { Color color; float cv; hmTexture = new Texture2D(width, height, TextureFormat.ARGB32, false); float[,] heightMap = terrain.terrainData.GetHeights(0, 0, width, height); // why alphamap? for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { cv = heightMap[x, y]; color = new Color(cv, cv, cv, 1); hmTexture.SetPixel(x, y, color); } } hmTexture.Apply(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { int viewWidth = (int)(EditorGUIUtility.currentViewWidth - 100); serializedObject.Update(); CustomTerrain terrain = (CustomTerrain)target; // scrollbar starting code Rect r = EditorGUILayout.BeginVertical(); scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(r.width), GUILayout.Height(r.height)); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(resetTerrain); showRandom = EditorGUILayout.Foldout(showRandom, "Random"); if (showRandom) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Set Heights Between Random Values", EditorStyles.boldLabel); EditorGUILayout.PropertyField(randomHeightRange); if (GUILayout.Button("Random Heights")) { terrain.RandomTerrain(); } } showLoadHeights = EditorGUILayout.Foldout(showLoadHeights, "Load Heights"); if (showLoadHeights) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Load Heights From Texture", EditorStyles.boldLabel); EditorGUILayout.PropertyField(heightMapImage); EditorGUILayout.PropertyField(heightMapScale); if (GUILayout.Button("Load Texture")) { terrain.LoadTexture(); } } showPerlin = EditorGUILayout.Foldout(showPerlin, "Single Perlin Noise"); if (showPerlin) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Set Heights with Perlin Noise", EditorStyles.boldLabel); EditorGUILayout.Slider(perlinXScale, 0, 1, new GUIContent("X Scale")); EditorGUILayout.Slider(perlinYScale, 0, 1, new GUIContent("Y Scale")); EditorGUILayout.IntSlider(perlinOffsetX, 0, 10000, new GUIContent("X Offset")); EditorGUILayout.IntSlider(perlinOffsetY, 0, 10000, new GUIContent("Y Offset")); EditorGUILayout.IntSlider(perlinOctaves, 1, 10, new GUIContent("Octaves")); EditorGUILayout.Slider(perlinPersistence, 0.1f, 10, new GUIContent("Persistence")); EditorGUILayout.Slider(perlinFrequencyMultiplier, 2, 10, new GUIContent("Frequency Multiplier")); EditorGUILayout.Slider(perlinHeightScale, 0, 1, new GUIContent("Height Scale")); if (GUILayout.Button("Perlin Noise")) { terrain.Perlin(); } } showMultiplePerlin = EditorGUILayout.Foldout(showMultiplePerlin, "Multiple Perlin Noise"); if (showMultiplePerlin) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Multiple Perlin Noise", EditorStyles.boldLabel); perlinParameterTable = GUITableLayout.DrawTable(perlinParameterTable, perlinParameters); GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewPerlin(); } if (GUILayout.Button("-")) { terrain.RemovePerlin(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply Multiple Perlin")) { terrain.MultiplePerlin(); } } showVoronoi = EditorGUILayout.Foldout(showVoronoi, "Voronoi"); if (showVoronoi) { EditorGUILayout.IntSlider(voronoiPeakCount, 1, 10, new GUIContent("Peak Count")); EditorGUILayout.Slider(voronoiFalloff, 0, 10, new GUIContent("Falloff")); EditorGUILayout.Slider(voronoiDropoff, 0, 10, new GUIContent("Dropoff")); EditorGUILayout.Slider(voronoiMinHeight, 0, 1, new GUIContent("Min Height")); EditorGUILayout.Slider(voronoiMaxHeight, 0, 1, new GUIContent("Max Height")); EditorGUILayout.PropertyField(voronoiType); if (GUILayout.Button("Voronoi")) { terrain.Voronoi(); } } showMidPointDisplacement = EditorGUILayout.Foldout(showMidPointDisplacement, "Mid Point Displacement"); if (showMidPointDisplacement) { EditorGUILayout.Slider(mpdMinHeight, -10, 0, new GUIContent("Min Height")); EditorGUILayout.Slider(mpdMaxHeight, 0, 10, new GUIContent("Max Height")); EditorGUILayout.Slider(mpdRoughness, 0, 5, new GUIContent("Roughness")); EditorGUILayout.Slider(mpdHeightDampenerPower, 0, 1, new GUIContent("Height Dampener Power")); if (GUILayout.Button("MPD")) { terrain.MidPointDisplacement(); } } showSplatMaps = EditorGUILayout.Foldout(showSplatMaps, "Splat Maps"); if (showSplatMaps) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Splat Maps", EditorStyles.boldLabel); splatMapTable = GUITableLayout.DrawTable(splatMapTable, splatHeights); GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewSplatHeight(); } if (GUILayout.Button("-")) { terrain.RemoveSplatHeight(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply SplatMaps")) { terrain.ApplySplatMaps(); } } showVegetation = EditorGUILayout.Foldout(showVegetation, "Vegetation"); if (showVegetation) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Vegetation", EditorStyles.boldLabel); EditorGUILayout.IntSlider(maxTrees, 0, 10000, new GUIContent("Maximum Trees")); EditorGUILayout.IntSlider(treeSpacing, 2, 20, new GUIContent("Tree Spacing")); vegetationTable = GUITableLayout.DrawTable(vegetationTable, vegetation); GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewVegetation(); } if (GUILayout.Button("-")) { terrain.RemoveVegetation(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply Vegetation")) { terrain.ApplyVegetation(); } } showDetails = EditorGUILayout.Foldout(showDetails, "Details"); if (showDetails) { EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); GUILayout.Label("Details", EditorStyles.boldLabel); EditorGUILayout.IntSlider(maxDetails, 0, 10000, new GUIContent("Maximum Details")); EditorGUILayout.IntSlider(detailSpacing, 1, 20, new GUIContent("Detail Spacing")); detailsTable = GUITableLayout.DrawTable(detailsTable, details); // sync unity's detail distance with max details value from slider // so we can see all the details while developing. may want to dial back if framerate // is affected terrain.GetComponent <Terrain>().detailObjectDistance = maxDetails.intValue; GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { terrain.AddNewDetails(); } if (GUILayout.Button("-")) { terrain.RemoveDetails(); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Apply Details")) { terrain.ApplyDetails(); } } showWater = EditorGUILayout.Foldout(showWater, "Water"); if (showWater) { EditorGUILayout.Slider(waterHeight, 0, 1, new GUIContent("Water Height")); EditorGUILayout.PropertyField(waterGameObject); if (GUILayout.Button("Apply Water")) { terrain.ApplyWater(); } EditorGUILayout.PropertyField(shorelineMaterial); if (GUILayout.Button("Draw Shoreline")) { terrain.DrawShoreline(); } } showErosion = EditorGUILayout.Foldout(showErosion, "Erosion"); if (showErosion) { EditorGUILayout.PropertyField(erosionType); EditorGUILayout.Slider(erosionStrength, 0, 1, new GUIContent("Erosion Strength")); EditorGUILayout.Slider(erosionAmount, 0, 1, new GUIContent("Erosion Amount")); EditorGUILayout.IntSlider(droplets, 0, 500, new GUIContent("Droplets")); EditorGUILayout.Slider(solubility, 0.001f, 1, new GUIContent("Solubility")); EditorGUILayout.IntSlider(springsPerDroplet, 0, 20, new GUIContent("Springs per River")); EditorGUILayout.IntSlider(erosionSmoothAmount, 0, 10, new GUIContent("Smooth Amount")); if (GUILayout.Button("Erode")) { terrain.Erode(); } } showClouds = EditorGUILayout.Foldout(showClouds, "Clouds"); if (showClouds) { EditorGUILayout.PropertyField(numberOfClouds, new GUIContent("Number of Clouds")); EditorGUILayout.PropertyField(particlesPerCloud, new GUIContent("Particles per Cloud")); EditorGUILayout.PropertyField(cloudParticleSize, new GUIContent("Cloud Particle Size")); EditorGUILayout.PropertyField(cloudMinSize, new GUIContent("Min Size")); EditorGUILayout.PropertyField(cloudMaxSize, new GUIContent("Max Size")); EditorGUILayout.PropertyField(cloudMaterial, new GUIContent("Cloud Material")); EditorGUILayout.PropertyField(cloudShadowMaterial, new GUIContent("Cloud Shadow Material")); EditorGUILayout.PropertyField(cloudColor, new GUIContent("Color")); EditorGUILayout.PropertyField(cloudLiningColor, new GUIContent("Lining")); EditorGUILayout.PropertyField(cloudMinSpeed, new GUIContent("Min Speed")); EditorGUILayout.PropertyField(cloudMaxSpeed, new GUIContent("Max Speed")); EditorGUILayout.PropertyField(cloudDistanceTraveled, new GUIContent("Distance Traveled")); if (GUILayout.Button("Generate Clouds")) { terrain.GenerateClouds(); } } showSmooth = EditorGUILayout.Foldout(showSmooth, "Smooth Terrain"); if (showSmooth) { EditorGUILayout.IntSlider(smoothAmount, 1, 10, new GUIContent("Smooth Amount")); if (GUILayout.Button("Smooth")) { terrain.SmoothStandalone(); } } EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); if (GUILayout.Button("Reset Terrain")) { terrain.ResetTerrain(); } showHeightMap = EditorGUILayout.Foldout(showHeightMap, "Height Map"); if (showHeightMap) { // begin centered row GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Label(heightMapTexture, GUILayout.Width(viewWidth), GUILayout.Height(viewWidth)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); // end centered row // begin centered row GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Refresh", GUILayout.Width(viewWidth))) { float[,] heights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight); LoadArrayToTexture2D(heightMapTexture, heights); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); // end centered row } // scrollbar ending code EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); }