// KlakSpout - Spout video frame sharing plugin for Unity // https://github.com/keijiro/KlakSpout using UnityEngine; using UnityEditor; using System; using System.Collections.Generic; namespace Klak.Spout { static class MaterialPropertySelector { #region Public method // Material property drop-down list public static void DropdownList( SerializedProperty rendererProperty, SerializedProperty materialProperty ) { // Try retrieving the target shader. var shader = RetrieveTargetShader(rendererProperty); // Abandon the current value if it failed to get a shader. if (shader == null) { materialProperty.stringValue = ""; return; } // Cache property names found in the target shader. CachePropertyNames(shader); // Abandon the current value if there is no property candidate. if (_propertyNames.Length == 0) { materialProperty.stringValue = ""; return; } // Show the dropdown list. var index = Array.IndexOf(_propertyNames, materialProperty.stringValue); var newIndex = EditorGUILayout.Popup("Property", index, _propertyNames); // Update the serialized property if the selection was changed. if (index != newIndex) materialProperty.stringValue = _propertyNames[newIndex]; } #endregion #region Private members static string[] _propertyNames; // Property name list static Shader _cachedShader; // Shader used to cache the name list // Retrieve a shader from a given renderer. static Shader RetrieveTargetShader(SerializedProperty rendererProperty) { var renderer = rendererProperty.objectReferenceValue as Renderer; if (renderer == null) return null; var material = renderer.sharedMaterial; if (material == null) return null; return material.shader; } // Cache property names provided within a specified shader. static void CachePropertyNames(Shader shader) { // Exit early when the shader is same to the cached one. if (shader == _cachedShader) return; var temp = new List(); var count = ShaderUtil.GetPropertyCount(shader); for (var i = 0; i < count; i++) { var propType = ShaderUtil.GetPropertyType(shader, i); if (propType == ShaderUtil.ShaderPropertyType.TexEnv) temp.Add(ShaderUtil.GetPropertyName(shader, i)); } _propertyNames = temp.ToArray(); _cachedShader = shader; } #endregion } }