#if URP using System; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace StylizedWater2.DynamicEffects { [CustomEditor(typeof(WaterDynamicEffectsRenderFeature))] public class RenderFeatureEditor : Editor { private SerializedProperty settings; private SerializedProperty renderRange; private SerializedProperty fadePercentage; private SerializedProperty texelsPerUnit; private SerializedProperty maxResolution; private SerializedProperty highPrecision; private SerializedProperty enableDisplacement; private SerializedProperty enableNormals; private SerializedProperty halfResolutionNormals; private SerializedProperty normalMipmaps; private SerializedProperty ignoreSceneView; private SerializedProperty displacementNormalShader; [MenuItem("Window/Stylized Water 2/Set up Dynamic Effects", false, 3000)] private static void SetupRenderers() { if (PipelineUtilities.RenderFeatureMissing(out ScriptableRendererData[] renderers)) { string[] rendererNames = new string[renderers.Length]; for (int i = 0; i < rendererNames.Length; i++) { rendererNames[i] = "• " + renderers[i].name; } if (EditorUtility.DisplayDialog("Dynamic Effects", $"The Dynamic Effects render feature hasn't been added to the following renderers:\n\n" + String.Join(Environment.NewLine, rendererNames) + $"\n\nThis is required for rendering to take effect.", "Setup", "Ignore")) { PipelineUtilities.SetupRenderFeature(name:"Stylized Water 2: Dynamic Effects"); } } else { EditorUtility.DisplayDialog(AssetInfo.ASSET_NAME, "The Dynamic Effects render feature has already been added to your default renderers", "Ok"); } } [MenuItem("Window/Analysis/Dynamic Effects debugger", false, 0)] private static void OpenDebugger() { DynamicEffectsBufferDebugger.Open(); } void OnEnable() { settings = serializedObject.FindProperty("settings"); renderRange = settings.FindPropertyRelative("renderRange"); fadePercentage = settings.FindPropertyRelative("fadePercentage"); texelsPerUnit = settings.FindPropertyRelative("texelsPerUnit"); maxResolution = settings.FindPropertyRelative("maxResolution"); highPrecision = settings.FindPropertyRelative("highPrecision"); enableDisplacement = settings.FindPropertyRelative("enableDisplacement"); enableNormals = settings.FindPropertyRelative("enableNormals"); halfResolutionNormals = settings.FindPropertyRelative("halfResolutionNormals"); normalMipmaps = settings.FindPropertyRelative("normalMipmaps"); ignoreSceneView = settings.FindPropertyRelative("ignoreSceneView"); displacementNormalShader = serializedObject.FindProperty("displacementNormalShader"); if (target.name == "NewWaterDynamicEffectsRenderFeature") target.name = "Stylized Water 2: Dynamic Effects"; } public override void OnInspectorGUI() { using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField($"Version {WaterDynamicEffectsRenderFeature.Version}", EditorStyles.miniLabel); if (GUILayout.Button(new GUIContent(" Documentation", EditorGUIUtility.FindTexture("_Help")))) { Application.OpenURL("https://staggart.xyz/unity/stylized-water-2/sw2-dynamic-effects-docs/"); } if (GUILayout.Button(new GUIContent(" Debugger", EditorGUIUtility.IconContent("Profiler.Rendering").image, "Inspect the render buffer output"))) { OpenDebugger(); } } EditorGUILayout.Space(); #if UNITY_6000_0_OR_NEWER && URP if (GraphicsSettings.GetRenderPipelineSettings().enableRenderCompatibilityMode == false) { EditorGUILayout.HelpBox("Using Render Graph in Unity 6+ is not supported." + "\n\nBackwards compatibility mode must be enabled.", MessageType.Error); GUILayout.Space(-32); using (new EditorGUILayout.HorizontalScope()) { GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Enable", EditorGUIUtility.IconContent("d_tab_next").image), GUILayout.Width(60))) { GraphicsSettings.GetRenderPipelineSettings().enableRenderCompatibilityMode = true; EditorUtility.DisplayDialog($"Dynamic Effects v{WaterDynamicEffectsRenderFeature.Version}", "Please note that this option will be removed in a future Unity version, this version of the asset will no longer be functional then." + "\n\n" + "A license upgrade for Unity 6+ support may be available on the asset store, please check the documentation for current information.", "OK"); } GUILayout.Space(8); } GUILayout.Space(11); } #endif serializedObject.Update(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(renderRange); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(fadePercentage, new GUIContent("Fade range (%)", fadePercentage.tooltip)); EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.PropertyField(texelsPerUnit); EditorGUILayout.PropertyField(maxResolution); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(EditorGUIUtility.labelWidth); EditorGUILayout.HelpBox($"Current resolution: {WaterDynamicEffectsRenderFeature.CalculateResolution(renderRange.floatValue, texelsPerUnit.intValue, maxResolution.intValue)}px", MessageType.None); } EditorGUILayout.PropertyField(highPrecision); EditorGUILayout.Space(); EditorGUILayout.PropertyField(enableDisplacement); EditorGUILayout.PropertyField(enableNormals); using (new EditorGUI.DisabledGroupScope(enableNormals.boolValue == false)) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(normalMipmaps); EditorGUILayout.PropertyField(halfResolutionNormals); EditorGUI.indentLevel--; } EditorGUILayout.Space(); EditorGUILayout.PropertyField(ignoreSceneView); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } //base.OnInspectorGUI(); if (displacementNormalShader.objectReferenceValue == null) { EditorGUILayout.HelpBox("Internal shader not referenced!", MessageType.Error); if (GUILayout.Button("Find & assign")) { displacementNormalShader.objectReferenceValue = Shader.Find("Hidden/StylizedWater2/DisplacementToNormals"); serializedObject.ApplyModifiedProperties(); } } UI.DrawFooter(); } } public class DynamicEffectsBufferDebugger : EditorWindow { private const int m_width = 550; private const int m_height = 300; #if SWS_DEV [MenuItem("SWS/Debug/Dynamic Effects Buffers")] #endif public static void Open() { DynamicEffectsBufferDebugger window = GetWindow(false); window.titleContent = new GUIContent("Dynamic Effects Debugger", Resources.Load("dynamic-effect-icon-256px")); window.autoRepaintOnSceneChange = true; window.minSize = new Vector2(m_width, m_height); //window.maxSize = new Vector2(m_width, m_height); window.Show(); } private float width = 300f; private Vector2 scrollPos; private ColorWriteMask colorMask = ColorWriteMask.All; private int colorChannel = 1; private void OnGUI() { Repaint(); width = (Mathf.Min(this.position.height, this.position.width) * 0.8f) - 10f; scrollPos = EditorGUILayout.BeginScrollView(scrollPos); RenderTexture interactionData = Shader.GetGlobalTexture("_WaterDynamicEffectsBuffer") as RenderTexture; RenderTexture interactionNormals = Shader.GetGlobalTexture("_WaterDynamicEffectsNormals") as RenderTexture; using (new EditorGUILayout.HorizontalScope()) { using (new EditorGUILayout.VerticalScope()) { DrawTexture("Data", interactionData); } using (new EditorGUILayout.VerticalScope()) { DrawTexture("Normals", interactionNormals); } } EditorGUILayout.EndScrollView(); } private void DrawTexture(string label, Texture texture) { if (!texture) return; EditorGUILayout.LabelField($"{label} ({texture.width}px @ {(UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(texture) / 1024f / 1024f).ToString("F2")}mb)", EditorStyles.boldLabel); Rect rect = EditorGUILayout.GetControlRect(); Rect position = EditorGUI.PrefixLabel(rect, GUIUtility.GetControlID(FocusType.Passive), GUIContent.none); position.width = width; //colorChannel = EditorGUI.Popup(position, "Channel mask", colorChannel, new string[] { "RGB", "R", "G", "B", "A" }); colorChannel = (int)GUI.Toolbar(position, colorChannel, new GUIContent[] { new GUIContent("RGBA"), new GUIContent("RGB"), new GUIContent("R"), new GUIContent("G"), new GUIContent("B"), new GUIContent("A") }); switch (colorChannel) { case 1: colorMask = ColorWriteMask.All; break; case 2: colorMask = ColorWriteMask.Red; break; case 3: colorMask = ColorWriteMask.Green; break; case 4: colorMask = ColorWriteMask.Blue; break; case 5: colorMask = ColorWriteMask.Alpha; break; } rect.y += 17f; rect.height = width; rect.width = width; if (colorChannel == 0) //RGBA { EditorGUI.DrawTextureTransparent(rect, texture, ScaleMode.ScaleToFit, 1f); } else if (colorMask == ColorWriteMask.Alpha) { EditorGUI.DrawTextureAlpha(rect, texture, ScaleMode.ScaleToFit, 1f, 0); } else { EditorGUI.DrawPreviewTexture(rect, texture, null, ScaleMode.ScaleToFit, 1f, 0, colorMask); } GUILayout.Space(rect.height); } } } #endif