From 8250bc128d91b87d30d6691546f2a3fcc50b3c28 Mon Sep 17 00:00:00 2001 From: Misaki Date: Sun, 17 Aug 2025 13:01:40 +0900 Subject: [PATCH] Added new KeywordEnumTypeDrawer; Added new method to use generic to add ui scope --- Editor/Contracts/IMaterialUIScopeContainer.cs | 6 +- Editor/Helpers/MaterialHelper.cs | 6 + Editor/Helpers/MaterialHelper.cs.meta | 2 + Editor/MaterialUIScope.cs | 2 +- Editor/PropertyDrawer/EnumFlagsDrawer.cs | 2 +- .../PropertyDrawer/KeywordEnumTypeDrawer.cs | 115 ++++++++++++++++++ .../KeywordEnumTypeDrawer.cs.meta | 2 + Editor/ScopedShaderGUI.cs | 12 +- package.json | 2 +- 9 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 Editor/Helpers/MaterialHelper.cs create mode 100644 Editor/Helpers/MaterialHelper.cs.meta create mode 100644 Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs create mode 100644 Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs.meta diff --git a/Editor/Contracts/IMaterialUIScopeContainer.cs b/Editor/Contracts/IMaterialUIScopeContainer.cs index 6afaf21..a6d91b3 100644 --- a/Editor/Contracts/IMaterialUIScopeContainer.cs +++ b/Editor/Contracts/IMaterialUIScopeContainer.cs @@ -7,7 +7,11 @@ namespace Misaki.ShaderGUI { public void AddUIScope(IMaterialUIScope scope); - public T GetUIScope() where T : class, IMaterialUIScope; + public void AddUIScope() + where T : IMaterialUIScope, new(); + + public T GetUIScope() + where T : IMaterialUIScope; public void Initialize(MaterialEditor materialEditor, MaterialProperty[] properties); diff --git a/Editor/Helpers/MaterialHelper.cs b/Editor/Helpers/MaterialHelper.cs new file mode 100644 index 0000000..d0df867 --- /dev/null +++ b/Editor/Helpers/MaterialHelper.cs @@ -0,0 +1,6 @@ +namespace Misaki.ShaderGUI +{ + public static class MaterialHelper + { + } +} diff --git a/Editor/Helpers/MaterialHelper.cs.meta b/Editor/Helpers/MaterialHelper.cs.meta new file mode 100644 index 0000000..b7f4ccb --- /dev/null +++ b/Editor/Helpers/MaterialHelper.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bcf12ee4f77a09b49820a65e2eb5574e \ No newline at end of file diff --git a/Editor/MaterialUIScope.cs b/Editor/MaterialUIScope.cs index c1c1cf1..4f39ed3 100644 --- a/Editor/MaterialUIScope.cs +++ b/Editor/MaterialUIScope.cs @@ -32,7 +32,7 @@ namespace Misaki.ShaderGUI public MaterialEditor Editor => editor; - public abstract void LoadMaterialProperties(); + protected abstract void LoadMaterialProperties(); protected abstract void DrawContent(); diff --git a/Editor/PropertyDrawer/EnumFlagsDrawer.cs b/Editor/PropertyDrawer/EnumFlagsDrawer.cs index c8bd94a..2dec83e 100644 --- a/Editor/PropertyDrawer/EnumFlagsDrawer.cs +++ b/Editor/PropertyDrawer/EnumFlagsDrawer.cs @@ -28,7 +28,7 @@ namespace Misaki.ShaderGUI { if (!IsPropertyTypeSuitable(prop)) { - var c = EditorGUIUtility.TrTempContent("Toggle used on a non-float property: " + prop.name); + var c = EditorGUIUtility.TrTempContent($"Enum flags used on a property {prop.name} with unsupported type: {prop.propertyType}"); EditorGUI.LabelField(position, c, EditorStyles.helpBox); return; } diff --git a/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs b/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs new file mode 100644 index 0000000..aef61ad --- /dev/null +++ b/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs @@ -0,0 +1,115 @@ +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace Misaki.ShaderGUI +{ + public class KeywordEnumTypeDrawer : MaterialPropertyDrawer + { + private readonly Type enumType; + + public KeywordEnumTypeDrawer(string enumTypeName, string assemblyName) + { + enumType = Type.GetType(Assembly.CreateQualifiedName(assemblyName, enumTypeName), true); + } + + 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 + } + + private static string GetKeywordName(MaterialProperty prop, Enum enumValue) + { + var keyword = prop.name.ToUpper() + '_' + enumValue.ToString().ToUpper(); + return keyword; + } + + private void OnPropertyChanged(MaterialProperty prop) + { + var values = Enum.GetValues(enumType); + foreach (var mat in prop.targets) + { + if (mat is not Material material) + { + continue; + } + +#if UNITY_6000_1_OR_NEWER + var valueIndex = prop.propertyType == ShaderPropertyType.Int ? prop.intValue : (int)prop.floatValue; +#else + var valueIndex = prop.type == MaterialProperty.PropType.Int ? prop.intValue : (int)prop.floatValue; +#endif + + for (var i = 0; i < values.Length; i++) + { + var keywordName = GetKeywordName(prop, (Enum)Enum.ToObject(enumType, i)); + if (i == valueIndex) + { + material.EnableKeyword(keywordName); + } + else + { + material.DisableKeyword(keywordName); + } + } + } + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (!IsPropertyTypeSuitable(prop)) + { + var c = EditorGUIUtility.TrTempContent(($"Keyword enum type used on a property {prop.name} with unsupported type: {prop.propertyType}")); + 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)prop.floatValue; + EditorGUI.showMixedValue = prop.hasMixedValue; + var enumValue = EditorGUI.EnumPopup(position, label, (Enum)Enum.ToObject(enumType, value)); + value = Convert.ToInt32(enumValue); + EditorGUI.showMixedValue = false; + + if (EditorGUI.EndChangeCheck()) + { + prop.floatValue = value; + OnPropertyChanged(prop); + } + } + else + { + EditorGUI.BeginChangeCheck(); + + var value = prop.intValue; + EditorGUI.showMixedValue = prop.hasMixedValue; + var enumValue = EditorGUI.EnumPopup(position, label, (Enum)Enum.ToObject(enumType, value)); + value = Convert.ToInt32(enumValue); + + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + prop.intValue = value; + OnPropertyChanged(prop); + } + } + + MaterialEditor.EndProperty(); + } + } +} \ No newline at end of file diff --git a/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs.meta b/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs.meta new file mode 100644 index 0000000..d142610 --- /dev/null +++ b/Editor/PropertyDrawer/KeywordEnumTypeDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cc930296c99db9847b93eb6ed4b6df87 \ No newline at end of file diff --git a/Editor/ScopedShaderGUI.cs b/Editor/ScopedShaderGUI.cs index 307ab0c..ff869c7 100644 --- a/Editor/ScopedShaderGUI.cs +++ b/Editor/ScopedShaderGUI.cs @@ -15,9 +15,17 @@ namespace Misaki.ShaderGUI _scopes.Add(scope); } - public T GetUIScope() where T : class, IMaterialUIScope + public void AddUIScope() + where T : IMaterialUIScope, new() { - return _scopes.Find(s => s is T) as T; + var scope = new T(); + _scopes.Add(scope); + } + + public T GetUIScope() + where T : IMaterialUIScope + { + return (T)_scopes.Find(s => s is T); } public void Initialize(MaterialEditor materialEditor, MaterialProperty[] properties) diff --git a/package.json b/package.json index 55113f4..507a097 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.misaki.shader-gui", - "version": "1.1.3", + "version": "1.1.5", "displayName": "Shader GUI", "description": "A toolset for creating custom shader gui in Unity with ease", "keywords": [