Exemplo n.º 1
0
        public void TerrainToolboxUtilities_WhenSplitTerrain_HeightmapResolutionIsCorrect(int xSplit, int zSplit, int originalHeightmapRes)
        {
            TerrainToolboxWindow toolboxWindow   = EditorWindow.GetWindow(typeof(TerrainToolboxWindow)) as TerrainToolboxWindow;
            Texture2D            gradientTexture = CreateGradientTexture();
            int baseLevel     = 0;
            int remapLevel    = 1;
            int numberOfTiles = 1;

            ToolboxHelper.CopyTextureToTerrainHeight(m_TerrainComponent.terrainData, gradientTexture, Vector2Int.zero, originalHeightmapRes, numberOfTiles, baseLevel, remapLevel);

            Selection.activeGameObject = m_TerrainGO;
            m_TerrainGO.name           = "TestTerrain";
            m_TerrainComponent.name    = "TestComponent";

            RenderTexture oldRT = RenderTexture.active;

            RenderTexture.active = m_TerrainComponent.terrainData.heightmapTexture;

            // Run the test
            TestSplitTerrainHeightmapResolution(toolboxWindow, originalHeightmapRes, xSplit, zSplit);

            AssetDatabase.Refresh();
            RenderTexture.active = oldRT;
            toolboxWindow.Close();
        }
        public void EnableVisualization()
        {
            if (GameObject.FindObjectOfType <Terrain>() == null)
            {
                m_selectedMode         = VISUALIZERMODE.None;
                m_Settings.ModeWarning = true;
                return;
            }

            if (m_Terrains == null || GameObject.FindObjectsOfType <Terrain>().Length != m_Terrains.Count || m_Terrains[0] == null)
            {
                m_Terrains.Clear();
                m_Terrains.AddRange(ToolboxHelper.GetAllTerrainsInScene());
                m_Settings.TerrainMaxHeight = m_Terrains[0].terrainData.size.y;
            }

            switch (m_selectedMode)
            {
            case VISUALIZERMODE.AltitudeHeatmap:
                UpdateHeatmapSettings();
                break;

            default:
                RevertMaterial();
                break;
            }

            m_Settings.ModeWarning = false;
            m_previousMode         = m_selectedMode;
        }
Exemplo n.º 3
0
        void ShowGizmoGUI()
        {
            TerrainToolboxUtilities.DrawSeperatorLine();
            bool gizmoToggle = m_Settings.EnableGizmo && ToolboxHelper.GizmoGO != null ? true : false;

            m_Settings.ShowGizmoSettings = TerrainToolGUIHelper.DrawToggleHeaderFoldout(Styles.Gizmo, m_Settings.ShowGizmoSettings, ref gizmoToggle, 0f);

            if (gizmoToggle && !ToolboxHelper.GizmoEnabled)
            {
                ToolboxHelper.ShowGizmo();
                ToolboxHelper.UpdateGizmos(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength, m_Settings.StartPosition, m_Settings.GroupID);
            }
            else if (!gizmoToggle && ToolboxHelper.GizmoEnabled)
            {
                ToolboxHelper.HideGizmo();
            }

            if (ToolboxHelper.GizmoEnabled && ToolboxHelper.GizmoGO != null)
            {
                if (GUI.changed)
                {
                    ToolboxHelper.UpdateGizmos(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength, m_Settings.StartPosition, m_Settings.GroupID);
                }
                else if (ToolboxHelper.GizmoGO.transform.hasChanged)
                {
                    Transform  gizmoTransform = ToolboxHelper.GizmoGO.transform;
                    Vector3Int gizmoScale     = Vector3Int.RoundToInt(gizmoTransform.localScale);
                    m_Settings.TerrainWidth  = gizmoScale.x;
                    m_Settings.TerrainLength = gizmoScale.z;
                    m_Settings.TerrainHeight = gizmoScale.y;
                    m_Settings.StartPosition = ToolboxHelper.GetGizmoPosition();
                }
            }



            // Update gizmo colors
            Color previousColor = m_Settings.GizmoCubeColor + m_Settings.GizmoWireColor;

            if (m_Settings.ShowGizmoSettings)
            {
                EditorGUI.BeginDisabledGroup(!m_Settings.EnableGizmo);
                EditorGUILayout.Space();
                m_Settings.GizmoCubeColor = EditorGUILayout.ColorField(Styles.CubeColor, m_Settings.GizmoCubeColor);
                m_Settings.GizmoWireColor = EditorGUILayout.ColorField(Styles.CubeWireColor, m_Settings.GizmoWireColor);
                EditorGUI.EndDisabledGroup();
            }
            m_Settings.EnableGizmo = gizmoToggle;

            if (previousColor != m_Settings.GizmoCubeColor + m_Settings.GizmoWireColor)
            {
                UnityEditor.SceneView.RepaintAll();
            }

            ToolboxHelper.SetGizmoColor(m_Settings.GizmoCubeColor, m_Settings.GizmoWireColor);
        }
Exemplo n.º 4
0
        public void TerrainToolboxUtilites_WhenExportHeightmap_LevelCorrectionWorks(float min, float max, Heightmap.Format format, Heightmap.Depth depth = Heightmap.Depth.Bit16)
        {
            TerrainToolboxWindow toolboxWindow   = EditorWindow.GetWindow(typeof(TerrainToolboxWindow)) as TerrainToolboxWindow;
            Texture2D            gradientTexture = CreateGradientTexture();

            int heightmapResolution = 513;
            int numberOfTiles       = 1;
            int baseLevel           = 0;
            int remapLevel          = 1;

            ToolboxHelper.CopyTextureToTerrainHeight(m_TerrainComponent.terrainData, gradientTexture, Vector2Int.zero, heightmapResolution, numberOfTiles, baseLevel, remapLevel);

            Selection.activeGameObject = m_TerrainGO;
            m_TerrainGO.name           = "TestTerrain";
            m_TerrainComponent.name    = "TestComponent";

            RenderTexture oldRT = RenderTexture.active;

            RenderTexture.active = m_TerrainComponent.terrainData.heightmapTexture;

            //Run Tests and Cleanup files
            string fileName = m_TerrainGO.name + "_heightmap";
            string path     = Path.Combine(toolboxWindow.m_TerrainUtilitiesMode.m_Settings.HeightmapFolderPath, fileName);

            switch (format)
            {
            case Heightmap.Format.PNG:
                path += ".png";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, format));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;

            case Heightmap.Format.TGA:
                path += ".tga";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, format));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;

            case Heightmap.Format.RAW:
                path += ".raw";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, depth));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;
            }

            AssetDatabase.Refresh();
            RenderTexture.active = oldRT;
            toolboxWindow.Close();
        }
