Skip to content

Commit

Permalink
Add ShowIf()
Browse files Browse the repository at this point in the history
Add ShowIf() to control the show or hide of a single or a group of properties based on multiple conditions.
  • Loading branch information
JasonMa0012 committed Oct 22, 2023
1 parent 1bdbb23 commit 03300ae
Show file tree
Hide file tree
Showing 22 changed files with 541 additions and 83 deletions.
4 changes: 2 additions & 2 deletions Editor/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ public static void DrawToolbarButtons(ref Rect toolBarRect, LWGUI lwgui)
foreach (var propertyStaticDataPair in lwgui.perShaderData.propertyDatas)
{
if (propertyStaticDataPair.Value.isMain || propertyStaticDataPair.Value.isAdvancedHeader)
propertyStaticDataPair.Value.isExpanded = true;
propertyStaticDataPair.Value.isExpanding = true;
}
}

Expand All @@ -546,7 +546,7 @@ public static void DrawToolbarButtons(ref Rect toolBarRect, LWGUI lwgui)
foreach (var propertyStaticDataPair in lwgui.perShaderData.propertyDatas)
{
if (propertyStaticDataPair.Value.isMain || propertyStaticDataPair.Value.isAdvancedHeader)
propertyStaticDataPair.Value.isExpanded = false;
propertyStaticDataPair.Value.isExpanding = false;
}
}

Expand Down
6 changes: 3 additions & 3 deletions Editor/LWGUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] pro
var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect);
var label = string.IsNullOrEmpty(propStaticData.advancedHeaderString) ? "Advanced" : propStaticData.advancedHeaderString;
RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, this);
propStaticData.isExpanded = EditorGUI.Foldout(rect, propStaticData.isExpanded, label);
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, label);

if (!propStaticData.isExpanded)
if (!propStaticData.isExpanding)
{
RevertableHelper.SetRevertableGUIWidths();
EditorGUI.indentLevel = indentLevel;
Expand Down Expand Up @@ -163,7 +163,7 @@ private void DrawProperty(MaterialProperty prop)
RevertableHelper.FixGUIWidthMismatch(prop.type, materialEditor);
RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, this);
if (propStaticData.isAdvancedHeaderProperty)
propStaticData.isExpanded = EditorGUI.Foldout(rect, propStaticData.isExpanded, string.Empty);
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, string.Empty);
materialEditor.ShaderProperty(rect, prop, label);
Helper.EndProperty(this, prop);
}
Expand Down
109 changes: 86 additions & 23 deletions Editor/MetaDataHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

namespace LWGUI
{
Expand All @@ -15,6 +16,12 @@ public enum SearchMode
Num = 3
}

public enum LogicalOperator
{
And,
Or
}

public struct DisplayModeData
{
public bool showAllAdvancedProperties;
Expand All @@ -27,6 +34,14 @@ public struct DisplayModeData
public bool IsDefaultDisplayMode() { return !(showAllAdvancedProperties || showAllHiddenProperties || showOnlyModifiedProperties); }
}

public class ShowIfData
{
public LogicalOperator logicalOperator = LogicalOperator.And;
public string targetPropertyName = string.Empty;
public CompareFunction compareFunction = CompareFunction.Equal;
public float value = 0;
}

/// <summary>
/// All static metadata for a Property, determined after the Shader is compiled.
/// </summary>
Expand All @@ -46,10 +61,11 @@ public class PropertyStaticData
public List<PropertyStaticData> children = new List<PropertyStaticData>();

// Visibility
public string conditionalDisplayKeyword = string.Empty; // [Group(groupName_conditionalDisplayKeyword)]
public bool isSearchDisplayed = true; // Draws when the search match is successful
public bool isExpanded = false; // Draws when the group has been expanded
public bool isHidden = false; // [Hidden]
public string conditionalDisplayKeyword = string.Empty; // [Group(groupName_conditionalDisplayKeyword)]
public bool isSearchMatched = true; // Draws when the search match is successful
public bool isExpanding = false; // Draws when the group is expanding
public bool isHidden = false; // [Hidden]
public List<ShowIfData> showIfDatas = new List<ShowIfData>(); // [ShowIf()]

