Açıklama Yok
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.

VolumeProfile.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine.Assertions;
  5. namespace UnityEngine.Rendering
  6. {
  7. /// <summary>
  8. /// An Asset which holds a set of settings to use with a <see cref="Volume"/>.
  9. /// </summary>
  10. [CurrentPipelineHelpURL("Volume-Profile")]
  11. [Icon("Packages/com.unity.render-pipelines.core/Editor/Icons/Processed/VolumeProfile Icon.asset")]
  12. public sealed class VolumeProfile : ScriptableObject
  13. {
  14. /// <summary>
  15. /// A list of every setting that this Volume Profile stores.
  16. /// </summary>
  17. public List<VolumeComponent> components = new List<VolumeComponent>();
  18. /// <summary>
  19. /// **Note**: For Internal Use Only<br/>
  20. /// A dirty check used to redraw the profile inspector when something has changed. This is
  21. /// currently only used in the editor.
  22. /// </summary>
  23. [NonSerialized]
  24. public bool isDirty = true; // Editor only, doesn't have any use outside of it
  25. void OnEnable()
  26. {
  27. // Make sure every setting is valid. If a profile holds a script that doesn't exist
  28. // anymore, nuke it to keep the volume clean. Note that if you delete a script that is
  29. // currently in use in a volume you'll still get a one-time error in the console, it's
  30. // harmless and happens because Unity does a redraw of the editor (and thus the current
  31. // frame) before the recompilation step.
  32. components.RemoveAll(x => x == null);
  33. }
  34. // The lifetime of ScriptableObjects is different from MonoBehaviours. When the last reference to a
  35. // VolumeProfile goes out of scope (e.g. when a scene containing Volume components is unloaded), Unity will call
  36. // OnDisable() on the VolumeProfile. We need to release the internal resources in this case to avoid leaks.
  37. internal void OnDisable()
  38. {
  39. if (components == null)
  40. return;
  41. for (int i = 0; i < components.Count; i++)
  42. {
  43. if (components[i] != null)
  44. components[i].Release();
  45. }
  46. }
  47. /// <summary>
  48. /// Resets the dirty state of the Volume Profile. Unity uses this to force-refresh and redraw the
  49. /// Volume Profile editor when you modify the Asset via script instead of the Inspector.
  50. /// </summary>
  51. public void Reset()
  52. {
  53. isDirty = true;
  54. }
  55. /// <summary>
  56. /// Adds a <see cref="VolumeComponent"/> to this Volume Profile.
  57. /// </summary>
  58. /// <remarks>
  59. /// You can only have a single component of the same type per Volume Profile.
  60. /// </remarks>
  61. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  62. /// <param name="overrides">Specifies whether Unity should automatically override all the settings when
  63. /// you add a <see cref="VolumeComponent"/> to the Volume Profile.</param>
  64. /// <returns>The instance for the given type that you added to the Volume Profile</returns>
  65. /// <seealso cref="Add"/>
  66. public T Add<T>(bool overrides = false)
  67. where T : VolumeComponent
  68. {
  69. return (T)Add(typeof(T), overrides);
  70. }
  71. /// <summary>
  72. /// Adds a <see cref="VolumeComponent"/> to this Volume Profile.
  73. /// </summary>
  74. /// <remarks>
  75. /// You can only have a single component of the same type per Volume Profile.
  76. /// </remarks>
  77. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  78. /// <param name="overrides">Specifies whether Unity should automatically override all the settings when
  79. /// you add a <see cref="VolumeComponent"/> to the Volume Profile.</param>
  80. /// <returns>The instance created for the given type that has been added to the profile</returns>
  81. /// <seealso cref="Add{T}"/>
  82. public VolumeComponent Add(Type type, bool overrides = false)
  83. {
  84. if (Has(type))
  85. throw new InvalidOperationException("Component already exists in the volume");
  86. var component = (VolumeComponent)CreateInstance(type);
  87. #if UNITY_EDITOR
  88. component.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy;
  89. component.name = type.Name;
  90. #endif
  91. component.SetAllOverridesTo(overrides);
  92. components.Add(component);
  93. isDirty = true;
  94. return component;
  95. }
  96. /// <summary>
  97. /// Removes a <see cref="VolumeComponent"/> from this Volume Profile.
  98. /// </summary>
  99. /// <remarks>
  100. /// This method does nothing if the type does not exist in the Volume Profile.
  101. /// </remarks>
  102. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  103. /// <seealso cref="Remove"/>
  104. public void Remove<T>()
  105. where T : VolumeComponent
  106. {
  107. Remove(typeof(T));
  108. }
  109. /// <summary>
  110. /// Removes a <see cref="VolumeComponent"/> from this Volume Profile.
  111. /// </summary>
  112. /// <remarks>
  113. /// This method does nothing if the type does not exist in the Volume Profile.
  114. /// </remarks>
  115. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  116. /// <seealso cref="Remove{T}"/>
  117. public void Remove(Type type)
  118. {
  119. int toRemove = -1;
  120. for (int i = 0; i < components.Count; i++)
  121. {
  122. if (components[i].GetType() == type)
  123. {
  124. toRemove = i;
  125. break;
  126. }
  127. }
  128. if (toRemove >= 0)
  129. {
  130. components.RemoveAt(toRemove);
  131. isDirty = true;
  132. }
  133. }
  134. /// <summary>
  135. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/> you pass in.
  136. /// </summary>
  137. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  138. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  139. /// <c>false</c> otherwise.</returns>
  140. /// <seealso cref="Has"/>
  141. /// <seealso cref="HasSubclassOf"/>
  142. public bool Has<T>()
  143. where T : VolumeComponent
  144. {
  145. return Has(typeof(T));
  146. }
  147. /// <summary>
  148. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/> you pass in.
  149. /// </summary>
  150. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  151. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  152. /// <c>false</c> otherwise.</returns>
  153. /// <seealso cref="Has{T}"/>
  154. /// <seealso cref="HasSubclassOf"/>
  155. public bool Has(Type type)
  156. {
  157. foreach (var component in components)
  158. {
  159. if (component.GetType() == type)
  160. return true;
  161. }
  162. return false;
  163. }
  164. /// <summary>
  165. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/>, which is a subclass of <paramref name="type"/>,
  166. /// that you pass in.
  167. /// </summary>
  168. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  169. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  170. /// <c>false</c> otherwise.</returns>
  171. /// <seealso cref="Has"/>
  172. /// <seealso cref="Has{T}"/>
  173. public bool HasSubclassOf(Type type)
  174. {
  175. foreach (var component in components)
  176. {
  177. if (component.GetType().IsSubclassOf(type))
  178. return true;
  179. }
  180. return false;
  181. }
  182. /// <summary>
  183. /// Gets the <see cref="VolumeComponent"/> of the specified type, if it exists.
  184. /// </summary>
  185. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  186. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  187. /// or <c>null</c>.</param>
  188. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  189. /// <c>false</c> otherwise.</returns>
  190. /// <seealso cref="TryGet{T}(Type, out T)"/>
  191. /// <seealso cref="TryGetSubclassOf{T}"/>
  192. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  193. public bool TryGet<T>(out T component)
  194. where T : VolumeComponent
  195. {
  196. return TryGet(typeof(T), out component);
  197. }
  198. /// <summary>
  199. /// Gets the <see cref="VolumeComponent"/> of the specified type, if it exists.
  200. /// </summary>
  201. /// <typeparam name="T">A type of <see cref="VolumeComponent"/></typeparam>
  202. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  203. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  204. /// or <c>null</c>.</param>
  205. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  206. /// <c>false</c> otherwise.</returns>
  207. /// <seealso cref="TryGet{T}(out T)"/>
  208. /// <seealso cref="TryGetSubclassOf{T}"/>
  209. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  210. public bool TryGet<T>(Type type, out T component)
  211. where T : VolumeComponent
  212. {
  213. component = null;
  214. foreach (var comp in components)
  215. {
  216. if (comp.GetType() == type)
  217. {
  218. component = (T)comp;
  219. return true;
  220. }
  221. }
  222. return false;
  223. }
  224. /// <summary>
  225. /// Gets the <see cref="VolumeComponent"/>, which is a subclass of <paramref name="type"/>, if
  226. /// it exists.
  227. /// </summary>
  228. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  229. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  230. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  231. /// or <c>null</c>.</param>
  232. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  233. /// <c>false</c> otherwise.</returns>
  234. /// <seealso cref="TryGet{T}(Type, out T)"/>
  235. /// <seealso cref="TryGet{T}(out T)"/>
  236. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  237. public bool TryGetSubclassOf<T>(Type type, out T component)
  238. where T : VolumeComponent
  239. {
  240. component = null;
  241. foreach (var comp in components)
  242. {
  243. if (comp.GetType().IsSubclassOf(type))
  244. {
  245. component = (T)comp;
  246. return true;
  247. }
  248. }
  249. return false;
  250. }
  251. /// <summary>
  252. /// Gets all the <see cref="VolumeComponent"/> that are subclasses of the specified type,
  253. /// if there are any.
  254. /// </summary>
  255. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  256. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  257. /// <param name="result">The output list that contains all the <see cref="VolumeComponent"/>
  258. /// if any. Note that Unity does not clear this list.</param>
  259. /// <returns><c>true</c> if any <see cref="VolumeComponent"/> have been found in the profile,
  260. /// <c>false</c> otherwise.</returns>
  261. /// <seealso cref="TryGet{T}(Type, out T)"/>
  262. /// <seealso cref="TryGet{T}(out T)"/>
  263. /// <seealso cref="TryGetSubclassOf{T}"/>
  264. public bool TryGetAllSubclassOf<T>(Type type, List<T> result)
  265. where T : VolumeComponent
  266. {
  267. Assert.IsNotNull(components);
  268. int count = result.Count;
  269. foreach (var comp in components)
  270. {
  271. if (comp.GetType().IsSubclassOf(type))
  272. result.Add((T)comp);
  273. }
  274. return count != result.Count;
  275. }
  276. /// <summary>
  277. /// A custom hashing function that Unity uses to compare the state of parameters.
  278. /// </summary>
  279. /// <returns>A computed hash code for the current instance.</returns>
  280. public override int GetHashCode()
  281. {
  282. unchecked
  283. {
  284. int hash = 17;
  285. for (int i = 0; i < components.Count; i++)
  286. hash = hash * 23 + components[i].GetHashCode();
  287. return hash;
  288. }
  289. }
  290. internal int GetComponentListHashCode()
  291. {
  292. unchecked
  293. {
  294. int hash = 17;
  295. for (int i = 0; i < components.Count; i++)
  296. hash = hash * 23 + components[i].GetType().GetHashCode();
  297. return hash;
  298. }
  299. }
  300. /// <summary>
  301. /// Removes any components that were destroyed externally from the iternal list of components
  302. /// </summary>
  303. internal void Sanitize()
  304. {
  305. for (int i = components.Count - 1; i >= 0; i--)
  306. if (components[i] == null)
  307. components.RemoveAt(i);
  308. }
  309. #if UNITY_EDITOR
  310. void OnValidate()
  311. {
  312. // Delay the callback because when undoing the deletion of a VolumeComponent from a profile,
  313. // it's possible VolumeComponent.OnEnable() has not yet been called, resulting in a crash when trying to
  314. // update the default state.
  315. EditorApplication.delayCall += () =>
  316. {
  317. if (VolumeManager.instance.isInitialized)
  318. VolumeManager.instance.OnVolumeProfileChanged(this);
  319. };
  320. }
  321. #endif
  322. }
  323. }