Exemplo n.º 5
0
        void LoadSettings()
        {
            string filePath = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsWindow);

            if (File.Exists(filePath))
            {
                string windowSettingsData = File.ReadAllText(filePath);
                int    value = 0;
                if (int.TryParse(windowSettingsData, out value))
                {
                    m_SelectedMode = (TerrainManagerMode)value;
                }
            }
        }
		public void SaveSettings()
		{
			if (m_SelectedPreset != null)
			{
				m_Settings.PresetPath = AssetDatabase.GetAssetPath(m_SelectedPreset);
			}
			else
			{
				m_Settings.PresetPath = string.Empty;
			}

			string filePath = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsCreate);
			string createSettingsData = JsonUtility.ToJson(m_Settings);
			File.WriteAllText(filePath, createSettingsData);			
		}
        void GetAndSetActiveRenderPipelineSettings()
        {
            ToolboxHelper.RenderPipeline m_ActiveRenderPipeline = ToolboxHelper.GetRenderPipeline();
            m_VisualizationMaterial = AssetDatabase.LoadAssetAtPath <Material>("Packages/com.unity.terrain-tools/editor/terraintoolbox/materials/terrainvisualization.mat");

            //Get terrains
            if (m_Terrains == null || GameObject.FindObjectsOfType <Terrain>().Length != m_Terrains.Count || m_Terrains[0] == null)
            {
                m_Terrains.Clear();
                m_Terrains.AddRange(ToolboxHelper.GetAllTerrainsInScene());
                m_Settings.TerrainMaxHeight = m_Terrains[0].terrainData.size.y;
            }

            //Get materials to revert to
            m_TerrainMaterials.Clear();
            foreach (Terrain terrain in m_Terrains)
            {
                m_TerrainMaterials.Add(terrain.materialTemplate);
            }

            switch (m_ActiveRenderPipeline)
            {
            case ToolboxHelper.RenderPipeline.HD:
                m_VisualizationMaterial.shader = Shader.Find("Hidden/HDRP_TerrainVisualization");
                break;

            case ToolboxHelper.RenderPipeline.LW:
                m_VisualizationMaterial.shader = Shader.Find("Hidden/LWRP_TerrainVisualization");
                break;

            default:
                if (m_Terrains == null || m_Terrains.Count == 0)
                {
                    break;
                }
#if UNITY_2019_2_OR_NEWER
#else
                m_TerrainMaterialType = m_Terrains[0].materialType;
                if (m_TerrainMaterialType == Terrain.MaterialType.BuiltInLegacySpecular)
                {
                    m_TerrainLegacyShininess = m_Terrains[0].legacyShininess;
                    m_TerrainLegacySpecular  = m_Terrains[0].legacySpecular;
                }
#endif
                m_VisualizationMaterial.shader = Shader.Find("Hidden/Builtin_TerrainVisualization");
                break;
            }
        }
