12using System.Reflection;
13using System.Collections.Generic;
21 private static Dictionary<FieldInfo, List<CombinablePropertyAttribute>> _cachedAttributes =
new Dictionary<FieldInfo, List<CombinablePropertyAttribute>>();
23 private List<CombinablePropertyAttribute> attributes =
new List<CombinablePropertyAttribute>();
24 private void getAttributes(SerializedProperty property) {
29 FieldInfo fieldInfo, out List<CombinablePropertyAttribute> outAttributes)
31 if (!_cachedAttributes.TryGetValue(fieldInfo, out outAttributes)) {
32 outAttributes =
new List<CombinablePropertyAttribute>();
36 if (combinableProperty !=
null) {
37 if (combinableProperty.SupportedTypes.Count() != 0 && !combinableProperty.SupportedTypes.Contains(property.propertyType)) {
38 Debug.LogError(
"Property attribute " +
39 combinableProperty.GetType().Name +
40 " does not support property type " +
41 property.propertyType +
".");
44 outAttributes.Add(combinableProperty);
48 _cachedAttributes[fieldInfo] = outAttributes;
55 getAttributes(property);
58 .Where(o => o !=
null).FirstOrDefault();
59 if (topPanelDrawer !=
null) {
60 return topPanelDrawer.GetHeight() + EditorGUI.GetPropertyHeight(property,
61 includeChildren:
true);
64 return EditorGUI.GetPropertyHeight(property, includeChildren:
true);
71 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
72 getAttributes(property);
78 public static void OnGUI(List<CombinablePropertyAttribute> attributes,
79 FieldInfo fieldInfo, Rect position, SerializedProperty property,
82 float defaultLabelWidth = EditorGUIUtility.labelWidth;
83 float fieldWidth = position.width - EditorGUIUtility.labelWidth;
85 bool canUseDefaultDrawer =
true;
86 bool shouldDisable =
false;
88 RangeAttribute rangeAttribute =
null;
89 if (fieldInfo !=
null) {
90 rangeAttribute = fieldInfo.GetCustomAttributes(typeof(RangeAttribute),
true).FirstOrDefault() as RangeAttribute;
97 foreach (var a
in attributes) {
98 if (fieldInfo !=
null) {
99 a.Init(fieldInfo, property.serializedObject.targetObjects);
108 canUseDefaultDrawer =
false;
113 canUseDefaultDrawer =
false;
125 if (fullPropertyDrawer !=
null) {
126 Debug.LogError(
"Cannot have 2 advanced attributes that both override the field drawing");
141 if (fullPropertyDrawer !=
null && !canUseDefaultDrawer) {
142 Debug.LogError(
"Cannot have an advanced attribute drawer that draws a custom field, and also have an advanced attribute drawer that draws between label and field!");
147 Rect topPanel =
new Rect();
148 if (topPanelDrawer !=
null) {
150 topPanel = r.TakeBottom(topPanelDrawer.GetHeight(), out r);
153 if (dragAndDropSupport !=
null) {
154 processDragAndDrop(dragAndDropSupport, ref r, property);
157 EditorGUI.BeginChangeCheck();
158 EditorGUI.BeginDisabledGroup(shouldDisable);
160 if (topPanelDrawer !=
null) {
161 topPanelDrawer.Draw(topPanel, property);
164 drawAdditive<IBeforeLabelAdditiveDrawer>(attributes, ref r, property);
166 if (canUseDefaultDrawer) {
167 r.width = EditorGUIUtility.labelWidth + fieldWidth;
169 if (fullPropertyDrawer !=
null) {
170 fullPropertyDrawer.DrawProperty(r, property, label);
172 if (rangeAttribute !=
null) {
173 if (property.propertyType == SerializedPropertyType.Integer) {
174 property.intValue = EditorGUI.IntSlider(r, label, property.intValue, (
int)rangeAttribute.min, (
int)rangeAttribute.max);
175 }
else if (property.propertyType == SerializedPropertyType.Float) {
176 property.floatValue = EditorGUI.Slider(r, label, property.floatValue, rangeAttribute.min, rangeAttribute.max);
178 EditorGUI.PropertyField(r, property, label, includeChildren:
true);
181 EditorGUI.PropertyField(r, property, label, includeChildren:
true);
188 r.width = EditorGUIUtility.labelWidth;
189 r = EditorGUI.PrefixLabel(r, label);
191 drawAdditive<IAfterLabelAdditiveDrawer>(attributes, ref r, property);
192 drawAdditive<IBeforeFieldAdditiveDrawer>(attributes, ref r, property);
194 r.width = fieldWidth;
195 EditorGUI.PropertyField(r, property, GUIContent.none,
196 includeChildren:
true);
200 drawAdditive<IAfterFieldAdditiveDrawer>(attributes, ref r, property);
202 EditorGUI.EndDisabledGroup();
204 bool didChange =
false;
206 didChange = EditorGUI.EndChangeCheck();
208 catch (System.Exception e) {
209 Debug.LogWarning(
"CombinablePropertyDrawer exception getting didChange: " +
213 if (didChange || !property.hasMultipleDifferentValues) {
214 foreach (var a
in attributes) {
222 foreach (var a
in attributes) {
223 a.OnPropertyChanged(property);
227 EditorGUIUtility.labelWidth = defaultLabelWidth;
230 private static void drawAdditive<T>(List<CombinablePropertyAttribute> attributes,
231 ref Rect r, SerializedProperty property)
233 foreach (var a
in attributes) {
236 r.width = t.GetWidth();
243 private static void processDragAndDrop(ISupportDragAndDrop dragAndDropSupport,
244 ref Rect r, SerializedProperty property) {
245 Event curEvent = Event.current;
246 Rect dropArea = dragAndDropSupport.GetDropArea(r, property);
248 switch (curEvent.type) {
249 case EventType.Repaint:
250 case EventType.DragUpdated:
251 case EventType.DragPerform:
252 if (!dropArea.Contains(curEvent.mousePosition, allowInverse:
true)) {
256 bool isValidDrop = dragAndDropSupport.IsDropValid(
257 DragAndDrop.objectReferences, property);
260 DragAndDrop.visualMode = DragAndDropVisualMode.Link;
262 DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
265 if (curEvent.type == EventType.DragPerform && isValidDrop) {
266 DragAndDrop.AcceptDrag();
268 dragAndDropSupport.ProcessDroppedObjects(
269 DragAndDrop.objectReferences, property);
static void GetAttributes(SerializedProperty property, FieldInfo fieldInfo, out List< CombinablePropertyAttribute > outAttributes)
override float GetPropertyHeight(SerializedProperty property, GUIContent label)
override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
static void OnGUI(List< CombinablePropertyAttribute > attributes, FieldInfo fieldInfo, Rect position, SerializedProperty property, GUIContent label)
override bool CanCacheInspectorGUI(SerializedProperty property)