using System; using System.Collections.Generic; using System.Linq; using System.Threading; using UnityEditor; using UnityEditor.ShaderGraph.Internal; using UnityEngine; using UnityEngine.Rendering; using Object = UnityEngine.Object; namespace UnityEditor.ShaderGraph.Drawing { internal static class ShaderGraphPropertyDrawers { static Dictionary s_CompoundPropertyFoldoutStates = new(); public static void DrawShaderGraphGUI(MaterialEditor materialEditor, IEnumerable properties) { Material m = materialEditor.target as Material; Shader s = m.shader; string path = AssetDatabase.GetAssetPath(s); ShaderGraphMetadata metadata = null; foreach (var obj in AssetDatabase.LoadAllAssetsAtPath(path)) { if (obj is ShaderGraphMetadata meta) { metadata = meta; break; } } if (metadata != null) DrawShaderGraphGUI(materialEditor, properties, metadata.categoryDatas); else PropertiesDefaultGUI(materialEditor, properties); } static void PropertiesDefaultGUI(MaterialEditor materialEditor, IEnumerable properties) { foreach (var property in properties) { if ((property.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) != 0) continue; float h = materialEditor.GetPropertyHeight(property, property.displayName); Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField); materialEditor.ShaderProperty(r, property, property.displayName); } } static Rect GetRect(MaterialProperty prop) { return EditorGUILayout.GetControlRect(true, MaterialEditor.GetDefaultPropertyHeight(prop)); } static MaterialProperty FindProperty(string propertyName, IEnumerable properties) { foreach (var prop in properties) { if (prop.name == propertyName) { return prop; } } return null; } public static void DrawShaderGraphGUI(MaterialEditor materialEditor, IEnumerable properties, IEnumerable categoryDatas) { foreach (MinimalCategoryData mcd in categoryDatas) { DrawCategory(materialEditor, properties, mcd); } } static void DrawCategory(MaterialEditor materialEditor, IEnumerable properties, MinimalCategoryData minimalCategoryData) { if (minimalCategoryData.categoryName.Length > 0) { minimalCategoryData.expanded = EditorGUILayout.BeginFoldoutHeaderGroup(minimalCategoryData.expanded, minimalCategoryData.categoryName); } else { // force draw if no category name to do foldout on minimalCategoryData.expanded = true; } if (minimalCategoryData.expanded) { foreach (var propData in minimalCategoryData.propertyDatas) { if (propData.isCompoundProperty == false) { MaterialProperty prop = FindProperty(propData.referenceName, properties); if (prop == null) continue; DrawMaterialProperty(materialEditor, prop, propData.propertyType, propData.isKeyword, propData.keywordType); } else { DrawCompoundProperty(materialEditor, properties, propData); } } } EditorGUILayout.EndFoldoutHeaderGroup(); } static void DrawCompoundProperty(MaterialEditor materialEditor, IEnumerable properties, GraphInputData compoundPropertyData) { EditorGUI.indentLevel++; bool foldoutState = true; var exists = s_CompoundPropertyFoldoutStates.ContainsKey(compoundPropertyData); if (!exists) s_CompoundPropertyFoldoutStates.Add(compoundPropertyData, true); else foldoutState = s_CompoundPropertyFoldoutStates[compoundPropertyData]; foldoutState = EditorGUILayout.Foldout(foldoutState, compoundPropertyData.referenceName); if (foldoutState) { EditorGUI.indentLevel++; foreach (var subProperty in compoundPropertyData.subProperties) { var property = FindProperty(subProperty.referenceName, properties); if (property == null) continue; DrawMaterialProperty(materialEditor, property, subProperty.propertyType); } EditorGUI.indentLevel--; } if (exists) s_CompoundPropertyFoldoutStates[compoundPropertyData] = foldoutState; EditorGUI.indentLevel--; } static void DrawMaterialProperty(MaterialEditor materialEditor, MaterialProperty property, PropertyType propertyType, bool isKeyword = false, KeywordType keywordType = KeywordType.Boolean) { if (isKeyword) { switch (keywordType) { case KeywordType.Boolean: DrawBooleanKeyword(materialEditor, property); break; case KeywordType.Enum: DrawEnumKeyword(materialEditor, property); break; } } else { switch (propertyType) { case PropertyType.SamplerState: DrawSamplerStateProperty(materialEditor, property); break; case PropertyType.Matrix4: DrawMatrix4Property(materialEditor, property); break; case PropertyType.Matrix3: DrawMatrix3Property(materialEditor, property); break; case PropertyType.Matrix2: DrawMatrix2Property(materialEditor, property); break; case PropertyType.Texture2D: DrawTexture2DProperty(materialEditor, property); break; case PropertyType.Texture2DArray: DrawTexture2DArrayProperty(materialEditor, property); break; case PropertyType.Texture3D: DrawTexture3DProperty(materialEditor, property); break; case PropertyType.Cubemap: DrawCubemapProperty(materialEditor, property); break; case PropertyType.Gradient: break; case PropertyType.Vector4: DrawVector4Property(materialEditor, property); break; case PropertyType.Vector3: DrawVector3Property(materialEditor, property); break; case PropertyType.Vector2: DrawVector2Property(materialEditor, property); break; case PropertyType.Float: DrawFloatProperty(materialEditor, property); break; case PropertyType.Boolean: DrawBooleanProperty(materialEditor, property); break; case PropertyType.VirtualTexture: DrawVirtualTextureProperty(materialEditor, property); break; case PropertyType.Color: DrawColorProperty(materialEditor, property); break; } } } static void DrawColorProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawEnumKeyword(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawBooleanKeyword(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawVirtualTextureProperty(MaterialEditor materialEditor, MaterialProperty property) { } static void DrawBooleanProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawFloatProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawVector2Property(MaterialEditor materialEditor, MaterialProperty property) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = property.hasMixedValue; Vector2 newValue = EditorGUI.Vector2Field(GetRect(property), property.displayName, new Vector2(property.vectorValue.x, property.vectorValue.y)); EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) { property.vectorValue = newValue; } } static void DrawVector3Property(MaterialEditor materialEditor, MaterialProperty property) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = property.hasMixedValue; Vector3 newValue = EditorGUI.Vector3Field(GetRect(property), property.displayName, new Vector3(property.vectorValue.x, property.vectorValue.y, property.vectorValue.z)); EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) { property.vectorValue = newValue; } } static void DrawVector4Property(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawCubemapProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawTexture3DProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawTexture2DArrayProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawTexture2DProperty(MaterialEditor materialEditor, MaterialProperty property) { materialEditor.ShaderProperty(property, property.displayName); } static void DrawMatrix2Property(MaterialEditor materialEditor, MaterialProperty property) { //we dont expose } static void DrawMatrix3Property(MaterialEditor materialEditor, MaterialProperty property) { //we dont expose } static void DrawMatrix4Property(MaterialEditor materialEditor, MaterialProperty property) { //we dont expose } static void DrawSamplerStateProperty(MaterialEditor materialEditor, MaterialProperty property) { //we dont expose } } }