Exemplo n.º 8
0
        public void FlipTexture()
        {
            var texture = new Texture2D(2, 2);

            texture.SetPixels(new [] { Color.white, Color.black, Color.black, Color.black });
            texture.Apply();
            ToolboxHelper.FlipTexture(texture, true);
            var horizontalFlip = texture.GetPixels();

            Assert.That(horizontalFlip[1], Is.EqualTo(Color.white));

            ToolboxHelper.FlipTexture(texture, false);
            var verticalFlip = texture.GetPixels();

            Assert.That(verticalFlip[3], Is.EqualTo(Color.white));
        }
        public void SaveSettings()
        {
            if (m_SelectedPreset != null)
            {
                m_PresetPath = AssetDatabase.GetAssetPath(m_SelectedPreset);
            }
            else
            {
                m_PresetPath = string.Empty;
            }

            string filePath     = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsVisualization);
            string settingsData = JsonUtility.ToJson(m_Settings);

            File.WriteAllText(filePath, settingsData);
            SceneView.RepaintAll();
        }
        bool ValidateHeightmap()
        {
            if (!ToolboxHelper.IsPowerOfTwo(m_Settings.HeightmapWidth) || !ToolboxHelper.IsPowerOfTwo(m_Settings.HeightmapHeight))
            {
                // texture is not power of two
                Debug.LogError("TerrainToolbox: Imported heightmap resolution is not power of two.");
                return(false);
            }

            if (m_Settings.TilesX != 0 && m_Settings.TilesZ != 0)
            {
                float tileHeightX = (float)m_Settings.HeightmapWidth / (float)m_Settings.TilesX;
                float tileHeightZ = (float)m_Settings.HeightmapWidth / (float)m_Settings.TilesZ;
                if (tileHeightX != tileHeightZ)
                {
                    // heights per tile is non-square
                    Debug.LogError("TerrainToolbox: Heightmap resolution per tile is not square size with current settings.");
                    return(false);
                }
                if (!ToolboxHelper.IsInteger(tileHeightX) || !ToolboxHelper.IsInteger(tileHeightZ))
                {
                    // heights per tile is not integer
                    Debug.LogError("TerrainToolbox: Heightmap resolution per tile is not integer with current settings. You will get seams between tiles.");
                    return(false);
                }
                if (tileHeightX > 4096 || tileHeightX < 32)
                {
                    // heightmap size per tile out of range
                    Debug.LogError("TerrainToolbox: Heightmap resolution per tile is out of range. Supported resolution is from 32 to 4096.");
                    return(false);
                }
            }

            if (m_Settings.HeightmapMode == Heightmap.Mode.Batch)
            {
                int tiles = m_Settings.TilesX * m_Settings.TilesZ;
                if (m_Settings.TileHeightmapPaths.Count != tiles)
                {
                    // missing tile heightmap files
                    Debug.LogError("TerrainToolbox: Number of heightmaps does not match number of terrain tiles.");
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 11
0
        // Unity PNG encoder does not support 16bit export, change will come later 2019
        public static void ExportTerrainHeightsToTexture(TerrainData terrainData, Heightmap.Format format, string path, bool flipVertical, Vector2 inputLevelsRange)
        {
            RenderTexture oldRT   = RenderTexture.active;
            int           width   = terrainData.heightmapTexture.width - 1;
            int           height  = terrainData.heightmapTexture.height - 1;
            var           texture = new Texture2D(width, height, terrainData.heightmapTexture.graphicsFormat, TextureCreationFlags.None);

            RenderTexture.active = terrainData.heightmapTexture;
            texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);

            //Remap Texture
            Color[] pixels = texture.GetPixels();
            for (int i = 0; i < pixels.Length; i += 4)
            {
                pixels[i].r     = (pixels[i].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 1].r = (pixels[i + 1].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 2].r = (pixels[i + 2].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 3].r = (pixels[i + 3].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
            }
            texture.SetPixels(pixels);
            texture.Apply();

            //Flip Texture
            if (flipVertical)
            {
                ToolboxHelper.FlipTexture(texture, true);
            }

            byte[] bytes;
            switch (format)
            {
            case Heightmap.Format.TGA:
                bytes = texture.EncodeToTGA();
                path  = path + ".tga";
                break;

            default:
                bytes = texture.EncodeToPNG();
                path  = path + ".png";
                break;
            }

            File.WriteAllBytes(path, bytes);
            RenderTexture.active = oldRT;
        }
Exemplo n.º 12
0
        void GetAndSetActiveRenderPipelineSettings()
        {
            ToolboxHelper.RenderPipeline m_ActiveRenderPipeline = ToolboxHelper.GetRenderPipeline();
            switch (m_ActiveRenderPipeline)
            {
            case ToolboxHelper.RenderPipeline.HD:
                m_MaxLayerCount = kMaxLayerHD;
                break;

            case ToolboxHelper.RenderPipeline.LW:
                m_MaxLayerCount = kMaxNoLimit;
                break;

            default:
                m_MaxLayerCount = kMaxNoLimit;
                break;
            }
        }
		public void LoadSettings()
		{
			string filePath = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsCreate);
			if (File.Exists(filePath))
			{
				string createSettingsData = File.ReadAllText(filePath);
				JsonUtility.FromJsonOverwrite(createSettingsData, m_Settings);
			}

			if (m_Settings.PresetPath == string.Empty)
			{
				m_SelectedPreset = null;
			}
			else
			{
				m_SelectedPreset = AssetDatabase.LoadAssetAtPath(m_Settings.PresetPath, typeof(TerrainCreationSettings)) as TerrainCreationSettings;
			}
		}
        public void SaveSettings()
        {
            if (m_SelectedPreset != null)
            {
                m_Settings.PresetPath = AssetDatabase.GetAssetPath(m_SelectedPreset);
            }
            else
            {
                m_Settings.PresetPath = string.Empty;
            }

            string filePath     = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsSettings);
            string settingsData = JsonUtility.ToJson(m_Settings);

            File.WriteAllText(filePath, settingsData);
            RevertMaterial();
            m_selectedMode = VISUALIZERMODE.None;
            SceneView.RepaintAll();
        }
		void ShowGeneralGUI()
		{
			EditorGUILayout.LabelField("General", EditorStyles.boldLabel);
			EditorGUILayout.Space();
			++EditorGUI.indentLevel;
			// Terrain Sizing
			EditorGUI.BeginChangeCheck();
			m_Settings.TerrainWidth = EditorGUILayout.IntField(Styles.TerrainWidth, m_Settings.TerrainWidth);
			m_Settings.TerrainLength = EditorGUILayout.IntField(Styles.TerrainLength, m_Settings.TerrainLength);			
			m_Settings.TerrainHeight = EditorGUILayout.IntField(Styles.TerrainHeight, m_Settings.TerrainHeight);
			m_Settings.StartPosition = EditorGUILayout.Vector3Field(Styles.StartPosition, m_Settings.StartPosition);
			if (EditorGUI.EndChangeCheck())
			{
				m_Settings.HeightmapRemapMax = m_Settings.TerrainHeight;
			}

			// Update Gizmo in scene
			if (ToolboxHelper.GizmoEnabled)
			{
				ToolboxHelper.UpdateGizmos(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength, m_Settings.StartPosition, m_Settings.GroupID);
			}

			EditorGUI.BeginChangeCheck();
			m_Settings.TilesX = EditorGUILayout.IntField(Styles.TilesXAxis, m_Settings.TilesX);
			m_Settings.TilesZ = EditorGUILayout.IntField(Styles.TilesZAxis, m_Settings.TilesZ);
			if (EditorGUI.EndChangeCheck() && m_Settings.EnableHeightmapImport)
			{
				UpdateHeightmapInformation(m_Settings.GlobalHeightmapPath);
			}			

			// Terrain Group Settings
			m_Settings.GroupID = EditorGUILayout.IntField(Styles.GroupingID, m_Settings.GroupID);
			m_Settings.ShowGroupSettings = EditorGUILayout.Foldout(m_Settings.ShowGroupSettings, Styles.GroupSettings, true);
			if (m_Settings.ShowGroupSettings)
			{
				m_Settings.PixelError = EditorGUILayout.FloatField(Styles.PixelError, m_Settings.PixelError);
				m_Settings.BaseMapDistance = EditorGUILayout.IntField(Styles.BaseMapDistance, m_Settings.BaseMapDistance);
				m_Settings.MaterialOverride = EditorGUILayout.ObjectField(Styles.ShareMaterial, m_Settings.MaterialOverride, typeof(Material), false) as Material;
				m_Settings.HeightmapResolution = EditorGUILayout.IntPopup("Tile Height Resolution", m_Settings.HeightmapResolution, HeightmapSizeNames, HeightmapSize);
			}
			--EditorGUI.indentLevel;
		}
Exemplo n.º 16
0
        void RefreshTerrainInScene()
        {
            m_Terrains.Clear();
            m_Terrains.AddRange(ToolboxHelper.GetAllTerrainsInScene());
            if (m_Terrains.Count == 0)
            {
                m_ModeWarning = true;
                return;
            }

            m_TerrainMaxHeight = m_Terrains.Max(t => t.terrainData.size.y);

            m_TerrainMaterials.Clear();
            foreach (Terrain terrain in m_Terrains)
            {
                m_TerrainMaterials.Add(terrain.materialTemplate);
            }

            m_ModeWarning = false;
        }
Exemplo n.º 17
0
        public void SaveSettings()
        {
            if (m_SelectedPreset != null)
            {
                m_PresetPath = AssetDatabase.GetAssetPath(m_SelectedPreset);
            }
            else
            {
                m_PresetPath = string.Empty;
            }

            string filePath     = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsVisualization);
            string settingsData = JsonUtility.ToJson(m_Settings);

            File.WriteAllText(filePath, settingsData);
            SceneView.RepaintAll();

            EditorSceneManager.sceneSaving         -= OnSceneSaving;
            EditorSceneManager.sceneSaved          -= OnSceneSaved;
            EditorSceneManager.sceneOpened         -= OnSceneOpened;
            EditorApplication.playModeStateChanged -= PlayModeChanged;
            Undo.undoRedoPerformed -= OnUndo;
        }
        public void LoadSettings()
        {
            string filePath = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsVisualization);

            if (File.Exists(filePath))
            {
                string settingsData = File.ReadAllText(filePath);
                JsonUtility.FromJsonOverwrite(settingsData, m_Settings);
            }

            if (m_PresetPath == string.Empty)
            {
                m_SelectedPreset = null;
            }
            else
            {
                m_SelectedPreset = AssetDatabase.LoadAssetAtPath(m_PresetPath, typeof(TerrainVisualizationSettings)) as TerrainVisualizationSettings;
            }
            EditorSceneManager.sceneSaving         += OnSceneSaving;
            EditorSceneManager.sceneSaved          += OnSceneSaved;
            EditorSceneManager.sceneOpened         += OnSceneOpened;
            EditorApplication.playModeStateChanged += PlayModeChanged;
        }
