using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering.HighDefinition; using System.Linq; using System; namespace UnityEditor.Rendering.HighDefinition { // A Material can be authored from the shader graph or by hand. When written by hand we need to provide an inspector. // Such a Material will share some properties between it various variant (shader graph variant or hand authored variant). // To create a such GUI, we provide Material UI Blocks, a modular API to create custom Material UI that allow // you to reuse HDRP pre-defined blocks and access support header toggles automatically. // Examples of such material UIs can be found in the classes UnlitGUI, LitGUI or LayeredLitGUI. /// /// Wrapper to handle Material UI Blocks, it will handle initialization of the blocks when drawing the GUI. /// public class MaterialUIBlockList : List { [System.NonSerialized] bool m_Initialized = false; Material[] m_Materials; /// /// Parent of the ui block list, in case of nesting (Layered Lit material) /// public MaterialUIBlockList parent; /// /// List of materials currently selected in the inspector /// public Material[] materials => m_Materials; /// /// Construct a sub ui block list by passing the parent ui block list (useful for layered UI where ui blocks are nested) /// /// public MaterialUIBlockList(MaterialUIBlockList parent) => this.parent = parent; /// /// Construct a ui block list /// public MaterialUIBlockList() : this(null) { } /// /// Render the list of ui blocks /// /// /// public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) { // Use default labelWidth EditorGUIUtility.labelWidth = 0f; Initialize(materialEditor, properties); foreach (var uiBlock in this) { try { // We load material properties at each frame because materials can be animated and to make undo/redo works uiBlock.UpdateMaterialProperties(properties); uiBlock.OnGUI(); } // Never catch ExitGUIException as they are used to handle color picker and object pickers. catch (ExitGUIException) { throw; } catch (Exception e) { Debug.LogException(e); } } // Reset label width back to the default of 0 (fix UUM-66215) // NOTE: Because of how EditorGUIUtility.labelWidth works, when the internal value is 0, // we cannot read that value back from the property getter. So we just set it to 0 here. EditorGUIUtility.labelWidth = 0; } /// /// Initialize the ui blocks /// This function is called automatically by MaterialUIBlockList.OnGUI so you only need this when you want to render the UI Blocks in a custom order /// /// Material editor instance. /// The list of properties in the inspected material(s). public void Initialize(MaterialEditor materialEditor, MaterialProperty[] properties) { if (!m_Initialized) { foreach (var uiBlock in this) uiBlock.Initialize(materialEditor, properties, this); m_Materials = materialEditor.targets.Select(target => target as Material).ToArray(); m_Initialized = true; } } /// /// Fetch the first ui block of type T in the current list of material blocks /// /// MaterialUIBlock type /// public T FetchUIBlock() where T : MaterialUIBlock { return this.FirstOrDefault(uiBlock => uiBlock is T) as T; } } }