You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
14 KiB
305 lines
14 KiB
using System; |
|
using System.Linq; |
|
using UnityEngine; |
|
using UnityEngine.Experimental.Rendering.Universal; |
|
using UnityEngine.Rendering.Universal; |
|
using System.Collections.Generic; |
|
using System.Reflection; |
|
|
|
namespace UnityEditor.Experimental.Rendering.Universal |
|
{ |
|
[CustomPropertyDrawer(typeof(RenderObjects.RenderObjectsSettings), true)] |
|
internal class RenderObjectsPassFeatureEditor : PropertyDrawer |
|
{ |
|
internal class Styles |
|
{ |
|
public static float defaultLineSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; |
|
public static GUIContent callback = new GUIContent("Event", "Choose at which point this render pass is executed in the frame."); |
|
|
|
//Headers |
|
public static GUIContent filtersHeader = new GUIContent("Filters", "Settings that control which objects should be rendered."); |
|
public static GUIContent renderHeader = new GUIContent("Overrides", "Different parts of the rendering that you can choose to override."); |
|
|
|
//Filters |
|
public static GUIContent renderQueueFilter = new GUIContent("Queue", "Only render objects in the selected render queue range."); |
|
public static GUIContent layerMask = new GUIContent("Layer Mask", "Only render objects in a layer that match the given layer mask."); |
|
public static GUIContent shaderPassFilter = new GUIContent("LightMode Tags", "Controls which shader passes to render by filtering by LightMode tag."); |
|
|
|
//Render Options |
|
public static GUIContent overrideMaterial = new GUIContent("Material", "Choose an override material, every renderer will be rendered with this material."); |
|
public static GUIContent overrideMaterialPass = new GUIContent("Pass Index", "The pass index for the override material to use."); |
|
|
|
//Depth Settings |
|
public static GUIContent overrideDepth = new GUIContent("Depth", "Select this option to specify how this Renderer Feature affects or uses the values in the Depth buffer."); |
|
public static GUIContent writeDepth = new GUIContent("Write Depth", "Choose to write depth to the screen."); |
|
public static GUIContent depthState = new GUIContent("Depth Test", "Choose a new depth test function."); |
|
|
|
//Camera Settings |
|
public static GUIContent overrideCamera = new GUIContent("Camera", "Override camera matrices. Toggling this setting will make camera use perspective projection."); |
|
public static GUIContent cameraFOV = new GUIContent("Field Of View", "The camera's view angle measured in degrees along vertical axis."); |
|
public static GUIContent positionOffset = new GUIContent("Position Offset", "Position offset to apply to the original camera's position."); |
|
public static GUIContent restoreCamera = new GUIContent("Restore", "Restore to the original camera matrices after the execution of the render passes added by this feature."); |
|
} |
|
|
|
//Headers and layout |
|
private HeaderBool m_FiltersFoldout; |
|
private int m_FilterLines = 3; |
|
private HeaderBool m_RenderFoldout; |
|
private int m_MaterialLines = 2; |
|
private int m_DepthLines = 3; |
|
private int m_CameraLines = 4; |
|
|
|
// Serialized Properties |
|
private SerializedProperty m_Callback; |
|
private SerializedProperty m_PassTag; |
|
//Filter props |
|
private SerializedProperty m_FilterSettings; |
|
private SerializedProperty m_RenderQueue; |
|
private SerializedProperty m_LayerMask; |
|
private SerializedProperty m_ShaderPasses; |
|
//Render props |
|
private SerializedProperty m_OverrideMaterial; |
|
private SerializedProperty m_OverrideMaterialPass; |
|
//Depth props |
|
private SerializedProperty m_OverrideDepth; |
|
private SerializedProperty m_WriteDepth; |
|
private SerializedProperty m_DepthState; |
|
//Stencil props |
|
private SerializedProperty m_StencilSettings; |
|
//Caemra props |
|
private SerializedProperty m_CameraSettings; |
|
private SerializedProperty m_OverrideCamera; |
|
private SerializedProperty m_FOV; |
|
private SerializedProperty m_CameraOffset; |
|
private SerializedProperty m_RestoreCamera; |
|
|
|
private List<SerializedObject> m_properties = new List<SerializedObject>(); |
|
|
|
static bool FilterRenderPassEvent(int evt) => |
|
// Return all events higher or equal than before rendering prepasses |
|
evt >= (int)RenderPassEvent.BeforeRenderingPrePasses && |
|
// filter obsolete events |
|
typeof(RenderPassEvent).GetField(Enum.GetName(typeof(RenderPassEvent), evt))?.GetCustomAttribute(typeof(ObsoleteAttribute)) == null; |
|
|
|
// Return all render pass event names that match filterRenderPassEvent |
|
private GUIContent[] m_EventOptionNames = Enum.GetValues(typeof(RenderPassEvent)).Cast<int>() |
|
.Where(FilterRenderPassEvent) |
|
.Select(x => new GUIContent(Enum.GetName(typeof(RenderPassEvent), x))).ToArray(); |
|
|
|
// Return all render pass event options that match filterRenderPassEvent |
|
private int[] m_EventOptionValues = Enum.GetValues(typeof(RenderPassEvent)).Cast<int>() |
|
.Where(FilterRenderPassEvent).ToArray(); |
|
|
|
private void Init(SerializedProperty property) |
|
{ |
|
//Header bools |
|
var key = $"{this.ToString().Split('.').Last()}.{property.serializedObject.targetObject.name}"; |
|
m_FiltersFoldout = new HeaderBool($"{key}.FiltersFoldout", true); |
|
m_RenderFoldout = new HeaderBool($"{key}.RenderFoldout"); |
|
|
|
|
|
m_Callback = property.FindPropertyRelative("Event"); |
|
m_PassTag = property.FindPropertyRelative("passTag"); |
|
|
|
//Filter props |
|
m_FilterSettings = property.FindPropertyRelative("filterSettings"); |
|
m_RenderQueue = m_FilterSettings.FindPropertyRelative("RenderQueueType"); |
|
m_LayerMask = m_FilterSettings.FindPropertyRelative("LayerMask"); |
|
m_ShaderPasses = m_FilterSettings.FindPropertyRelative("PassNames"); |
|
|
|
//Render options |
|
m_OverrideMaterial = property.FindPropertyRelative("overrideMaterial"); |
|
m_OverrideMaterialPass = property.FindPropertyRelative("overrideMaterialPassIndex"); |
|
|
|
//Depth props |
|
m_OverrideDepth = property.FindPropertyRelative("overrideDepthState"); |
|
m_WriteDepth = property.FindPropertyRelative("enableWrite"); |
|
m_DepthState = property.FindPropertyRelative("depthCompareFunction"); |
|
|
|
//Stencil |
|
m_StencilSettings = property.FindPropertyRelative("stencilSettings"); |
|
|
|
//Camera |
|
m_CameraSettings = property.FindPropertyRelative("cameraSettings"); |
|
m_OverrideCamera = m_CameraSettings.FindPropertyRelative("overrideCamera"); |
|
m_FOV = m_CameraSettings.FindPropertyRelative("cameraFieldOfView"); |
|
m_CameraOffset = m_CameraSettings.FindPropertyRelative("offset"); |
|
m_RestoreCamera = m_CameraSettings.FindPropertyRelative("restoreCamera"); |
|
|
|
m_properties.Add(property.serializedObject); |
|
} |
|
|
|
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) |
|
{ |
|
rect.height = EditorGUIUtility.singleLineHeight; |
|
EditorGUI.BeginChangeCheck(); |
|
EditorGUI.BeginProperty(rect, label, property); |
|
|
|
if (!m_properties.Contains(property.serializedObject)) |
|
{ |
|
Init(property); |
|
} |
|
|
|
var passName = property.serializedObject.FindProperty("m_Name").stringValue; |
|
if (passName != m_PassTag.stringValue) |
|
{ |
|
m_PassTag.stringValue = passName; |
|
property.serializedObject.ApplyModifiedProperties(); |
|
} |
|
|
|
//Forward Callbacks |
|
EditorGUI.BeginChangeCheck(); |
|
int selectedValue = EditorGUI.IntPopup(rect, Styles.callback, m_Callback.intValue, m_EventOptionNames, m_EventOptionValues); |
|
if (EditorGUI.EndChangeCheck()) |
|
m_Callback.intValue = selectedValue; |
|
rect.y += Styles.defaultLineSpace; |
|
|
|
DoFilters(ref rect); |
|
|
|
m_RenderFoldout.value = EditorGUI.Foldout(rect, m_RenderFoldout.value, Styles.renderHeader, true); |
|
SaveHeaderBool(m_RenderFoldout); |
|
rect.y += Styles.defaultLineSpace; |
|
if (m_RenderFoldout.value) |
|
{ |
|
EditorGUI.indentLevel++; |
|
//Override material |
|
DoMaterialOverride(ref rect); |
|
rect.y += Styles.defaultLineSpace; |
|
//Override depth |
|
DoDepthOverride(ref rect); |
|
rect.y += Styles.defaultLineSpace; |
|
//Override stencil |
|
EditorGUI.PropertyField(rect, m_StencilSettings); |
|
rect.y += EditorGUI.GetPropertyHeight(m_StencilSettings); |
|
//Override camera |
|
DoCameraOverride(ref rect); |
|
rect.y += Styles.defaultLineSpace; |
|
|
|
EditorGUI.indentLevel--; |
|
} |
|
|
|
EditorGUI.EndProperty(); |
|
if (EditorGUI.EndChangeCheck()) |
|
property.serializedObject.ApplyModifiedProperties(); |
|
} |
|
|
|
void DoFilters(ref Rect rect) |
|
{ |
|
m_FiltersFoldout.value = EditorGUI.Foldout(rect, m_FiltersFoldout.value, Styles.filtersHeader, true); |
|
SaveHeaderBool(m_FiltersFoldout); |
|
rect.y += Styles.defaultLineSpace; |
|
if (m_FiltersFoldout.value) |
|
{ |
|
EditorGUI.indentLevel++; |
|
//Render queue filter |
|
EditorGUI.PropertyField(rect, m_RenderQueue, Styles.renderQueueFilter); |
|
rect.y += Styles.defaultLineSpace; |
|
//Layer mask |
|
EditorGUI.PropertyField(rect, m_LayerMask, Styles.layerMask); |
|
rect.y += Styles.defaultLineSpace; |
|
//Shader pass list |
|
EditorGUI.PropertyField(rect, m_ShaderPasses, Styles.shaderPassFilter, true); |
|
rect.y += EditorGUI.GetPropertyHeight(m_ShaderPasses); |
|
EditorGUI.indentLevel--; |
|
} |
|
} |
|
|
|
void DoMaterialOverride(ref Rect rect) |
|
{ |
|
//Override material |
|
EditorGUI.PropertyField(rect, m_OverrideMaterial, Styles.overrideMaterial); |
|
if (m_OverrideMaterial.objectReferenceValue) |
|
{ |
|
rect.y += Styles.defaultLineSpace; |
|
EditorGUI.indentLevel++; |
|
EditorGUI.BeginChangeCheck(); |
|
EditorGUI.PropertyField(rect, m_OverrideMaterialPass, Styles.overrideMaterialPass); |
|
if (EditorGUI.EndChangeCheck()) |
|
m_OverrideMaterialPass.intValue = Mathf.Max(0, m_OverrideMaterialPass.intValue); |
|
EditorGUI.indentLevel--; |
|
} |
|
} |
|
|
|
void DoDepthOverride(ref Rect rect) |
|
{ |
|
EditorGUI.PropertyField(rect, m_OverrideDepth, Styles.overrideDepth); |
|
if (m_OverrideDepth.boolValue) |
|
{ |
|
rect.y += Styles.defaultLineSpace; |
|
EditorGUI.indentLevel++; |
|
//Write depth |
|
EditorGUI.PropertyField(rect, m_WriteDepth, Styles.writeDepth); |
|
rect.y += Styles.defaultLineSpace; |
|
//Depth testing options |
|
EditorGUI.PropertyField(rect, m_DepthState, Styles.depthState); |
|
EditorGUI.indentLevel--; |
|
} |
|
} |
|
|
|
void DoCameraOverride(ref Rect rect) |
|
{ |
|
EditorGUI.PropertyField(rect, m_OverrideCamera, Styles.overrideCamera); |
|
if (m_OverrideCamera.boolValue) |
|
{ |
|
rect.y += Styles.defaultLineSpace; |
|
EditorGUI.indentLevel++; |
|
//FOV |
|
EditorGUI.Slider(rect, m_FOV, 4f, 179f, Styles.cameraFOV); |
|
rect.y += Styles.defaultLineSpace; |
|
//Offset vector |
|
var offset = m_CameraOffset.vector4Value; |
|
EditorGUI.BeginChangeCheck(); |
|
var newOffset = EditorGUI.Vector3Field(rect, Styles.positionOffset, new Vector3(offset.x, offset.y, offset.z)); |
|
if (EditorGUI.EndChangeCheck()) |
|
m_CameraOffset.vector4Value = new Vector4(newOffset.x, newOffset.y, newOffset.z, 1f); |
|
rect.y += Styles.defaultLineSpace; |
|
//Restore prev camera projections |
|
EditorGUI.PropertyField(rect, m_RestoreCamera, Styles.restoreCamera); |
|
rect.y += Styles.defaultLineSpace; |
|
|
|
EditorGUI.indentLevel--; |
|
} |
|
} |
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) |
|
{ |
|
float height = Styles.defaultLineSpace; |
|
|
|
Init(property); |
|
height += Styles.defaultLineSpace * (m_FiltersFoldout.value ? m_FilterLines : 1); |
|
height += m_FiltersFoldout.value ? EditorGUI.GetPropertyHeight(m_ShaderPasses) : 0; |
|
|
|
height += Styles.defaultLineSpace; // add line for overrides dropdown |
|
if (m_RenderFoldout.value) |
|
{ |
|
height += Styles.defaultLineSpace * (m_OverrideMaterial.objectReferenceValue != null ? m_MaterialLines : 1); |
|
height += Styles.defaultLineSpace * (m_OverrideDepth.boolValue ? m_DepthLines : 1); |
|
height += EditorGUI.GetPropertyHeight(m_StencilSettings); |
|
height += Styles.defaultLineSpace * (m_OverrideCamera.boolValue ? m_CameraLines : 1); |
|
} |
|
|
|
return height; |
|
} |
|
|
|
private void SaveHeaderBool(HeaderBool boolObj) |
|
{ |
|
EditorPrefs.SetBool(boolObj.key, boolObj.value); |
|
} |
|
|
|
class HeaderBool |
|
{ |
|
public string key; |
|
public bool value; |
|
|
|
public HeaderBool(string _key, bool _default = false) |
|
{ |
|
key = _key; |
|
if (EditorPrefs.HasKey(key)) |
|
value = EditorPrefs.GetBool(key); |
|
else |
|
value = _default; |
|
EditorPrefs.SetBool(key, value); |
|
} |
|
} |
|
} |
|
}
|
|
|