using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
namespace UnityEditor.Rendering
{
///
/// Base implementation for drawing Default Volume Profile UI in Graphics Settings.
///
public abstract class DefaultVolumeProfileSettingsPropertyDrawer : PropertyDrawer
{
// UUM-77758: Due to how PropertyDrawers are created and cached, there is no way to retrieve them reliably
// later. We know that only one DefaultVolumeProfile exists at any given time, so we can access it through
// static variables.
static SerializedProperty s_DefaultVolumeProfileSerializedProperty;
static DefaultVolumeProfileEditor s_DefaultVolumeProfileEditor;
VisualElement m_Root;
/// SerializedObject representing the settings object
protected SerializedObject m_SettingsSerializedObject;
/// SerializedProperty representing the Default Volume Profile
protected SerializedProperty m_VolumeProfileSerializedProperty;
/// Foldout state
protected EditorPrefBool m_DefaultVolumeProfileFoldoutExpanded;
/// VisualElement containing the DefaultVolumeProfileEditor
protected VisualElement m_EditorContainer;
/// Default Volume Profile label width
protected const int k_DefaultVolumeLabelWidth = 260;
/// Info box message
protected abstract GUIContent volumeInfoBoxLabel { get; }
///
/// CreatePropertyGUI implementation.
///
/// Property to create UI for
/// VisualElement containing the created UI
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
m_Root = new VisualElement();
var header = CreateHeader();
if (header != null)
m_Root.Add(header);
m_SettingsSerializedObject = property.serializedObject;
m_VolumeProfileSerializedProperty = property.FindPropertyRelative("m_VolumeProfile");
m_DefaultVolumeProfileFoldoutExpanded = new EditorPrefBool($"{GetType()}.DefaultVolumeProfileFoldoutExpanded", true);
m_EditorContainer = new VisualElement();
if (!RenderPipelineManager.pipelineSwitchCompleted)
// Defer creation of the UI until the render pipeline is created and VolumeManager is initialized
RenderPipelineManager.activeRenderPipelineCreated += CreateDefaultVolumeProfileEditor;
else
CreateDefaultVolumeProfileEditor();
m_Root.Add(CreateAssetFieldUI());
m_Root.Add(m_EditorContainer);
return m_Root;
}
///
/// Creates the header for the Volume Profile editor.
///
/// VisualElement containing the header. Null for no header.
protected virtual VisualElement CreateHeader() => null;
///
/// Creates the Default Volume Profile editor.
///
protected void CreateDefaultVolumeProfileEditor()
{
RenderPipelineManager.activeRenderPipelineCreated -= CreateDefaultVolumeProfileEditor;
VolumeProfile profile = m_VolumeProfileSerializedProperty.objectReferenceValue as VolumeProfile;
if (profile == null)
return;
if (profile == VolumeManager.instance.globalDefaultProfile)
VolumeProfileUtils.EnsureAllOverridesForDefaultProfile(profile);
if (s_DefaultVolumeProfileSerializedProperty != m_VolumeProfileSerializedProperty)
{
s_DefaultVolumeProfileSerializedProperty = m_VolumeProfileSerializedProperty;
s_DefaultVolumeProfileEditor = new DefaultVolumeProfileEditor(profile, m_SettingsSerializedObject);
}
m_EditorContainer.Add(s_DefaultVolumeProfileEditor.Create());
m_EditorContainer.Q("volume-override-info-box").text = volumeInfoBoxLabel.text;
if (m_DefaultVolumeProfileFoldoutExpanded.value)
m_EditorContainer.style.display = DisplayStyle.Flex;
}
///
/// Destroys the Default Volume Profile editor.
///
protected void DestroyDefaultVolumeProfileEditor()
{
m_EditorContainer.style.display = DisplayStyle.None;
m_EditorContainer?.Clear();
if (s_DefaultVolumeProfileEditor != null)
s_DefaultVolumeProfileEditor.Destroy();
s_DefaultVolumeProfileEditor = null;
s_DefaultVolumeProfileSerializedProperty = null;
}
///
/// Implementation of the Default Volume Profile asset field.
///
/// VisualElement containing the UI
protected abstract VisualElement CreateAssetFieldUI();
///
/// Context menu implementation for Default Volume Profile.
///
/// Default Volume Profile Settings type
/// Render Pipeline type
public abstract class DefaultVolumeProfileSettingsContextMenu : IRenderPipelineGraphicsSettingsContextMenu
where TSetting : class, IDefaultVolumeProfileSettings
where TRenderPipeline : RenderPipeline
{
///
/// Path where new Default Volume Profile will be created.
///
protected abstract string defaultVolumeProfilePath { get; }
void IRenderPipelineGraphicsSettingsContextMenu.PopulateContextMenu(TSetting setting, PropertyDrawer _, ref GenericMenu menu)
{
bool canCreateNewAsset = RenderPipelineManager.currentPipeline is TRenderPipeline;
VolumeProfileUtils.AddVolumeProfileContextMenuItems(ref menu,
setting.volumeProfile,
s_DefaultVolumeProfileEditor.allEditors,
overrideStateOnReset: true,
defaultVolumeProfilePath: defaultVolumeProfilePath,
onNewVolumeProfileCreated: createdProfile =>
{
s_DefaultVolumeProfileSerializedProperty.objectReferenceValue = createdProfile;
s_DefaultVolumeProfileSerializedProperty.serializedObject.ApplyModifiedProperties();
VolumeProfile initialAsset = null;
var initialAssetSettings = EditorGraphicsSettings.GetRenderPipelineSettingsFromInterface();
if (initialAssetSettings.Length > 0)
{
if (initialAssetSettings.Length > 1)
throw new InvalidOperationException("Found multiple settings implementing IDefaultVolumeProfileAsset, expected only one");
initialAsset = initialAssetSettings[0].defaultVolumeProfile;
}
VolumeProfileUtils.UpdateGlobalDefaultVolumeProfile(createdProfile, initialAsset);
},
onComponentEditorsExpandedCollapsed: s_DefaultVolumeProfileEditor.RebuildListViews,
canCreateNewAsset);
}
}
}
}