summaryrefslogtreecommitdiff
path: root/Assets/Plugins/AdvancedInspector/Attributes/Inspect.cs
blob: 210e35582109cd8839822123796c072eb2bc69fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
using System;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;

namespace AdvancedInspector
{
    /// <summary>
    /// Makes a property viewable in the Inspector of Unity.
    /// Turns a method into a button in the Inspector.
    /// You can input a conditional statement for your property to show up or not.
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method)]
    public class InspectAttribute : Attribute, IRuntimeAttribute<bool>
    {
        public delegate bool InspectDelegate();
        public delegate bool InspectStaticDelegate(InspectAttribute inspect, object instance, object value);

        private InspectorLevel level;

        /// <summary>
        /// Inspector level are use to hide more advanced item.
        /// Items under the current Inspector levels are hidden.
        /// </summary>
        public InspectorLevel Level
        {
            get { return level; }
            set { level = value; }
        }

        private bool condition = true;

        /// <summary>
        /// Inverse the condition used by the IRuntime method.
        /// </summary>
        public bool Condition
        {
            get { return condition; }
            set { condition = value; }
        }

        private int priority = 0;

        /// <summary>
        /// Priority of display of this item.
        /// Smaller values are displayed first. Negative value are supported.
        /// </summary>
        public int Priority
        {
            get { return priority; }
            set { priority = value; }
        }

        #region IRuntime Implementation
        private string methodName = "";

        public string MethodName
        {
            get { return methodName; }
            set { methodName = value; }
        }

        public Type Template
        {
            get { return typeof(InspectDelegate); }
        }

        public Type TemplateStatic
        {
            get { return typeof(InspectStaticDelegate); }
        }

        private List<Delegate> delegates = new List<Delegate>();

        public List<Delegate> Delegates
        {
            get { return delegates; }
            set { delegates = value; }
        }

        public bool Invoke(int index, object instance, object value)
        {
            if (delegates.Count == 0 || index >= delegates.Count)
                return true;

            try
            {
                if (delegates[index].Target == null)
                {
                    if (condition)
                        return (bool)delegates[index].DynamicInvoke(this, instance, value);
                    else
                        return !(bool)delegates[index].DynamicInvoke(this, instance, value);
                }
                else
                {
                    if (condition)
                        return (bool)delegates[index].DynamicInvoke();
                    else
                        return !(bool)delegates[index].DynamicInvoke();
                }
            }
            catch (Exception e)
            {
                if (e is TargetInvocationException)
                    e = ((TargetInvocationException)e).InnerException;

                Debug.LogError(string.Format("Invoking a method to retrieve a Inspect attribute failed. The exception was \"{0}\".", e.Message));
                return true;
            }
        }
        #endregion

        #region Compile Time Constructor
        public InspectAttribute()
            : this(InspectorLevel.Basic, "", true, 0) { }

        public InspectAttribute(int priority)
            : this(InspectorLevel.Basic, "", true, priority) { }

        public InspectAttribute(InspectorLevel level)
            : this(level, "", true, 0) { }

        public InspectAttribute(InspectorLevel level, int priority)
            : this(level, "", true, priority) { }

        public InspectAttribute(InspectorLevel level, string methodName)
            : this(level, methodName, true, 0) { }

        public InspectAttribute(InspectorLevel level, string methodName, int priority)
            : this(level, methodName, true, priority) { }

        public InspectAttribute(InspectorLevel level, string methodName, bool condition)
            : this(level, methodName, condition, 0) { }

        public InspectAttribute(string methodName)
            : this(InspectorLevel.Basic, methodName, true, 0) { }

        public InspectAttribute(string methodName, int priority)
            : this(InspectorLevel.Basic, methodName, true, priority) { }

        public InspectAttribute(string methodName, bool condition)
            : this(InspectorLevel.Basic, methodName, condition, 0) { }

        public InspectAttribute(string methodName, bool condition, int priority)
            : this(InspectorLevel.Basic, methodName, condition, priority) { }

        public InspectAttribute(InspectorLevel level, string methodName, bool condition, int priority)
        {
            this.level = level;
            this.condition = condition;
            this.methodName = methodName;
            this.priority = priority;
        }
        #endregion

        #region Runtime Constructor
        public InspectAttribute(Delegate method)
            : this(InspectorLevel.Basic, method, true, 0) { }

        public InspectAttribute(Delegate method, int priority)
            : this(InspectorLevel.Basic, method, true, priority) { }

        public InspectAttribute(Delegate method, bool condition)
            : this(InspectorLevel.Basic, method, condition, 0) { }

        public InspectAttribute(Delegate method, bool condition, int priority)
            : this(InspectorLevel.Basic, method, condition, priority) { }

        public InspectAttribute(InspectorLevel level, Delegate method)
            : this(level, method, true, 0) { }

        public InspectAttribute(InspectorLevel level, Delegate method, int priority)
            : this(level, method, true, priority) { }

        public InspectAttribute(InspectorLevel level, Delegate method, bool condition, int priority)
        {
            this.level = level;
            this.condition = condition;
            this.priority = priority;
            this.delegates.Add(method);
        }
        #endregion
    }

    /// <summary>
    /// You can change or add your own levels.
    /// </summary>
    public enum InspectorLevel
    {
        Basic = 0,
        Advanced = 1,
        Debug = 2
    }
}