9using System.Collections;
10using System.Collections.Generic;
13using UnityEditorInternal;
17 [CustomPropertyDrawer(typeof(SerializableHashSetBase), useForChildren:
true)]
20 private ReorderableList _list;
21 private SerializedProperty _currProperty;
23 private List<Value> _values =
new List<Value>();
26 public bool isDuplicate;
27 public SerializedProperty value;
29 public Value(
int index,
bool isDuplicate, SerializedProperty value) {
31 this.isDuplicate = isDuplicate;
37 _list =
new ReorderableList(_values, typeof(
Value),
40 displayAddButton:
true,
41 displayRemoveButton:
true);
43 _list.drawElementCallback = drawElementCallback;
44 _list.elementHeightCallback = elementHeightCallback;
45 _list.drawHeaderCallback = drawHeader;
46 _list.onAddCallback = onAddCallback;
47 _list.onRemoveCallback = onRemoveCallback;
48 _list.onReorderCallback = onReorderCallback;
51 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
52 if (property.hasMultipleDifferentValues) {
53 GUI.Box(position,
"");
54 EditorGUI.LabelField(position,
"Multi-object editing not supported for Serialized HashSets.", EditorStyles.miniLabel);
56 _currProperty = property;
58 updatePairsFromProperty(property);
60 EditorGUIUtility.labelWidth /= 2;
61 _list.DoList(position);
62 EditorGUIUtility.labelWidth *= 2;
67 if (property.hasMultipleDifferentValues) {
68 return EditorGUIUtility.singleLineHeight;
70 updatePairsFromProperty(property);
71 return _list.GetHeight();
75 private void updatePairsFromProperty(SerializedProperty property) {
76 SerializedProperty values =
property.FindPropertyRelative(
"_values");
81 int count = values.arraySize;
82 for (
int i = 0; i < count; i++) {
83 SerializedProperty value = values.GetArrayElementAtIndex(i);
90 _values.Add(
new Value(i, isDup, value));
94 private void drawHeader(Rect rect) {
95 EditorGUI.LabelField(rect, _currProperty.displayName);
96 rect.x += rect.width - 110;
98 if (GUI.Button(rect,
"Clear Duplicates")) {
99 markDirty(_currProperty);
101 Undo.RecordObject(_currProperty.serializedObject.targetObject,
"Cleared duplicates");
102 (fieldInfo.GetValue(_currProperty.serializedObject.targetObject) as ICanReportDuplicateInformation).ClearDuplicates();
104 _currProperty.serializedObject.Update();
106 markDirty(_currProperty);
107 updatePairsFromProperty(_currProperty);
111 private void drawElementCallback(Rect rect,
int index,
bool isActive,
bool isFocused) {
112 Value value = _values[index];
114 if (value.isDuplicate) {
115 GUI.contentColor =
new Color(1, 0.7f, 0);
116 GUI.color =
new Color(1, 0.7f, 0.5f);
119 if (value.value.propertyType == SerializedPropertyType.ObjectReference && value.value.objectReferenceValue ==
null) {
120 GUI.contentColor =
new Color(1, 0, 0);
121 GUI.color =
new Color(1, 0, 0);
124 drawProp(value.value, rect);
126 GUI.contentColor =
Color.white;
127 GUI.color =
Color.white;
128 GUI.backgroundColor =
Color.white;
131 private void onAddCallback(ReorderableList list) {
132 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
136 updatePairsFromProperty(_currProperty);
139 private void onRemoveCallback(ReorderableList list) {
140 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
142 actuallyDeleteAt(values, list.index);
144 updatePairsFromProperty(_currProperty);
147 private void onReorderCallback(ReorderableList list) {
148 SerializedProperty values = _currProperty.FindPropertyRelative(
"_values");
150 int startIndex = -1, endIndex = -1;
151 bool isForward =
true;
153 for (
int i = 0; i < _values.Count; i++) {
154 if (i != _values[i].index) {
155 if (_values[i].index - i > 1) {
163 for (
int i = _values.Count; i-- != 0;) {
164 if (i != _values[i].index) {
171 values.MoveArrayElement(startIndex, endIndex);
173 values.MoveArrayElement(endIndex, startIndex);
176 updatePairsFromProperty(_currProperty);
179 private float elementHeightCallback(
int index) {
180 Value value = _values[index];
181 float size = getSize(value.value);
182 _list.elementHeight = size;
186 private float getSize(SerializedProperty prop) {
188 if (prop.propertyType == SerializedPropertyType.Generic) {
189 SerializedProperty copy = prop.Copy();
190 SerializedProperty endProp = copy.GetEndProperty(
false);
192 copy.NextVisible(
true);
193 while (!SerializedProperty.EqualContents(copy, endProp)) {
194 size += EditorGUI.GetPropertyHeight(copy);
195 copy.NextVisible(
false);
198 size = EditorGUI.GetPropertyHeight(prop, GUIContent.none,
false);
203 private void drawProp(SerializedProperty prop, Rect r) {
204 if (prop.propertyType == SerializedPropertyType.Generic) {
205 SerializedProperty copy = prop.Copy();
206 SerializedProperty endProp = copy.GetEndProperty(
false);
207 copy.NextVisible(
true);
208 while (!SerializedProperty.EqualContents(copy, endProp)) {
209 r.height = EditorGUI.GetPropertyHeight(copy);
210 EditorGUI.PropertyField(r, copy,
true);
212 copy.NextVisible(
false);
215 r.height = EditorGUI.GetPropertyHeight(prop);
216 EditorGUI.PropertyField(r, prop, GUIContent.none,
false);
220 private void markDirty(SerializedProperty property) {
221 SerializedProperty values =
property.FindPropertyRelative(
"_values");
222 int size = values.arraySize;
224 values.InsertArrayElementAtIndex(size);
225 actuallyDeleteAt(values, size);
228 private static void actuallyDeleteAt(SerializedProperty property,
int index) {
229 int arraySize =
property.arraySize;
231 while (property.arraySize == arraySize) {
232 property.DeleteArrayElementAtIndex(index);
SerializableHashSetEditor()
override float GetPropertyHeight(SerializedProperty property, GUIContent label)
override void OnGUI(Rect position, SerializedProperty property, GUIContent label)