362 lines
17 KiB
C#
362 lines
17 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
|
|
namespace WaterSystem.Data
|
|
{
|
|
[CustomEditor(typeof(WaterSurfaceData))]
|
|
public class WaterSurfaceDataEditor : Editor
|
|
{
|
|
[SerializeField]
|
|
ReorderableList waveList;
|
|
|
|
private void OnValidate()
|
|
{
|
|
var init = serializedObject.FindProperty("_init");
|
|
if(init?.boolValue == false)
|
|
Setup();
|
|
|
|
var standardHeight = EditorGUIUtility.singleLineHeight;
|
|
var standardLine = standardHeight + EditorGUIUtility.standardVerticalSpacing;
|
|
//Reorderable list stuff////////////////////////////////////////////////
|
|
waveList = new ReorderableList(serializedObject, serializedObject.FindProperty("_waves"), true, true, true, true);
|
|
|
|
//Single entry GUI
|
|
waveList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
|
|
{
|
|
var element = waveList.serializedProperty.GetArrayElementAtIndex(index);
|
|
rect.y += 2;
|
|
|
|
// Swell height
|
|
var preWidth = EditorGUIUtility.labelWidth;
|
|
EditorGUIUtility.labelWidth = rect.width * 0.2f;
|
|
Rect ampRect = new Rect(rect.x, rect.y + standardLine, rect.width * 0.5f, standardHeight);
|
|
var waveAmp = element.FindPropertyRelative("amplitude");
|
|
waveAmp.floatValue = EditorGUI.Slider(ampRect, "Swell Height", waveAmp.floatValue, 0.1f, 30f);
|
|
// Wavelength
|
|
Rect lengthRect = new Rect(rect.x + ampRect.width, rect.y + standardLine, rect.width * 0.5f, standardHeight);
|
|
var waveLen = element.FindPropertyRelative("wavelength");
|
|
waveLen.floatValue = EditorGUI.Slider(lengthRect, "Wavelength", waveLen.floatValue, 1.0f, 200f);
|
|
EditorGUIUtility.labelWidth = preWidth;
|
|
// Directional controls
|
|
Rect dirToggleRect = new Rect(rect.x, rect.y + 2 + standardLine * 2, rect.width * 0.5f, standardHeight);
|
|
Rect omniToggleRect = new Rect(rect.x + rect.width * 0.5f, dirToggleRect.y, rect.width * 0.5f, standardHeight);
|
|
Rect containerRect = new Rect(rect.x, dirToggleRect.y + 1, rect.width, standardLine * 3.2f);
|
|
// Direction/origin
|
|
var waveType = element.FindPropertyRelative("onmiDir");
|
|
var wTypeBool = (int)waveType.floatValue == 1 ? true : false;
|
|
GUI.Box(containerRect, "", EditorStyles.helpBox );
|
|
wTypeBool = !GUI.Toggle(dirToggleRect, !wTypeBool, "Directional", EditorStyles.miniButtonLeft);
|
|
wTypeBool = GUI.Toggle(omniToggleRect, wTypeBool, "Omni-directional", EditorStyles.miniButtonRight);
|
|
waveType.floatValue = wTypeBool ? 1 : 0;
|
|
|
|
Rect dirRect = new Rect(rect.x + 4, dirToggleRect.y + standardLine, rect.width - 8, standardHeight);
|
|
Rect buttonRect = new Rect(rect.x + 4, dirRect.y + standardLine + 2, rect.width - 8, standardHeight);
|
|
// Directional
|
|
if(!wTypeBool)
|
|
{
|
|
var waveDir = element.FindPropertyRelative("direction");
|
|
waveDir.floatValue = EditorGUI.Slider(dirRect, "Facing Direction", waveDir.floatValue, -180.0f, 180.0f);
|
|
if(GUI.Button(buttonRect, "Align with Scene Camera"))
|
|
waveDir.floatValue = CameraRelativeDirection();
|
|
}
|
|
else
|
|
{// Omni-Directional
|
|
EditorGUIUtility.wideMode = true;
|
|
//var perWidth = EditorGUIUtility.labelWidth;
|
|
//EditorGUIUtility.labelWidth = 20f;
|
|
var waveOrig = element.FindPropertyRelative("origin");
|
|
waveOrig.vector2Value = EditorGUI.Vector2Field(dirRect, "Point of Origin", waveOrig.vector2Value);
|
|
if(GUI.Button(buttonRect, "Project Origin from Scene Camera"))
|
|
waveOrig.vector2Value = CameraRelativeOrigin(waveOrig.vector2Value);
|
|
//EditorGUIUtility.labelWidth = perWidth;
|
|
}
|
|
};
|
|
|
|
// Check can remove to make sure at least one wave remains
|
|
waveList.onCanRemoveCallback = (ReorderableList l) =>
|
|
{
|
|
return l.count > 1;
|
|
};
|
|
|
|
// Check on remove to give a warning incase removing by accident
|
|
waveList.onRemoveCallback = (ReorderableList l) =>
|
|
{
|
|
if (EditorUtility.DisplayDialog("Warning!", "Are you sure you want to delete the wave?", "Yes", "No"))
|
|
{
|
|
ReorderableList.defaultBehaviours.DoRemoveButton(l);
|
|
}
|
|
};
|
|
// When adding, check if under 10, if so add a new random wave
|
|
waveList.onAddCallback = (ReorderableList l) =>
|
|
{
|
|
var index = l.serializedProperty.arraySize;
|
|
if (index < 10)
|
|
{
|
|
l.serializedProperty.arraySize++;
|
|
l.index = index;
|
|
var element = l.serializedProperty.GetArrayElementAtIndex(index);
|
|
element.FindPropertyRelative("amplitude").floatValue = Random.Range(0.25f, 1.5f);
|
|
element.FindPropertyRelative("direction").floatValue = Random.Range(-180f, 180f);
|
|
element.FindPropertyRelative("wavelength").floatValue = Random.Range(2f, 8f);
|
|
}
|
|
else
|
|
{
|
|
EditorUtility.DisplayDialog("Warning!", "You have reached the limit of 10 waves for this Water.", "Close");
|
|
}
|
|
};
|
|
//Draw header
|
|
waveList.drawHeaderCallback = (Rect rect) =>
|
|
{
|
|
EditorGUI.LabelField(rect, "Wave List");
|
|
};
|
|
//Do height of list entry
|
|
waveList.elementHeightCallback = (index) =>
|
|
{
|
|
var elementHeight = standardLine * 6f;
|
|
return elementHeight;
|
|
};
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
EditorGUILayout.LabelField("Visual Settings", EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel += 1;
|
|
// Max visibility - slider 3-300
|
|
var maxDepth = serializedObject.FindProperty("_waterMaxVisibility");
|
|
EditorGUILayout.Slider(maxDepth, 3, 300, new GUIContent("Maximum Visibility", maxDepthTT));
|
|
// Colouring settings
|
|
DoSmallHeader("Coloring Controls");
|
|
// Absorbstion Ramp
|
|
var absorpRamp = serializedObject.FindProperty("_absorptionRamp");
|
|
EditorGUILayout.PropertyField(absorpRamp, new GUIContent("Absorption Color", absorpRampTT), true, null);
|
|
// Scatter Ramp
|
|
var scatterRamp = serializedObject.FindProperty("_scatterRamp");
|
|
EditorGUILayout.PropertyField(scatterRamp, new GUIContent("Scattering Color", scatterRampTT), true, null);
|
|
// Foam Ramps
|
|
DoSmallHeader("Surface Foam");
|
|
var foamSettings = serializedObject.FindProperty("_foamSettings");
|
|
var foamType = foamSettings.FindPropertyRelative("foamType");
|
|
foamType.intValue = GUILayout.Toolbar(foamType.intValue, foamTypeOptions);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
switch (foamType.intValue)
|
|
{
|
|
case 0: //// Auto ////
|
|
{
|
|
EditorGUILayout.HelpBox("Automatic will distribute the foam suitable for an average swell", MessageType.Info);
|
|
}
|
|
break;
|
|
case 1: //// Simple ////
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
DoInlineLabel("Foam Profile", foamCurveTT, 50f);
|
|
var basicFoam = foamSettings.FindPropertyRelative("basicFoam");
|
|
basicFoam.animationCurveValue = EditorGUILayout.CurveField(basicFoam.animationCurveValue, Color.white, new Rect(Vector2.zero, Vector2.one));
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
break;
|
|
case 2: //// Simple ////
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
DoInlineLabel("Foam Profiles", foam3curvesTT, 50f);
|
|
var liteFoam = foamSettings.FindPropertyRelative("liteFoam");
|
|
liteFoam.animationCurveValue = EditorGUILayout.CurveField(liteFoam.animationCurveValue, new Color(0.5f, 0.75f, 1f, 1f), new Rect(Vector2.zero, Vector2.one));
|
|
var mediumFoam = foamSettings.FindPropertyRelative("mediumFoam");
|
|
mediumFoam.animationCurveValue = EditorGUILayout.CurveField(mediumFoam.animationCurveValue, new Color(0f, 0.5f, 1f, 1f), new Rect(Vector2.zero, Vector2.one));
|
|
var denseFoam = foamSettings.FindPropertyRelative("denseFoam");
|
|
denseFoam.animationCurveValue = EditorGUILayout.CurveField(denseFoam.animationCurveValue, Color.blue, new Rect(Vector2.zero, Vector2.one));
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
break;
|
|
}
|
|
|
|
EditorGUI.indentLevel -= 1;
|
|
EditorGUILayout.LabelField("Wave Settings", EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel += 1;
|
|
// Wave type - Automatic / Customized
|
|
//wavesType = EditorGUILayout.Popup("System Type", wavesType, wavesTypeOptions);
|
|
// Toolbar labels here
|
|
|
|
var customWaves = serializedObject.FindProperty("_customWaves");
|
|
var intVal = customWaves.boolValue ? 1 : 0;
|
|
intVal = GUILayout.Toolbar(intVal, wavesTypeOptions);
|
|
customWaves.boolValue = intVal == 1 ? true : false;
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
switch(customWaves.boolValue ? 1 : 0)
|
|
{
|
|
case 0: //// Automatic ////
|
|
{
|
|
var basicSettings = serializedObject.FindProperty("_basicWaveSettings");
|
|
// Wave count (display warning of on mobile platform and over 6) dropdown 1 > 10
|
|
var autoCount = basicSettings.FindPropertyRelative("numWaves");
|
|
EditorGUILayout.IntSlider(autoCount, 1, 10, new GUIContent("Wave Count", waveCountTT), null);
|
|
// Average Wave height - slider 0.05 - 30
|
|
var avgHeight = basicSettings.FindPropertyRelative("amplitude");
|
|
EditorGUILayout.Slider(avgHeight, 0.1f, 30.0f, new GUIContent("Avg Swell Height", avgHeightTT), null);
|
|
// Average Wavelength - slider 1 - 200
|
|
var avgWavelength = basicSettings.FindPropertyRelative("wavelength");
|
|
EditorGUILayout.Slider(avgWavelength, 1.0f, 200.0f, new GUIContent("Avg Wavelength", avgWavelengthTT), null);
|
|
// Wind direction - slider -180-180
|
|
EditorGUILayout.BeginHorizontal();
|
|
var windDir = basicSettings.FindPropertyRelative("direction");
|
|
EditorGUILayout.Slider(windDir, -180.0f, 180.0f, new GUIContent("Wind Direction", windDirTT), null);
|
|
if(GUILayout.Button(new GUIContent("Align to scene camera", alignButtonTT)))
|
|
windDir.floatValue = CameraRelativeDirection();
|
|
EditorGUILayout.EndHorizontal();
|
|
// [override] - random otherwise(on creation/override check)
|
|
// Random seed - int input
|
|
EditorGUILayout.BeginHorizontal();
|
|
var randSeed = serializedObject.FindProperty("randomSeed");
|
|
randSeed.intValue = EditorGUILayout.IntField(new GUIContent("Random Seed", randSeedTT), randSeed.intValue);
|
|
if (GUILayout.Button("Randomize Waves"))
|
|
{
|
|
randSeed.intValue = System.DateTime.Now.Millisecond * 100 - System.DateTime.Now.Millisecond;
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
break;
|
|
case 1: //// Customized ////
|
|
{
|
|
EditorGUI.indentLevel -= 1;
|
|
// Re-orderable list with wave details
|
|
waveList.DoLayoutList();
|
|
/// Type - Directional / Omi-directional
|
|
//// Amplitude - slider 0.05 - 30
|
|
//// Wavelength - slider 1 - 200
|
|
////// Direction(facing) - slider -180-180 && face scene camera direction(if scene view)
|
|
// OR
|
|
////// Origin(point of origin) - Vector input && origin at camera aim
|
|
}
|
|
break;
|
|
}
|
|
|
|
EditorUtility.SetDirty(this);
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void DoSmallHeader(string header)
|
|
{
|
|
EditorGUI.indentLevel -= 1;
|
|
EditorGUILayout.LabelField(header, EditorStyles.miniBoldLabel);
|
|
EditorGUI.indentLevel += 1;
|
|
}
|
|
|
|
void DoInlineLabel(string label, string tooltip, float width)
|
|
{
|
|
var preWidth = EditorGUIUtility.labelWidth;
|
|
EditorGUIUtility.labelWidth = width;
|
|
EditorGUILayout.LabelField(new GUIContent(label, tooltip));
|
|
EditorGUIUtility.labelWidth = preWidth;
|
|
}
|
|
|
|
void Setup()
|
|
{
|
|
WaterSurfaceData wsd = (WaterSurfaceData)target;
|
|
wsd._init = true;
|
|
wsd._absorptionRamp = DefaultAbsorptionGrad();
|
|
wsd._scatterRamp = DefaultScatterGrad();
|
|
EditorUtility.SetDirty(wsd);
|
|
}
|
|
|
|
Gradient DefaultAbsorptionGrad() // Preset for absorption
|
|
{
|
|
Gradient g = new Gradient();
|
|
GradientColorKey[] gck = new GradientColorKey[5];
|
|
GradientAlphaKey[] gak = new GradientAlphaKey[1];
|
|
gak[0].alpha = 1;
|
|
gak[0].time = 0;
|
|
gck[0].color = Color.white;
|
|
gck[0].time = 0f;
|
|
gck[1].color = new Color(0.22f, 0.87f, 0.87f);
|
|
gck[1].time = 0.082f;
|
|
gck[2].color = new Color(0f, 0.47f, 0.49f);
|
|
gck[2].time = 0.318f;
|
|
gck[3].color = new Color(0f, 0.275f, 0.44f);
|
|
gck[3].time = 0.665f;
|
|
gck[4].color = Color.black;
|
|
gck[4].time = 1f;
|
|
g.SetKeys(gck, gak);
|
|
return g;
|
|
}
|
|
|
|
Gradient DefaultScatterGrad() // Preset for scattering
|
|
{
|
|
Gradient g = new Gradient();
|
|
GradientColorKey[] gck = new GradientColorKey[4];
|
|
GradientAlphaKey[] gak = new GradientAlphaKey[1];
|
|
gak[0].alpha = 1;
|
|
gak[0].time = 0;
|
|
gck[0].color = Color.black;
|
|
gck[0].time = 0f;
|
|
gck[1].color = new Color(0.08f, 0.41f, 0.34f);
|
|
gck[1].time = 0.15f;
|
|
gck[2].color = new Color(0.13f, 0.55f, 0.45f);
|
|
gck[2].time = 0.42f;
|
|
gck[3].color = new Color(0.21f, 0.62f, 0.6f);
|
|
gck[3].time = 1f;
|
|
g.SetKeys(gck, gak);
|
|
return g;
|
|
}
|
|
|
|
float CameraRelativeDirection()
|
|
{
|
|
float degrees = 0;
|
|
|
|
Vector3 camFwd = UnityEditor.SceneView.lastActiveSceneView.camera.transform.forward;
|
|
camFwd.y = 0f;
|
|
camFwd.Normalize();
|
|
float dot = Vector3.Dot(-Vector3.forward, camFwd);
|
|
degrees = Mathf.LerpUnclamped(90.0f, 180.0f, dot);
|
|
if(camFwd.x < 0)
|
|
degrees *= -1f;
|
|
|
|
return Mathf.RoundToInt(degrees * 1000) / 1000;
|
|
}
|
|
|
|
Vector2 CameraRelativeOrigin(Vector2 original)
|
|
{
|
|
Camera sceneCam = UnityEditor.SceneView.lastActiveSceneView.camera;
|
|
|
|
float angle = 90f - Vector3.Angle(sceneCam.transform.forward, Vector3.down);
|
|
if (angle > 0.1f)
|
|
{
|
|
Vector3 intersect = Vector2.zero;
|
|
float hypot = (sceneCam.transform.position.y) * (1 / Mathf.Sin(Mathf.Deg2Rad * angle));
|
|
Vector3 fwd = sceneCam.transform.forward * hypot;
|
|
intersect = fwd + sceneCam.transform.position;
|
|
return new Vector2(intersect.x, intersect.z);
|
|
}
|
|
else
|
|
{
|
|
return original;
|
|
}
|
|
}
|
|
|
|
static string[] wavesTypeOptions = new string[] { "Automatic", "Customized" };
|
|
|
|
static string[] foamTypeOptions = new string[3] { "Automatic", "Simple Curve", "Density Curves" };
|
|
|
|
|
|
////TOOLTIPS////
|
|
private string maxDepthTT = "This controls the max depth of the waters transparency/visiblility, the absorption and scattering gradients map to this depth. Units:Meters";
|
|
private string absorpRampTT = "This gradient controls the color of the water as it gets deeper, darkening the surfaces under the water as they get deeper.";
|
|
private string scatterRampTT = "This gradient controls the 'scattering' of the water from shallow to deep, lighting the water as there becomes more of it.";
|
|
private string waveCountTT = "Number of waves the automatic setup creates, if aiming for mobile set to 6 or less";
|
|
private string avgHeightTT = "The average height of the waves. Units:Meters";
|
|
private string avgWavelengthTT = "The average wavelength of the waves. Units:Meters";
|
|
private string windDirTT = "The general wind direction, this is in degrees from Z+";
|
|
private string alignButtonTT = "This aligns the wave direction to the current scene view camera facing direction";
|
|
private string foamCurveTT = "This curve control the foam propagation. X is wave height and Y is foam opacity";
|
|
private string foam3curvesTT = "These three curves control the Lite, Medium and Dense foam propagation. X is wave height and Y is foam opacity";
|
|
private string randSeedTT = "This seed controls the automatic wave generation";
|
|
}
|
|
}
|