VolumeProfile.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine.Assertions;
  4. namespace UnityEngine.Rendering
  5. {
  6. /// <summary>
  7. /// An Asset which holds a set of settings to use with a <see cref="Volume"/>.
  8. /// </summary>
  9. [HelpURL(Documentation.baseURLHDRP + Documentation.version + Documentation.subURL + "Volume-Profile" + Documentation.endURL)]
  10. public sealed class VolumeProfile : ScriptableObject
  11. {
  12. /// <summary>
  13. /// A list of every setting that this Volume Profile stores.
  14. /// </summary>
  15. public List<VolumeComponent> components = new List<VolumeComponent>();
  16. /// <summary>
  17. /// A dirty check used to redraw the profile inspector when something has changed. This is
  18. /// currently only used in the editor.
  19. /// </summary>
  20. [NonSerialized]
  21. public bool isDirty = true; // Editor only, doesn't have any use outside of it
  22. void OnEnable()
  23. {
  24. // Make sure every setting is valid. If a profile holds a script that doesn't exist
  25. // anymore, nuke it to keep the volume clean. Note that if you delete a script that is
  26. // currently in use in a volume you'll still get a one-time error in the console, it's
  27. // harmless and happens because Unity does a redraw of the editor (and thus the current
  28. // frame) before the recompilation step.
  29. components.RemoveAll(x => x == null);
  30. }
  31. /// <summary>
  32. /// Resets the dirty state of the Volume Profile. Unity uses this to force-refresh and redraw the
  33. /// Volume Profile editor when you modify the Asset via script instead of the Inspector.
  34. /// </summary>
  35. public void Reset()
  36. {
  37. isDirty = true;
  38. }
  39. /// <summary>
  40. /// Adds a <see cref="VolumeComponent"/> to this Volume Profile.
  41. /// </summary>
  42. /// <remarks>
  43. /// You can only have a single component of the same type per Volume Profile.
  44. /// </remarks>
  45. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  46. /// <param name="overrides">Specifies whether Unity should automatically override all the settings when
  47. /// you add a <see cref="VolumeComponent"/> to the Volume Profile.</param>
  48. /// <returns>The instance for the given type that you added to the Volume Profile</returns>
  49. /// <seealso cref="Add"/>
  50. public T Add<T>(bool overrides = false)
  51. where T : VolumeComponent
  52. {
  53. return (T)Add(typeof(T), overrides);
  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. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  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 created for the given type that has been added to the profile</returns>
  65. /// <see cref="Add{T}"/>
  66. public VolumeComponent Add(Type type, bool overrides = false)
  67. {
  68. if (Has(type))
  69. throw new InvalidOperationException("Component already exists in the volume");
  70. var component = (VolumeComponent)CreateInstance(type);
  71. component.SetAllOverridesTo(overrides);
  72. components.Add(component);
  73. isDirty = true;
  74. return component;
  75. }
  76. /// <summary>
  77. /// Removes a <see cref="VolumeComponent"/> from this Volume Profile.
  78. /// </summary>
  79. /// <remarks>
  80. /// This method does nothing if the type does not exist in the Volume Profile.
  81. /// </remarks>
  82. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  83. /// <seealso cref="Remove"/>
  84. public void Remove<T>()
  85. where T : VolumeComponent
  86. {
  87. Remove(typeof(T));
  88. }
  89. /// <summary>
  90. /// Removes a <see cref="VolumeComponent"/> from this Volume Profile.
  91. /// </summary>
  92. /// <remarks>
  93. /// This method does nothing if the type does not exist in the Volume Profile.
  94. /// </remarks>
  95. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  96. /// <seealso cref="Remove{T}"/>
  97. public void Remove(Type type)
  98. {
  99. int toRemove = -1;
  100. for (int i = 0; i < components.Count; i++)
  101. {
  102. if (components[i].GetType() == type)
  103. {
  104. toRemove = i;
  105. break;
  106. }
  107. }
  108. if (toRemove >= 0)
  109. {
  110. components.RemoveAt(toRemove);
  111. isDirty = true;
  112. }
  113. }
  114. /// <summary>
  115. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/> you pass in.
  116. /// </summary>
  117. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  118. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  119. /// <c>false</c> otherwise.</returns>
  120. /// <seealso cref="Has"/>
  121. /// <seealso cref="HasSubclassOf"/>
  122. public bool Has<T>()
  123. where T : VolumeComponent
  124. {
  125. return Has(typeof(T));
  126. }
  127. /// <summary>
  128. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/> you pass in.
  129. /// </summary>
  130. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  131. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  132. /// <c>false</c> otherwise.</returns>
  133. /// <seealso cref="Has{T}"/>
  134. /// <seealso cref="HasSubclassOf"/>
  135. public bool Has(Type type)
  136. {
  137. foreach (var component in components)
  138. {
  139. if (component.GetType() == type)
  140. return true;
  141. }
  142. return false;
  143. }
  144. /// <summary>
  145. /// Checks if this Volume Profile contains the <see cref="VolumeComponent"/>, which is a subclass of <paramref name="type"/>,
  146. /// that you pass in.
  147. /// </summary>
  148. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  149. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> exists in the Volume Profile,
  150. /// <c>false</c> otherwise.</returns>
  151. /// <seealso cref="Has"/>
  152. /// <seealso cref="Has{T}"/>
  153. public bool HasSubclassOf(Type type)
  154. {
  155. foreach (var component in components)
  156. {
  157. if (component.GetType().IsSubclassOf(type))
  158. return true;
  159. }
  160. return false;
  161. }
  162. /// <summary>
  163. /// Gets the <see cref="VolumeComponent"/> of the specified type, if it exists.
  164. /// </summary>
  165. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  166. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  167. /// or <c>null</c>.</param>
  168. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  169. /// <c>false</c> otherwise.</returns>
  170. /// <seealso cref="TryGet{T}(Type, out T)"/>
  171. /// <seealso cref="TryGetSubclassOf{T}"/>
  172. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  173. public bool TryGet<T>(out T component)
  174. where T : VolumeComponent
  175. {
  176. return TryGet(typeof(T), out component);
  177. }
  178. /// <summary>
  179. /// Gets the <see cref="VolumeComponent"/> of the specified type, if it exists.
  180. /// </summary>
  181. /// <typeparam name="T">A type of <see cref="VolumeComponent"/></typeparam>
  182. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  183. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  184. /// or <c>null</c>.</param>
  185. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  186. /// <c>false</c> otherwise.</returns>
  187. /// <seealso cref="TryGet{T}(out T)"/>
  188. /// <seealso cref="TryGetSubclassOf{T}"/>
  189. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  190. public bool TryGet<T>(Type type, out T component)
  191. where T : VolumeComponent
  192. {
  193. component = null;
  194. foreach (var comp in components)
  195. {
  196. if (comp.GetType() == type)
  197. {
  198. component = (T)comp;
  199. return true;
  200. }
  201. }
  202. return false;
  203. }
  204. /// <summary>
  205. /// Gets the <seealso cref="VolumeComponent"/>, which is a subclass of <paramref name="type"/>, if
  206. /// it exists.
  207. /// </summary>
  208. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  209. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  210. /// <param name="component">The output argument that contains the <see cref="VolumeComponent"/>
  211. /// or <c>null</c>.</param>
  212. /// <returns><c>true</c> if the <see cref="VolumeComponent"/> is in the Volume Profile,
  213. /// <c>false</c> otherwise.</returns>
  214. /// <seealso cref="TryGet{T}(Type, out T)"/>
  215. /// <seealso cref="TryGet{T}(out T)"/>
  216. /// <seealso cref="TryGetAllSubclassOf{T}"/>
  217. public bool TryGetSubclassOf<T>(Type type, out T component)
  218. where T : VolumeComponent
  219. {
  220. component = null;
  221. foreach (var comp in components)
  222. {
  223. if (comp.GetType().IsSubclassOf(type))
  224. {
  225. component = (T)comp;
  226. return true;
  227. }
  228. }
  229. return false;
  230. }
  231. /// <summary>
  232. /// Gets all the <seealso cref="VolumeComponent"/> that are subclasses of the specified type,
  233. /// if there are any.
  234. /// </summary>
  235. /// <typeparam name="T">A type of <see cref="VolumeComponent"/>.</typeparam>
  236. /// <param name="type">A type that inherits from <see cref="VolumeComponent"/>.</param>
  237. /// <param name="result">The output list that contains all the <seealso cref="VolumeComponent"/>
  238. /// if any. Note that Unity does not clear this list.</param>
  239. /// <returns><c>true</c> if any <see cref="VolumeComponent"/> have been found in the profile,
  240. /// <c>false</c> otherwise.</returns>
  241. /// <seealso cref="TryGet{T}(Type, out T)"/>
  242. /// <seealso cref="TryGet{T}(out T)"/>
  243. /// <seealso cref="TryGetSubclassOf{T}"/>
  244. public bool TryGetAllSubclassOf<T>(Type type, List<T> result)
  245. where T : VolumeComponent
  246. {
  247. Assert.IsNotNull(components);
  248. int count = result.Count;
  249. foreach (var comp in components)
  250. {
  251. if (comp.GetType().IsSubclassOf(type))
  252. result.Add((T)comp);
  253. }
  254. return count != result.Count;
  255. }
  256. }
  257. }