#if UNITY_EDITOR using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace Gaia { /// /// Flags passed to NoiseSettingsGUI.OnGUI. Used to specify which portions of the Noise Settings GUI to draw. /// public enum NoiseSettingsGUIFlags { Preview = (1 << 0), Settings = (1 << 1), All = ( ~0 ), } /// /// Class used to draw the GUI for Noise Settings. /// public class NoiseSettingsGUI { /// /// The SerializedObject for the NoiseSettings that this NoiseSettingsGUI instance is currently rendering the GUI for. /// public SerializedObject serializedNoise; // noise settings properties // noise settings properties // noise settings properties // coord space settings properties private SerializedProperty transformSettings; public SerializedProperty translation; public SerializedProperty rotation; public SerializedProperty scale; public SerializedProperty flipScaleX; public SerializedProperty flipScaleY; public SerializedProperty flipScaleZ; // domain settings properties public SerializedProperty domainSettings; public SerializedProperty noiseTypeName; public SerializedProperty noiseTypeParams; public SerializedProperty fractalTypeName; public SerializedProperty fractalTypeParams; // filter stack settings // private SerializedProperty filterSettings; // private FilterStackView m_filterStackView; // private FilterStack m_filterStack; // private SerializedObject m_serializedFilterStack; // private bool m_showFilterStack; private RenderTexture m_previewRT; private bool m_noisePreviewIsLocked = false; /// /// The current NoiseSettings object that is associated with this instance of NoiseSettingsGUI. /// public NoiseSettings target = null; public Rect rect; public Spawner m_spawner; /// /// Sets up this instance of NoiseSettingsGUI with the specified NoiseSettings object. /// GUI will be drawn for this NoiseSettings instance. /// /// The NoiseSettings instance for which GUI will be drawn public void Init(NoiseSettings noiseSettings) { Init(new SerializedObject(noiseSettings)); } /// /// Sets up this instance of NoiseSettingsGUI with the specified SerializedObject containing an object reference /// to a NoiseSettings instance. GUI will be drawn for this serialized NoiseSettings instance. /// /// A SerializedObject instance containing an object reference to a NoiseSettings object public void Init(SerializedObject serializedNoise) { this.serializedNoise = serializedNoise; target = this.serializedNoise.targetObject as NoiseSettings; // transform settings transformSettings = this.serializedNoise.FindProperty("transformSettings"); translation = transformSettings.FindPropertyRelative("translation"); rotation = transformSettings.FindPropertyRelative("rotation"); scale = transformSettings.FindPropertyRelative("scale"); flipScaleX = transformSettings.FindPropertyRelative("flipScaleX"); flipScaleY = transformSettings.FindPropertyRelative("flipScaleY"); flipScaleZ = transformSettings.FindPropertyRelative("flipScaleZ"); // domain settings domainSettings = this.serializedNoise.FindProperty("domainSettings"); noiseTypeName = domainSettings.FindPropertyRelative("noiseTypeName"); noiseTypeParams = domainSettings.FindPropertyRelative("noiseTypeParams"); fractalTypeName = domainSettings.FindPropertyRelative("fractalTypeName"); fractalTypeParams = domainSettings.FindPropertyRelative("fractalTypeParams"); // filter settings // filterSettings = serializedNoise.FindProperty( "filterSettings" ); // m_filterStack = filterSettings.FindPropertyRelative( "filterStack" ).objectReferenceValue as FilterStack; // m_serializedFilterStack = new SerializedObject( m_filterStack ); // m_filterStackView = new FilterStackView( new GUIContent( "Filters" ), m_serializedFilterStack, m_serializedFilterStack.targetObject as FilterStack ); } /// /// Renders the GUI for the NoiseSettings instance associated with this NoiseSettingsGUI instance. /// /// Flags specifying which portions of the GUI to draw public void OnGUI(NoiseSettingsGUIFlags flags = NoiseSettingsGUIFlags.All) { serializedNoise.Update(); if((flags & NoiseSettingsGUIFlags.Preview) != 0) { DrawPreviewTexture(256f,ref m_noisePreviewIsLocked); } if((flags & NoiseSettingsGUIFlags.Settings) != 0) { TerrainToolGUIHelper.DrawFoldout(transformSettings, Styles.transformSettings, TransformSettingsGUI); TerrainToolGUIHelper.DrawFoldout(domainSettings, Styles.domainSettings, DomainSettingsGUI); // TerrainToolGUIHelper.DrawFoldout(filterSettings, Styles.filterSettings, FilterSettingsGUI); } serializedNoise.ApplyModifiedProperties(); } private void TransformSettingsGUI() { EditorGUILayout.PropertyField(translation); EditorGUILayout.PropertyField(rotation); EditorGUILayout.PropertyField(scale); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel(Styles.flipScale); flipScaleX.boolValue = TerrainToolGUIHelper.ToggleButton(Styles.flipScaleX, flipScaleX.boolValue); flipScaleY.boolValue = TerrainToolGUIHelper.ToggleButton(Styles.flipScaleY, flipScaleY.boolValue); flipScaleZ.boolValue = TerrainToolGUIHelper.ToggleButton(Styles.flipScaleZ, flipScaleZ.boolValue); } EditorGUILayout.EndHorizontal(); } private void DomainSettingsGUI() { noiseTypeName.stringValue = NoiseLib.NoiseTypePopup(Styles.noiseType, noiseTypeName.stringValue); INoiseType noiseType = NoiseLib.GetNoiseTypeInstance(noiseTypeName.stringValue); noiseTypeParams.stringValue = noiseType?.DoGUI(noiseTypeParams.stringValue); fractalTypeName.stringValue = NoiseLib.FractalTypePopup(Styles.fractalType, fractalTypeName.stringValue); IFractalType fractalType = NoiseLib.GetFractalTypeInstance(fractalTypeName.stringValue); fractalTypeParams.stringValue = fractalType?.DoGUI(fractalTypeParams.stringValue); } private void DoMinMaxSliderInt(GUIContent label, SerializedProperty prop, SerializedProperty minMaxProp) { int min = minMaxProp.vector2IntValue.x; int max = minMaxProp.vector2IntValue.y; prop.intValue = TerrainToolGUIHelper.MinMaxSliderInt(label, prop.intValue, ref min, ref max); minMaxProp.vector2IntValue = new Vector2Int(min, max); } private void DoMinMaxSlider(GUIContent label, SerializedProperty prop, SerializedProperty minMaxProp) { float min = minMaxProp.vector2Value.x; float max = minMaxProp.vector2Value.y; prop.floatValue = TerrainToolGUIHelper.MinMaxSlider(label, prop.floatValue, ref min, ref max); minMaxProp.vector2Value = new Vector2(min, max); } // private void FilterSettingsGUI() // { // m_filterStackView.OnGUI(); // } private void HandlePreviewTextureInput(Rect previewRect) { if(GUIUtility.hotControl != 0) { return; } Vector3 t = translation.vector3Value; Vector3 r = rotation.vector3Value; Vector3 s = scale.vector3Value; EventType eventType = Event.current.type; bool draggingPreview = Event.current.button == 0 && (eventType == EventType.MouseDown || eventType == EventType.MouseDrag); Vector2 previewDims = new Vector2(previewRect.width, previewRect.height); Vector2 abs = new Vector2(Mathf.Abs(s.x), Mathf.Abs(s.z)); if (Event.current.type == EventType.ScrollWheel) { abs += Vector2.one * .001f; float scroll = Event.current.delta.y; s.x += abs.x * scroll * .05f; s.z += abs.y * scroll * .05f; scale.vector3Value = s; Event.current.Use(); GUI.changed = true; } else if (draggingPreview) { // change noise offset panning icon Vector2 sign = new Vector2(-Mathf.Sign(s.x), Mathf.Sign(s.z)); Vector2 delta = Event.current.delta / previewDims * abs * sign; Vector3 d3 = new Vector3(delta.x, 0, delta.y); d3 = Quaternion.Euler( r ) * d3; t += d3; translation.vector3Value = t; Event.current.Use(); GUI.changed = true; } } /// /// Renders an interactive Noise Preview along with tooltip icons and an optional Export button that opens a new ExportNoiseWindow. /// A background image is also rendered behind the preview that takes up the entire width of the EditorWindow currently being drawn. /// /// Minimum size for the Preview /// Whether or not to render the Export button public void DrawPreviewTexture(float minSize, ref bool isLocked) { // Draw label with tooltip //GUILayout.Label( Styles.noisePreview ); float padding = 4f; float iconWidth = 40f; int size = (int)Mathf.Min(minSize, EditorGUIUtility.currentViewWidth); Rect currentRect = rect; currentRect.y += EditorGUIUtility.singleLineHeight *2f; Rect totalRect = new Rect(currentRect.x, currentRect.y, currentRect.width, size); //GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, size + padding * 2); // extra pixels for highlight border Color prev = GUI.color; GUI.color = new Color(.1f, .1f, .1f, 1f); GUI.DrawTexture(totalRect, Texture2D.whiteTexture, ScaleMode.StretchToFill, false); GUI.color = Color.white; // draw info icon // if(totalRect.Contains(Event.current.mousePosition)) { Rect infoIconRect = new Rect( totalRect.x + padding, totalRect.y + padding, iconWidth, iconWidth ); GUI.Label( infoIconRect, Styles.infoIcon ); // GUI.Label( infoIconRect, Styles.noiseTooltip ); } float buttonWidth = GUI.skin.button.CalcSize(Styles.buttonUnlocked).x; float buttonHeight = EditorGUIUtility.singleLineHeight; Rect lockButtonRect = new Rect(totalRect.x + padding, totalRect.y + padding * 2f + GUI.skin.button.CalcSize(Styles.infoIcon).y, buttonWidth, buttonHeight); if (isLocked) { if (GUI.Button(lockButtonRect, Styles.buttonLocked)) { isLocked = false; } } else { if (GUI.Button(lockButtonRect, Styles.buttonUnlocked)) { isLocked = true; } } m_noisePreviewIsLocked = isLocked; // draw export button //Rect exportRect = new Rect( totalRect.xMax - buttonWidth - padding, totalRect.yMax - buttonHeight - padding, buttonWidth, buttonHeight ); //if(GUI.Button(exportRect, Styles.export)) //{ // serializedNoise.ApplyModifiedProperties(); // serializedNoise.Update(); // ExportNoiseWindow.ShowWindow( serializedNoise.targetObject as NoiseSettings ); //} float safeSpace = Mathf.Max( iconWidth * 2, buttonWidth * 2 ) + padding * 4; float minWidth = Mathf.Min( size, totalRect.width - safeSpace ); Rect previewRect = new Rect(totalRect.x + totalRect.width / 2 - minWidth / 2, totalRect.y + totalRect.height / 2 - minWidth / 2, minWidth, minWidth); EditorGUIUtility.AddCursorRect(previewRect, MouseCursor.Pan); if (previewRect.Contains(Event.current.mousePosition) && !isLocked) { serializedNoise.Update(); HandlePreviewTextureInput(previewRect); serializedNoise.ApplyModifiedProperties(); } if ( Event.current.type == EventType.Repaint ) { // create preview RT here and keep until the next Repaint if( m_previewRT != null ) { RenderTexture.ReleaseTemporary( m_previewRT ); } NoiseSettings noiseSettings = serializedNoise.targetObject as NoiseSettings; m_previewRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.ARGB32); RenderTexture tempRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.RFloat); RenderTexture prevActive = RenderTexture.active; NoiseUtils.Blit2D(noiseSettings, tempRT); NoiseUtils.BlitPreview2D(tempRT, m_previewRT); RenderTexture.active = prevActive; GUI.DrawTexture(previewRect, m_previewRT, ScaleMode.ScaleToFit, false); RenderTexture.ReleaseTemporary(tempRT); } GUI.color = prev; } static class Styles { public static GUIContent noiseSettings = EditorGUIUtility.TrTextContent("Noise Settings:"); public static GUIContent randomize = EditorGUIUtility.TrTextContent("Randomize"); public static GUIContent reset = EditorGUIUtility.TrTextContent("Reset"); public static GUIContent flipScale = EditorGUIUtility.TrTextContent("Flip Scale", "Flips the scale of the Noise Domain Space"); public static GUIContent flipScaleX = EditorGUIUtility.TrTextContent("X", "Flips the scale of the Noise Domain Space along the X-axis"); public static GUIContent flipScaleY = EditorGUIUtility.TrTextContent("Y", "Flips the scale of the Noise Domain Space along the Y-axis"); public static GUIContent flipScaleZ = EditorGUIUtility.TrTextContent("Z", "Flips the scale of the Noise Domain Space along the Z-axis"); public static GUIContent noiseType = EditorGUIUtility.TrTextContent("Noise Type", "The type of Noise to be used"); public static GUIContent fractalType = EditorGUIUtility.TrTextContent("Fractal Type", "The type of Fractal to be used when generating Noise"); public static GUIContent noisePreview; public static GUIContent noiseTooltip = EditorGUIUtility.TrTextContent("", "Scroll Mouse Wheel:\nZooms the preview in and out and changes the noise scale\n\n" + "Left-mouse Drag:\nPans the noise field and changes the noise translation\n\n" + "Color Key:\nCyan = negative noise values\nGrayscale = values between 0 and 1\nBlack = values are 0\nRed = Values greater than 1. Used for debugging texture normalization"); public static GUIContent seed = EditorGUIUtility.TrTextContent("Seed"); public static GUIContent domainSettings = EditorGUIUtility.TrTextContent("Domain Settings", "Settings governing the Noise Domain. This is specific to each Noise Type and Fractal Type implementation"); public static GUIContent transformSettings = EditorGUIUtility.TrTextContent("Transform Settings", "Settings governing the transformations applied to positions in the Noise Domain Space"); // public static GUIContent filterSettings = EditorGUIUtility.TrTextContent("Filter Settings"); public static GUIContent ridgePower = EditorGUIUtility.TrTextContent("Ridge Power"); public static GUIContent billowPower = EditorGUIUtility.TrTextContent("Billow Power"); public static GUIContent voronoiPower = EditorGUIUtility.TrTextContent("Voronoi Power"); public static GUIContent power = EditorGUIUtility.TrTextContent("Power"); public static GUIContent export = EditorGUIUtility.TrTextContent("Export", "Open a window providing options for exporting Noise to Textures"); public static GUIContent buttonLocked = EditorGUIUtility.TrTextContent("Locked", "The preview texture is currently locked for changes from mouse input. Click here to unlock it."); public static GUIContent buttonUnlocked = EditorGUIUtility.TrTextContent("Unlocked", "The preview texture is currently active for changes from mouse input. Click here to lock it."); public static GUIContent infoIcon = new GUIContent("", EditorGUIUtility.FindTexture("console.infoicon"), "Scroll Mouse Wheel:\nZooms the preview in and out and changes the noise scale\n\n" + "Left-mouse Drag:\nPans the noise field and changes the noise translation\n\n" + "Color Key:\nCyan = negative noise values\nGrayscale = values between 0 and 1\nBlack = values are 0\nRed = Values greater than 1. Used for debugging texture normalization"); static Styles() { noisePreview = EditorGUIUtility.TrTextContent("Noise Field Preview:"); // , // "Scroll Mouse Wheel:\nZooms the preview in and out and changes the noise scale\n\n" + // "Left-mouse Drag:\nPans the noise field and changes the noise translation\n\n" + // "Color Key:\nCyan = negative noise values\nGrayscale = values between 0 and 1\nBlack = values are 0\nRed = Values greater than 1. Used for debugging texture normalization"); // noisePreview.image = infoIcon.image; } } } } #endif