HBAOEditor.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditor.Rendering;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Reflection;
  7. namespace HorizonBasedAmbientOcclusion
  8. {
  9. [CustomEditor(typeof(HBAO))]
  10. public class HBAOEditor : Editor
  11. {
  12. private HBAO m_HBAO;
  13. private Texture2D m_HBAOTex;
  14. private GUIStyle m_SettingsGroupStyle;
  15. private GUIStyle m_TitleLabelStyle;
  16. private int m_SelectedPreset;
  17. // settings group <setting, property reference>
  18. private Dictionary<FieldInfo, List<SerializedProperty>> m_GroupFields = new Dictionary<FieldInfo, List<SerializedProperty>>();
  19. private readonly Dictionary<int, HBAO.Preset> m_Presets = new Dictionary<int, HBAO.Preset>()
  20. {
  21. { 0, HBAO.Preset.Normal },
  22. { 1, HBAO.Preset.FastPerformance },
  23. { 2, HBAO.Preset.FastestPerformance },
  24. { 3, HBAO.Preset.Custom },
  25. { 4, HBAO.Preset.HighQuality },
  26. { 5, HBAO.Preset.HighestQuality }
  27. };
  28. void OnEnable()
  29. {
  30. m_HBAO = (HBAO)target;
  31. m_HBAOTex = Resources.Load<Texture2D>("hbao");
  32. var settingsGroups = typeof(HBAO).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
  33. .Where(x => x.GetCustomAttributes(typeof(HBAO.SettingsGroup), false).Any());
  34. foreach (var group in settingsGroups)
  35. {
  36. foreach (var setting in group.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public))
  37. {
  38. if (!m_GroupFields.ContainsKey(group))
  39. m_GroupFields[group] = new List<SerializedProperty>();
  40. var property = serializedObject.FindProperty(group.Name + "." + setting.Name);
  41. if (property != null)
  42. m_GroupFields[group].Add(property);
  43. }
  44. }
  45. m_SelectedPreset = m_Presets.Values.ToList().IndexOf(m_HBAO.GetCurrentPreset());
  46. }
  47. public override void OnInspectorGUI()
  48. {
  49. serializedObject.Update();
  50. SetStyles();
  51. EditorGUILayout.BeginVertical();
  52. {
  53. // header
  54. GUILayout.Space(10.0f);
  55. GUILayout.Label(m_HBAOTex, m_TitleLabelStyle, GUILayout.ExpandWidth(true));
  56. //if (m_HBAO.GetComponents<MonoBehaviour>()[0] != m_HBAO)
  57. //{
  58. //GUILayout.Space(6.0f);
  59. //EditorGUILayout.HelpBox("This Post FX should be one of the first in your effect stack", MessageType.Info);
  60. //}
  61. Event e = Event.current;
  62. // settings groups
  63. foreach (var group in m_GroupFields)
  64. {
  65. var groupProperty = serializedObject.FindProperty(group.Key.Name);
  66. if (groupProperty == null)
  67. continue;
  68. GUILayout.Space(6.0f);
  69. Rect rect = GUILayoutUtility.GetRect(16f, 22f, m_SettingsGroupStyle);
  70. GUI.Box(rect, ObjectNames.NicifyVariableName(groupProperty.displayName), m_SettingsGroupStyle);
  71. if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
  72. {
  73. groupProperty.isExpanded = !groupProperty.isExpanded;
  74. e.Use();
  75. }
  76. if (!groupProperty.isExpanded)
  77. continue;
  78. // presets is a special case
  79. if (group.Key.FieldType == typeof(HBAO.Presets))
  80. {
  81. GUILayout.Space(6.0f);
  82. m_SelectedPreset = GUILayout.SelectionGrid(m_SelectedPreset, m_Presets.Values.Select(x => ObjectNames.NicifyVariableName(x.ToString())).ToArray(), 3);
  83. GUILayout.Space(6.0f);
  84. if (GUILayout.Button("Apply Preset"))
  85. {
  86. Undo.RecordObject(target, "Apply Preset");
  87. m_HBAO.ApplyPreset(m_Presets[m_SelectedPreset]);
  88. EditorUtility.SetDirty(target);
  89. if (!EditorApplication.isPlaying)
  90. {
  91. UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
  92. }
  93. }
  94. }
  95. foreach (var field in group.Value)
  96. {
  97. // hide real presets
  98. if (group.Key.FieldType == typeof(HBAO.Presets))
  99. continue;
  100. // hide resolution when deinterleaved HBAO is on
  101. if (group.Key.FieldType == typeof(HBAO.GeneralSettings) && field.name == "resolution")
  102. {
  103. if (m_HBAO.GetDeinterleaving() != HBAO.Deinterleaving.Disabled)
  104. {
  105. continue;
  106. }
  107. }
  108. // warn about deinterleaving not supported with SPSR
  109. else if (group.Key.FieldType == typeof(HBAO.GeneralSettings) && field.name == "debugMode")
  110. {
  111. #if UNITY_2019_3_OR_NEWER
  112. if (m_HBAO.GetDeinterleaving() != HBAO.Deinterleaving.Disabled &&
  113. IsVrRunning() && PlayerSettings.stereoRenderingPath == StereoRenderingPath.SinglePass)
  114. {
  115. GUILayout.Space(6.0f);
  116. EditorGUILayout.HelpBox("Deinterleaving is not supported with Single Pass Stereo Rendering...", MessageType.Warning);
  117. }
  118. #else
  119. if (m_HBAO.GetDeinterleaving() != HBAO.Deinterleaving.Disabled &&
  120. PlayerSettings.virtualRealitySupported && PlayerSettings.stereoRenderingPath == StereoRenderingPath.SinglePass)
  121. {
  122. GUILayout.Space(6.0f);
  123. EditorGUILayout.HelpBox("Deinterleaving is not supported with Single Pass Stereo Rendering...", MessageType.Warning);
  124. }
  125. #endif
  126. }
  127. // hide noise type when deinterleaved HBAO is on
  128. else if (group.Key.FieldType == typeof(HBAO.GeneralSettings) && field.name == "noiseType")
  129. {
  130. if (m_HBAO.GetDeinterleaving() != HBAO.Deinterleaving.Disabled)
  131. {
  132. continue;
  133. }
  134. }
  135. // hide useMultiBounce setting in BeforeReflections integration stage
  136. else if (group.Key.FieldType == typeof(HBAO.AOSettings) && field.name == "useMultiBounce")
  137. {
  138. if (m_HBAO.GetPipelineStage() == HBAO.PipelineStage.BeforeReflections)
  139. {
  140. continue;
  141. }
  142. }
  143. // hide multiBounceInfluence setting when not used
  144. else if (group.Key.FieldType == typeof(HBAO.AOSettings) && field.name == "multiBounceInfluence")
  145. {
  146. if (m_HBAO.GetPipelineStage() == HBAO.PipelineStage.BeforeReflections || !m_HBAO.UseMultiBounce())
  147. {
  148. continue;
  149. }
  150. }
  151. // warn about distance falloff greater than max distance
  152. else if (group.Key.FieldType == typeof(HBAO.AOSettings) && field.name == "perPixelNormals")
  153. {
  154. if (m_HBAO.GetAoDistanceFalloff() > m_HBAO.GetAoMaxDistance())
  155. {
  156. GUILayout.Space(6.0f);
  157. EditorGUILayout.HelpBox("Distance Falloff shoudn't be superior to Max Distance", MessageType.Warning);
  158. }
  159. }
  160. // hide albedoMultiplier when not in deferred
  161. else if (group.Key.FieldType == typeof(HBAO.ColorBleedingSettings) && field.name == "albedoMultiplier")
  162. {
  163. if (m_HBAO.GetPipelineStage() == HBAO.PipelineStage.BeforeImageEffectsOpaque)
  164. continue;
  165. }
  166. EditorGUILayout.BeginHorizontal();
  167. GUILayout.Space(12.0f);
  168. EditorGUILayout.PropertyField(field);
  169. EditorGUILayout.EndHorizontal();
  170. }
  171. }
  172. }
  173. EditorGUILayout.EndVertical();
  174. serializedObject.ApplyModifiedProperties();
  175. }
  176. private void SetStyles()
  177. {
  178. // set banner label style
  179. m_TitleLabelStyle = new GUIStyle(GUI.skin.label);
  180. m_TitleLabelStyle.alignment = TextAnchor.MiddleCenter;
  181. m_TitleLabelStyle.contentOffset = new Vector2(0f, 0f);
  182. // get shuriken module title style
  183. GUIStyle skurikenModuleTitleStyle = "ShurikenModuleTitle";
  184. // clone it as to not interfere with the original, and adjust it
  185. m_SettingsGroupStyle = new GUIStyle(skurikenModuleTitleStyle);
  186. m_SettingsGroupStyle.font = (new GUIStyle("Label")).font;
  187. m_SettingsGroupStyle.fontStyle = FontStyle.Bold;
  188. m_SettingsGroupStyle.border = new RectOffset(15, 7, 4, 4);
  189. m_SettingsGroupStyle.fixedHeight = 22;
  190. m_SettingsGroupStyle.contentOffset = new Vector2(10f, -2f);
  191. }
  192. #if UNITY_2019_3_OR_NEWER
  193. List<UnityEngine.XR.XRDisplaySubsystemDescriptor> displaysDescs = new List<UnityEngine.XR.XRDisplaySubsystemDescriptor>();
  194. List<UnityEngine.XR.XRDisplaySubsystem> displays = new List<UnityEngine.XR.XRDisplaySubsystem>();
  195. private bool IsVrRunning()
  196. {
  197. bool vrIsRunning = false;
  198. displays.Clear();
  199. SubsystemManager.GetInstances(displays);
  200. foreach (var displaySubsystem in displays)
  201. {
  202. if (displaySubsystem.running)
  203. {
  204. vrIsRunning = true;
  205. break;
  206. }
  207. }
  208. return vrIsRunning;
  209. }
  210. #endif
  211. [CustomPropertyDrawer(typeof(HBAO.MinMaxSliderAttribute))]
  212. public class MinMaxSliderDrawer : PropertyDrawer
  213. {
  214. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  215. {
  216. if (property.propertyType == SerializedPropertyType.Vector2)
  217. {
  218. Vector2 range = property.vector2Value;
  219. float min = range.x;
  220. float max = range.y;
  221. var attr = attribute as HBAO.MinMaxSliderAttribute;
  222. EditorGUI.BeginChangeCheck();
  223. EditorGUI.MinMaxSlider(position, label, ref min, ref max, attr.min, attr.max);
  224. if (EditorGUI.EndChangeCheck())
  225. {
  226. range.x = min;
  227. range.y = max;
  228. property.vector2Value = range;
  229. }
  230. }
  231. else
  232. {
  233. EditorGUI.LabelField(position, label, "Use only with Vector2");
  234. }
  235. }
  236. }
  237. }
  238. }