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); } } } }