using System; using Jovian.InspectorTools.Internal; using Jovian.Utilities.Editor; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace Jovian.InspectorTools { public class RequireArraySizeAttribute : ArrayAttribute, IPropertyCondition { public readonly int size; public readonly SizeComparison comparison; public enum SizeComparison { Equal, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual } public RequireArraySizeAttribute(int size, SizeComparison comparison = SizeComparison.Equal) { this.size = size; this.comparison = comparison; } #if UNITY_EDITOR private bool DoesArraySizeMeetCondition(int arraySize) { return comparison switch { SizeComparison.Equal => arraySize == size, SizeComparison.LessThan => arraySize < size, SizeComparison.LessThanOrEqual => arraySize <= size, SizeComparison.GreaterThan => arraySize > size, SizeComparison.GreaterThanOrEqual => arraySize >= size, _ => throw new ArgumentOutOfRangeException() }; } private string GetConditionString(int arraySize) { return comparison switch { SizeComparison.Equal => $"Array.size must be equal to {size} (current={arraySize})", SizeComparison.LessThan => $"Array.size must be less than {size} (current={arraySize})", SizeComparison.LessThanOrEqual => $"Array.size must be less than or equal to {size} (current={arraySize})", SizeComparison.GreaterThan => $"Array.size must be greater than {size} (current={arraySize})", SizeComparison.GreaterThanOrEqual => $"Array.size must be greater than or equal to {size} (current={arraySize})", _ => throw new ArgumentOutOfRangeException() }; } public bool DoesPropertyMeetCondition(SerializedProperty property, out string description) { description = string.Empty; if (!property.isArray && (property.propertyPath.EndsWith(".Array.size") || EditorSerializationUtility.IsPropertyAnArrayElement(property))) { return true; // don't check array conditions for elements } if (!property.isArray) { description = $"{property.name} must be an array"; return false; } if (!(property.isArray && DoesArraySizeMeetCondition(property.arraySize))) { description = GetConditionString(property.arraySize); return false; } return true; } public override void OnPreGUI(ref Rect position, SerializedProperty property, ref GUIContent label) { if (!DoesPropertyMeetCondition(property, out string description)) { RequiredUtil.LayoutRequired(ref position, description, indent: true); } } public override void OnPostGUI(ref Rect position, SerializedProperty property, ref GUIContent label) { if (!DoesPropertyMeetCondition(property, out string description)) { RequiredUtil.DrawRequired(ref position, description, indent: true); } } #endif } }