// MIT License - Copyright (c) 2025 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Core.Attributes { using System; using System.Collections.Generic; using UnityEngine; using WallstopStudios.UnityHelpers.Utils; /// /// Comparison strategy applied when resolving visibility. /// public enum WShowIfComparison { /// /// Reserved value. Prefer selecting a specific comparison mode. /// [Obsolete("WShowIfComparison.Unknown is reserved. Choose an explicit comparison mode.")] Unknown = 0, /// /// Shows the property when the condition evaluates to true or matches the provided expected values. /// Equal = 1, /// /// Shows the property when the condition evaluates to false or does not match the provided expected values. /// NotEqual = 2, /// /// Shows the property when the condition is greater than the expected value (numbers and comparable types). /// GreaterThan = 3, /// /// Shows the property when the condition is greater than or equal to the expected value (numbers and comparable types). /// GreaterThanOrEqual = 4, /// /// Shows the property when the condition is less than the expected value (numbers and comparable types). /// LessThan = 5, /// /// Shows the property when the condition is less than or equal to the expected value (numbers and comparable types). /// LessThanOrEqual = 6, /// /// Shows the property when the condition resolves to null (supports semantics). /// IsNull = 7, /// /// Shows the property when the condition resolves to a non-null value (supports semantics). /// IsNotNull = 8, /// /// Shows the property when the condition resolves to a null or empty string, or an empty collection. /// IsNullOrEmpty = 9, /// /// Shows the property when the condition resolves to a non-empty string or collection. /// IsNotNullOrEmpty = 10, } /// /// Conditionally hides or shows a serialized field based on the value of another property or field on the same object. /// /// /// /// works with booleans, numbers, enums, strings, references, and even custom comparable types. /// You can specify comparison strategies such as or and /// optionally pass explicit expected values for equality checks. /// /// /// When multiple conditions are required, stack the attribute instance per rule or combine it with other inspector helpers such as /// to keep complex editors manageable. /// /// /// /// Basic boolean toggle: /// /// public bool advancedMode; /// /// [WShowIf(nameof(advancedMode))] /// public float advancedSetting; /// /// Numerical comparisons: /// /// public int upgradeLevel; /// /// [WShowIf(nameof(upgradeLevel), WShowIfComparison.GreaterThanOrEqual, 3)] /// public Ability ultimateAbility; /// /// Reference checks and inverse usage: /// /// public GameObject overridePrefab; /// /// [WShowIf(nameof(overridePrefab), WShowIfComparison.IsNull)] /// public GameObject fallbackPrefab; /// /// [WShowIf(nameof(overridePrefab), inverse: true)] /// public AbilityOverrides overrideSettings; /// /// public sealed class WShowIfAttribute : PropertyAttribute { /// /// Gets the name of the field or property that determines visibility. /// public readonly string conditionField; /// /// Gets a value indicating whether the visibility rule should be inverted. /// public readonly bool inverse; /// /// Gets the comparison strategy that should be applied to the condition value. /// public readonly WShowIfComparison comparison; /// /// Gets the explicit values that must match the condition field in order for the target to display. /// public object[] expectedValues; /// /// Configures a conditional visibility rule for an inspector field. /// /// Name of the member used for evaluation. /// Optional explicit values that should evaluate as visible. public WShowIfAttribute(string conditionField, params object[] expectedValues) : this(conditionField, false, WShowIfComparison.Equal, expectedValues) { } /// /// Configures a conditional visibility rule with explicit inversion for an inspector field. /// /// Name of the member used for evaluation. /// Set to true to flip the visibility result. /// Optional explicit values that should evaluate as visible. public WShowIfAttribute(string conditionField, bool inverse, params object[] expectedValues) : this(conditionField, inverse, WShowIfComparison.Equal, expectedValues) { } /// /// Configures a conditional visibility rule with a specific comparison mode. /// /// Name of the member used for evaluation. /// Comparison strategy applied to the condition value. /// Optional explicit values that should evaluate as visible. public WShowIfAttribute( string conditionField, WShowIfComparison comparison, params object[] expectedValues ) : this(conditionField, false, comparison, expectedValues) { } /// /// Configures a conditional visibility rule for an inspector field. /// /// Name of the member used for evaluation. /// Set to true to flip the visibility result. /// Comparison strategy applied to the condition value. /// Optional explicit values that should evaluate as visible. public WShowIfAttribute( string conditionField, bool inverse, WShowIfComparison comparison, params object[] expectedValues ) { if (string.IsNullOrEmpty(conditionField)) { throw new ArgumentException( "Condition member name cannot be null or empty.", nameof(conditionField) ); } this.conditionField = conditionField; this.inverse = inverse; this.comparison = comparison; if (expectedValues == null || expectedValues.Length == 0) { this.expectedValues = Array.Empty(); } else { using (Buffers.List.Get(out List buffer)) { buffer.AddRange(expectedValues); this.expectedValues = buffer.ToArray(); } } } } }