Exemplo n.º 19
0
        void GetAndSetActiveRenderPipelineSettings()
        {
            ToolboxHelper.RenderPipeline m_ActiveRenderPipeline = ToolboxHelper.GetRenderPipeline();
            m_VisualizationMaterial = AssetDatabase.LoadAssetAtPath <Material>("Packages/com.unity.terrain-tools/editor/terraintoolbox/materials/terrainvisualization.mat");

            switch (m_ActiveRenderPipeline)
            {
            case ToolboxHelper.RenderPipeline.HD:
                m_VisualizationMaterial.shader = Shader.Find("Hidden/HDRP_TerrainVisualization");
                break;

            case ToolboxHelper.RenderPipeline.LW:
                m_VisualizationMaterial.shader = Shader.Find("Hidden/LWRP_TerrainVisualization");
                break;

            case ToolboxHelper.RenderPipeline.Universal:
                m_VisualizationMaterial.shader = Shader.Find("Hidden/Universal_TerrainVisualization");
                break;

            default:
                if (m_Terrains == null || m_Terrains.Count == 0)
                {
                    break;
                }
#if UNITY_2019_2_OR_NEWER
#else
                m_TerrainMaterialType = m_Terrains[0].materialType;
                if (m_TerrainMaterialType == Terrain.MaterialType.BuiltInLegacySpecular)
                {
                    m_TerrainLegacyShininess = m_Terrains[0].legacyShininess;
                    m_TerrainLegacySpecular  = m_Terrains[0].legacySpecular;
                }
#endif
                m_VisualizationMaterial.shader = Shader.Find("Hidden/Builtin_TerrainVisualization");
                break;
            }
        }
        void ShowImportHeightmapGUI()
        {
            // Heightmap Mode
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(Styles.HeightmapMode);
            ToggleHightmapMode();
            EditorGUILayout.EndHorizontal();

            // Heightmap selector
            if (m_Settings.HeightmapMode == Heightmap.Mode.Global)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(Styles.SelectGlobalHeightmap);
                EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
                EditorGUILayout.LabelField(m_Settings.GlobalHeightmapPath);
                EditorGUI.BeginChangeCheck();
                if (GUILayout.Button("...", GUILayout.Width(25.0f)))
                {
                    m_Settings.GlobalHeightmapPath = EditorUtility.OpenFilePanelWithFilters("Select raw image file...", "Assets", new string[] { "Raw Image File", "raw" });
                }
                if (EditorGUI.EndChangeCheck())
                {
                    UpdateHeightmapInformation(m_Settings.GlobalHeightmapPath);
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndHorizontal();
            }
            else if (m_Settings.HeightmapMode == Heightmap.Mode.Tiles)
            {
                int fileIndex = 0;
                int numFiles  = m_Settings.TilesX * m_Settings.TilesZ;
                for (int i = 0; i < numFiles; i++)
                {
                    m_Settings.TileHeightmapPaths.Add(string.Empty);
                }

                for (int x = 0; x < m_Settings.TilesZ; x++)
                {
                    for (int y = 0; y < m_Settings.TilesX; y++)
                    {
                        EditorGUILayout.BeginHorizontal();
                        string tileIndex = "X-" + x + " | " + "Y-" + y;
                        EditorGUILayout.LabelField(tileIndex);

                        EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
                        EditorGUILayout.LabelField(m_Settings.TileHeightmapPaths[fileIndex]);
                        EditorGUI.BeginChangeCheck();
                        if (GUILayout.Button("...", GUILayout.Width(25.0f)))
                        {
                            m_Settings.TileHeightmapPaths[fileIndex] = EditorUtility.OpenFilePanelWithFilters("Select raw image file...", "Assets", new string[] { "Raw Image File", "raw" });
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            UpdateHeightmapInformation(m_Settings.TileHeightmapPaths[fileIndex]);
                        }
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.EndHorizontal();

                        fileIndex++;
                    }
                }
            }
            else if (m_Settings.HeightmapMode == Heightmap.Mode.Batch)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(Styles.SelectBatchHeightmapFolder);
                EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
                EditorGUILayout.LabelField(m_Settings.BatchHeightmapFolder);
                EditorGUI.BeginChangeCheck();
                if (GUILayout.Button("...", GUILayout.Width(25.0f)))
                {
                    m_Settings.BatchHeightmapFolder = EditorUtility.OpenFolderPanel("Select heightmaps folder...", "", "");
                }
                if (EditorGUI.EndChangeCheck() && Directory.Exists(m_Settings.BatchHeightmapFolder))
                {
                    List <string> heightFiles = Directory.GetFiles(m_Settings.BatchHeightmapFolder, "*.raw").ToList();
                    m_Settings.TileHeightmapPaths = SortBatchHeightmapFiles(heightFiles);
                    UpdateHeightmapInformation(m_Settings.TileHeightmapPaths[0]);
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndHorizontal();
            }
            // Heightmap settings
            string infoMsg  = "Heightmap(s) must use a single channel and be either 8 or 16 bit in RAW format. Resolution must be a power of two. \n";
            string sizeMsg  = string.Format("Resolution: {0} x {1} \n", m_Settings.HeightmapWidth, m_Settings.HeightmapHeight);
            string tileMsg  = string.Format("Number of Tiles: {0} x {1} \n", m_Settings.TilesX, m_Settings.TilesZ);
            string depthMsg = string.Format("Bit depth: {0}", ToolboxHelper.GetBitDepth(m_Settings.HeightmapDepth));
            string msg      = infoMsg + sizeMsg + tileMsg + depthMsg;

            EditorGUILayout.HelpBox(msg, MessageType.Info);
            m_Settings.HeightmapResolution = EditorGUILayout.IntPopup("Tile Height Resolution", m_Settings.HeightmapResolution, HeightmapSizeNames, HeightmapSize);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.MinMaxSlider(Styles.HeightmapRemap, ref m_Settings.HeightmapRemapMin, ref m_Settings.HeightmapRemapMax, 0f, (float)m_Settings.TerrainHeight);
            EditorGUILayout.LabelField(Styles.HeightmapRemapMin, GUILayout.Width(40.0f));
            m_Settings.HeightmapRemapMin = EditorGUILayout.FloatField(m_Settings.HeightmapRemapMin, GUILayout.Width(75.0f));
            EditorGUILayout.LabelField(Styles.HeightmapRemapMax, GUILayout.Width(40.0f));
            m_Settings.HeightmapRemapMax = EditorGUILayout.FloatField(m_Settings.HeightmapRemapMax, GUILayout.Width(75.0f));
            EditorGUILayout.EndHorizontal();
            m_Settings.FlipMode = (Heightmap.Flip)EditorGUILayout.EnumPopup(Styles.FlipAxis, m_Settings.FlipMode);
        }
