CapersProject/Assets/StylizedWater2/Editor/Inspectors/AlignToWavesInspector.cs
2024-08-06 16:37:03 +09:00

262 lines
10 KiB
C#

//Stylized Water 2
//Staggart Creations (http://staggart.xyz)
//Copyright protected under Unity Asset Store EULA
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
#if UNITY_2021_2_OR_NEWER
using PrefabStageUtility = UnityEditor.SceneManagement.PrefabStageUtility;
#else
using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
#endif
namespace StylizedWater2
{
[CanEditMultipleObjects]
[CustomEditor(typeof(AlignToWaves))]
public class AlignToWavesInspector : Editor
{
AlignToWaves script;
SerializedProperty waterObject;
SerializedProperty autoFind;
SerializedProperty dynamicMaterial;
SerializedProperty waterLevelSource;
SerializedProperty waterLevel;
SerializedProperty childTransform;
SerializedProperty heightOffset;
SerializedProperty rollAmount;
SerializedProperty samples;
private bool editSamples;
private bool isRiver;
private bool wavesEnabled;
private string proSkinPrefix => EditorGUIUtility.isProSkin ? "d_" : "";
private void OnEnable()
{
script = (AlignToWaves)target;
waterObject = serializedObject.FindProperty("waterObject");
autoFind = serializedObject.FindProperty("autoFind");
dynamicMaterial = serializedObject.FindProperty("dynamicMaterial");
waterLevelSource = serializedObject.FindProperty("waterLevelSource");
waterLevel = serializedObject.FindProperty("waterLevel");
childTransform = serializedObject.FindProperty("childTransform");
heightOffset = serializedObject.FindProperty("heightOffset");
rollAmount = serializedObject.FindProperty("rollAmount");
samples = serializedObject.FindProperty("samples");
//Auto fetch if there is only one water body in the scene
if (waterObject.objectReferenceValue == null && WaterObject.Instances.Count == 1)
{
serializedObject.Update();
waterObject.objectReferenceValue = WaterObject.Instances[0];
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedPropertiesWithoutUndo();
}
ValidateMaterial();
}
private void OnDisable()
{
AlignToWaves.Disable = false;
Tools.hidden = false;
}
public override void OnInspectorGUI()
{
UI.DrawHeader();
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(EditorGUIUtility.labelWidth);
AlignToWaves.EnableInEditor =
GUILayout.Toggle(AlignToWaves.EnableInEditor, new GUIContent(" Run in edit-mode (global)", EditorGUIUtility.IconContent(
(AlignToWaves.EnableInEditor ? "animationvisibilitytoggleon" : "animationvisibilitytoggleoff")).image), "Button");
}
EditorGUILayout.Space();
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(waterObject);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(autoFind);
EditorGUILayout.PropertyField(dynamicMaterial);
EditorGUI.indentLevel--;
UI.DrawNotification(isRiver, "Material has river mode enabled, buoyancy only works for flat water bodies", MessageType.Error);
UI.DrawNotification(!wavesEnabled && !isRiver, "Material used on the water object does not have waves enabled.", MessageType.Error);
if (script.waterObject && script.waterObject.material)
{
UI.DrawNotification((script.waterObject.material.GetFloat("_WorldSpaceUV") == 0f), "Material must use world-projected UV", "Change", ()=> script.waterObject.material.SetFloat("_WorldSpaceUV", 1f), MessageType.Error);
}
if(!autoFind.boolValue && waterObject.objectReferenceValue == null)
{
UI.DrawNotification("A water object must be assigned!", MessageType.Error);
}
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel("Water level source");
waterLevelSource.intValue = GUILayout.Toolbar(waterLevelSource.intValue, new GUIContent[] { new GUIContent("Fixed Value"), new GUIContent("Water Object") });
}
if (waterLevelSource.intValue == (int)AlignToWaves.WaterLevelSource.FixedValue) EditorGUILayout.PropertyField(waterLevel);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(heightOffset);
EditorGUILayout.PropertyField(rollAmount);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Sample positions", EditorStyles.boldLabel);
if (targets.Length > 1)
{
EditorGUILayout.HelpBox("Cannot be modified for a multi-selection", MessageType.Info);
}
else
{
if (samples.arraySize > 0)
{
editSamples =
GUILayout.Toggle(editSamples,
new GUIContent(" Edit samples", EditorGUIUtility.IconContent("sv_icon_dot0_pix16_gizmo").image),
"Button", GUILayout.MaxWidth(125f), GUILayout.MaxHeight(30f));
}
else
{
EditorGUILayout.HelpBox("No sample positions added. The transform's pivot position is used", MessageType.None);
}
for (int i = 0; i < samples.arraySize; i++)
{
SerializedProperty param = samples.GetArrayElementAtIndex(i);
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(param, true);
if (GUILayout.Button(new GUIContent("",
EditorGUIUtility.IconContent(proSkinPrefix + "TreeEditor.Trash").image, "Delete item"), GUILayout.MaxWidth(30f)))
{
samples.DeleteArrayElementAtIndex(i);
selectedSampleIndex = -1;
EditorUtility.SetDirty(target);
}
}
}
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent("Add", EditorGUIUtility.IconContent(proSkinPrefix + "Toolbar Plus").image, "Add new sample point")))
{
samples.InsertArrayElementAtIndex(samples.arraySize);
selectedSampleIndex = samples.arraySize - 1;
EditorUtility.SetDirty(target);
}
}
}
EditorGUILayout.PropertyField(childTransform);
if (childTransform.objectReferenceValue == null && samples.arraySize > 0)
UI.DrawNotification("Assign a transform to rotate/scale the sample positions with");
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
ValidateMaterial();
}
UI.DrawFooter();
}
private void ValidateMaterial()
{
if (script.waterObject && script.waterObject.material)
{
if (script.waterObject.material != script.waterObject.meshRenderer.sharedMaterial) script.waterObject.material = script.waterObject.meshRenderer.sharedMaterial;
wavesEnabled = WaveParameters.WavesEnabled(script.waterObject.material);
isRiver = script.waterObject.material.IsKeywordEnabled("_RIVER");
}
}
private int selectedSampleIndex;
Vector3 sampleWorldPos;
Vector3 prevSampleWorldPos;
private void OnSceneGUI()
{
if (!script) return;
AlignToWaves.Disable = PrefabStageUtility.GetCurrentPrefabStage() != null || editSamples;
if (editSamples)
{
//Mute default controls
Tools.hidden = true;
Handles.color = new Color(0.66f, 0.66f, 0.66f, 1);
for (int i = 0; i < script.samples.Count; i++)
{
sampleWorldPos = script.ConvertToWorldSpace(script.samples[i]);
float size = HandleUtility.GetHandleSize(sampleWorldPos) * 0.25f;
if (Handles.Button(sampleWorldPos, Quaternion.identity, size, size, Handles.SphereHandleCap))
{
selectedSampleIndex = i;
}
}
if (selectedSampleIndex > -1)
{
sampleWorldPos = script.ConvertToWorldSpace(script.samples[selectedSampleIndex]);
prevSampleWorldPos = sampleWorldPos;
sampleWorldPos = Handles.PositionHandle(sampleWorldPos, script.childTransform ? script.childTransform.rotation : script.transform.rotation );
script.samples[selectedSampleIndex] = script.ConvertToLocalSpace(sampleWorldPos);
//If moved
if (sampleWorldPos != prevSampleWorldPos)
{
prevSampleWorldPos = sampleWorldPos;
EditorUtility.SetDirty(target);
}
}
}
else
{
selectedSampleIndex = -1;
Tools.hidden = false;
if (script.samples == null) return;
Handles.color = new Color(1,1,1, 0.25f);
for (int i = 0; i < script.samples.Count; i++)
{
sampleWorldPos = script.ConvertToWorldSpace(script.samples[i]);
Handles.SphereHandleCap(0, sampleWorldPos, SceneView.lastActiveSceneView.camera.transform.rotation, HandleUtility.GetHandleSize(sampleWorldPos) * 0.25f, EventType.Repaint);
}
}
}
}
}