11using UnityEditorInternal;
12using System.Collections.Generic;
16 [CustomPropertyDrawer(typeof(SerializableDictionaryBase), useForChildren:
true)]
19 private ReorderableList _list;
20 private SerializedProperty _currProperty;
22 private List<Pair> _pairs =
new List<Pair>();
25 public bool isDuplicate;
26 public SerializedProperty a;
27 public SerializedProperty b;
29 public Pair(
int index,
bool isDuplicate, SerializedProperty a, SerializedProperty b) {
31 this.isDuplicate = isDuplicate;
38 _list =
new ReorderableList(_pairs, typeof(Pair),
41 displayAddButton:
true,
42 displayRemoveButton:
true);
44 _list.drawElementCallback = drawElementCallback;
45 _list.elementHeightCallback = elementHeightCallback;
46 _list.drawHeaderCallback = drawHeader;
47 _list.onAddCallback = onAddCallback;
48 _list.onRemoveCallback = onRemoveCallback;
49 _list.onReorderCallback = onReorderCallback;
53 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
54 if (property.hasMultipleDifferentValues) {
55 GUI.Box(position,
"");
56 EditorGUI.LabelField(position,
"Multi-object editing not supported for Serialized Dictionaries.", EditorStyles.miniLabel);
58 _currProperty = property;
60 updatePairsFromProperty(property);
62 EditorGUIUtility.labelWidth /= 2;
63 _list.DoList(position);
64 EditorGUIUtility.labelWidth *= 2;
69 if (property.hasMultipleDifferentValues) {
70 return EditorGUIUtility.singleLineHeight;
72 updatePairsFromProperty(property);
73 return _list.GetHeight();
77 private void updatePairsFromProperty(SerializedProperty property) {
78 SerializedProperty keys =
property.FindPropertyRelative(
"_keys");
79 SerializedProperty values =
property.FindPropertyRelative(
"_values");
84 int count = keys.arraySize;
85 for (
int i = 0; i < count; i++) {
86 SerializedProperty key = keys.GetArrayElementAtIndex(i);
87 SerializedProperty value = values.GetArrayElementAtIndex(i);
94 _pairs.Add(
new Pair(i, isDup, key, value));
98 private void drawHeader(Rect rect) {
99 EditorGUI.LabelField(rect, _currProperty.displayName);
100 rect.x += rect.width - 110;
102 if (GUI.Button(rect,
"Clear Duplicates")) {
103 markDirty(_currProperty);
105 Undo.RecordObject(_currProperty.serializedObject.targetObject,
"Cleared duplicates");
106 (fieldInfo.GetValue(_currProperty.serializedObject.targetObject) as ICanReportDuplicateInformation).ClearDuplicates();
108 _currProperty.serializedObject.Update();
110 markDirty(_currProperty);
111 updatePairsFromProperty(_currProperty);
115 private void drawElementCallback(Rect rect,
int index,
bool isActive,
bool isFocused) {
116 Rect leftRect = rect;
117 leftRect.width *= (fieldInfo.GetValue(_currProperty.serializedObject.targetObject) as ISerializableDictionary).KeyDisplayRatio();
119 Rect rightRect = rect;
120 rightRect.x += leftRect.width;
121 rightRect.width -= leftRect.width;
123 Pair pair = _pairs[index];
125 if (pair.isDuplicate) {
126 GUI.contentColor =
new Color(1, 0.7f, 0);
127 GUI.color =
new Color(1, 0.7f, 0.5f);
130 if (pair.a.propertyType == SerializedPropertyType.ObjectReference && pair.a.objectReferenceValue ==
null) {
131 GUI.contentColor =
new Color(1, 0, 0);
132 GUI.color =
new Color(1, 0, 0);
135 drawProp(pair.a, leftRect);
137 GUI.contentColor =
Color.white;
138 GUI.color =
Color.white;
139 GUI.backgroundColor =
Color.white;
141 drawProp(pair.b, rightRect);
144 private void onAddCallback(ReorderableList list) {
145 SerializedProperty keys = _currProperty.FindPropertyRelative(
"_keys");
146 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
151 updatePairsFromProperty(_currProperty);
154 private void onRemoveCallback(ReorderableList list) {
155 SerializedProperty keys = _currProperty.FindPropertyRelative(
"_keys");
156 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
158 actuallyDeleteAt(keys, list.index);
159 actuallyDeleteAt(values, list.index);
161 updatePairsFromProperty(_currProperty);
164 private void onReorderCallback(ReorderableList list) {
165 SerializedProperty keys = _currProperty.FindPropertyRelative(
"_keys");
166 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
168 int startIndex = -1, endIndex = -1;
169 bool isForward =
true;
171 for (
int i = 0; i < _pairs.Count; i++) {
172 if (i != _pairs[i].index) {
173 if (_pairs[i].index - i > 1) {
181 for (
int i = _pairs.Count; i-- != 0;) {
182 if (i != _pairs[i].index) {
189 keys.MoveArrayElement(startIndex, endIndex);
190 values.MoveArrayElement(startIndex, endIndex);
192 keys.MoveArrayElement(endIndex, startIndex);
193 values.MoveArrayElement(endIndex, startIndex);
196 updatePairsFromProperty(_currProperty);
199 private float elementHeightCallback(
int index) {
200 Pair pair = _pairs[index];
201 float size = Mathf.Max(getSize(pair.a), getSize(pair.b));
202 _list.elementHeight = size;
206 private float getSize(SerializedProperty prop) {
209 if (prop.propertyType == SerializedPropertyType.Generic) {
210 SerializedProperty copy = prop.Copy();
211 SerializedProperty endProp = copy.GetEndProperty(
false);
213 copy.NextVisible(
true);
214 while (!SerializedProperty.EqualContents(copy, endProp)) {
215 size += EditorGUI.GetPropertyHeight(copy);
216 copy.NextVisible(
false);
219 size = EditorGUI.GetPropertyHeight(prop, GUIContent.none,
false);
224 private void drawProp(SerializedProperty prop, Rect r) {
225 if (prop.propertyType == SerializedPropertyType.Generic) {
226 SerializedProperty copy = prop.Copy();
227 SerializedProperty endProp = copy.GetEndProperty(
false);
228 copy.NextVisible(
true);
229 while (!SerializedProperty.EqualContents(copy, endProp)) {
230 r.height = EditorGUI.GetPropertyHeight(copy);
231 EditorGUI.PropertyField(r, copy,
true);
233 copy.NextVisible(
false);
236 r.height = EditorGUI.GetPropertyHeight(prop);
237 EditorGUI.PropertyField(r, prop, GUIContent.none,
false);
241 private void markDirty(SerializedProperty property) {
242 SerializedProperty keys =
property.FindPropertyRelative(
"_keys");
243 int size = keys.arraySize;
245 keys.InsertArrayElementAtIndex(size);
246 actuallyDeleteAt(keys, size);
249 private static void actuallyDeleteAt(SerializedProperty property,
int index) {
250 int arraySize =
property.arraySize;
252 while (property.arraySize == arraySize) {
253 property.DeleteArrayElementAtIndex(index);
override float GetPropertyHeight(SerializedProperty property, GUIContent label)
override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
SerializableDictionaryEditor()