From abcd996e41007c904c0f97b218687c1c4f912af0 Mon Sep 17 00:00:00 2001 From: Jason Ma Date: Fri, 27 Feb 2026 21:37:11 +0800 Subject: [PATCH] - Add Keyword support for ShowIf() and ActiveIf() - Fix RampAtlas Crash - Fix RampDrawer when Ramp User Data can not find - Fix ClearShaderPerfCache Error - Optimize Ramp creation behavior #90 --- Editor/AssetProcessor/ShaderModifyListener.cs | 2 + Editor/Helper/IOHelper.cs | 52 ++++++ Editor/Helper/MetaDataHelper.cs | 13 +- Editor/Helper/ToolbarHelper.cs | 1 + Editor/ScriptableObject/LwguiRampAtlas.cs | 11 +- .../ConditionDisplay/ActiveIfDecorator.cs | 8 +- .../ConditionDisplay/ShowIfDecorator.cs | 31 +++- .../RampAtlasIndexerDrawer.cs | 0 .../RampAtlasIndexerDrawer.cs.meta | 2 +- .../ExtraDrawers/Texture/RampDrawer.cs | 171 ++++++++++++------ README.md | 12 +- README_CN.md | 18 +- Test/SampleKeyword.shader | 11 +- package.json | 2 +- 14 files changed, 223 insertions(+), 111 deletions(-) rename Editor/ShaderDrawers/ExtraDrawers/{Texture => Numeric}/RampAtlasIndexerDrawer.cs (100%) rename Editor/ShaderDrawers/ExtraDrawers/{Texture => Numeric}/RampAtlasIndexerDrawer.cs.meta (83%) diff --git a/Editor/AssetProcessor/ShaderModifyListener.cs b/Editor/AssetProcessor/ShaderModifyListener.cs index 5d877f6..689a53d 100644 --- a/Editor/AssetProcessor/ShaderModifyListener.cs +++ b/Editor/AssetProcessor/ShaderModifyListener.cs @@ -22,6 +22,8 @@ private static void OnPostprocessAllAssets(string[] importedAssets, string[] del ) { var shader = AssetDatabase.LoadAssetAtPath(assetPath); + if (shader == null) continue; + MetaDataHelper.ReleaseShaderMetadataCache(shader); ShaderPerfMonitor.ClearShaderPerfCache(shader); ReflectionHelper.InvalidatePropertyCache(shader); diff --git a/Editor/Helper/IOHelper.cs b/Editor/Helper/IOHelper.cs index 060b312..aaa0dbb 100644 --- a/Editor/Helper/IOHelper.cs +++ b/Editor/Helper/IOHelper.cs @@ -66,6 +66,35 @@ public static string GetValidFileName(string text) public static bool ExistAndNotEmpty(string filePath) => File.Exists(filePath) && new FileInfo(filePath).Length > 1; + public static string GenerateUniqueFileName(string directory, string baseName, string extension) + { + var absDirectory = GetAbsPath(directory); + + string rootName = baseName; + int startIndex = 1; + + int lastUnderscore = baseName.LastIndexOf('_'); + if (lastUnderscore >= 0 && lastUnderscore < baseName.Length - 1 + && int.TryParse(baseName.Substring(lastUnderscore + 1), out int existingIndex)) + { + rootName = baseName.Substring(0, lastUnderscore); + startIndex = existingIndex + 1; + } + + if (!File.Exists(Path.Combine(absDirectory, baseName + "." + extension))) + return baseName; + + int index = startIndex; + string candidate; + do + { + candidate = rootName + "_" + index; + index++; + } while (File.Exists(Path.Combine(absDirectory, candidate + "." + extension))); + + return candidate; + } + public static void WriteBinaryFile(string filePath, byte[] bytes) { try @@ -105,6 +134,26 @@ public static string ReadTextFile(string filePath) } } + /// + /// Displays the "save file" dialog and returns the selected path name. + /// + /// The title of the window to display. + /// The working directory that this dialog opens on. + /// The placeholder text to display in the "Save As" text field. This is the name of file to be saved. + /// The file extension to use in the saved file path. For example, enter "png" to save an image in the PNG format. + /// + /// A string absolute path to the saved file if the dialog was canceled or the save failed, it returns an empty string. + /// + public static string SaveFilePanel(string title, string relativeDirectory, string defaultName, string extension) + { + // When a new folder is created in the file selection window, the Current Work Directory is modified, which causes Unity to crash + var savedCwd = Directory.GetCurrentDirectory(); + var absPath = EditorUtility.SaveFilePanel(title, relativeDirectory, defaultName, extension); + Directory.SetCurrentDirectory(savedCwd); + + return absPath; + } + #endregion #region Process @@ -198,6 +247,9 @@ public static string GetCompiledShaderVariantCacheDirectory(Shader shader, Shade public static void ClearShaderPerfCache(Shader shader) { + if (shader == null) + return; + try { var shaderDir = GetCompiledShaderCacheRootDirectory(shader); diff --git a/Editor/Helper/MetaDataHelper.cs b/Editor/Helper/MetaDataHelper.cs index 7b82285..cdcbc20 100644 --- a/Editor/Helper/MetaDataHelper.cs +++ b/Editor/Helper/MetaDataHelper.cs @@ -114,7 +114,7 @@ public static void ReleaseAllShadersMetadataCache() public static void ReleaseShaderMetadataCache(Shader shader) { - if (shader && _perShaderCachesDic.ContainsKey(shader)) + if (shader) _perShaderCachesDic.Remove(shader); } @@ -128,18 +128,17 @@ public static void ReleaseAllMaterialsMetadataCache(Shader shader) public static void ReleaseMaterialMetadataCache(Material material) { if (material - && material.shader - && _perShaderCachesDic.ContainsKey(material.shader) - && _perShaderCachesDic[material.shader].perMaterialDataCachesDic.ContainsKey(material)) + && material.shader + && _perShaderCachesDic.ContainsKey(material.shader)) _perShaderCachesDic[material.shader].perMaterialDataCachesDic.Remove(material); } public static void ForceUpdateAllMaterialsMetadataCache(Shader shader) { - if (shader && _perShaderCachesDic.ContainsKey(shader)) + if (shader && _perShaderCachesDic.TryGetValue(shader, out var perShaderCache)) { - foreach (var perMaterialCachKWPair in _perShaderCachesDic[shader].perMaterialDataCachesDic) - perMaterialCachKWPair.Value.perMaterialData.forceInit = true; + foreach (var perMaterialCacheKWPair in perShaderCache.perMaterialDataCachesDic) + perMaterialCacheKWPair.Value.perMaterialData.forceInit = true; } } diff --git a/Editor/Helper/ToolbarHelper.cs b/Editor/Helper/ToolbarHelper.cs index 088db86..05b7649 100644 --- a/Editor/Helper/ToolbarHelper.cs +++ b/Editor/Helper/ToolbarHelper.cs @@ -267,6 +267,7 @@ private static bool FindMaterialAssetByMaterialInstance(Material material, LWGUI materialAsset = onFindMaterialAssetInRendererByMaterialInstance(renderer, material); } + // Look for renderer.sharedMaterials as a fallback, if the runtime has modified the sharedMaterials will not work if (materialAsset == null) { int index = renderer.materials.ToList().FindIndex(materialInstance => materialInstance == material); diff --git a/Editor/ScriptableObject/LwguiRampAtlas.cs b/Editor/ScriptableObject/LwguiRampAtlas.cs index c1ce475..b383f5d 100644 --- a/Editor/ScriptableObject/LwguiRampAtlas.cs +++ b/Editor/ScriptableObject/LwguiRampAtlas.cs @@ -348,10 +348,8 @@ private void OnEnable() private void OnValidate() { - // Skip at the end of compilation - if (Event.current == null - // Skip when editing Text Field - || EditorGUIUtility.editingTextField) + // It is only called when the user manually saves it, avoiding some strange bugs + if (!_saveTextureToggle) return; InitData(); @@ -504,10 +502,7 @@ public static LwguiRampAtlas SaveRampAtlasSOToAsset(LwguiRampAtlas rampAtlasSO, string createdFileRelativePath = string.Empty; while (true) { - // TODO: Warning: - // PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead - var absPath = EditorUtility.SaveFilePanel("Create a Ramp Atlas SO", rootPath, defaultFileName, "asset"); - + var absPath = IOHelper.SaveFilePanel("Create a Ramp Atlas SO", rootPath, defaultFileName, "asset"); if (absPath.StartsWith(IOHelper.ProjectPath)) { createdFileRelativePath = IOHelper.GetRelativePath(absPath); diff --git a/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs b/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs index 196230a..b9317fc 100644 --- a/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs +++ b/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs @@ -9,7 +9,7 @@ namespace LWGUI /// Control whether the property can be edited based on multiple conditions. /// /// logicalOperator: And | Or (Default: And). - /// propName: Target Property Name used for comparison. + /// propNameOrKeyword: Target Property Name or Keyword used for comparison. If no matching property is found, it falls back to checking material keywords (enabled = 1, disabled = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). /// value: Target Property Value used for comparison. /// @@ -17,12 +17,12 @@ public class ActiveIfDecorator : SubDrawer { public ShowIfDecorator.ShowIfData activeIfData = new(); - public ActiveIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } + public ActiveIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } - public ActiveIfDecorator(string logicalOperator, string propName, string compareFunction, float value) + public ActiveIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) { activeIfData.logicalOperator = logicalOperator.ToLower() == "or" ? ShowIfDecorator.LogicalOperator.Or : ShowIfDecorator.LogicalOperator.And; - activeIfData.targetPropertyName = propName; + activeIfData.targetPropertyNameOrKeyword = propNameOrKeyword; activeIfData.compareFunction = ShowIfDecorator.ParseCompareFunction(compareFunction); activeIfData.value = value; } diff --git a/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs b/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs index c198e38..c998044 100644 --- a/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs +++ b/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs @@ -13,7 +13,7 @@ namespace LWGUI /// Control the show or hide of a single or a group of properties based on multiple conditions. /// /// logicalOperator: And | Or (Default: And). - /// propName: Target Property Name used for comparison. + /// propNameOrKeyword: Target Property Name or Keyword used for comparison. If no matching property is found, it falls back to checking material keywords (enabled = 1, disabled = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). /// value: Target Property Value used for comparison. /// @@ -27,10 +27,10 @@ public enum LogicalOperator public class ShowIfData { - public LogicalOperator logicalOperator = LogicalOperator.And; - public string targetPropertyName = string.Empty; - public CompareFunction compareFunction = CompareFunction.Equal; - public float value = 0; + public LogicalOperator logicalOperator = LogicalOperator.And; + public string targetPropertyNameOrKeyword = string.Empty; + public CompareFunction compareFunction = CompareFunction.Equal; + public float value = 0; } public ShowIfData showIfData = new(); @@ -68,12 +68,12 @@ public static CompareFunction ParseCompareFunction(string compareFunction) return (CompareFunction)Enum.Parse(typeof(CompareFunction), compareFunctionName); } - public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } + public ShowIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } - public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value) + public ShowIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) { showIfData.logicalOperator = logicalOperator.ToLower() == "or" ? LogicalOperator.Or : LogicalOperator.And; - showIfData.targetPropertyName = propName; + showIfData.targetPropertyNameOrKeyword = propNameOrKeyword; showIfData.compareFunction = ParseCompareFunction(compareFunction); showIfData.value = value; } @@ -137,12 +137,19 @@ public static bool GetShowIfResultToFilterDrawerApplying(MaterialProperty prop) return GetShowIfResultFromMaterial(showIfDatas, material); } + public static float GetTargetValue(ShowIfData showIfData, Material material) + { + if (material.HasProperty(showIfData.targetPropertyNameOrKeyword)) + return material.GetFloat(showIfData.targetPropertyNameOrKeyword); + return material.IsKeywordEnabled(showIfData.targetPropertyNameOrKeyword) ? 1f : 0f; + } + public static bool GetShowIfResultFromMaterial(List showIfDatas, Material material) { bool result = true; foreach (var showIfData in showIfDatas) { - var targetValue = material.GetFloat(showIfData.targetPropertyName); + var targetValue = GetTargetValue(showIfData, material); Compare(showIfData, targetValue, ref result); } @@ -153,7 +160,11 @@ public static void GetShowIfResult(PropertyStaticData propStaticData, PropertyDy { foreach (var showIfData in propStaticData.showIfDatas) { - var targetValue = perMaterialData.propDynamicDatas[showIfData.targetPropertyName].property.floatValue; + float targetValue; + if (perMaterialData.propDynamicDatas.TryGetValue(showIfData.targetPropertyNameOrKeyword, out var targetPropDynamicData)) + targetValue = targetPropDynamicData.property.floatValue; + else + targetValue = perMaterialData.material.IsKeywordEnabled(showIfData.targetPropertyNameOrKeyword) ? 1f : 0f; Compare(showIfData, targetValue, ref propDynamicData.isShowing); } } diff --git a/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs b/Editor/ShaderDrawers/ExtraDrawers/Numeric/RampAtlasIndexerDrawer.cs similarity index 100% rename from Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs rename to Editor/ShaderDrawers/ExtraDrawers/Numeric/RampAtlasIndexerDrawer.cs diff --git a/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta b/Editor/ShaderDrawers/ExtraDrawers/Numeric/RampAtlasIndexerDrawer.cs.meta similarity index 83% rename from Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta rename to Editor/ShaderDrawers/ExtraDrawers/Numeric/RampAtlasIndexerDrawer.cs.meta index ce22f6e..e5bf24a 100644 --- a/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta +++ b/Editor/ShaderDrawers/ExtraDrawers/Numeric/RampAtlasIndexerDrawer.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a4fd29490f9fb904680cb50a2f83ceb5 +guid: 66c9d8ae70e49244196e7e2bd4b437d5 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs b/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs index 4bf8939..6397144 100644 --- a/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs +++ b/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs @@ -40,6 +40,14 @@ public class RampDrawer : SubDrawer private static readonly float _rampButtonsHeight = EditorGUIUtility.singleLineHeight; + + private static string _lastSaveDirectoryPrefKey = nameof(_lastSaveDirectoryPrefKey) + ": " + Application.dataPath; + private static string _lastSaveDirectory + { + get => EditorPrefs.GetString(_lastSaveDirectoryPrefKey, string.Empty); + set => EditorPrefs.SetString(_lastSaveDirectoryPrefKey, value); + } + protected virtual float rampPreviewHeight => EditorGUIUtility.singleLineHeight; protected override float GetVisibleHeight(MaterialProperty prop) { return rampPreviewHeight + _rampButtonsHeight; } @@ -128,16 +136,34 @@ protected virtual void CreateNewRampMap(MaterialProperty prop, MaterialEditor ed protected virtual void CloneRampMap(MaterialProperty prop, MaterialEditor editor, LwguiGradient gradient) { string createdFileRelativePath = string.Empty; + + string dialogDirectory = rootPath; + string dialogFileName = defaultFileName; + string absRootPath = IOHelper.GetAbsPath(rootPath); + string lastSaveDirectory = _lastSaveDirectory; + string absLastSaveDirectory = IOHelper.GetAbsPath(lastSaveDirectory); + + + if (gradient != null && prop.textureValue != null) + { + var currentPath = AssetDatabase.GetAssetPath(prop.textureValue); + if (!string.IsNullOrEmpty(currentPath) && currentPath.StartsWith(rootPath)) + { + dialogDirectory = Path.GetDirectoryName(currentPath); + var baseName = Path.GetFileNameWithoutExtension(currentPath); + dialogFileName = IOHelper.GenerateUniqueFileName(dialogDirectory, baseName, fileExtension); + } + } + else if (!string.IsNullOrEmpty(lastSaveDirectory) && lastSaveDirectory.StartsWith(rootPath) && Directory.Exists(absLastSaveDirectory)) + { + dialogDirectory = lastSaveDirectory; + } + + Directory.CreateDirectory(IOHelper.GetAbsPath(dialogDirectory)); + while (true) { - var absRootPath = IOHelper.GetAbsPath(rootPath); - if (!Directory.Exists(absRootPath)) - Directory.CreateDirectory(absRootPath); - - // TODO: Warning: - // PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead - var absPath = EditorUtility.SaveFilePanel(saveFilePanelTitle, rootPath, defaultFileName, fileExtension); - + var absPath = IOHelper.SaveFilePanel(saveFilePanelTitle, dialogDirectory, dialogFileName, fileExtension); if (absPath.StartsWith(absRootPath)) { createdFileRelativePath = IOHelper.GetRelativePath(absPath); @@ -156,6 +182,8 @@ protected virtual void CloneRampMap(MaterialProperty prop, MaterialEditor editor if (!string.IsNullOrEmpty(createdFileRelativePath)) { + _lastSaveDirectory = Path.GetDirectoryName(createdFileRelativePath); + var width = prop.textureValue != null ? prop.textureValue.width : defaultWidth; var height = prop.textureValue != null ? prop.textureValue.height : defaultHeight; RampHelper.CreateAndSaveNewGradientTexture(width, height, createdFileRelativePath, colorSpace == ColorSpace.Linear, gradient); @@ -224,7 +252,25 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l OnRampPropUpdate(position, prop, label, editor); - var gradient = GetLwguiGradient(prop, out var isDirty); + LwguiGradient gradient = null; + var isDirty = false; + string gradientErrorMessage = null; + + try + { + gradient = GetLwguiGradient(prop, out isDirty); + } + catch (System.Exception e) + { + gradientErrorMessage = "Ramp data corrupted! Check Console for details."; + Debug.LogError("LWGUI: Failed to parse gradient from '" + prop.displayName + "': " + e.Message); + } + + if (gradient == null && gradientErrorMessage == null + && prop.GetPropertyType() == ShaderPropertyType.Texture && prop.textureValue != null) + { + gradientErrorMessage = "Ramp data missing or corrupted! Check Console for details."; + } // Draw Label var labelRect = new Rect(position); @@ -243,61 +289,68 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l if (buttonRect.width < 50f) return; } - // Draw Ramp Editor - RampHelper.RampEditor(buttonRect, ref gradient, colorSpace, viewChannelMask, timeRange, isDirty, - out bool hasGradientChanges, - out bool doEditWhenNoGradient, - out doRegisterUndo, - out bool doClone, - out bool doCreate, - out bool doSaveGradient, - out bool doDiscardGradient, - OnGradientEditorChange); - - // Edit When No Gradient - if (doEditWhenNoGradient) + if (gradientErrorMessage != null) { - EditWhenNoRampMap(prop, editor); + EditorGUI.HelpBox(buttonRect, gradientErrorMessage, MessageType.Error); } - - // Clone - if (doClone) - { - LwguiGradientWindow.CloseWindow(); - CloneRampMap(prop, editor, gradient); - OnCreateNewRampMap(prop); - LWGUI.OnValidate(metaDatas); - } - - // Create - if (doCreate) + else { - LwguiGradientWindow.CloseWindow(); - CreateNewRampMap(prop, editor); - OnCreateNewRampMap(prop); - LWGUI.OnValidate(metaDatas); - } + // Draw Ramp Editor + RampHelper.RampEditor(buttonRect, ref gradient, colorSpace, viewChannelMask, timeRange, isDirty, + out bool hasGradientChanges, + out bool doEditWhenNoGradient, + out doRegisterUndo, + out bool doClone, + out bool doCreate, + out bool doSaveGradient, + out bool doDiscardGradient, + OnGradientEditorChange); + + // Edit When No Gradient + if (doEditWhenNoGradient) + { + EditWhenNoRampMap(prop, editor); + } - // Change - if (hasGradientChanges && gradient != null) - { - ChangeRampMap(prop, gradient); - OnEditRampMap(prop, gradient); - } - - // Save - if (doSaveGradient && gradient != null) - { - SaveRampMap(prop, gradient); - OnSaveRampMap(prop, gradient); - } + // Clone + if (doClone) + { + LwguiGradientWindow.CloseWindow(); + CloneRampMap(prop, editor, gradient); + OnCreateNewRampMap(prop); + LWGUI.OnValidate(metaDatas); + } + + // Create + if (doCreate) + { + LwguiGradientWindow.CloseWindow(); + CreateNewRampMap(prop, editor); + OnCreateNewRampMap(prop); + LWGUI.OnValidate(metaDatas); + } - // Discard - if (doDiscardGradient) - { - LwguiGradientWindow.CloseWindow(); - gradient = DiscardRampMap(prop, gradient); - OnDiscardRampMap(prop, gradient); + // Change + if (hasGradientChanges && gradient != null) + { + ChangeRampMap(prop, gradient); + OnEditRampMap(prop, gradient); + } + + // Save + if (doSaveGradient && gradient != null) + { + SaveRampMap(prop, gradient); + OnSaveRampMap(prop, gradient); + } + + // Discard + if (doDiscardGradient) + { + LwguiGradientWindow.CloseWindow(); + gradient = DiscardRampMap(prop, gradient); + OnDiscardRampMap(prop, gradient); + } } // Texture Object Field, handle switch texture event diff --git a/README.md b/README.md index 4dfe422..27281ef 100644 --- a/README.md +++ b/README.md @@ -940,11 +940,11 @@ public HiddenDecorator() /// Control the show or hide of a single or a group of properties based on multiple conditions. /// /// logicalOperator: And | Or (Default: And). -/// propName: Target Property Name used for comparison. +/// propNameOrKeyword: Target Property Name or Keyword used for comparison. If no matching property is found, it falls back to checking material keywords (enabled = 1, disabled = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). /// value: Target Property Value used for comparison. -public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } -public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value) +public ShowIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } +public ShowIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) ``` Example: @@ -980,13 +980,13 @@ Example: /// Control whether a single property or a group can be edited based on multiple conditions. /// /// logicalOperator: And | Or (Default: And). -/// propName: Target Property Name used for comparison. +/// propNameOrKeyword: Target Property Name or Keyword used for comparison. If no matching property is found, it falls back to checking material keywords (enabled = 1, disabled = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). /// value: Target Property Value used for comparison. /// /// When the condition is false, the property is read-only. -public ActiveIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } -public ActiveIfDecorator(string logicalOperator, string propName, string compareFunction, float value) +public ActiveIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } +public ActiveIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) ``` Example: diff --git a/README_CN.md b/README_CN.md index 1c3f86f..5c21b47 100644 --- a/README_CN.md +++ b/README_CN.md @@ -934,14 +934,14 @@ public HiddenDecorator() #### ShowIf ```c# -/// Control the show or hide of a single or a group of properties based on multiple conditions. +/// 基于多个条件控制单个或一组属性的显示/隐藏. /// -/// logicalOperator: And | Or (Default: And). -/// propName: Target Property Name used for comparison. +/// logicalOperator: And | Or (默认: And). +/// propNameOrKeyword: 用于比较的目标属性名或Keyword. 若未找到匹配的属性, 则回退为检查材质Keyword (启用 = 1, 未启用 = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). -/// value: Target Property Value used for comparison. -public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } -public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value) +/// value: 用于比较的目标值. +public ShowIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } +public ShowIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) ``` Example: @@ -977,13 +977,13 @@ Example: /// 基于多个条件控制单个属性或一组属性是否可编辑. /// /// logicalOperator: And | Or (默认: And). -/// propName: 用于比较的目标属性名. +/// propNameOrKeyword: 用于比较的目标属性名或Keyword. 若未找到匹配的属性, 则回退为检查材质Keyword (启用 = 1, 未启用 = 0). /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). /// value: 用于比较的目标值. /// /// 当条件为 false 时, 属性会变为只读. -public ActiveIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } -public ActiveIfDecorator(string logicalOperator, string propName, string compareFunction, float value) +public ActiveIfDecorator(string propNameOrKeyword, string comparisonMethod, float value) : this("And", propNameOrKeyword, comparisonMethod, value) { } +public ActiveIfDecorator(string logicalOperator, string propNameOrKeyword, string compareFunction, float value) ``` 示例: diff --git a/Test/SampleKeyword.shader b/Test/SampleKeyword.shader index ce30e9a..e71cbcb 100644 --- a/Test/SampleKeyword.shader +++ b/Test/SampleKeyword.shader @@ -4,11 +4,11 @@ Shader "Hidden" { [Preset(_, LWGUI_ShaderPropertyPreset2)] _preset2 ("Preset", float) = 0 - [KeywordEnum(key1, key2)] - _keywordEnum ("KeywordEnum", float) = 0 + [KeywordEnum(key1, key2)] _keywordEnum ("KeywordEnum", float) = 0 - [KWEnum(_, Name 1, _KWENUM_KEY1, Name 2, _KWENUM_KEY2)] - _kwenum ("KWEnum", float) = 0 + [KWEnum(_, Name 1, _KWENUM_KEY1, Name 2, _KWENUM_KEY2)] _kwenum ("KWEnum", float) = 0 + [ShowIf(_KWENUM_KEY1, E, 1)] _float1 ("Show If - Name 1", float) = 0 + [ActiveIf(_KWENUM_KEY2, E, 1)] _float2 ("Active If - Name 2", float) = 0 [Toggle(_TOGGLE_KEYWORD)] _toggle1 ("Toggle", float) = 0 @@ -18,8 +18,7 @@ Shader "Hidden" [SubEnum(g0, Off, 0, On, 1)] _ZWrite ("ZWrite Mode", Float) = 1 [SubToggle(g0, _SUBTOGGLE_KEYWORD)] _toggle ("Sub Toggle", float) = 0 - [SubKeywordEnum(g0, key1, key2)] - _subKeywordEnum ("SubKeywordEnum", float) = 0 + [SubKeywordEnum(g0, key1, key2)] _subKeywordEnum ("SubKeywordEnum", float) = 0 } SubShader { diff --git a/package.json b/package.json index 789ebb1..e6cef5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.jasonma.lwgui", - "version": "1.33.0", + "version": "1.34.0", "displayName": "LWGUI", "description": "A Lightweight, Flexible, Powerful Shader GUI System for Unity.", "keywords": [