using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using UnityEngine; namespace AdvancedInspector { /// /// When a property is flagged this way, a help box is added after the inspector's field. /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] public class HelpAttribute : Attribute, IRuntimeAttribute { public const string IsNull = "HelpAttribute.IsValueNull"; public const string IsNullOrEmpty = "HelpAttribute.IsStringNullOrEmpty"; public const string IsMatch = "HelpAttribute.IsRegexMatch"; public delegate HelpAttribute HelpDelegate(); public delegate HelpAttribute HelpStaticDelegate(HelpAttribute help, object instance, object value); private HelpType type; /// /// Help type. /// Displays a specific icon. /// public HelpType Type { get { return type; } set { type = value; } } private string message; /// /// Help message. /// public string Message { get { return message; } set { message = value; } } private HelpPosition position = HelpPosition.After; /// /// By default, the helpbox is drawn after the field. /// If this is false, it is drawn before the field. /// public HelpPosition Position { get { return position; } set { position = value; } } private string regex; /// /// When using the IsRegex conditional, this string is used as a regular expresion. /// public string Regex { get { return regex; } set { regex = value; } } #region IRuntime Implementation private string methodName = ""; public string MethodName { get { return methodName; } } public Type Template { get { return typeof(HelpDelegate); } } public Type TemplateStatic { get { return typeof(HelpStaticDelegate); } } private List delegates = new List(); public List Delegates { get { return delegates; } set { delegates = value; } } public HelpAttribute Invoke(int index, object instance, object value) { if (delegates.Count == 0 || index >= delegates.Count) return this; try { if (delegates[index].Target == null) { return delegates[0].DynamicInvoke(this, instance, value) as HelpAttribute; } else { return delegates[0].DynamicInvoke() as HelpAttribute; } } catch (Exception e) { if (e is TargetInvocationException) e = ((TargetInvocationException)e).InnerException; Debug.LogError(string.Format("Invoking a method failed while trying to retrieve a Help attribute. The exception was \"{0}\".", e.Message)); return null; } } #endregion public HelpAttribute(string methodName) : this(methodName, HelpType.None, HelpPosition.After, "") { } public HelpAttribute(string methodName, HelpType type, string message) : this(methodName, type, HelpPosition.After, message) { } public HelpAttribute(HelpType type, string message) : this("", type, HelpPosition.After, message) { } public HelpAttribute(HelpType type, HelpPosition position, string message) : this("", type, position, message) { } public HelpAttribute(string methodName, HelpType type, HelpPosition position, string message) { this.methodName = methodName; this.type = type; this.position = position; this.message = message; } public HelpAttribute(Delegate method) { this.delegates.Add(method); } private static HelpAttribute IsValueNull(HelpAttribute help, object instance, object value) { if (value == null || (value is UnityEngine.Object && ((UnityEngine.Object)value) == null)) { return help; } return null; } private static HelpAttribute IsStringNullOrEmpty(HelpAttribute help, object instance, object value) { if (value is string && string.IsNullOrEmpty((string)value)) return help; return null; } private static HelpAttribute IsRegexMatch(HelpAttribute help, object instance, object value) { if (value == null) return null; string text = value.ToString(); if (System.Text.RegularExpressions.Regex.IsMatch(text, help.regex)) return help; return null; } } /// /// Because the internal enum for help display is Editor only. /// public enum HelpType { None = 0, Info = 1, Warning = 2, Error = 3, } /// /// The position where the help box should be placed. /// public enum HelpPosition { After, Before } }