Tanoda
SerializableDictionary.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using UnityEngine;
10using System;
11using System.Text;
12using System.Collections.Generic;
13using System.Linq;
14using System.Collections;
15
16namespace Leap.Unity {
17
18 [Obsolete("It is no longer required to annotate SerializableDictionary with an SDictionary attribute")]
19 public class SDictionaryAttribute : PropertyAttribute { }
20
21 public abstract class SerializableDictionaryBase { }
22
24#if UNITY_EDITOR
25 List<int> GetDuplicationInformation();
26 void ClearDuplicates();
27#endif
28 }
29
30 public interface ISerializableDictionary {
32 }
33
40 IEnumerable<KeyValuePair<TKey, TValue>>,
42 ISerializationCallbackReceiver,
44
45 [SerializeField]
46 private List<TKey> _keys = new List<TKey>();
47
48 [SerializeField]
49 private List<TValue> _values = new List<TValue>();
50
51 [NonSerialized]
52 private Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
53
54 #region DICTIONARY API
55
56 public TValue this[TKey key] {
57 get { return _dictionary[key]; }
58 set { _dictionary[key] = value; }
59 }
60
61 public Dictionary<TKey, TValue>.KeyCollection Keys {
62 get { return _dictionary.Keys; }
63 }
64
65 public Dictionary<TKey, TValue>.ValueCollection Values {
66 get { return _dictionary.Values; }
67 }
68
69 public int Count {
70 get { return _dictionary.Count; }
71 }
72
73 public void Add(TKey key, TValue value) {
74 _dictionary.Add(key, value);
75 }
76
77 public void Clear() {
78 _dictionary.Clear();
79 }
80
81 public bool ContainsKey(TKey key) {
82 return _dictionary.ContainsKey(key);
83 }
84
85 public bool ContainsValue(TValue value) {
86 return _dictionary.ContainsValue(value);
87 }
88
89 public bool Remove(TKey key) {
90 return _dictionary.Remove(key);
91 }
92
93 public bool TryGetValue(TKey key, out TValue value) {
94 return _dictionary.TryGetValue(key, out value);
95 }
96
97 public Dictionary<TKey, TValue>.Enumerator GetEnumerator() {
98 return _dictionary.GetEnumerator();
99 }
100
101 IEnumerator IEnumerable.GetEnumerator() {
102 return _dictionary.GetEnumerator();
103 }
104
105 public static implicit operator Dictionary<TKey, TValue>(SerializableDictionary<TKey, TValue> serializableDictionary) {
106 return serializableDictionary._dictionary;
107 }
108
109 #endregion
110
115 public virtual float KeyDisplayRatio() {
116 return 0.5f;
117 }
118
119 public override string ToString() {
120 StringBuilder toReturn = new StringBuilder();
121 List<TKey> keys = _dictionary.Keys.ToList<TKey>();
122 List<TValue> values = _dictionary.Values.ToList<TValue>();
123 toReturn.Append("[");
124 for (int i = 0; i < keys.Count; i++) {
125 toReturn.Append("{");
126 toReturn.Append(keys[i].ToString());
127 toReturn.Append(" : ");
128 toReturn.Append(values[i].ToString());
129 toReturn.Append("}, \n");
130 }
131 toReturn.Remove(toReturn.Length - 3, 3);
132 toReturn.Append("]");
133 return toReturn.ToString();
134 }
135
136 public void OnAfterDeserialize() {
137 _dictionary.Clear();
138
139 if (_keys != null && _values != null) {
140 int count = Mathf.Min(_keys.Count, _values.Count);
141 for (int i = 0; i < count; i++) {
142 TKey key = _keys[i];
143 TValue value = _values[i];
144
145 if (key == null) {
146 continue;
147 }
148
149 _dictionary[key] = value;
150 }
151 }
152
153#if !UNITY_EDITOR
154 _keys.Clear();
155 _values.Clear();
156#endif
157 }
158
159#if UNITY_EDITOR
160 public List<int> GetDuplicationInformation() {
161 Dictionary<TKey, int> info = new Dictionary<TKey, int>();
162
163 for (int i = 0; i < _keys.Count; i++) {
164 TKey key = _keys[i];
165 if (key == null) {
166 continue;
167 }
168
169 if (info.ContainsKey(key)) {
170 info[key]++;
171 } else {
172 info[key] = 1;
173 }
174 }
175
176 List<int> dups = new List<int>();
177 for (int i = 0; i < _keys.Count; i++) {
178 TKey key = _keys[i];
179 if (key == null) {
180 continue;
181 }
182
183 dups.Add(info[key]);
184 }
185
186 return dups;
187 }
188
189 public void ClearDuplicates() {
190 HashSet<TKey> takenKeys = new HashSet<TKey>();
191 for (int i = 0; i < _keys.Count; i++) {
192 TKey key = _keys[i];
193 if (takenKeys.Contains(key)) {
194 _keys.RemoveAt(i);
195 _values.RemoveAt(i);
196 i--;
197 } else {
198 takenKeys.Add(key);
199 }
200 }
201 }
202#endif
203
204 public void OnBeforeSerialize() {
205 if (_keys == null) {
206 _keys = new List<TKey>();
207 }
208
209 if (_values == null) {
210 _values = new List<TValue>();
211 }
212
213#if UNITY_EDITOR
214 for (int i = _keys.Count; i-- != 0;) {
215 TKey key = _keys[i];
216 if (key == null) continue;
217
218 if (!_dictionary.ContainsKey(key)) {
219 _keys.RemoveAt(i);
220 _values.RemoveAt(i);
221 }
222 }
223#endif
224
225 Dictionary<TKey, TValue>.Enumerator enumerator = _dictionary.GetEnumerator();
226 while (enumerator.MoveNext()) {
227 var pair = enumerator.Current;
228
229#if UNITY_EDITOR
230 if (!_keys.Contains(pair.Key)) {
231 _keys.Add(pair.Key);
232 _values.Add(pair.Value);
233 }
234#else
235 _keys.Add(pair.Key);
236 _values.Add(pair.Value);
237#endif
238 }
239 }
240
241 IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() {
242 return ((IEnumerable<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
243 }
244 }
245}
In order to have this class be serialized, you will always need to create your own non-generic versio...
virtual float KeyDisplayRatio()
Returns how much of the display space should be allocated to the key. Should be a value in the range ...
bool TryGetValue(TKey key, out TValue value)
Dictionary< TKey, TValue >.ValueCollection Values
Dictionary< TKey, TValue >.Enumerator GetEnumerator()
void Add(TKey key, TValue value)
Dictionary< TKey, TValue >.KeyCollection Keys