Exemplo n.º 21
0
        void SaveSettings()
        {
            string filePath = ToolboxHelper.GetPrefFilePath(ToolboxHelper.ToolboxPrefsWindow);

            File.WriteAllText(filePath, ((int)m_SelectedMode).ToString());
        }
        void ApplySettingsToTerrains(Terrain[] terrains)
        {
            int index = 0;

            try
            {
                foreach (var terrain in terrains)
                {
                    EditorUtility.DisplayProgressBar("Applying settings changes on terrains", string.Format("Updating terrain tile {0}", terrain.name), ((float)index / terrains.Length));

                    if (m_Settings.EnableBasicSettings)
                    {
                        Undo.RecordObject(terrain, "Terrain property change");

                        terrain.groupingID           = m_Settings.GroupingID;
                        terrain.allowAutoConnect     = m_Settings.AutoConnect;
                        terrain.drawHeightmap        = m_Settings.DrawHeightmap;
                        terrain.drawInstanced        = m_Settings.DrawInstanced;
                        terrain.heightmapPixelError  = m_Settings.PixelError;
                        terrain.basemapDistance      = m_Settings.BaseMapDistance;
                        terrain.shadowCastingMode    = m_Settings.ShadowCastingMode;
                        terrain.materialTemplate     = m_Settings.MaterialTemplate;
                        terrain.reflectionProbeUsage = m_Settings.ReflectionProbeUsage;
#if UNITY_2019_2_OR_NEWER
#else
                        terrain.materialType = m_Settings.MaterialType;
                        if (m_Settings.MaterialType != Terrain.MaterialType.Custom)
                        {
                            terrain.legacySpecular  = m_Settings.LegacySpecular;
                            terrain.legacyShininess = m_Settings.LegacyShininess;
                        }
#endif
                    }

                    if (m_Settings.EnableMeshResSettings)
                    {
                        Undo.RecordObject(terrain.terrainData, "TerrainData property change");
                        Vector3 size = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength);
                        terrain.terrainData.size = size;
                        terrain.terrainData.SetDetailResolution(m_Settings.DetailResolutaion, m_Settings.DetailResolutionPerPatch);
                    }

                    if (m_Settings.EnableTextureResSettings)
                    {
                        terrain.terrainData.baseMapResolution = m_Settings.BaseTextureResolution;
                        if (m_Settings.AlphaMapResolution != terrain.terrainData.alphamapResolution)
                        {
                            ToolboxHelper.ResizeControlTexture(terrain.terrainData, m_Settings.AlphaMapResolution);
                        }
                        if (m_Settings.HeightMapResolution != terrain.terrainData.heightmapResolution)
                        {
                            ToolboxHelper.ResizeHeightmap(terrain.terrainData, m_Settings.HeightMapResolution);
                        }
                    }

                    if (m_Settings.EnableTreeSettings)
                    {
                        Undo.RecordObject(terrain, "Terrain property change");

                        terrain.drawTreesAndFoliage         = m_Settings.DrawTreesAndFoliage;
                        terrain.bakeLightProbesForTrees     = m_Settings.BakeLightProbesForTrees;
                        terrain.deringLightProbesForTrees   = m_Settings.DeringLightProbesForTrees;
                        terrain.preserveTreePrototypeLayers = m_Settings.PreserveTreePrototypeLayers;
                        terrain.detailObjectDistance        = m_Settings.DetailObjectDistance;
                        terrain.collectDetailPatches        = m_Settings.CollectDetailPatches;
                        terrain.detailObjectDensity         = m_Settings.DetailObjectDensity;
                        terrain.treeDistance            = m_Settings.TreeDistance;
                        terrain.treeBillboardDistance   = m_Settings.TreeBillboardDistance;
                        terrain.treeCrossFadeLength     = m_Settings.TreeCrossFadeLength;
                        terrain.treeMaximumFullLODCount = m_Settings.TreeMaximumFullLODCount;
                    }

                    if (m_Settings.EnableWindSettings)
                    {
                        Undo.RecordObject(terrain.terrainData, "TerrainData property change");
                        terrain.terrainData.wavingGrassStrength = m_Settings.WavingGrassStrength;
                        terrain.terrainData.wavingGrassSpeed    = m_Settings.WavingGrassSpeed;
                        terrain.terrainData.wavingGrassAmount   = m_Settings.WavingGrassAmount;
                        terrain.terrainData.wavingGrassTint     = m_Settings.WavingGrassTint;
                    }

                    index++;
                }
            }
            finally
            {
                AssetDatabase.Refresh();
                EditorUtility.ClearProgressBar();
            }
        }
