RenderObjectsPassFeatureEditor.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using System.Linq;
  2. using UnityEngine;
  3. using UnityEditorInternal;
  4. using UnityEngine.Experimental.Rendering.Universal;
  5. using System.Collections.Generic;
  6. namespace UnityEditor.Experimental.Rendering.Universal
  7. {
  8. [CustomPropertyDrawer(typeof(RenderObjects.RenderObjectsSettings), true)]
  9. internal class RenderObjectsPassFeatureEditor : PropertyDrawer
  10. {
  11. internal class Styles
  12. {
  13. public static float defaultLineSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  14. public static GUIContent callback = new GUIContent("Event", "Choose at which point this render pass is executed in the frame.");
  15. //Headers
  16. public static GUIContent filtersHeader = new GUIContent("Filters", "Settings that control which objects should be rendered.");
  17. public static GUIContent renderHeader = new GUIContent("Overrides", "Different parts of the rendering that you can choose to override.");
  18. //Filters
  19. public static GUIContent renderQueueFilter = new GUIContent("Queue", "Only render objects in the selected render queue range.");
  20. public static GUIContent layerMask = new GUIContent("Layer Mask", "Only render objects in a layer that match the given layer mask.");
  21. public static GUIContent shaderPassFilter = new GUIContent("Shader Passes", "Controls which shader passes to use when rendering objects. The name given here must match the LightMode tag in a shader pass.");
  22. //Render Options
  23. public static GUIContent overrideMaterial = new GUIContent("Material", "Choose an override material, every renderer will be rendered with this material.");
  24. public static GUIContent overrideMaterialPass = new GUIContent("Pass Index", "The pass index for the override material to use.");
  25. //Depth Settings
  26. public static GUIContent overrideDepth = new GUIContent("Depth", "Override depth rendering.");
  27. public static GUIContent writeDepth = new GUIContent("Write Depth", "Choose to write depth to the screen.");
  28. public static GUIContent depthState = new GUIContent("Depth Test", "Choose a new depth test function.");
  29. //Camera Settings
  30. public static GUIContent overrideCamera = new GUIContent("Camera", "Override camera matrices.");
  31. public static GUIContent cameraFOV = new GUIContent("Field Of View", "The camera's view angle measured in degrees along vertical axis.");
  32. public static GUIContent positionOffset = new GUIContent("Position Offset", "Position offset to apply to the original camera's position.");
  33. public static GUIContent restoreCamera = new GUIContent("Restore", "Restore to the original camera matrices after the execution of the render passes added by this feature.");
  34. }
  35. //Headers and layout
  36. private HeaderBool m_FiltersFoldout;
  37. private int m_FilterLines = 3;
  38. private HeaderBool m_RenderFoldout;
  39. private int m_MaterialLines = 2;
  40. private int m_DepthLines = 3;
  41. private int m_CameraLines = 4;
  42. // Serialized Properties
  43. private SerializedProperty m_Callback;
  44. private SerializedProperty m_PassTag;
  45. //Filter props
  46. private SerializedProperty m_FilterSettings;
  47. private SerializedProperty m_RenderQueue;
  48. private SerializedProperty m_LayerMask;
  49. private SerializedProperty m_ShaderPasses;
  50. //Render props
  51. private SerializedProperty m_OverrideMaterial;
  52. private SerializedProperty m_OverrideMaterialPass;
  53. //Depth props
  54. private SerializedProperty m_OverrideDepth;
  55. private SerializedProperty m_WriteDepth;
  56. private SerializedProperty m_DepthState;
  57. //Stencil props
  58. private SerializedProperty m_OverrideStencil;
  59. //Caemra props
  60. private SerializedProperty m_CameraSettings;
  61. private SerializedProperty m_OverrideCamera;
  62. private SerializedProperty m_FOV;
  63. private SerializedProperty m_CameraOffset;
  64. private SerializedProperty m_RestoreCamera;
  65. private ReorderableList m_ShaderPassesList;
  66. private List<SerializedObject> m_properties = new List<SerializedObject>();
  67. private void Init(SerializedProperty property)
  68. {
  69. //Header bools
  70. var key = $"{this.ToString().Split('.').Last()}.{property.serializedObject.targetObject.name}";
  71. m_FiltersFoldout = new HeaderBool($"{key}.FiltersFoldout", true);
  72. m_RenderFoldout = new HeaderBool($"{key}.RenderFoldout");
  73. m_Callback = property.FindPropertyRelative("Event");
  74. m_PassTag = property.FindPropertyRelative("passTag");
  75. //Filter props
  76. m_FilterSettings = property.FindPropertyRelative("filterSettings");
  77. m_RenderQueue = m_FilterSettings.FindPropertyRelative("RenderQueueType");
  78. m_LayerMask = m_FilterSettings.FindPropertyRelative("LayerMask");
  79. m_ShaderPasses = m_FilterSettings.FindPropertyRelative("PassNames");
  80. //Render options
  81. m_OverrideMaterial = property.FindPropertyRelative("overrideMaterial");
  82. m_OverrideMaterialPass = property.FindPropertyRelative("overrideMaterialPassIndex");
  83. //Depth props
  84. m_OverrideDepth = property.FindPropertyRelative("overrideDepthState");
  85. m_WriteDepth = property.FindPropertyRelative("enableWrite");
  86. m_DepthState = property.FindPropertyRelative("depthCompareFunction");
  87. //Stencil
  88. m_OverrideStencil = property.FindPropertyRelative("stencilSettings");
  89. //Camera
  90. m_CameraSettings = property.FindPropertyRelative("cameraSettings");
  91. m_OverrideCamera = m_CameraSettings.FindPropertyRelative("overrideCamera");
  92. m_FOV = m_CameraSettings.FindPropertyRelative("cameraFieldOfView");
  93. m_CameraOffset = m_CameraSettings.FindPropertyRelative("offset");
  94. m_RestoreCamera = m_CameraSettings.FindPropertyRelative("restoreCamera");
  95. m_properties.Add(property.serializedObject);
  96. CreateShaderPassList();
  97. }
  98. private void CreateShaderPassList()
  99. {
  100. m_ShaderPassesList = new ReorderableList(null, m_ShaderPasses, false, true, true, true);
  101. m_ShaderPassesList.drawElementCallback =
  102. (Rect rect, int index, bool isActive, bool isFocused) =>
  103. {
  104. var element = m_ShaderPassesList.serializedProperty.GetArrayElementAtIndex(index);
  105. var propRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
  106. var labelWidth = EditorGUIUtility.labelWidth;
  107. EditorGUIUtility.labelWidth = 50;
  108. element.stringValue = EditorGUI.TextField(propRect, "Name", element.stringValue);
  109. EditorGUIUtility.labelWidth = labelWidth;
  110. };
  111. m_ShaderPassesList.drawHeaderCallback = (Rect testHeaderRect) =>
  112. {
  113. EditorGUI.LabelField(testHeaderRect, Styles.shaderPassFilter);
  114. };
  115. }
  116. public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
  117. {
  118. rect.height = EditorGUIUtility.singleLineHeight;
  119. EditorGUI.BeginChangeCheck();
  120. EditorGUI.BeginProperty(rect, label, property);
  121. if (!m_properties.Contains(property.serializedObject))
  122. {
  123. Init(property);
  124. }
  125. var passName = property.serializedObject.FindProperty("m_Name").stringValue;
  126. if (passName != m_PassTag.stringValue)
  127. {
  128. m_PassTag.stringValue = passName;
  129. property.serializedObject.ApplyModifiedProperties();
  130. }
  131. //Forward Callbacks
  132. EditorGUI.PropertyField(rect, m_Callback, Styles.callback);
  133. rect.y += Styles.defaultLineSpace;
  134. DoFilters(ref rect);
  135. m_RenderFoldout.value = EditorGUI.Foldout(rect, m_RenderFoldout.value, Styles.renderHeader, true);
  136. SaveHeaderBool(m_RenderFoldout);
  137. rect.y += Styles.defaultLineSpace;
  138. if (m_RenderFoldout.value)
  139. {
  140. EditorGUI.indentLevel++;
  141. //Override material
  142. DoMaterialOverride(ref rect);
  143. rect.y += Styles.defaultLineSpace;
  144. //Override depth
  145. DoDepthOverride(ref rect);
  146. rect.y += Styles.defaultLineSpace;
  147. //Override stencil
  148. EditorGUI.PropertyField(rect, m_OverrideStencil);
  149. rect.y += EditorGUI.GetPropertyHeight(m_OverrideStencil);
  150. //Override camera
  151. DoCameraOverride(ref rect);
  152. rect.y += Styles.defaultLineSpace;
  153. EditorGUI.indentLevel--;
  154. }
  155. EditorGUI.EndProperty();
  156. if (EditorGUI.EndChangeCheck())
  157. property.serializedObject.ApplyModifiedProperties();
  158. }
  159. void DoFilters(ref Rect rect)
  160. {
  161. m_FiltersFoldout.value = EditorGUI.Foldout(rect, m_FiltersFoldout.value, Styles.filtersHeader, true);
  162. SaveHeaderBool(m_FiltersFoldout);
  163. rect.y += Styles.defaultLineSpace;
  164. if (m_FiltersFoldout.value)
  165. {
  166. EditorGUI.indentLevel++;
  167. //Render queue filter
  168. EditorGUI.PropertyField(rect, m_RenderQueue, Styles.renderQueueFilter);
  169. rect.y += Styles.defaultLineSpace;
  170. //Layer mask
  171. EditorGUI.PropertyField(rect, m_LayerMask, Styles.layerMask);
  172. rect.y += Styles.defaultLineSpace;
  173. //Shader pass list
  174. EditorGUI.indentLevel--;
  175. m_ShaderPassesList.DoList(rect);
  176. rect.y += m_ShaderPassesList.GetHeight();
  177. }
  178. }
  179. void DoMaterialOverride(ref Rect rect)
  180. {
  181. //Override material
  182. EditorGUI.PropertyField(rect, m_OverrideMaterial, Styles.overrideMaterial);
  183. if (m_OverrideMaterial.objectReferenceValue)
  184. {
  185. rect.y += Styles.defaultLineSpace;
  186. EditorGUI.indentLevel++;
  187. EditorGUI.BeginChangeCheck();
  188. EditorGUI.PropertyField(rect, m_OverrideMaterialPass, Styles.overrideMaterialPass);
  189. if (EditorGUI.EndChangeCheck())
  190. m_OverrideMaterialPass.intValue = Mathf.Max(0, m_OverrideMaterialPass.intValue);
  191. EditorGUI.indentLevel--;
  192. }
  193. }
  194. void DoDepthOverride(ref Rect rect)
  195. {
  196. EditorGUI.PropertyField(rect, m_OverrideDepth, Styles.overrideDepth);
  197. if (m_OverrideDepth.boolValue)
  198. {
  199. rect.y += Styles.defaultLineSpace;
  200. EditorGUI.indentLevel++;
  201. //Write depth
  202. EditorGUI.PropertyField(rect, m_WriteDepth, Styles.writeDepth);
  203. rect.y += Styles.defaultLineSpace;
  204. //Depth testing options
  205. EditorGUI.PropertyField(rect, m_DepthState, Styles.depthState);
  206. EditorGUI.indentLevel--;
  207. }
  208. }
  209. void DoCameraOverride(ref Rect rect)
  210. {
  211. EditorGUI.PropertyField(rect, m_OverrideCamera, Styles.overrideCamera);
  212. if (m_OverrideCamera.boolValue)
  213. {
  214. rect.y += Styles.defaultLineSpace;
  215. EditorGUI.indentLevel++;
  216. //FOV
  217. EditorGUI.Slider(rect, m_FOV, 4f, 179f, Styles.cameraFOV);
  218. rect.y += Styles.defaultLineSpace;
  219. //Offset vector
  220. var offset = m_CameraOffset.vector4Value;
  221. EditorGUI.BeginChangeCheck();
  222. var newOffset = EditorGUI.Vector3Field(rect, Styles.positionOffset, new Vector3(offset.x, offset.y, offset.z));
  223. if(EditorGUI.EndChangeCheck())
  224. m_CameraOffset.vector4Value = new Vector4(newOffset.x, newOffset.y, newOffset.z, 1f);
  225. rect.y += Styles.defaultLineSpace;
  226. //Restore prev camera projections
  227. EditorGUI.PropertyField(rect, m_RestoreCamera, Styles.restoreCamera);
  228. rect.y += Styles.defaultLineSpace;
  229. EditorGUI.indentLevel--;
  230. }
  231. }
  232. public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
  233. {
  234. float height = Styles.defaultLineSpace;
  235. Init(property);
  236. height += Styles.defaultLineSpace * (m_FiltersFoldout.value ? m_FilterLines : 1);
  237. height += m_FiltersFoldout.value ? m_ShaderPassesList.GetHeight() : 0;
  238. height += Styles.defaultLineSpace; // add line for overrides dropdown
  239. if (m_RenderFoldout.value)
  240. {
  241. height += Styles.defaultLineSpace * (m_OverrideMaterial.objectReferenceValue != null ? m_MaterialLines : 1);
  242. height += Styles.defaultLineSpace * (m_OverrideDepth.boolValue ? m_DepthLines : 1);
  243. height += EditorGUI.GetPropertyHeight(m_OverrideStencil);
  244. height += Styles.defaultLineSpace * (m_OverrideCamera.boolValue ? m_CameraLines : 1);
  245. }
  246. return height;
  247. }
  248. private void SaveHeaderBool(HeaderBool boolObj)
  249. {
  250. EditorPrefs.SetBool(boolObj.key, boolObj.value);
  251. }
  252. class HeaderBool
  253. {
  254. public string key;
  255. public bool value;
  256. public HeaderBool(string _key, bool _default = false)
  257. {
  258. key = _key;
  259. if (EditorPrefs.HasKey(key))
  260. value = EditorPrefs.GetBool(key);
  261. else
  262. value = _default;
  263. EditorPrefs.SetBool(key, value);
  264. }
  265. }
  266. }
  267. }