SerializableHashSet.cs
3.21 KB
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
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2017. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using Leap.Unity.Query;
namespace Leap.Unity {
/// <summary>
/// You must mark a serializable hash set field with this
/// attribute in order to use the custom inspector editor
/// </summary>
public class SHashSetAttribute : PropertyAttribute { }
public class SerializableHashSet<T> : HashSet<T>,
ICanReportDuplicateInformation,
ISerializationCallbackReceiver {
[SerializeField]
private List<T> _values;
public void ClearDuplicates() {
HashSet<T> takenValues = new HashSet<T>();
for (int i = _values.Count; i-- != 0;) {
var value = _values[i];
if (takenValues.Contains(value)) {
_values.RemoveAt(i);
} else {
takenValues.Add(value);
}
}
}
public List<int> GetDuplicationInformation() {
Dictionary<T, int> info = new Dictionary<T, int>();
foreach (var value in _values) {
if (value == null) {
continue;
}
if (info.ContainsKey(value)) {
info[value]++;
} else {
info[value] = 1;
}
}
List<int> dups = new List<int>();
foreach (var value in _values) {
if (value == null) {
continue;
}
dups.Add(info[value]);
}
return dups;
}
public void OnAfterDeserialize() {
Clear();
if (_values != null) {
foreach (var value in _values) {
if (value != null) {
Add(value);
}
}
}
#if !UNITY_EDITOR
_values.Clear();
#endif
}
public void OnBeforeSerialize() {
if (_values == null) {
_values = new List<T>();
}
#if UNITY_EDITOR
//Delete any values not present
for (int i = _values.Count; i-- != 0;) {
T value = _values[i];
if (value == null) {
continue;
}
if (!Contains(value)) {
_values.RemoveAt(i);
}
}
//Add any values not accounted for
foreach (var value in this) {
if (isNull(value)) {
if (!_values.Query().Any(obj => isNull(obj))) {
_values.Add(value);
}
} else {
if (!_values.Contains(value)) {
_values.Add(value);
}
}
}
#else
//At runtime we just recreate the list
_values.Clear();
_values.AddRange(this);
#endif
}
private bool isNull(object obj) {
if (obj == null) {
return true;
}
if (obj is Object) {
return (obj as Object) == null;
}
return false;
}
}
}