UniversalRenderPipelineCameraEditor.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.AnimatedValues;
  5. using UnityEditor.SceneManagement;
  6. using UnityEditorInternal;
  7. using UnityEngine;
  8. using UnityEngine.Rendering;
  9. using UnityEngine.Rendering.Universal;
  10. using Object = UnityEngine.Object;
  11. namespace UnityEditor.Rendering.Universal
  12. {
  13. [CustomEditorForRenderPipeline(typeof(Camera), typeof(UniversalRenderPipelineAsset))]
  14. [CanEditMultipleObjects]
  15. class UniversalRenderPipelineCameraEditor : CameraEditor
  16. {
  17. internal enum BackgroundType
  18. {
  19. Skybox = 0,
  20. SolidColor,
  21. DontCare,
  22. }
  23. static class Styles
  24. {
  25. // Groups
  26. public static GUIContent commonCameraSettingsText = EditorGUIUtility.TrTextContent("Projection", "These settings control how the camera views the world.");
  27. public static GUIContent environmentSettingsText = EditorGUIUtility.TrTextContent("Environment", "These settings control what the camera background looks like.");
  28. public static GUIContent outputSettingsText = EditorGUIUtility.TrTextContent("Output", "These settings control how the camera output is formatted.");
  29. public static GUIContent renderingSettingsText = EditorGUIUtility.TrTextContent("Rendering", "These settings control for the specific rendering features for this camera.");
  30. public static GUIContent stackSettingsText = EditorGUIUtility.TrTextContent("Stack", "The list of overlay cameras assigned to this camera.");
  31. public static GUIContent backgroundType = EditorGUIUtility.TrTextContent("Background Type", "Controls how to initialize the Camera's background.\n\nSkybox initializes camera with Skybox, defaulting to a background color if no skybox is found.\n\nSolid Color initializes background with the background color.\n\nUninitialized has undefined values for the camera background. Use this only if you are rendering all pixels in the Camera's view.");
  32. public static GUIContent cameraType = EditorGUIUtility.TrTextContent("Render Type", "Controls which type of camera this is.");
  33. public static GUIContent renderingShadows = EditorGUIUtility.TrTextContent("Render Shadows", "Makes this camera render shadows.");
  34. public static GUIContent requireDepthTexture = EditorGUIUtility.TrTextContent("Depth Texture", "On makes this camera create a _CameraDepthTexture, which is a copy of the rendered depth values.\nOff makes the camera not create a depth texture.\nUse Pipeline Settings applies settings from the Render Pipeline Asset.");
  35. public static GUIContent requireOpaqueTexture = EditorGUIUtility.TrTextContent("Opaque Texture", "On makes this camera create a _CameraOpaqueTexture, which is a copy of the rendered view.\nOff makes the camera not create an opaque texture.\nUse Pipeline Settings applies settings from the Render Pipeline Asset.");
  36. public static GUIContent allowMSAA = EditorGUIUtility.TrTextContent("MSAA", "Use Multi Sample Anti-Aliasing to reduce aliasing.");
  37. public static GUIContent allowHDR = EditorGUIUtility.TrTextContent("HDR", "High Dynamic Range gives you a wider range of light intensities, so your lighting looks more realistic. With it, you can still see details and experience less saturation even with bright light.", (Texture) null);
  38. public static GUIContent priority = EditorGUIUtility.TrTextContent("Priority", "A camera with a higher priority is drawn on top of a camera with a lower priority [ -100, 100 ].");
  39. public static GUIContent clearDepth = EditorGUIUtility.TrTextContent("Clear Depth", "If enabled, depth from the previous camera will be cleared.");
  40. public static GUIContent rendererType = EditorGUIUtility.TrTextContent("Renderer", "Controls which renderer this camera uses.");
  41. public static GUIContent volumesSettingsText = EditorGUIUtility.TrTextContent("Volumes", "These settings define how Volumes affect this Camera.");
  42. public static GUIContent volumeLayerMask = EditorGUIUtility.TrTextContent("Mask", "This Camera is only affected by Volumes in the Layers that are assigned to the Camera.");
  43. public static GUIContent volumeTrigger = EditorGUIUtility.TrTextContent("Trigger", "A Transform component that acts as a trigger for Volume blending. If none is set, the Camera itself acts as a trigger.");
  44. public static GUIContent volumeUpdates = EditorGUIUtility.TrTextContent("Update Mode", "Select how Unity updates Volumes: every frame or when triggered via scripting. In the Editor, Unity updates Volumes every frame when not in the Play mode.");
  45. public static GUIContent renderPostProcessing = EditorGUIUtility.TrTextContent("Post Processing", "Enable this to make this camera render post-processing effects.");
  46. public static GUIContent antialiasing = EditorGUIUtility.TrTextContent("Anti-aliasing", "The anti-aliasing method to use.");
  47. public static GUIContent antialiasingQuality = EditorGUIUtility.TrTextContent("Quality", "The quality level to use for the selected anti-aliasing method.");
  48. public static GUIContent stopNaN = EditorGUIUtility.TrTextContent("Stop NaN", "Automatically replaces NaN/Inf in shaders by a black pixel to avoid breaking some effects. This will affect performances and should only be used if you experience NaN issues that you can't fix. Has no effect on GLES2 platforms.");
  49. public static GUIContent dithering = EditorGUIUtility.TrTextContent("Dithering", "Applies 8-bit dithering to the final render to reduce color banding.");
  50. #if ENABLE_VR && ENABLE_XR_MODULE
  51. public static GUIContent[] xrTargetEyeOptions =
  52. {
  53. new GUIContent("None"),
  54. new GUIContent("Both"),
  55. };
  56. public static int[] xrTargetEyeValues = { 0, 1 };
  57. public static readonly GUIContent xrTargetEye = EditorGUIUtility.TrTextContent("Target Eye", "Allows XR rendering if target eye sets to both eye. Disable XR for this camera otherwise.");
  58. #endif
  59. public static readonly GUIContent targetTextureLabel = EditorGUIUtility.TrTextContent("Output Texture", "The texture to render this camera into, if none then this camera renders to screen.");
  60. public static readonly string hdrDisabledWarning = "HDR rendering is disabled in the Universal Render Pipeline asset.";
  61. public static readonly string mssaDisabledWarning = "Anti-aliasing is disabled in the Universal Render Pipeline asset.";
  62. public static readonly string missingRendererWarning = "The currently selected Renderer is missing from the Universal Render Pipeline asset.";
  63. public static readonly string noRendererError = "There are no valid Renderers available on the Universal Render Pipeline asset.";
  64. public static GUIContent[] cameraBackgroundType =
  65. {
  66. new GUIContent("Skybox"),
  67. new GUIContent("Solid Color"),
  68. new GUIContent("Uninitialized"),
  69. };
  70. public static int[] cameraBackgroundValues = { 0, 1, 2};
  71. // Using the pipeline Settings
  72. public static GUIContent[] displayedCameraOptions =
  73. {
  74. new GUIContent("Off"),
  75. new GUIContent("Use Pipeline Settings"),
  76. };
  77. public static int[] cameraOptions = { 0, 1 };
  78. // Camera Types
  79. public static List<GUIContent> m_CameraTypeNames = null;
  80. public static readonly string[] cameraTypeNames = Enum.GetNames(typeof(CameraRenderType));
  81. // Beautified anti-aliasing options
  82. public static GUIContent[] antialiasingOptions =
  83. {
  84. new GUIContent("None"),
  85. new GUIContent("Fast Approximate Anti-aliasing (FXAA)"),
  86. new GUIContent("Subpixel Morphological Anti-aliasing (SMAA)"),
  87. };
  88. public static int[] antialiasingValues = { 0, 1, 2};
  89. }
  90. ReorderableList m_LayerList;
  91. public Camera camera { get { return target as Camera; } }
  92. static List<Camera> k_Cameras;
  93. List<Camera> validCameras = new List<Camera>();
  94. // This is the valid list of types, so if we need to add more types we just add it here.
  95. List<CameraRenderType> validCameraTypes = new List<CameraRenderType>{CameraRenderType.Overlay};
  96. List<Camera> errorCameras = new List<Camera>();
  97. Texture2D m_ErrorIcon;
  98. // Temporary saved bools for foldout header
  99. SavedBool m_CommonCameraSettingsFoldout;
  100. SavedBool m_EnvironmentSettingsFoldout;
  101. SavedBool m_OutputSettingsFoldout;
  102. SavedBool m_RenderingSettingsFoldout;
  103. SavedBool m_StackSettingsFoldout;
  104. // Animation Properties
  105. public bool isSameClearFlags { get { return !settings.clearFlags.hasMultipleDifferentValues; } }
  106. public bool isSameOrthographic { get { return !settings.orthographic.hasMultipleDifferentValues; } }
  107. Dictionary<Object, UniversalAdditionalCameraData> m_AdditionalCameraDatas = new Dictionary<Object, UniversalAdditionalCameraData>();
  108. SerializedObject m_AdditionalCameraDataSO;
  109. readonly AnimBool m_ShowBGColorAnim = new AnimBool();
  110. readonly AnimBool m_ShowOrthoAnim = new AnimBool();
  111. readonly AnimBool m_ShowTargetEyeAnim = new AnimBool();
  112. SerializedProperty m_AdditionalCameraDataRenderShadowsProp;
  113. SerializedProperty m_AdditionalCameraDataRenderDepthProp;
  114. SerializedProperty m_AdditionalCameraDataRenderOpaqueProp;
  115. SerializedProperty m_AdditionalCameraDataRendererProp;
  116. SerializedProperty m_AdditionalCameraDataCameraTypeProp;
  117. SerializedProperty m_AdditionalCameraDataCameras;
  118. SerializedProperty m_AdditionalCameraDataVolumeLayerMask;
  119. SerializedProperty m_AdditionalCameraDataVolumeTrigger;
  120. SerializedProperty m_AdditionalCameraDataVolumeFrameworkUpdateMode;
  121. SerializedProperty m_AdditionalCameraDataRenderPostProcessing;
  122. SerializedProperty m_AdditionalCameraDataAntialiasing;
  123. SerializedProperty m_AdditionalCameraDataAntialiasingQuality;
  124. SerializedProperty m_AdditionalCameraDataStopNaN;
  125. SerializedProperty m_AdditionalCameraDataDithering;
  126. SerializedProperty m_AdditionalCameraClearDepth;
  127. #if ENABLE_VR && ENABLE_XR_MODULE
  128. SerializedProperty m_AdditionalCameraDataAllowXRRendering;
  129. #endif
  130. void SetAnimationTarget(AnimBool anim, bool initialize, bool targetValue)
  131. {
  132. if (initialize)
  133. {
  134. anim.value = targetValue;
  135. anim.valueChanged.AddListener(Repaint);
  136. }
  137. else
  138. {
  139. anim.target = targetValue;
  140. }
  141. }
  142. void UpdateAnimationValues(bool initialize)
  143. {
  144. SetAnimationTarget(m_ShowBGColorAnim, initialize, isSameClearFlags && (camera.clearFlags == CameraClearFlags.SolidColor || camera.clearFlags == CameraClearFlags.Skybox));
  145. SetAnimationTarget(m_ShowOrthoAnim, initialize, isSameOrthographic && camera.orthographic);
  146. SetAnimationTarget(m_ShowTargetEyeAnim, initialize, settings.targetEye.intValue != (int)StereoTargetEyeMask.Both);
  147. }
  148. void UpdateCameraTypeIntPopupData()
  149. {
  150. if (Styles.m_CameraTypeNames == null)
  151. {
  152. Styles.m_CameraTypeNames = new List<GUIContent>();
  153. foreach (string typeName in Styles.cameraTypeNames)
  154. {
  155. Styles.m_CameraTypeNames.Add(new GUIContent(typeName));
  156. }
  157. }
  158. }
  159. public new void OnEnable()
  160. {
  161. base.OnEnable();
  162. m_CommonCameraSettingsFoldout = new SavedBool($"{target.GetType()}.CommonCameraSettingsFoldout", false);
  163. m_EnvironmentSettingsFoldout = new SavedBool($"{target.GetType()}.EnvironmentSettingsFoldout", false);
  164. m_OutputSettingsFoldout = new SavedBool($"{target.GetType()}.OutputSettingsFoldout", false);
  165. m_RenderingSettingsFoldout = new SavedBool($"{target.GetType()}.RenderingSettingsFoldout", false);
  166. m_StackSettingsFoldout = new SavedBool($"{target.GetType()}.StackSettingsFoldout", false);
  167. var additionalCameraList = new List<Object>();
  168. foreach (var cameraTarget in targets)
  169. {
  170. var additionData = (cameraTarget as Component).gameObject.GetComponent<UniversalAdditionalCameraData>();
  171. if(additionData == null)
  172. additionData = (cameraTarget as Component).gameObject.AddComponent<UniversalAdditionalCameraData>();
  173. m_AdditionalCameraDatas[cameraTarget] = additionData;
  174. additionalCameraList.Add(additionData);
  175. }
  176. m_ErrorIcon = EditorGUIUtility.Load("icons/console.erroricon.sml.png") as Texture2D;
  177. validCameras.Clear();
  178. errorCameras.Clear();
  179. settings.OnEnable();
  180. init(additionalCameraList);
  181. UpdateAnimationValues(true);
  182. UpdateCameraTypeIntPopupData();
  183. UpdateCameras();
  184. }
  185. void UpdateCameras()
  186. {
  187. var o = new PropertyFetcher<UniversalAdditionalCameraData>(m_AdditionalCameraDataSO);
  188. m_AdditionalCameraDataCameras = o.Find("m_Cameras");
  189. var camType = (CameraRenderType)m_AdditionalCameraDataCameraTypeProp.intValue;
  190. if (camType == CameraRenderType.Base)
  191. {
  192. m_LayerList = new ReorderableList(m_AdditionalCameraDataSO, m_AdditionalCameraDataCameras, true, false, true, true);
  193. m_LayerList.drawElementCallback += DrawElementCallback;
  194. m_LayerList.onSelectCallback += SelectElement;
  195. m_LayerList.onRemoveCallback = list =>
  196. {
  197. m_AdditionalCameraDataCameras.DeleteArrayElementAtIndex(list.index);
  198. ReorderableList.defaultBehaviours.DoRemoveButton(list);
  199. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  200. };
  201. m_LayerList.onAddDropdownCallback = (rect, list) => AddCameraToCameraList(rect, list);
  202. }
  203. }
  204. void SelectElement(ReorderableList list)
  205. {
  206. var element = m_AdditionalCameraDataCameras.GetArrayElementAtIndex(list.index);
  207. var cam = element.objectReferenceValue as Camera;
  208. if (Event.current.clickCount == 2)
  209. {
  210. Selection.activeObject = cam;
  211. }
  212. EditorGUIUtility.PingObject(cam);
  213. }
  214. static GUIContent s_TextImage = new GUIContent();
  215. static GUIContent TempContent(string text, string tooltip, Texture i)
  216. {
  217. s_TextImage.image = i;
  218. s_TextImage.text = text;
  219. s_TextImage.tooltip = tooltip;
  220. return s_TextImage;
  221. }
  222. GUIContent m_NameContent = new GUIContent();
  223. void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused)
  224. {
  225. rect.height = EditorGUIUtility.singleLineHeight;
  226. rect.y += 1;
  227. var element = m_AdditionalCameraDataCameras.GetArrayElementAtIndex(index);
  228. var cam = element.objectReferenceValue as Camera;
  229. if (cam != null)
  230. {
  231. bool warning = false;
  232. string warningInfo = "";
  233. var type = cam.gameObject.GetComponent<UniversalAdditionalCameraData>().renderType;
  234. if (!validCameraTypes.Contains(type))
  235. {
  236. warning = true;
  237. warningInfo += "Not a supported type";
  238. if (!errorCameras.Contains(cam))
  239. {
  240. errorCameras.Add(cam);
  241. }
  242. }
  243. else if (errorCameras.Contains(cam))
  244. {
  245. errorCameras.Remove(cam);
  246. }
  247. var labelWidth = EditorGUIUtility.labelWidth;
  248. EditorGUIUtility.labelWidth -= 20f;
  249. if (warning)
  250. {
  251. GUIStyle errorStyle = new GUIStyle(EditorStyles.label) { padding = new RectOffset { left = -16 } };
  252. m_NameContent.text = cam.name;
  253. EditorGUI.LabelField(rect, m_NameContent, TempContent(type.GetName(), warningInfo, m_ErrorIcon), errorStyle);
  254. }
  255. else
  256. {
  257. EditorGUI.LabelField(rect, cam.name, type.ToString());
  258. // Printing if Post Processing is on or not.
  259. var isPostActive = cam.gameObject.GetComponent<UniversalAdditionalCameraData>().renderPostProcessing;
  260. if (isPostActive)
  261. {
  262. Rect selectRect = new Rect(rect.width - 20, rect.y, 50, EditorGUIUtility.singleLineHeight);
  263. EditorGUI.LabelField(selectRect, "PP");
  264. }
  265. }
  266. EditorGUIUtility.labelWidth = labelWidth;
  267. }
  268. else
  269. {
  270. camera.GetComponent<UniversalAdditionalCameraData>().UpdateCameraStack();
  271. // Need to clean out the errorCamera list here.
  272. errorCameras.Clear();
  273. }
  274. }
  275. // Modified version of StageHandle.FindComponentsOfType<T>()
  276. // This version more closely represents unity object referencing restrictions.
  277. // I added these restrictions:
  278. // - Can not reference scene object outside scene
  279. // - Can not reference cross scenes
  280. // - Can reference child objects if it is prefab
  281. Camera[] FindCamerasToReference(GameObject gameObject)
  282. {
  283. var scene = gameObject.scene;
  284. var inScene = !EditorUtility.IsPersistent(camera) || scene.IsValid();
  285. var inPreviewScene = EditorSceneManager.IsPreviewScene(scene) && scene.IsValid();
  286. var inCurrentScene = !EditorUtility.IsPersistent(camera) && scene.IsValid();
  287. Camera[] cameras = Resources.FindObjectsOfTypeAll<Camera>();
  288. List<Camera> result = new List<Camera>();
  289. if (!inScene)
  290. {
  291. foreach (var camera in cameras)
  292. {
  293. if (camera.transform.IsChildOf(gameObject.transform))
  294. result.Add(camera);
  295. }
  296. }
  297. else if (inPreviewScene)
  298. {
  299. foreach (var camera in cameras)
  300. {
  301. if (camera.gameObject.scene == scene)
  302. result.Add(camera);
  303. }
  304. }
  305. else if (inCurrentScene)
  306. {
  307. foreach (var camera in cameras)
  308. {
  309. if (!EditorUtility.IsPersistent(camera) && !EditorSceneManager.IsPreviewScene(camera.gameObject.scene) && camera.gameObject.scene == scene)
  310. result.Add(camera);
  311. }
  312. }
  313. return result.ToArray();
  314. }
  315. void AddCameraToCameraList(Rect rect, ReorderableList list)
  316. {
  317. // Need to do clear the list here otherwise the meu just fills up with more and more entries
  318. validCameras.Clear();
  319. var allCameras = FindCamerasToReference(camera.gameObject);
  320. foreach (var camera in allCameras)
  321. {
  322. var component = camera.gameObject.GetComponent<UniversalAdditionalCameraData>();
  323. if (component != null)
  324. {
  325. if (validCameraTypes.Contains(component.renderType))
  326. {
  327. validCameras.Add(camera);
  328. }
  329. }
  330. }
  331. var names = new GUIContent[validCameras.Count];
  332. for (int i = 0; i < validCameras.Count; ++i)
  333. {
  334. names[i] = new GUIContent((i+1) + " " + validCameras[i].name);
  335. }
  336. if (!validCameras.Any())
  337. {
  338. names = new GUIContent[1];
  339. names[0] = new GUIContent("No Overlay Cameras exist.");
  340. }
  341. EditorUtility.DisplayCustomMenu(rect, names, -1, AddCameraToCameraListMenuSelected, null);
  342. }
  343. void AddCameraToCameraListMenuSelected(object userData, string[] options, int selected)
  344. {
  345. if(!validCameras.Any())
  346. return;
  347. var length = m_AdditionalCameraDataCameras.arraySize;
  348. ++m_AdditionalCameraDataCameras.arraySize;
  349. m_AdditionalCameraDataCameras.serializedObject.ApplyModifiedProperties();
  350. m_AdditionalCameraDataCameras.GetArrayElementAtIndex(length).objectReferenceValue = validCameras[selected];
  351. m_AdditionalCameraDataCameras.serializedObject.ApplyModifiedProperties();
  352. }
  353. void init(List<Object> additionalCameraData)
  354. {
  355. if(additionalCameraData == null)
  356. return;
  357. m_AdditionalCameraDataSO = new SerializedObject(additionalCameraData.ToArray());
  358. m_AdditionalCameraDataRenderShadowsProp = m_AdditionalCameraDataSO.FindProperty("m_RenderShadows");
  359. m_AdditionalCameraDataRenderDepthProp = m_AdditionalCameraDataSO.FindProperty("m_RequiresDepthTextureOption");
  360. m_AdditionalCameraDataRenderOpaqueProp = m_AdditionalCameraDataSO.FindProperty("m_RequiresOpaqueTextureOption");
  361. m_AdditionalCameraDataRendererProp = m_AdditionalCameraDataSO.FindProperty("m_RendererIndex");
  362. m_AdditionalCameraDataVolumeLayerMask = m_AdditionalCameraDataSO.FindProperty("m_VolumeLayerMask");
  363. m_AdditionalCameraDataVolumeTrigger = m_AdditionalCameraDataSO.FindProperty("m_VolumeTrigger");
  364. m_AdditionalCameraDataVolumeFrameworkUpdateMode = m_AdditionalCameraDataSO.FindProperty("m_VolumeFrameworkUpdateModeOption");
  365. m_AdditionalCameraDataRenderPostProcessing = m_AdditionalCameraDataSO.FindProperty("m_RenderPostProcessing");
  366. m_AdditionalCameraDataAntialiasing = m_AdditionalCameraDataSO.FindProperty("m_Antialiasing");
  367. m_AdditionalCameraDataAntialiasingQuality = m_AdditionalCameraDataSO.FindProperty("m_AntialiasingQuality");
  368. m_AdditionalCameraDataStopNaN = m_AdditionalCameraDataSO.FindProperty("m_StopNaN");
  369. m_AdditionalCameraDataDithering = m_AdditionalCameraDataSO.FindProperty("m_Dithering");
  370. m_AdditionalCameraClearDepth = m_AdditionalCameraDataSO.FindProperty("m_ClearDepth");
  371. m_AdditionalCameraDataCameraTypeProp = m_AdditionalCameraDataSO.FindProperty("m_CameraType");
  372. m_AdditionalCameraDataCameras = m_AdditionalCameraDataSO.FindProperty("m_Cameras");
  373. #if ENABLE_VR && ENABLE_XR_MODULE
  374. m_AdditionalCameraDataAllowXRRendering = m_AdditionalCameraDataSO.FindProperty("m_AllowXRRendering");
  375. #endif
  376. }
  377. public new void OnDisable()
  378. {
  379. base.OnDisable();
  380. m_ShowBGColorAnim.valueChanged.RemoveListener(Repaint);
  381. m_ShowOrthoAnim.valueChanged.RemoveListener(Repaint);
  382. m_ShowTargetEyeAnim.valueChanged.RemoveListener(Repaint);
  383. }
  384. BackgroundType GetBackgroundType(CameraClearFlags clearFlags)
  385. {
  386. switch (clearFlags)
  387. {
  388. case CameraClearFlags.Skybox:
  389. return BackgroundType.Skybox;
  390. case CameraClearFlags.Nothing:
  391. return BackgroundType.DontCare;
  392. // DepthOnly is not supported by design in UniversalRP. We upgrade it to SolidColor
  393. default:
  394. return BackgroundType.SolidColor;
  395. }
  396. }
  397. public override void OnInspectorGUI()
  398. {
  399. var rpAsset = UniversalRenderPipeline.asset;
  400. if(rpAsset == null)
  401. {
  402. base.OnInspectorGUI();
  403. return;
  404. }
  405. settings.Update();
  406. m_AdditionalCameraDataSO.Update();
  407. UpdateAnimationValues(false);
  408. // Get the type of Camera we are using
  409. CameraRenderType camType = (CameraRenderType)m_AdditionalCameraDataCameraTypeProp.intValue;
  410. DrawCameraType();
  411. EditorGUILayout.Space();
  412. // If we have different cameras selected that are of different types we do not allow multi editing and we do not draw any more UI.
  413. if (m_AdditionalCameraDataCameraTypeProp.hasMultipleDifferentValues)
  414. {
  415. EditorGUILayout.HelpBox("Cannot multi edit cameras of different types.", MessageType.Info);
  416. return;
  417. }
  418. EditorGUI.indentLevel++;
  419. DrawCommonSettings();
  420. DrawRenderingSettings(camType, rpAsset);
  421. DrawEnvironmentSettings(camType);
  422. // Settings only relevant to base cameras
  423. if (camType == CameraRenderType.Base)
  424. {
  425. DrawOutputSettings(rpAsset);
  426. DrawStackSettings();
  427. }
  428. EditorGUI.indentLevel--;
  429. settings.ApplyModifiedProperties();
  430. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  431. }
  432. void DrawCommonSettings()
  433. {
  434. m_CommonCameraSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_CommonCameraSettingsFoldout.value, Styles.commonCameraSettingsText);
  435. if (m_CommonCameraSettingsFoldout.value)
  436. {
  437. settings.DrawProjection();
  438. settings.DrawClippingPlanes();
  439. EditorGUILayout.Space();
  440. EditorGUILayout.Space();
  441. }
  442. EditorGUILayout.EndFoldoutHeaderGroup();
  443. }
  444. void DrawStackSettings()
  445. {
  446. m_StackSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_StackSettingsFoldout.value, Styles.stackSettingsText);
  447. if (m_AdditionalCameraDataCameras.hasMultipleDifferentValues)
  448. {
  449. EditorGUILayout.HelpBox("Cannot multi edit stack of multiple cameras.", MessageType.Info);
  450. EditorGUILayout.EndFoldoutHeaderGroup();
  451. return;
  452. }
  453. ScriptableRenderer.RenderingFeatures supportedRenderingFeatures = m_AdditionalCameraDatas[target]?.scriptableRenderer?.supportedRenderingFeatures;
  454. if (supportedRenderingFeatures != null && supportedRenderingFeatures.cameraStacking == false)
  455. {
  456. EditorGUILayout.HelpBox("The renderer used by this camera doesn't support camera stacking. Only Base camera will render.", MessageType.Warning);
  457. return;
  458. }
  459. if (m_StackSettingsFoldout.value)
  460. {
  461. m_LayerList.DoLayoutList();
  462. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  463. if (errorCameras.Any())
  464. {
  465. string errorString = "These cameras are not of a valid type:\n";
  466. string validCameras = "";
  467. foreach (var errorCamera in errorCameras)
  468. {
  469. errorString += errorCamera.name + "\n";
  470. }
  471. foreach (var validCameraType in validCameraTypes)
  472. {
  473. validCameras += validCameraType + " ";
  474. }
  475. errorString += "Valid types are " + validCameras;
  476. EditorGUILayout.HelpBox(errorString, MessageType.Warning);
  477. }
  478. EditorGUILayout.Space();
  479. EditorGUILayout.Space();
  480. }
  481. EditorGUILayout.EndFoldoutHeaderGroup();
  482. }
  483. void DrawEnvironmentSettings(CameraRenderType camType)
  484. {
  485. m_EnvironmentSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_EnvironmentSettingsFoldout.value, Styles.environmentSettingsText);
  486. if (m_EnvironmentSettingsFoldout.value)
  487. {
  488. if (camType == CameraRenderType.Base)
  489. {
  490. DrawClearFlags();
  491. if (!settings.clearFlags.hasMultipleDifferentValues)
  492. {
  493. if (GetBackgroundType((CameraClearFlags)settings.clearFlags.intValue) == BackgroundType.SolidColor)
  494. {
  495. using (var group = new EditorGUILayout.FadeGroupScope(m_ShowBGColorAnim.faded))
  496. {
  497. if (group.visible)
  498. {
  499. settings.DrawBackgroundColor();
  500. }
  501. }
  502. }
  503. }
  504. }
  505. DrawVolumes();
  506. EditorGUILayout.Space();
  507. EditorGUILayout.Space();
  508. }
  509. EditorGUILayout.EndFoldoutHeaderGroup();
  510. }
  511. void DrawRenderingSettings(CameraRenderType camType, UniversalRenderPipelineAsset rpAsset)
  512. {
  513. m_RenderingSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_RenderingSettingsFoldout.value, Styles.renderingSettingsText);
  514. if (m_RenderingSettingsFoldout.value)
  515. {
  516. DrawRenderer(rpAsset);
  517. if (camType == CameraRenderType.Base)
  518. {
  519. DrawPostProcessing();
  520. }
  521. else if (camType == CameraRenderType.Overlay)
  522. {
  523. DrawPostProcessingOverlay();
  524. EditorGUILayout.PropertyField(m_AdditionalCameraClearDepth, Styles.clearDepth);
  525. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  526. }
  527. DrawRenderShadows();
  528. if (camType == CameraRenderType.Base)
  529. {
  530. DrawPriority();
  531. DrawOpaqueTexture();
  532. DrawDepthTexture();
  533. }
  534. settings.DrawCullingMask();
  535. settings.DrawOcclusionCulling();
  536. EditorGUILayout.Space();
  537. EditorGUILayout.Space();
  538. }
  539. EditorGUILayout.EndFoldoutHeaderGroup();
  540. }
  541. void DrawPostProcessingOverlay()
  542. {
  543. EditorGUILayout.PropertyField(m_AdditionalCameraDataRenderPostProcessing, Styles.renderPostProcessing);
  544. }
  545. void DrawOutputSettings(UniversalRenderPipelineAsset rpAsset)
  546. {
  547. m_OutputSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_OutputSettingsFoldout.value, Styles.outputSettingsText);
  548. if (m_OutputSettingsFoldout.value)
  549. {
  550. DrawTargetTexture(rpAsset);
  551. if (camera.targetTexture == null)
  552. {
  553. DrawHDR();
  554. DrawMSAA();
  555. settings.DrawNormalizedViewPort();
  556. settings.DrawDynamicResolution();
  557. settings.DrawMultiDisplay();
  558. }
  559. else
  560. {
  561. settings.DrawNormalizedViewPort();
  562. }
  563. #if ENABLE_VR && ENABLE_XR_MODULE
  564. DrawXRRendering();
  565. #endif
  566. EditorGUILayout.Space();
  567. EditorGUILayout.Space();
  568. }
  569. EditorGUILayout.EndFoldoutHeaderGroup();
  570. }
  571. void DrawCameraType()
  572. {
  573. EditorGUI.BeginChangeCheck();
  574. EditorGUILayout.PropertyField(m_AdditionalCameraDataCameraTypeProp, Styles.cameraType);
  575. if (EditorGUI.EndChangeCheck())
  576. {
  577. UpdateCameras();
  578. // ScriptableRenderContext.SetupCameraProperties still depends on camera target texture
  579. // In order for overlay camera not to override base camera target texture we null it here
  580. CameraRenderType camType = (CameraRenderType)m_AdditionalCameraDataCameraTypeProp.intValue;
  581. if (camType == CameraRenderType.Overlay && settings.targetTexture.objectReferenceValue != null)
  582. settings.targetTexture.objectReferenceValue = null;
  583. }
  584. }
  585. void DrawClearFlags()
  586. {
  587. // Converts between ClearFlags and Background Type.
  588. BackgroundType backgroundType = GetBackgroundType((CameraClearFlags) settings.clearFlags.intValue);
  589. EditorGUI.showMixedValue = settings.clearFlags.hasMultipleDifferentValues;
  590. EditorGUI.BeginChangeCheck();
  591. Rect controlRect = EditorGUILayout.GetControlRect(true);
  592. EditorGUI.BeginProperty(controlRect, Styles.backgroundType, settings.clearFlags);
  593. BackgroundType selectedType = (BackgroundType)EditorGUI.IntPopup(controlRect, Styles.backgroundType, (int)backgroundType,
  594. Styles.cameraBackgroundType, Styles.cameraBackgroundValues);
  595. EditorGUI.EndProperty();
  596. if (EditorGUI.EndChangeCheck())
  597. {
  598. CameraClearFlags selectedClearFlags;
  599. switch (selectedType)
  600. {
  601. case BackgroundType.Skybox:
  602. selectedClearFlags = CameraClearFlags.Skybox;
  603. break;
  604. case BackgroundType.DontCare:
  605. selectedClearFlags = CameraClearFlags.Nothing;
  606. break;
  607. default:
  608. selectedClearFlags = CameraClearFlags.SolidColor;
  609. break;
  610. }
  611. settings.clearFlags.intValue = (int) selectedClearFlags;
  612. }
  613. }
  614. void DrawPriority()
  615. {
  616. EditorGUILayout.PropertyField(settings.depth, Styles.priority);
  617. }
  618. void DrawHDR()
  619. {
  620. Rect controlRect = EditorGUILayout.GetControlRect(true);
  621. EditorGUI.BeginProperty(controlRect, Styles.allowHDR, settings.HDR);
  622. int selectedValue = !settings.HDR.boolValue ? 0 : 1;
  623. settings.HDR.boolValue = EditorGUI.IntPopup(controlRect, Styles.allowHDR, selectedValue, Styles.displayedCameraOptions, Styles.cameraOptions) == 1;
  624. EditorGUI.EndProperty();
  625. }
  626. void DrawMSAA()
  627. {
  628. Rect controlRect = EditorGUILayout.GetControlRect(true);
  629. EditorGUI.BeginProperty(controlRect, Styles.allowMSAA, settings.allowMSAA);
  630. int selectedValue = !settings.allowMSAA.boolValue ? 0 : 1;
  631. settings.allowMSAA.boolValue = EditorGUI.IntPopup(controlRect, Styles.allowMSAA, selectedValue, Styles.displayedCameraOptions, Styles.cameraOptions) == 1;
  632. EditorGUI.EndProperty();
  633. }
  634. #if ENABLE_VR && ENABLE_XR_MODULE
  635. void DrawXRRendering()
  636. {
  637. Rect controlRect = EditorGUILayout.GetControlRect(true);
  638. EditorGUI.BeginProperty(controlRect, Styles.xrTargetEye, m_AdditionalCameraDataAllowXRRendering);
  639. int selectedValue = !m_AdditionalCameraDataAllowXRRendering.boolValue ? 0 : 1;
  640. m_AdditionalCameraDataAllowXRRendering.boolValue = EditorGUI.IntPopup(controlRect, Styles.xrTargetEye, selectedValue, Styles.xrTargetEyeOptions, Styles.xrTargetEyeValues) == 1;
  641. EditorGUI.EndProperty();
  642. }
  643. #endif
  644. void DrawTargetTexture(UniversalRenderPipelineAsset rpAsset)
  645. {
  646. EditorGUILayout.PropertyField(settings.targetTexture, Styles.targetTextureLabel);
  647. if (!settings.targetTexture.hasMultipleDifferentValues && rpAsset != null)
  648. {
  649. var texture = settings.targetTexture.objectReferenceValue as RenderTexture;
  650. int pipelineSamplesCount = rpAsset.msaaSampleCount;
  651. if (texture && texture.antiAliasing > pipelineSamplesCount)
  652. {
  653. string pipelineMSAACaps = (pipelineSamplesCount > 1)
  654. ? String.Format("is set to support {0}x", pipelineSamplesCount)
  655. : "has MSAA disabled";
  656. EditorGUILayout.HelpBox(String.Format("Camera target texture requires {0}x MSAA. Universal pipeline {1}.", texture.antiAliasing, pipelineMSAACaps),
  657. MessageType.Warning, true);
  658. }
  659. }
  660. }
  661. void DrawVolumes()
  662. {
  663. // Display the Volume Update mode, LayerMask and Trigger
  664. LayerMask selectedVolumeLayerMask = m_AdditionalCameraDataVolumeLayerMask.intValue;
  665. Transform selectedVolumeTrigger = (Transform)m_AdditionalCameraDataVolumeTrigger.objectReferenceValue;
  666. EditorGUILayout.LabelField(Styles.volumesSettingsText, EditorStyles.boldLabel);
  667. EditorGUI.indentLevel++;
  668. EditorGUI.BeginChangeCheck();
  669. DrawLayerMask(m_AdditionalCameraDataVolumeLayerMask, ref selectedVolumeLayerMask, Styles.volumeLayerMask);
  670. DrawObjectField(m_AdditionalCameraDataVolumeTrigger, ref selectedVolumeTrigger, Styles.volumeTrigger);
  671. EditorGUILayout.PropertyField(m_AdditionalCameraDataVolumeFrameworkUpdateMode, Styles.volumeUpdates);
  672. if (EditorGUI.EndChangeCheck())
  673. {
  674. m_AdditionalCameraDataVolumeLayerMask.intValue = selectedVolumeLayerMask;
  675. m_AdditionalCameraDataVolumeTrigger.objectReferenceValue = selectedVolumeTrigger;
  676. VolumeFrameworkUpdateMode curVolumeUpdateMode = (VolumeFrameworkUpdateMode)m_AdditionalCameraDataVolumeFrameworkUpdateMode.intValue;
  677. camera.SetVolumeFrameworkUpdateMode(curVolumeUpdateMode);
  678. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  679. }
  680. EditorGUI.indentLevel--;
  681. }
  682. void DrawRenderer(UniversalRenderPipelineAsset rpAsset)
  683. {
  684. int selectedRendererOption = m_AdditionalCameraDataRendererProp.intValue;
  685. EditorGUI.BeginChangeCheck();
  686. Rect controlRect = EditorGUILayout.GetControlRect(true);
  687. EditorGUI.BeginProperty(controlRect, Styles.rendererType, m_AdditionalCameraDataRendererProp);
  688. EditorGUI.showMixedValue = m_AdditionalCameraDataRendererProp.hasMultipleDifferentValues;
  689. int selectedRenderer = EditorGUI.IntPopup(controlRect, Styles.rendererType, selectedRendererOption, rpAsset.rendererDisplayList, UniversalRenderPipeline.asset.rendererIndexList);
  690. EditorGUI.EndProperty();
  691. if (!rpAsset.ValidateRendererDataList())
  692. {
  693. EditorGUILayout.HelpBox(Styles.noRendererError, MessageType.Error);
  694. }
  695. else if (!rpAsset.ValidateRendererData(selectedRendererOption))
  696. {
  697. EditorGUILayout.HelpBox(Styles.missingRendererWarning, MessageType.Warning);
  698. var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect());
  699. if (GUI.Button(rect, "Select Render Pipeline Asset"))
  700. {
  701. Selection.activeObject = AssetDatabase.LoadAssetAtPath<UniversalRenderPipelineAsset>(AssetDatabase.GetAssetPath(UniversalRenderPipeline.asset));
  702. }
  703. GUILayout.Space(5);
  704. }
  705. if (EditorGUI.EndChangeCheck())
  706. {
  707. m_AdditionalCameraDataRendererProp.intValue = selectedRenderer;
  708. m_AdditionalCameraDataSO.ApplyModifiedProperties();
  709. }
  710. }
  711. void DrawPostProcessing()
  712. {
  713. EditorGUILayout.PropertyField(m_AdditionalCameraDataRenderPostProcessing, Styles.renderPostProcessing);
  714. // Draw Final Post-processing
  715. DrawIntPopup(m_AdditionalCameraDataAntialiasing, Styles.antialiasing, Styles.antialiasingOptions, Styles.antialiasingValues);
  716. // If AntiAliasing has mixed value we do not draw the sub menu
  717. if (m_AdditionalCameraDataAntialiasing.hasMultipleDifferentValues)
  718. {
  719. return;
  720. }
  721. var selectedAntialiasing = (AntialiasingMode)m_AdditionalCameraDataAntialiasing.intValue;
  722. if (selectedAntialiasing == AntialiasingMode.SubpixelMorphologicalAntiAliasing)
  723. {
  724. EditorGUI.indentLevel++;
  725. EditorGUILayout.PropertyField(m_AdditionalCameraDataAntialiasingQuality, Styles.antialiasingQuality);
  726. if (CoreEditorUtils.buildTargets.Contains(GraphicsDeviceType.OpenGLES2))
  727. EditorGUILayout.HelpBox("Sub-pixel Morphological Anti-Aliasing isn't supported on GLES2 platforms.", MessageType.Warning);
  728. EditorGUI.indentLevel--;
  729. }
  730. EditorGUILayout.PropertyField(m_AdditionalCameraDataStopNaN, Styles.stopNaN);
  731. EditorGUILayout.PropertyField(m_AdditionalCameraDataDithering, Styles.dithering);
  732. }
  733. bool DrawLayerMask(SerializedProperty prop, ref LayerMask mask, GUIContent style)
  734. {
  735. var layers = InternalEditorUtility.layers;
  736. bool hasChanged = false;
  737. var controlRect = BeginProperty(prop, style);
  738. EditorGUI.BeginChangeCheck();
  739. // LayerMask needs to be converted to be used in a MaskField...
  740. int field = 0;
  741. for (int c = 0; c < layers.Length; c++)
  742. if ((mask & (1 << LayerMask.NameToLayer(layers[c]))) != 0)
  743. field |= 1 << c;
  744. field = EditorGUI.MaskField(controlRect, style, field, InternalEditorUtility.layers);
  745. if (EditorGUI.EndChangeCheck())
  746. hasChanged = true;
  747. // ...and converted back.
  748. mask = 0;
  749. for (int c = 0; c < layers.Length; c++)
  750. if ((field & (1 << c)) != 0)
  751. mask |= 1 << LayerMask.NameToLayer(layers[c]);
  752. EndProperty();
  753. return hasChanged;
  754. }
  755. bool DrawObjectField<T>(SerializedProperty prop, ref T value, GUIContent style)
  756. where T : Object
  757. {
  758. var defaultVal = value;
  759. bool hasChanged = false;
  760. var controlRect = BeginProperty(prop, style);
  761. EditorGUI.BeginChangeCheck();
  762. value = (T)EditorGUI.ObjectField(controlRect, style, value, typeof(T), true);
  763. if (EditorGUI.EndChangeCheck() && !Equals(defaultVal, value))
  764. {
  765. hasChanged = true;
  766. }
  767. EndProperty();
  768. return hasChanged;
  769. }
  770. void DrawDepthTexture()
  771. {
  772. EditorGUILayout.PropertyField(m_AdditionalCameraDataRenderDepthProp, Styles.requireDepthTexture);
  773. }
  774. void DrawOpaqueTexture()
  775. {
  776. EditorGUILayout.PropertyField(m_AdditionalCameraDataRenderOpaqueProp, Styles.requireOpaqueTexture);
  777. }
  778. void DrawIntPopup(SerializedProperty prop, GUIContent style, GUIContent[] optionNames, int[] optionValues)
  779. {
  780. var controlRect = BeginProperty(prop, style);
  781. EditorGUI.BeginChangeCheck();
  782. var value = EditorGUI.IntPopup(controlRect, style, prop.intValue, optionNames, optionValues);
  783. if (EditorGUI.EndChangeCheck())
  784. {
  785. prop.intValue = value;
  786. }
  787. EndProperty();
  788. }
  789. Rect BeginProperty(SerializedProperty prop, GUIContent style)
  790. {
  791. var controlRect = EditorGUILayout.GetControlRect(true);
  792. EditorGUI.BeginProperty(controlRect, style, prop);
  793. return controlRect;
  794. }
  795. void DrawRenderShadows()
  796. {
  797. EditorGUILayout.PropertyField(m_AdditionalCameraDataRenderShadowsProp, Styles.renderingShadows);
  798. }
  799. void EndProperty()
  800. {
  801. if (m_AdditionalCameraDataSO != null)
  802. EditorGUI.EndProperty();
  803. }
  804. }
  805. [ScriptableRenderPipelineExtension(typeof(UniversalRenderPipelineAsset))]
  806. class UniversalRenderPipelineCameraContextualMenu : IRemoveAdditionalDataContextualMenu<Camera>
  807. {
  808. //The call is delayed to the dispatcher to solve conflict with other SRP
  809. public void RemoveComponent(Camera camera, IEnumerable<Component> dependencies)
  810. {
  811. // do not use keyword is to remove the additional data. It will not work
  812. dependencies = dependencies.Where(c => c.GetType() != typeof(UniversalAdditionalCameraData));
  813. if (dependencies.Any())
  814. {
  815. EditorUtility.DisplayDialog("Can't remove component", $"Can't remove Camera because {dependencies.First().GetType().Name} depends on it.", "Ok");
  816. return;
  817. }
  818. var isAssetEditing = EditorUtility.IsPersistent(camera);
  819. try
  820. {
  821. if (isAssetEditing)
  822. {
  823. AssetDatabase.StartAssetEditing();
  824. }
  825. Undo.SetCurrentGroupName("Remove Universal Camera");
  826. var additionalCameraData = camera.GetComponent<UniversalAdditionalCameraData>();
  827. if (additionalCameraData != null)
  828. {
  829. Undo.DestroyObjectImmediate(additionalCameraData);
  830. }
  831. Undo.DestroyObjectImmediate(camera);
  832. }
  833. finally
  834. {
  835. if (isAssetEditing)
  836. {
  837. AssetDatabase.StopAssetEditing();
  838. }
  839. }
  840. }
  841. }
  842. }