using System; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; namespace Misaki.ShaderGUI { public class PopupUIDrawer : MaterialPropertyDrawer { private static readonly GUIContent[] _options = { new("Disabled"), new("Enabled") }; protected virtual void OnPropertyChanged(MaterialProperty prop) { } private static bool IsPropertyTypeSuitable(MaterialProperty prop) { #if UNITY_6000_1_OR_NEWER return prop.propertyType == ShaderPropertyType.Float || prop.propertyType == ShaderPropertyType.Range || prop.propertyType == ShaderPropertyType.Int; #else return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range || prop.type == MaterialProperty.PropType.Int; #endif } public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { if (!IsPropertyTypeSuitable(prop)) { var c = EditorGUIUtility.TrTempContent("Toggle used on a non-float property: " + prop.name); EditorGUI.LabelField(position, c, EditorStyles.helpBox); return; } MaterialEditor.BeginProperty(position, prop); #if UNITY_6000_1_OR_NEWER if (prop.propertyType != ShaderPropertyType.Int) #else if (prop.type != MaterialProperty.PropType.Int) #endif { EditorGUI.BeginChangeCheck(); var value = (int)Mathf.Abs(prop.floatValue); EditorGUI.showMixedValue = prop.hasMixedValue; value = EditorGUI.Popup(position, label, value, _options); EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) { prop.floatValue = value; OnPropertyChanged(prop); } } else { EditorGUI.BeginChangeCheck(); var value = Math.Abs(prop.intValue); EditorGUI.showMixedValue = prop.hasMixedValue; value = EditorGUI.Popup(position, label, value, _options); EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) { prop.intValue = value; OnPropertyChanged(prop); } } MaterialEditor.EndProperty(); } } public class PopupDrawer : PopupUIDrawer { private const string _KEYWORD_SUFFIX = "_ON"; private string _keyword; public PopupDrawer() { } public PopupDrawer(string keyword) { _keyword = keyword; } protected override void OnPropertyChanged(MaterialProperty prop) { _keyword ??= prop.name.ToUpper() + _KEYWORD_SUFFIX; foreach (var target in prop.targets) { if (target is not Material material) { continue; } #if UNITY_6000_1_OR_NEWER if (prop.propertyType != ShaderPropertyType.Int) #else if (prop.type != MaterialProperty.PropType.Int) #endif { material.SetKeyword(new LocalKeyword(material.shader, _keyword), prop.floatValue != 0); } else { material.SetKeyword(new LocalKeyword(material.shader, _keyword), prop.intValue != 0); } } } } public class PassPopupDrawer : PopupUIDrawer { private readonly string _passName; public PassPopupDrawer(string passName) { _passName = passName; } protected override void OnPropertyChanged(MaterialProperty prop) { foreach (var target in prop.targets) { if (target is not Material material) { continue; } #if UNITY_6000_1_OR_NEWER if (prop.propertyType != ShaderPropertyType.Int) #else if (prop.type != MaterialProperty.PropType.Int) #endif { material.SetShaderPassEnabled(_passName, prop.floatValue != 0); } else { material.SetShaderPassEnabled(_passName, prop.intValue != 0); } } } } }