123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Reflection;
-
- namespace UnityEngine.Rendering
- {
- /// <summary>
- /// This attribute allows you to add commands to the <b>Add Override</b> popup menu
- /// on Volumes.
- /// To filter VolumeComponentMenu based on current Render Pipeline, add SupportedOnRenderPipeline attribute to the class alongside with this attribute.
- /// </summary>
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class VolumeComponentMenu : Attribute
- {
- /// <summary>
- /// The name of the entry in the override list. You can use slashes to create sub-menus.
- /// </summary>
- public readonly string menu;
-
- // TODO: Add support for component icons
-
- /// <summary>
- /// Creates a new <see cref="VolumeComponentMenu"/> instance.
- /// </summary>
- /// <param name="menu">The name of the entry in the override list. You can use slashes to
- /// create sub-menus.</param>
- public VolumeComponentMenu(string menu)
- {
- this.menu = menu;
- }
- }
-
- /// <summary>
- /// This attribute allows you to add commands to the <b>Add Override</b> popup menu
- /// on Volumes and specify for which render pipelines will be supported
- /// </summary>
- [Obsolete(@"VolumeComponentMenuForRenderPipelineAttribute is deprecated. Use VolumeComponentMenu with SupportedOnCurrentPipeline instead. #from(2023.1)", false)]
- public class VolumeComponentMenuForRenderPipeline : VolumeComponentMenu
- {
- /// <summary>
- /// The list of pipeline types that the target class supports
- /// </summary>
- public Type[] pipelineTypes { get; }
-
- /// <summary>
- /// Creates a new <see cref="VolumeComponentMenuForRenderPipeline"/> instance.
- /// </summary>
- /// <param name="menu">The name of the entry in the override list. You can use slashes to
- /// create sub-menus.</param>
- /// <param name="pipelineTypes">The list of pipeline types that the target class supports</param>
- public VolumeComponentMenuForRenderPipeline(string menu, params Type[] pipelineTypes)
- : base(menu)
- {
- if (pipelineTypes == null)
- throw new Exception("Specify a list of supported pipeline");
-
- // Make sure that we only allow the class types that inherit from the render pipeline
- foreach (var t in pipelineTypes)
- {
- if (!typeof(RenderPipeline).IsAssignableFrom(t))
- throw new Exception(
- $"You can only specify types that inherit from {typeof(RenderPipeline)}, please check {t}");
- }
-
- this.pipelineTypes = pipelineTypes;
- }
- }
-
-
- /// <summary>
- /// An attribute to hide the volume component to be added through `Add Override` button on the volume component list
- /// </summary>
- [AttributeUsage(AttributeTargets.Class)]
- [Obsolete("VolumeComponentDeprecated has been deprecated (UnityUpgradable) -> [UnityEngine] UnityEngine.HideInInspector", false)]
- public sealed class VolumeComponentDeprecated : Attribute
- {
- }
-
- /// <summary>
- /// The base class for all the components that can be part of a <see cref="VolumeProfile"/>.
- /// The Volume framework automatically handles and interpolates any <see cref="VolumeParameter"/> members found in this class.
- /// </summary>
- /// <example>
- /// <code>
- /// using UnityEngine.Rendering;
- ///
- /// [Serializable, VolumeComponentMenuForRenderPipeline("Custom/Example Component")]
- /// public class ExampleComponent : VolumeComponent
- /// {
- /// public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f);
- /// }
- /// </code>
- /// </example>
- [Serializable]
- public partial class VolumeComponent : ScriptableObject
- {
- /// <summary>
- /// Local attribute for VolumeComponent fields only.
- /// It handles relative indentation of a property for inspector.
- /// </summary>
- public sealed class Indent : PropertyAttribute
- {
- /// <summary> Relative indent amount registered in this attribute </summary>
- public readonly int relativeAmount;
-
- /// <summary> Constructor </summary>
- /// <param name="relativeAmount">Relative indent change to use</param>
- public Indent(int relativeAmount = 1)
- => this.relativeAmount = relativeAmount;
- }
-
- /// <summary>
- /// The active state of the set of parameters defined in this class. You can use this to
- /// quickly turn on or off all the overrides at once.
- /// </summary>
- public bool active = true;
-
- /// <summary>
- /// The name displayed in the component header. If you do not set a name, Unity generates one from
- /// the class name automatically.
- /// </summary>
- public string displayName { get; protected set; } = "";
-
- /// <summary>
- /// The backing storage of <see cref="parameters"/>. Use this for performance-critical work.
- /// </summary>
- internal readonly List<VolumeParameter> parameterList = new();
-
- ReadOnlyCollection<VolumeParameter> m_ParameterReadOnlyCollection;
- /// <summary>
- /// A read-only collection of all the <see cref="VolumeParameter"/>s defined in this class.
- /// </summary>
- public ReadOnlyCollection<VolumeParameter> parameters
- {
- get
- {
- if (m_ParameterReadOnlyCollection == null)
- m_ParameterReadOnlyCollection = parameterList.AsReadOnly();
- return m_ParameterReadOnlyCollection;
- }
- }
-
- /// <summary>
- /// Extracts all the <see cref="VolumeParameter"/>s defined in this class and nested classes.
- /// </summary>
- /// <param name="o">The object to find the parameters</param>
- /// <param name="parameters">The list filled with the parameters.</param>
- /// <param name="filter">If you want to filter the parameters</param>
- internal static void FindParameters(object o, List<VolumeParameter> parameters, Func<FieldInfo, bool> filter = null)
- {
- if (o == null)
- return;
-
- var fields = o.GetType()
- .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
- .OrderBy(t => t.MetadataToken); // Guaranteed order
-
- foreach (var field in fields)
- {
- if (field.FieldType.IsSubclassOf(typeof(VolumeParameter)))
- {
- if (filter?.Invoke(field) ?? true)
- {
- VolumeParameter volumeParameter = (VolumeParameter)field.GetValue(o);
- parameters.Add(volumeParameter);
- }
- }
- else if (!field.FieldType.IsArray && field.FieldType.IsClass)
- FindParameters(field.GetValue(o), parameters, filter);
- }
- }
-
- /// <summary>
- /// Unity calls this method when it loads the class.
- /// </summary>
- /// <remarks>
- /// If you want to override this method, you must call <c>base.OnEnable()</c>.
- /// </remarks>
- protected virtual void OnEnable()
- {
- // Automatically grab all fields of type VolumeParameter for this instance
- parameterList.Clear();
- FindParameters(this, parameterList);
-
- foreach (var parameter in parameterList)
- {
- if (parameter != null)
- parameter.OnEnable();
- else
- Debug.LogWarning("Volume Component " + GetType().Name + " contains a null parameter; please make sure all parameters are initialized to a default value. Until this is fixed the null parameters will not be considered by the system.");
- }
- }
-
- /// <summary>
- /// Unity calls this method when the object goes out of scope.
- /// </summary>
- protected virtual void OnDisable()
- {
- foreach (var parameter in parameterList)
- {
- if (parameter != null)
- parameter.OnDisable();
- }
- }
-
- /// <summary>
- /// Interpolates a <see cref="VolumeComponent"/> with this component by an interpolation
- /// factor and puts the result back into the given <see cref="VolumeComponent"/>.
- /// </summary>
- /// <remarks>
- /// You can override this method to do your own blending. Either loop through the
- /// <see cref="parameters"/> list or reference direct fields. You should only use
- /// <see cref="VolumeParameter.SetValue"/> to set parameter values and not assign
- /// directly to the state object. you should also manually check
- /// <see cref="VolumeParameter.overrideState"/> before you set any values.
- /// </remarks>
- /// <param name="state">The internal component to interpolate from. You must store
- /// the result of the interpolation in this same component.</param>
- /// <param name="interpFactor">The interpolation factor in range [0,1].</param>
- /// <example>
- /// <para> Below is the default implementation for blending:</para>
- /// <code>
- /// public virtual void Override(VolumeComponent state, float interpFactor)
- /// {
- /// int count = parameters.Count;
- ///
- /// for (int i = 0; i < count; i++)
- /// {
- /// var stateParam = state.parameters[i];
- /// var toParam = parameters[i];
- ///
- /// if (toParam.overrideState)
- /// {
- /// // Keep track of the override state to ensure that state will be reset on next frame (and for debugging purpose)
- /// stateParam.overrideState = toParam.overrideState;
- /// stateParam.Interp(stateParam, toParam, interpFactor);
- /// }
- /// }
- /// }
- /// </code>
- /// </example>
- public virtual void Override(VolumeComponent state, float interpFactor)
- {
- int count = parameterList.Count;
-
- for (int i = 0; i < count; i++)
- {
- var stateParam = state.parameterList[i];
- var toParam = parameterList[i];
-
- if (toParam.overrideState)
- {
- // Keep track of the override state to ensure that state will be reset on next frame (and for debugging purpose)
- stateParam.overrideState = toParam.overrideState;
- stateParam.Interp(stateParam, toParam, interpFactor);
- }
- }
- }
-
- /// <summary>
- /// Sets the state of all the overrides on this component to a given value.
- /// </summary>
- /// <param name="state">The value to set the state of the overrides to.</param>
- public void SetAllOverridesTo(bool state)
- {
- SetOverridesTo(parameterList, state);
- }
-
- /// <summary>
- /// Sets the override state of the given parameters on this component to a given value.
- /// </summary>
- /// <param name="state">The value to set the state of the overrides to.</param>
- internal void SetOverridesTo(IEnumerable<VolumeParameter> enumerable, bool state)
- {
- foreach (var prop in enumerable)
- {
- prop.overrideState = state;
- var t = prop.GetType();
-
- if (VolumeParameter.IsObjectParameter(t))
- {
- // This method won't be called a lot but this is sub-optimal, fix me
- var innerParams = (ReadOnlyCollection<VolumeParameter>)
- t.GetProperty("parameters", BindingFlags.NonPublic | BindingFlags.Instance)
- .GetValue(prop, null);
-
- if (innerParams != null)
- SetOverridesTo(innerParams, state);
- }
- }
- }
-
- /// <summary>
- /// A custom hashing function that Unity uses to compare the state of parameters.
- /// </summary>
- /// <returns>A computed hash code for the current instance.</returns>
- public override int GetHashCode()
- {
- unchecked
- {
- //return parameters.Aggregate(17, (i, p) => i * 23 + p.GetHash());
-
- int hash = 17;
-
- for (int i = 0; i < parameterList.Count; i++)
- hash = hash * 23 + parameterList[i].GetHashCode();
-
- return hash;
- }
- }
-
- /// <summary>
- /// Returns true if any of the volume properites has been overridden.
- /// </summary>
- /// <returns>True if any of the volume properites has been overridden.</returns>
- public bool AnyPropertiesIsOverridden()
- {
- for (int i = 0; i < parameterList.Count; ++i)
- {
- if (parameterList[i].overrideState) return true;
- }
- return false;
- }
-
- /// <summary>
- /// Unity calls this method before the object is destroyed.
- /// </summary>
- protected virtual void OnDestroy() => Release();
-
- /// <summary>
- /// Releases all the allocated resources.
- /// </summary>
- public void Release()
- {
- if (parameterList == null)
- return;
-
- for (int i = 0; i < parameterList.Count; i++)
- {
- if (parameterList[i] != null)
- parameterList[i].Release();
- }
- }
- }
- }
|