Exemplo n.º 23
0
        void ApplySettingsToTerrains(Terrain[] terrains, string errorContext = "")
        {
            int index = 0;

            try
            {
                bool continueEdit = true;

                // Only show this warning if the user has Mesh Settings enabled.
                if (m_Settings.EnableMeshResSettings)
                {
                    var newSize = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight,
                                              m_Settings.TerrainLength);
                    foreach (var terrain in terrains)
                    {
                        // If any terrain has a size that's different from the specified settings, let's confirm
                        // the action.
                        if (terrain.terrainData.size != newSize)
                        {
                            var message =
                                "Some terrains have different sizes than the settings specified. This operation will resize the terrains potentially resulting in gaps and/or overlaps.";
                            if (string.IsNullOrEmpty(errorContext))
                            {
                                continueEdit = EditorUtility.DisplayDialog("Confirm",
                                                                           $"{message}\nAre you sure you want to continue?",
                                                                           "Continue", "Cancel");
                            }
                            else
                            {
                                continueEdit = EditorUtility.DisplayDialog("Confirm",
                                                                           $"1. {errorContext}\n2. {message}\n\nAre you sure you want to continue?",
                                                                           "Continue", "Cancel");
                            }
                            break;
                        }
                    }
                }

                if (continueEdit)
                {
                    foreach (var terrain in terrains)
                    {
                        EditorUtility.DisplayProgressBar("Applying settings changes on terrains",
                                                         string.Format("Updating terrain tile {0}", terrain.name),
                                                         ((float)index / terrains.Length));

                        if (m_Settings.EnableBasicSettings)
                        {
                            Undo.RecordObject(terrain, "Terrain property change");

                            terrain.groupingID           = m_Settings.GroupingID;
                            terrain.allowAutoConnect     = m_Settings.AutoConnect;
                            terrain.drawHeightmap        = m_Settings.DrawHeightmap;
                            terrain.drawInstanced        = m_Settings.DrawInstanced;
                            terrain.heightmapPixelError  = m_Settings.PixelError;
                            terrain.basemapDistance      = m_Settings.BaseMapDistance;
                            terrain.shadowCastingMode    = m_Settings.ShadowCastingMode;
                            terrain.materialTemplate     = m_Settings.MaterialTemplate;
                            terrain.reflectionProbeUsage = m_Settings.ReflectionProbeUsage;
#if UNITY_2019_2_OR_NEWER
#else
                            terrain.materialType = m_Settings.MaterialType;
                            if (m_Settings.MaterialType != Terrain.MaterialType.Custom)
                            {
                                terrain.legacySpecular  = m_Settings.LegacySpecular;
                                terrain.legacyShininess = m_Settings.LegacyShininess;
                            }
#endif
                        }

                        if (m_Settings.EnableMeshResSettings)
                        {
                            Undo.RecordObject(terrain.terrainData, "TerrainData property change");
                            Vector3 size = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight,
                                                       m_Settings.TerrainLength);
                            terrain.terrainData.size = size;
                            terrain.terrainData.SetDetailResolution(m_Settings.DetailResolutaion,
                                                                    m_Settings.DetailResolutionPerPatch);
                        }

                        if (m_Settings.EnableTextureResSettings)
                        {
                            terrain.terrainData.baseMapResolution = m_Settings.BaseTextureResolution;
                            if (m_Settings.AlphaMapResolution != terrain.terrainData.alphamapResolution)
                            {
                                ToolboxHelper.ResizeControlTexture(terrain.terrainData, m_Settings.AlphaMapResolution);
                            }

                            if (m_Settings.HeightMapResolution != terrain.terrainData.heightmapResolution)
                            {
                                ToolboxHelper.ResizeHeightmap(terrain.terrainData, m_Settings.HeightMapResolution);
                            }
                        }

                        if (m_Settings.EnableTreeSettings)
                        {
                            Undo.RecordObject(terrain, "Terrain property change");

                            terrain.drawTreesAndFoliage         = m_Settings.DrawTreesAndFoliage;
                            terrain.bakeLightProbesForTrees     = m_Settings.BakeLightProbesForTrees;
                            terrain.deringLightProbesForTrees   = m_Settings.DeringLightProbesForTrees;
                            terrain.preserveTreePrototypeLayers = m_Settings.PreserveTreePrototypeLayers;
                            terrain.detailObjectDistance        = m_Settings.DetailObjectDistance;
                            terrain.collectDetailPatches        = m_Settings.CollectDetailPatches;
                            terrain.detailObjectDensity         = m_Settings.DetailObjectDensity;
                            terrain.treeDistance            = m_Settings.TreeDistance;
                            terrain.treeBillboardDistance   = m_Settings.TreeBillboardDistance;
                            terrain.treeCrossFadeLength     = m_Settings.TreeCrossFadeLength;
                            terrain.treeMaximumFullLODCount = m_Settings.TreeMaximumFullLODCount;
                        }

                        if (m_Settings.EnableWindSettings)
                        {
                            Undo.RecordObject(terrain.terrainData, "TerrainData property change");
                            terrain.terrainData.wavingGrassStrength = m_Settings.WavingGrassStrength;
                            terrain.terrainData.wavingGrassSpeed    = m_Settings.WavingGrassSpeed;
                            terrain.terrainData.wavingGrassAmount   = m_Settings.WavingGrassAmount;
                            terrain.terrainData.wavingGrassTint     = m_Settings.WavingGrassTint;
                        }

                        index++;
                    }
                }
            }
            finally
            {
                AssetDatabase.Refresh();
                EditorUtility.ClearProgressBar();
            }
        }
        void Create()
        {
            // check lighting auto bake
            if (m_Settings.EnableLightingAutoBake)
            {
                UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.Iterative;
            }
            else
            {
                UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.OnDemand;
            }

            if (m_Settings.EnableClearExistingData)
            {
                ClearExistingTerrainGroup(m_Settings.GroupID);
            }

            // create tiles
            int        tileCount        = m_Settings.TilesX * m_Settings.TilesZ;
            Vector2Int tileOffset       = Vector2Int.zero;
            Vector2Int tileOffsetSource = Vector2Int.zero;
            Vector2Int tileResolution   = new Vector2Int(m_Settings.TerrainWidth / m_Settings.TilesX, m_Settings.TerrainLength / m_Settings.TilesZ);
            Vector3    tileSize         = new Vector3(tileResolution.x, m_Settings.TerrainHeight, tileResolution.y);
            Vector3    tilePosition     = m_Settings.StartPosition;

            Terrain[] terrains = new Terrain[tileCount];

            string assetFolderPath = GetAssetPathFromFullPath(m_Settings.TerrainAssetDirectory);
            int    tileIndex       = 0;

            try
            {
                // create terrain grouping object
                string       groupName    = "TerrainGroup_" + m_Settings.GroupID;
                GameObject   terrainGroup = new GameObject(groupName);
                TerrainGroup groupComp    = terrainGroup.AddComponent <TerrainGroup>();
                terrainGroup.transform.position = m_Settings.StartPosition;
                Heightmap globalHeightmap = null;

                Undo.RegisterCreatedObjectUndo(terrainGroup, "Create terrain");

                // heightmap offset
                if (m_Settings.UseGlobalHeightmap)
                {
                    byte[] rawData = File.ReadAllBytes(m_Settings.GlobalHeightmapPath);
                    globalHeightmap  = new Heightmap(rawData, m_Settings.FlipMode);
                    tileOffsetSource = new Vector2Int(globalHeightmap.Width / m_Settings.TilesX, globalHeightmap.Height / m_Settings.TilesZ);
                }
                else
                {
                    tileOffsetSource = tileResolution;
                }

                for (int x = 0; x < m_Settings.TilesX; x++, tileOffset.x += tileOffsetSource.x, tilePosition.x += tileResolution.x)
                {
                    tileOffset.y   = 0;
                    tilePosition.z = m_Settings.StartPosition.z;

                    for (int y = 0; y < m_Settings.TilesZ; y++, tileOffset.y += tileOffsetSource.y, tilePosition.z += tileResolution.y)
                    {
                        EditorUtility.DisplayProgressBar("Creating terrains", string.Format("Updating terrain tile ({0}, {1})", x, y), ((float)tileIndex / tileCount));

                        TerrainData terrainData = new TerrainData();
                        terrainData.alphamapResolution = m_Settings.ControlTextureResolution;
                        terrainData.baseMapResolution  = m_Settings.BaseTextureResolution;
                        terrainData.SetDetailResolution(m_Settings.DetailResolution, m_Settings.DetailResolutionPerPatch);

                        GameObject newGO      = Terrain.CreateTerrainGameObject(terrainData);
                        Terrain    newTerrain = newGO.GetComponent <Terrain>();
                        newTerrain.groupingID          = m_Settings.GroupID;
                        newTerrain.allowAutoConnect    = m_Settings.AutoConnect;
                        newTerrain.drawInstanced       = m_Settings.DrawInstanced;
                        newTerrain.heightmapPixelError = m_Settings.PixelError;
                        newTerrain.basemapDistance     = m_Settings.BaseMapDistance;
                        if (m_Settings.MaterialOverride != null)
                        {
                            newTerrain.materialTemplate = m_Settings.MaterialOverride;
#if UNITY_2019_2_OR_NEWER
#else
                            newTerrain.materialType = Terrain.MaterialType.Custom;
#endif
                        }

                        string terrainName = $"Terrain_{x}_{y}";;
                        if (m_Settings.EnableGuid)
                        {
                            Guid newGuid = Guid.NewGuid();
                            terrainName = $"Terrain_{x}_{y}_{newGuid}";
                        }
                        newGO.name = terrainName;
                        newTerrain.transform.position = tilePosition;
                        newTerrain.transform.SetParent(terrainGroup.transform);

                        // import height
                        if (m_Settings.HeightmapMode == Heightmap.Mode.Global && globalHeightmap != null)
                        {
                            Heightmap tileHeightmap = GetTileHeightmapFromGlobalHeightmap(globalHeightmap, tileOffset);
                            tileHeightmap.ApplyTo(newTerrain);
                        }

                        if (m_Settings.HeightmapMode == Heightmap.Mode.Tiles || m_Settings.HeightmapMode == Heightmap.Mode.Batch)
                        {
                            if (File.Exists(m_Settings.TileHeightmapPaths[tileIndex]))
                            {
                                var       remap       = (m_Settings.HeightmapRemapMax - m_Settings.HeightmapRemapMin) / m_Settings.TerrainHeight;
                                var       baseLevel   = m_Settings.HeightmapRemapMin / m_Settings.TerrainHeight;
                                byte[]    rawTileData = File.ReadAllBytes(m_Settings.TileHeightmapPaths[tileIndex]);
                                Heightmap tileHeight  = new Heightmap(rawTileData, m_Settings.FlipMode);
                                Heightmap tileMap     = new Heightmap(tileHeight, Vector2Int.zero, new Vector2Int(tileHeight.Width, tileHeight.Height), remap, baseLevel);
                                tileMap.ApplyTo(newTerrain);
                            }
                        }

                        terrains[tileIndex] = newTerrain;
                        tileIndex++;

                        // save terrain data asset
                        terrainData.size = tileSize;                         // set terrain size after heightmap process
                        string assetPath = $"{assetFolderPath}/{terrainName}.asset";
                        if (!Directory.Exists(assetFolderPath))
                        {
                            Directory.CreateDirectory(assetFolderPath);
                        }
                        AssetDatabase.CreateAsset(terrainData, assetPath);

                        // finally, resize height resolution if needed
                        if (terrainData.heightmapResolution != (m_Settings.HeightmapResolution))
                        {
                            ToolboxHelper.ResizeHeightmap(terrainData, (m_Settings.HeightmapResolution));
                        }

                        Undo.RegisterCreatedObjectUndo(newGO, "Create terrain");
                    }
                }

                m_Terrains     = terrains;
                m_CurrentGroup = terrainGroup;

                UpdateGroupSettings(groupComp);
                ToolboxHelper.CalculateAdjacencies(m_Terrains, m_Settings.TilesX, m_Settings.TilesZ);
            }
            finally
            {
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                EditorUtility.ClearProgressBar();
            }
        }
		public void OnGUI()
		{
			// scroll view of settings
			EditorGUIUtility.hierarchyMode = true;
			TerrainToolboxUtilities.DrawSeperatorLine();
			m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition);

			// General Settings
			ShowGeneralGUI();

			// Import Heightmap
			TerrainToolboxUtilities.DrawSeperatorLine();
			bool importHeightmapToggle = m_Settings.EnableHeightmapImport;
			m_Settings.ShowHeightmapSettings = TerrainToolGUIHelper.DrawToggleHeaderFoldout(Styles.ImportHeightmap, m_Settings.ShowHeightmapSettings, ref importHeightmapToggle, 0f);
			++EditorGUI.indentLevel;
			if (m_Settings.ShowHeightmapSettings)
			{
				EditorGUI.BeginDisabledGroup(!m_Settings.EnableHeightmapImport);
				ShowImportHeightmapGUI();
				EditorGUI.EndDisabledGroup();
			}
			m_Settings.EnableHeightmapImport = importHeightmapToggle;

			// Presets
			ShowPresetGUI();

			// Gizmos
			EditorGUILayout.BeginHorizontal();
			EditorGUILayout.LabelField(Styles.Gizmo, EditorStyles.boldLabel);
			if (GUILayout.Button(Styles.ShowGizmo))
			{
				ToolboxHelper.ShowGizmo();
			}
			if (GUILayout.Button(Styles.HideGizmo))
			{
				ToolboxHelper.HideGizmo();
			}
			EditorGUILayout.EndHorizontal();
			EditorGUILayout.Space();
			EditorGUILayout.EndScrollView();

			// Options
			ShowOptionsGUI();

			// Terrain info box
			--EditorGUI.indentLevel;
			string sizeMsg = string.Format("Terrain Size: {0}m x {1}m		", m_Settings.TerrainWidth, m_Settings.TerrainLength);
			string tileMsg = string.Format("Number of Tiles: {0} x {1} \n", m_Settings.TilesX, m_Settings.TilesZ);
			string heightMsg = string.Format("Terrain Height: {0}m		", m_Settings.TerrainHeight);			
			string tileSizeMsg = string.Format("Tile Size: {0} x {1} ", (m_Settings.TerrainWidth / m_Settings.TilesX), (m_Settings.TerrainLength / m_Settings.TilesZ));
			m_TerrainMessage = sizeMsg + tileMsg + heightMsg + tileSizeMsg;
			EditorGUILayout.HelpBox(m_TerrainMessage, MessageType.Info);

			// Create			
			EditorGUILayout.BeginHorizontal();
			if (GUILayout.Button(Styles.CreateBtn, GUILayout.Height(40)))
			{
				if (!RunCreateValidations())
				{
					EditorUtility.DisplayDialog("Error", "There are incompatible terrain creation settings that need to be resolved to continue. Please check Console for details.", "OK");
				}
				else
				{
					if (m_Settings.HeightmapMode == Heightmap.Mode.Global && File.Exists(m_Settings.GlobalHeightmapPath))
					{
						m_Settings.UseGlobalHeightmap = true;
					}
					else
					{
						m_Settings.UseGlobalHeightmap = false;
					}

					Create();
				}				
			}
			EditorGUILayout.EndHorizontal();
		}