// Metadata
public List<string> extraPropNames = new List<string>(); // Other Props that have been associated
Expand Down Expand Up @@ -244,7 +260,7 @@ public void UpdateSearchFilter()
// The First Search
foreach (var propertyData in propertyDatas)
{
propertyData.Value.isSearchDisplayed = isSearchStringEmpty
propertyData.Value.isSearchMatched = isSearchStringEmpty
? true
: IsWholeWordMatch(propertyData.Value.displayName, propertyData.Key, searchKeywords);
}
Expand All @@ -257,7 +273,7 @@ public void UpdateSearchFilter()
if (searchModeTemp == SearchMode.Auto)
{
// if has no group
if (!propertyDatas.Any((propertyData => propertyData.Value.isSearchDisplayed && propertyData.Value.isMain)))
if (!propertyDatas.Any((propertyData => propertyData.Value.isSearchMatched && propertyData.Value.isMain)))
searchModeTemp = SearchMode.Property;
else
searchModeTemp = SearchMode.Group;
Expand All @@ -269,8 +285,8 @@ public void UpdateSearchFilter()
// when a SubProp is displayed, the MainProp is also displayed
foreach (var propertyData in propertyDatas)
{
if (propertyData.Value.isMain && propertyData.Value.children.Any((childPropertyData => childPropertyData.isSearchDisplayed)))
propertyData.Value.isSearchDisplayed = true;
if (propertyData.Value.isMain && propertyData.Value.children.Any((childPropertyData => childPropertyData.isSearchMatched)))
propertyData.Value.isSearchMatched = true;
}
}
// search by group
Expand All @@ -281,7 +297,7 @@ public void UpdateSearchFilter()
{
if (propertyData.Value.isMain)
foreach (var childPropertyData in propertyData.Value.children)
childPropertyData.isSearchDisplayed = propertyData.Value.isSearchDisplayed;
childPropertyData.isSearchMatched = propertyData.Value.isSearchMatched;
}
}
}
Expand All @@ -308,7 +324,7 @@ public void ToggleShowAllAdvancedProperties()
foreach (var propertyStaticDataPair in propertyDatas)
{
if (propertyStaticDataPair.Value.isAdvancedHeader)
propertyStaticDataPair.Value.isExpanded = displayModeData.showAllAdvancedProperties;
propertyStaticDataPair.Value.isExpanding = displayModeData.showAllAdvancedProperties;
}
}
}
Expand All @@ -321,8 +337,9 @@ public class PropertyDynamicData
public MaterialProperty property;
public MaterialProperty defualtProperty; // Default values may be overridden by Preset
public string defaultValueDescription = string.Empty; // Description of the default values used in Tooltip
public bool hasModified = false; // Are properties modified in the material?
public bool revertChanged = false; // Used to call property EndChangeCheck()
public bool hasModified = false; // Are properties modified in the material?
public bool hasRevertChanged = false; // Used to call property EndChangeCheck()
public bool isShowing = true; // ShowIf() result

}

