using System;
using System.Collections.Generic;
namespace UnityEngine.Rendering
{
///
/// Represents the state of a Volume blending update within the Volume system.
///
///
///
/// This class is responsible for storing the blending of Volume components across multiple scenes and cameras,
/// By default, a global volume stack is provided by the to handle the blending of Volume data across your project.
/// This global stack simplifies managing and blending volume data at a project-wide level. However, if you require more granular control over
/// the blending process or want to store and manage the blending results separately (e.g., per camera or scene), you can create custom volume
/// stacks using .
/// The blending of volumes is based on a combination of several factors:
/// - **Volume Weight:** Determines how strongly a particular volume influences the final result.
/// - **Volume Parameters:** These can be visual settings such as post-processing effects, lighting adjustments, or other specialized effects defined
/// in the Volume components.
/// - **Camera Volume Stack:** Volume blending can vary per camera, allowing different volumes to be blended for different camera views or scenes.
///
/// While the default global volume stack works for most use cases, custom stacks provide greater flexibility and control, allowing developers
/// to manage and store volume blending results at a per-scene or per-camera level. This can be particularly useful in complex rendering setups
/// or when you want to apply different volume blends for different gameplay contexts or visual effects.
///
/// Keep in mind that frequent updates to the volume blending process (e.g., every frame) may have an impact on performance, especially when
/// dealing with large numbers of volumes or complex blending operations.
///
///
///
///
///
public sealed class VolumeStack : IDisposable
{
// Holds the state of _all_ component types you can possibly add on volumes
internal readonly Dictionary components = new();
// Flat list of every volume parameter for faster per-frame stack reset.
internal VolumeParameter[] parameters;
// Flag indicating that some properties have received overrides, therefore they must be reset in the next update.
internal bool requiresReset = true;
// Flag indicating that default state has changed, therefore all properties in the stack must be reset in the next update.
internal bool requiresResetForAllProperties = true;
internal VolumeStack()
{
}
internal void Clear()
{
foreach (var component in components)
CoreUtils.Destroy(component.Value);
components.Clear();
parameters = null;
}
internal void Reload(Type[] componentTypes)
{
Clear();
requiresReset = true;
requiresResetForAllProperties = true;
List parametersList = new();
foreach (var type in componentTypes)
{
var component = (VolumeComponent)ScriptableObject.CreateInstance(type);
components.Add(type, component);
parametersList.AddRange(component.parameters);
}
parameters = parametersList.ToArray();
isValid = true;
}
///
/// Gets the current state of the of type
/// in the stack.
///
/// A type of .
/// The current state of the of type
/// in the stack.
public T GetComponent()
where T : VolumeComponent
{
var comp = GetComponent(typeof(T));
return (T)comp;
}
///
/// Gets the current state of the of the specified type in the
/// stack.
///
/// The type of to look for.
/// The current state of the of the specified type,
/// or null if the type is invalid.
public VolumeComponent GetComponent(Type type)
{
components.TryGetValue(type, out var comp);
return comp;
}
///
/// Cleans up the content of this stack. Once a VolumeStack is disposed, it shouldn't
/// be used anymore.
///
public void Dispose()
{
Clear();
isValid = false;
}
///
/// Check if the stack is in valid state and can be used.
///
public bool isValid { get; private set; }
}
}