using System; using System.Collections.Generic; namespace UnityEngine.Rendering.PostProcessing { /// <summary> /// An asset holding a set of post-processing settings to use with a <see cref="PostProcessVolume"/>. /// </summary> /// <seealso cref="PostProcessVolume"/> public sealed class PostProcessProfile : ScriptableObject { /// <summary> /// A list of all settings stored in this profile. /// </summary> [Tooltip("A list of all settings currently stored in this profile.")] public List<PostProcessEffectSettings> settings = new List<PostProcessEffectSettings>(); /// <summary> /// Sets to <c>true</c> if the content of the profile has changed. This is only really used /// in the editor to handle inspector refreshes. /// </summary> [NonSerialized] public bool isDirty = true; void OnEnable() { // Make sure every setting is valid. If a profile holds a script that doesn't exist // anymore, nuke it to keep the profile clean. Note that if you delete a script that is // currently in use in a profile you'll still get a one-time error in the console, it's // harmless and happens because Unity does a redraw of the editor (and thus the current // frame) before the recompilation step. settings.RemoveAll(x => x == null); } /// <summary> /// Adds settings for an effect to the profile. /// </summary> /// <typeparam name="T">A type of <see cref="PostProcessEffectSettings"/></typeparam> /// <returns>The instance created from the given type</returns> /// <seealso cref="PostProcessEffectSettings"/> public T AddSettings<T>() where T : PostProcessEffectSettings { return (T)AddSettings(typeof(T)); } /// <summary> /// Adds settings for an effect to the profile. /// </summary> /// <param name="type">A type of <see cref="PostProcessEffectSettings"/></param> /// <returns>The instance created from the given type</returns> /// <seealso cref="PostProcessEffectSettings"/> public PostProcessEffectSettings AddSettings(Type type) { if (HasSettings(type)) throw new InvalidOperationException("Effect already exists in the stack"); var effect = (PostProcessEffectSettings)CreateInstance(type); effect.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy; effect.name = type.Name; effect.enabled.value = true; settings.Add(effect); isDirty = true; return effect; } /// <summary> /// Adds settings for an effect to the profile. /// </summary> /// <param name="effect">An instance of <see cref="PostProcessEffectSettings"/></param> /// <returns>The given effect instance</returns> /// <seealso cref="PostProcessEffectSettings"/> public PostProcessEffectSettings AddSettings(PostProcessEffectSettings effect) { if (HasSettings(settings.GetType())) throw new InvalidOperationException("Effect already exists in the stack"); settings.Add(effect); isDirty = true; return effect; } /// <summary> /// Removes settings for an effect from the profile. /// </summary> /// <typeparam name="T">The type to look for and remove from the profile</typeparam> /// <exception cref="InvalidOperationException">Thrown if the effect doesn't exist in the /// profile</exception> public void RemoveSettings<T>() where T : PostProcessEffectSettings { RemoveSettings(typeof(T)); } /// <summary> /// Removes settings for an effect from the profile. /// </summary> /// <param name="type">The type to look for and remove from the profile</param> /// <exception cref="InvalidOperationException">Thrown if the effect doesn't exist in the /// profile</exception> public void RemoveSettings(Type type) { int toRemove = -1; for (int i = 0; i < settings.Count; i++) { if (settings[i].GetType() == type) { toRemove = i; break; } } if (toRemove < 0) throw new InvalidOperationException("Effect doesn't exist in the profile"); settings.RemoveAt(toRemove); isDirty = true; } /// <summary> /// Checks if an effect has been added to the profile. /// </summary> /// <typeparam name="T">The type to look for</typeparam> /// <returns><c>true</c> if the effect exists in the profile, <c>false</c> otherwise</returns> public bool HasSettings<T>() where T : PostProcessEffectSettings { return HasSettings(typeof(T)); } /// <summary> /// Checks if an effect has been added to the profile. /// </summary> /// <param name="type">The type to look for</param> /// <returns><c>true</c> if the effect exists in the profile, <c>false</c> otherwise</returns> public bool HasSettings(Type type) { foreach (var setting in settings) { if (setting.GetType() == type) return true; } return false; } /// <summary> /// Returns settings for a given effect type. /// </summary> /// <typeparam name="T">The type to look for</typeparam> /// <returns>Settings for the given effect type, <c>null</c> otherwise</returns> public T GetSetting<T>() where T : PostProcessEffectSettings { foreach (var setting in settings) { if (setting is T) return setting as T; } return null; } /// <summary> /// Gets settings for a given effect type. /// </summary> /// <typeparam name="T">The type to look for</typeparam> /// <param name="outSetting">When this method returns, contains the value associated with /// the specified type, if the type is found; otherwise, this parameter will be <c>null</c>. /// This parameter is passed uninitialized.</param> /// <returns><c>true</c> if the effect exists in the profile, <c>false</c> otherwise</returns> public bool TryGetSettings<T>(out T outSetting) where T : PostProcessEffectSettings { var type = typeof(T); outSetting = null; foreach (var setting in settings) { if (setting.GetType() == type) { outSetting = (T)setting; return true; } } return false; } } }