Expand Down Expand Up @@ -355,6 +372,8 @@ public void BuildPerFrameData(Shader shader, Material material, MaterialProperty
{
List<MaterialPropertyDrawer> decoratorDrawers;
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);

// Get Presets
if (drawer != null)
{
if (drawer is IBasePresetDrawer)
Expand Down Expand Up @@ -400,10 +419,13 @@ public void BuildPerFrameData(Shader shader, Material material, MaterialProperty

foreach (var prop in props)
{
var propStaticData = perShaderData.propertyDatas[prop.name];
var propDynamicData = propertyDatas[prop.name];

// Override parent hasModified
if (propertyDatas[prop.name].hasModified)
if (propDynamicData.hasModified)
{
var parentPropData = perShaderData.propertyDatas[prop.name].parent;
var parentPropData = propStaticData.parent;
if (parentPropData != null)
{
propertyDatas[parentPropData.name].hasModified = true;
Expand All @@ -413,9 +435,9 @@ public void BuildPerFrameData(Shader shader, Material material, MaterialProperty
}

// Get default value descriptions
List<MaterialPropertyDrawer> decoratorDrawers;
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);
{
List<MaterialPropertyDrawer> decoratorDrawers;
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);
if (decoratorDrawers != null && decoratorDrawers.Count > 0)
{
foreach (var decoratorDrawer in decoratorDrawers)
Expand All @@ -429,9 +451,48 @@ public void BuildPerFrameData(Shader shader, Material material, MaterialProperty
if (drawer is IBaseDrawer)
(drawer as IBaseDrawer).GetDefaultValueDescription(shader, prop, perShaderData, this);
}
if (string.IsNullOrEmpty(propertyDatas[prop.name].defaultValueDescription))
propertyDatas[prop.name].defaultValueDescription =
RevertableHelper.GetPropertyDefaultValueText(propertyDatas[prop.name].defualtProperty);
if (string.IsNullOrEmpty(propDynamicData.defaultValueDescription))
propDynamicData.defaultValueDescription =
RevertableHelper.GetPropertyDefaultValueText(propDynamicData.defualtProperty);
}

// Get ShowIf() results
foreach (var showIfData in propStaticData.showIfDatas)
{
var propCurrentValue = propertyDatas[showIfData.targetPropertyName].property.floatValue;
bool compareResult;

switch (showIfData.compareFunction)
{
case CompareFunction.Less:
compareResult = propCurrentValue < showIfData.value;
break;
case CompareFunction.LessEqual:
compareResult = propCurrentValue <= showIfData.value;
break;
case CompareFunction.Greater:
compareResult = propCurrentValue > showIfData.value;
break;
case CompareFunction.NotEqual:
compareResult = propCurrentValue != showIfData.value;
break;
case CompareFunction.GreaterEqual:
compareResult = propCurrentValue >= showIfData.value;
break;
default:
compareResult = propCurrentValue == showIfData.value;
break;
}

switch (showIfData.logicalOperator)
{
case LogicalOperator.And:
propDynamicData.isShowing &= compareResult;
break;
case LogicalOperator.Or:
propDynamicData.isShowing |= compareResult;
break;
}
}
}
}
Expand All @@ -457,8 +518,8 @@ public bool EndChangeCheck(string propName = null)
var result = EditorGUI.EndChangeCheck();
if (!string.IsNullOrEmpty(propName))
{
result |= propertyDatas[propName].revertChanged;
propertyDatas[propName].revertChanged = false;
result |= propertyDatas[propName].hasRevertChanged;
propertyDatas[propName].hasRevertChanged = false;
}
return result;
}
Expand Down Expand Up @@ -531,12 +592,14 @@ public static bool GetPropertyVisibility(MaterialProperty prop, Material materia
if ( // if HideInInspector
Helper.IsPropertyHideInInspector(prop)
// if Search Filtered
|| !propertyStaticData.isSearchDisplayed
|| !propertyStaticData.isSearchMatched
// if the Conditional Display Keyword is not active
|| (!string.IsNullOrEmpty(propertyStaticData.conditionalDisplayKeyword) && !material.shaderKeywords.Any((str => str == propertyStaticData.conditionalDisplayKeyword)))
|| (!displayModeData.showAllHiddenProperties && propertyStaticData.isHidden)
// if show modified only
|| (displayModeData.showOnlyModifiedProperties && !propertyDynamicData.hasModified)
// ShowIf() == false
|| !propertyDynamicData.isShowing
)
{
result = false;
Expand All @@ -550,7 +613,7 @@ public static bool GetParentPropertyVisibility(PropertyStaticData parentPropStat
bool result = true;

if (parentPropStaticData != null
&& (!lwgui.perShaderData.propertyDatas[parentPropStaticData.name].isExpanded
&& (!lwgui.perShaderData.propertyDatas[parentPropStaticData.name].isExpanding
|| !MetaDataHelper.GetPropertyVisibility(lwgui.perFrameData.propertyDatas[parentPropStaticData.name].property, material, lwgui)))
{
result = false;
Expand Down
3 changes: 1 addition & 2 deletions Editor/ReflectionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,8 @@ public static void ShowModal(EditorWindow window)


#region MaterialProperty.PropertyData

private static Type MaterialProperty_Type = typeof(MaterialProperty);
#if UNITY_2022_1_OR_NEWER
private static Type MaterialProperty_Type = typeof(MaterialProperty);
private static Type PropertyData_Type = MaterialProperty_Type.GetNestedType("PropertyData", BindingFlags.NonPublic);
// MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool overriden)
private static MethodInfo PropertyData_MergeStack_Method = PropertyData_Type.GetMethod("MergeStack", BindingFlags.Static | BindingFlags.NonPublic);
Expand Down
4 changes: 2 additions & 2 deletions Editor/RevertableHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ private static void DoRevertProperty(MaterialProperty prop, LWGUI lwgui)
{
var propDynamicData = lwgui.perFrameData.propertyDatas[prop.name];
var extraPropNames = lwgui.perShaderData.propertyDatas[prop.name].extraPropNames;
propDynamicData.revertChanged = true;
propDynamicData.hasRevertChanged = true;
SetPropertyToDefault(propDynamicData.defualtProperty, prop);
foreach (var extraPropName in extraPropNames)
{
var extraPropDynamicData = lwgui.perFrameData.propertyDatas[extraPropName];
extraPropDynamicData.revertChanged = true;
extraPropDynamicData.hasRevertChanged = true;
SetPropertyToDefault(extraPropDynamicData.defualtProperty, extraPropDynamicData.property);
}
}
Expand Down
38 changes: 36 additions & 2 deletions Editor/ShaderDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;

namespace LWGUI
Expand Down Expand Up @@ -62,7 +63,7 @@ public virtual void BuildStaticMetaData(Shader inShader, MaterialProperty inProp
{
inoutPropertyStaticData.groupName = _group;
inoutPropertyStaticData.isMain = true;
inoutPropertyStaticData.isExpanded = _defaultFoldingState;
inoutPropertyStaticData.isExpanding = _defaultFoldingState;
}

public virtual void GetDefaultValueDescription(Shader inShader,
Expand All @@ -85,7 +86,7 @@ public override void OnGUI(Rect position, MaterialProperty prop, GUIContent labe

EditorGUI.BeginChangeCheck();

bool toggleResult = Helper.DrawFoldout(position, ref propertyStaticData.isExpanded, prop.floatValue > 0, _defaultToggleDisplayed, label);
bool toggleResult = Helper.DrawFoldout(position, ref propertyStaticData.isExpanding, prop.floatValue > 0, _defaultToggleDisplayed, label);

if (Helper.EndChangeCheck(lwgui, prop))
{
Expand Down Expand Up @@ -1328,4 +1329,37 @@ public override void BuildStaticMetaData(Shader inShader, MaterialProperty inPro

public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { }
}

/// <summary>
/// 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.
/// compareFunction: Less | Greater | LEqual | GEqual | Equal | NotEqual.
/// value: Target Property Value used for comparison.
/// </summary>
public class ShowIfDecorator : SubDrawer
{
private ShowIfData _showIfData = new ShowIfData();

public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { }
public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value)
{
_showIfData.logicalOperator = logicalOperator.ToLower() == "or" ? LogicalOperator.Or : LogicalOperator.And;
_showIfData.targetPropertyName = propName;
if (!Enum.IsDefined(typeof(CompareFunction), compareFunction))
Debug.LogError("Invalid compareFunction: '" + compareFunction + "', Must be one of the following: Less | Greater | LEqual | GEqual | Equal | NotEqual | Always.");
else
_showIfData.compareFunction = (CompareFunction)Enum.Parse(typeof(CompareFunction), compareFunction);
_showIfData.value = value;
}

protected override float GetVisibleHeight(MaterialProperty prop) { return 0; }

public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData)
{
inoutPropertyStaticData.showIfDatas.Add(_showIfData);
}

public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { }
}
} //namespace LWGUI
2 changes: 1 addition & 1 deletion Editor/ShaderPropertyPreset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void Apply(Material material, bool isDefaultMaterial, PerFrameData perFra
break;
}

propDynamicData.revertChanged = true;
propDynamicData.hasRevertChanged = true;
}
}

Expand Down
Loading

0 comments on commit 03300ae

Please sign in to comment.