using System;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEditor.Rendering;
namespace UnityEditor.Rendering.HighDefinition
{
///
/// Base implementation of a material GUI block to be disabled in the material inspector.
///
public abstract class MaterialUIBlock
{
/// The current material editor.
protected MaterialEditor materialEditor;
/// The list of selected materials to edit.
protected Material[] materials;
/// The list of available properties in the selected materials.
protected MaterialProperty[] properties;
/// Parent of the UI block.
protected MaterialUIBlockList parent;
/// Bit index used to store a foldout state in the editor preferences.
[Flags]
public enum ExpandableBit : uint
{
// Standard
///Reserved Base Bit
Base = 1 << 0,
///Reserved Input Bit
Input = 1 << 1,
///Reserved Tessellation Bit
Tessellation = 1 << 2,
///Reserved Transparency Bit
Transparency = 1 << 3,
// Free slot 4
///Reserved Detail Bit
Detail = 1 << 5,
///Reserved Emissive Bit
Emissive = 1 << 6,
///Reserved Advanced Bit
Advance = 1 << 7,
///Reserved Other Bit
Other = 1 << 8,
///Reserved ShaderGraph Bit
ShaderGraph = 1 << 9,
// Free slot 10
// Layered
///Reserved MainLayer Bit
MainLayer = 1 << 11,
///Reserved Layer1 Bit
Layer1 = 1 << 12,
///Reserved Layer2 Bit
Layer2 = 1 << 13,
///Reserved Layer3 Bit
Layer3 = 1 << 14,
///Reserved LayeringOptionMain Bit
LayeringOptionMain = 1 << 15,
///Reserved ShowLayer1 Bit
ShowLayer1 = 1 << 16,
///Reserved ShowLayer2 Bit
ShowLayer2 = 1 << 17,
///Reserved ShowLayer3 Bit
ShowLayer3 = 1 << 18,
///Reserved MaterialReferences Bit
MaterialReferences = 1 << 19,
///Reserved MainInput Bit
MainInput = 1 << 20,
///Reserved Layer1Input Bit
Layer1Input = 1 << 21,
///Reserved Layer2Input Bit
Layer2Input = 1 << 22,
///Reserved Layer3Input Bit
Layer3Input = 1 << 23,
///Reserved MainDetail Bit
MainDetail = 1 << 24,
///Reserved Layer1Detail Bit
Layer1Detail = 1 << 25,
///Reserved Layer2Detail Bit
Layer2Detail = 1 << 26,
///Reserved Layer3Detail Bit
Layer3Detail = 1 << 27,
///Reserved LayeringOption1 Bit
LayeringOption1 = 1 << 28,
///Reserved LayeringOption2 Bit
LayeringOption2 = 1 << 29,
///Reserved LayeringOption3 Bit
LayeringOption3 = 1 << 30,
// Note that we use the bit reserved for layered material UI in this enum, we can do this
// because this enum will be used for ShaderGraph custom UI and we can't author layered
// shader in shadergraph.
///User Bit 0
User0 = 1 << 11,
///User Bit 1
User1 = 1 << 12,
///User Bit 2
User2 = 1 << 13,
///User Bit 3
User3 = 1 << 14,
///User Bit 4
User4 = 1 << 15,
///User Bit 5
User5 = 1 << 16,
///User Bit 6
User6 = 1 << 17,
///User Bit 7
User7 = 1 << 18,
///User Bit 8
User8 = 1 << 19,
///User Bit 9
User9 = 1 << 20,
///User Bit 10
User10 = 1 << 21,
///User Bit 11
User11 = 1 << 22,
///User Bit 12
User12 = 1 << 23,
///User Bit 13
User13 = 1 << 24,
///User Bit 14
User14 = 1 << 25,
///User Bit 15
User15 = 1 << 26,
///User Bit 16
User16 = 1 << 27,
///User Bit 17
User17 = 1 << 28,
///User Bit 18
User18 = 1 << 29,
///User Bit 19
User19 = 1 << 30,
}
internal void Initialize(MaterialEditor materialEditor, MaterialProperty[] properties, MaterialUIBlockList parent)
{
this.materialEditor = materialEditor;
this.parent = parent;
materials = materialEditor.targets.Select(target => target as Material).ToArray();
// We should always register the key used to keep collapsable state
materialEditor.InitExpandableState();
}
internal void UpdateMaterialProperties(MaterialProperty[] properties)
{
this.properties = properties;
LoadMaterialProperties();
}
///
/// Find a material property in the list of available properties.
///
/// Name of the property.
/// Specifies whether the property is mandatory for your Inspector.
/// Returns the material property if it exists. Returns null otherwise.
protected MaterialProperty FindProperty(string propertyName, bool isMandatory = false)
{
// ShaderGUI.FindProperty is a protected member of ShaderGUI so we can't call it here:
// return ShaderGUI.FindProperty(propertyName, properties, isMandatory);
// TODO: move this to a map since this is done at every editor frame
foreach (var prop in properties)
if (prop.name == propertyName)
return prop;
if (isMandatory)
throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + properties.Length);
return null;
}
///
/// Find a material property with layering option
///
/// Name of the property.
/// Number of layers of the shader.
/// Specifies whether the property is mandatory for your Inspector.
/// Returns the material property if it exists. Returns null otherwise.
protected MaterialProperty[] FindPropertyLayered(string propertyName, int layerCount, bool isMandatory = false)
{
MaterialProperty[] properties = new MaterialProperty[layerCount];
// If the layerCount is 1, then it means that the property we're fetching is not from a layered material
// thus it doesn't have a prefix
string[] prefixes = (layerCount > 1) ? new[] {"0", "1", "2", "3"} : new[] {""};
for (int i = 0; i < layerCount; i++)
{
properties[i] = FindProperty(string.Format("{0}{1}", propertyName, prefixes[i]), isMandatory);
}
return properties;
}
///
/// Loads the material properties for the block.
///
public abstract void LoadMaterialProperties();
///
/// Renders the properties in the block.
///
public abstract void OnGUI();
}
}