using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Rendering.HighDefinition; using UnityEngine.Rendering; // Include material common properties names using static UnityEngine.Rendering.HighDefinition.HDMaterialProperties; 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). // HDShaderGUI is here to provide a support for setup material keyword and pass function. It will allow the GUI // to setup the material properties needed for rendering when switching shaders on a material. For the GUI part // of the material you must use Material UI Blocks, examples of doing so can be found in the classes UnlitGUI, // LitGUI or LayeredLitGUI. /// /// Use this class to build your custom Shader GUI for HDRP. /// You can use a class that inherits from HDShaderGUI in the Shader Graph Custom EditorGUI field. /// public abstract class HDShaderGUI : ShaderGUI { internal protected bool m_FirstFrame = true; // The following set of functions are call by the ShaderGraph // It will allow to display our common parameters + setup keyword correctly for them /// /// Sets up the keywords and passes for the material you pass in as a parameter. /// /// Target material. protected abstract void SetupMaterialKeywordsAndPass(Material material); /// /// Unity calls this function when you assign a new shader to the material. /// /// The current material. /// The shader the material currently uses. /// The new shader to assign to the material. public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) { base.AssignNewShaderToMaterial(material, oldShader, newShader); SetupMaterialKeywordsAndPass(material); } /// /// Sets up the keywords and passes for the material. You must call this function after you change a property on a material to ensure it's validity. /// /// GUI.changed is the usual value for this parameter. If this value is false, the function just exits. /// The materials to perform the setup on. protected void ApplyKeywordsAndPassesIfNeeded(bool changed, Material[] materials) { // !!! HACK !!! // When a user creates a new Material from the contextual menu, the material is created from the editor code and the appropriate shader is applied to it. // This means that we never setup keywords and passes for a newly created material. The material is then in an invalid state. // To work around this, as the material is automatically selected when created, we force an update of the keyword at the first "frame" of the editor. // Apply material keywords and pass: if (changed || m_FirstFrame) { m_FirstFrame = false; foreach (var material in materials) SetupMaterialKeywordsAndPass(material); } } /// /// Unity calls this function when it displays the GUI. This method is sealed so you cannot override it. To implement your custom GUI, use OnMaterialGUI instead. /// /// Material editor instance. /// The list of properties in the inspected material(s). public sealed override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) { if (!(RenderPipelineManager.currentPipeline is HDRenderPipeline)) { EditorGUILayout.HelpBox("Editing HDRP materials is only supported when an HDRP asset assigned in the graphic settings", MessageType.Warning); } else { OnMaterialGUI(materialEditor, props); } } /// /// Implement your custom GUI in this function. To display a UI similar to HDRP shaders, use a MaterialUIBlockList. /// /// The current material editor. /// The list of properties in the inspected material(s). protected abstract void OnMaterialGUI(MaterialEditor materialEditor, MaterialProperty[] props); readonly static string[] floatPropertiesToSynchronize = { kUseSplitLighting, }; /// /// Synchronize a set of properties that Unity requires for Shader Graph materials to work correctly. This function is for Shader Graph only. /// /// The target material. protected static void SynchronizeShaderGraphProperties(Material material) { var defaultProperties = new Material(material.shader); foreach (var floatToSync in floatPropertiesToSynchronize) if (material.HasProperty(floatToSync)) material.SetFloat(floatToSync, defaultProperties.GetFloat(floatToSync)); CoreUtils.Destroy(defaultProperties); defaultProperties = null; } } }