Initial. Added files
This commit is contained in:
746
Assets/Scripts/Utils/SerializableDictionary.cs
Executable file
746
Assets/Scripts/Utils/SerializableDictionary.cs
Executable file
@ -0,0 +1,746 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityObject = UnityEngine.Object;
|
||||
|
||||
[Serializable, DebuggerDisplay("Count = {Count}")]
|
||||
public class SerializableDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
||||
{
|
||||
[SerializeField, HideInInspector] int[] _Buckets;
|
||||
[SerializeField, HideInInspector] int[] _HashCodes;
|
||||
[SerializeField, HideInInspector] int[] _Next;
|
||||
[SerializeField, HideInInspector] int _Count;
|
||||
[SerializeField, HideInInspector] int _Version;
|
||||
[SerializeField, HideInInspector] int _FreeList;
|
||||
[SerializeField, HideInInspector] int _FreeCount;
|
||||
[SerializeField, HideInInspector] TKey[] _Keys;
|
||||
[SerializeField, HideInInspector] TValue[] _Values;
|
||||
|
||||
readonly IEqualityComparer<TKey> _Comparer;
|
||||
|
||||
// Mainly for debugging purposes - to get the key-value pairs display
|
||||
public Dictionary<TKey, TValue> AsDictionary
|
||||
{
|
||||
get { return new Dictionary<TKey, TValue>(this); }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return _Count - _FreeCount; }
|
||||
}
|
||||
|
||||
public TValue this[TKey key, TValue defaultValue]
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = FindIndex(key);
|
||||
if (index >= 0)
|
||||
return _Values[index];
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = FindIndex(key);
|
||||
if (index >= 0)
|
||||
return _Values[index];
|
||||
throw new KeyNotFoundException(key.ToString());
|
||||
}
|
||||
|
||||
set { Insert(key, value, false); }
|
||||
}
|
||||
|
||||
public SerializableDictionary()
|
||||
: this(0, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SerializableDictionary(int capacity)
|
||||
: this(capacity, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SerializableDictionary(IEqualityComparer<TKey> comparer)
|
||||
: this(0, comparer)
|
||||
{
|
||||
}
|
||||
|
||||
public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
if (capacity < 0)
|
||||
throw new ArgumentOutOfRangeException("capacity");
|
||||
|
||||
Initialize(capacity);
|
||||
|
||||
_Comparer = (comparer ?? EqualityComparer<TKey>.Default);
|
||||
}
|
||||
|
||||
public SerializableDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
: this(dictionary, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SerializableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
|
||||
: this((dictionary != null) ? dictionary.Count : 0, comparer)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> current in dictionary)
|
||||
Add(current.Key, current.Value);
|
||||
}
|
||||
|
||||
public bool ContainsValue(TValue value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
for (int i = 0; i < _Count; i++)
|
||||
{
|
||||
if (_HashCodes[i] >= 0 && _Values[i] == null)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultComparer = EqualityComparer<TValue>.Default;
|
||||
for (int i = 0; i < _Count; i++)
|
||||
{
|
||||
if (_HashCodes[i] >= 0 && defaultComparer.Equals(_Values[i], value))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return FindIndex(key) >= 0;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (_Count <= 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < _Buckets.Length; i++)
|
||||
_Buckets[i] = -1;
|
||||
|
||||
Array.Clear(_Keys, 0, _Count);
|
||||
Array.Clear(_Values, 0, _Count);
|
||||
Array.Clear(_HashCodes, 0, _Count);
|
||||
Array.Clear(_Next, 0, _Count);
|
||||
|
||||
_FreeList = -1;
|
||||
_Count = 0;
|
||||
_FreeCount = 0;
|
||||
_Version++;
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
Insert(key, value, true);
|
||||
}
|
||||
|
||||
private void Resize(int newSize, bool forceNewHashCodes)
|
||||
{
|
||||
int[] bucketsCopy = new int[newSize];
|
||||
for (int i = 0; i < bucketsCopy.Length; i++)
|
||||
bucketsCopy[i] = -1;
|
||||
|
||||
var keysCopy = new TKey[newSize];
|
||||
var valuesCopy = new TValue[newSize];
|
||||
var hashCodesCopy = new int[newSize];
|
||||
var nextCopy = new int[newSize];
|
||||
|
||||
Array.Copy(_Values, 0, valuesCopy, 0, _Count);
|
||||
Array.Copy(_Keys, 0, keysCopy, 0, _Count);
|
||||
Array.Copy(_HashCodes, 0, hashCodesCopy, 0, _Count);
|
||||
Array.Copy(_Next, 0, nextCopy, 0, _Count);
|
||||
|
||||
if (forceNewHashCodes)
|
||||
{
|
||||
for (int i = 0; i < _Count; i++)
|
||||
{
|
||||
if (hashCodesCopy[i] != -1)
|
||||
hashCodesCopy[i] = (_Comparer.GetHashCode(keysCopy[i]) & 2147483647);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _Count; i++)
|
||||
{
|
||||
int index = hashCodesCopy[i] % newSize;
|
||||
nextCopy[i] = bucketsCopy[index];
|
||||
bucketsCopy[index] = i;
|
||||
}
|
||||
|
||||
_Buckets = bucketsCopy;
|
||||
_Keys = keysCopy;
|
||||
_Values = valuesCopy;
|
||||
_HashCodes = hashCodesCopy;
|
||||
_Next = nextCopy;
|
||||
}
|
||||
|
||||
private void Resize()
|
||||
{
|
||||
Resize(PrimeHelper.ExpandPrime(_Count), false);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
int hash = _Comparer.GetHashCode(key) & 2147483647;
|
||||
int index = hash % _Buckets.Length;
|
||||
int num = -1;
|
||||
for (int i = _Buckets[index]; i >= 0; i = _Next[i])
|
||||
{
|
||||
if (_HashCodes[i] == hash && _Comparer.Equals(_Keys[i], key))
|
||||
{
|
||||
if (num < 0)
|
||||
_Buckets[index] = _Next[i];
|
||||
else
|
||||
_Next[num] = _Next[i];
|
||||
|
||||
_HashCodes[i] = -1;
|
||||
_Next[i] = _FreeList;
|
||||
_Keys[i] = default(TKey);
|
||||
_Values[i] = default(TValue);
|
||||
_FreeList = i;
|
||||
_FreeCount++;
|
||||
_Version++;
|
||||
return true;
|
||||
}
|
||||
num = i;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Insert(TKey key, TValue value, bool add)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (_Buckets == null)
|
||||
Initialize(0);
|
||||
|
||||
int hash = _Comparer.GetHashCode(key) & 2147483647;
|
||||
int index = hash % _Buckets.Length;
|
||||
int num1 = 0;
|
||||
for (int i = _Buckets[index]; i >= 0; i = _Next[i])
|
||||
{
|
||||
if (_HashCodes[i] == hash && _Comparer.Equals(_Keys[i], key))
|
||||
{
|
||||
if (add)
|
||||
throw new ArgumentException("Key already exists: " + key);
|
||||
|
||||
_Values[i] = value;
|
||||
_Version++;
|
||||
return;
|
||||
}
|
||||
num1++;
|
||||
}
|
||||
int num2;
|
||||
if (_FreeCount > 0)
|
||||
{
|
||||
num2 = _FreeList;
|
||||
_FreeList = _Next[num2];
|
||||
_FreeCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_Count == _Keys.Length)
|
||||
{
|
||||
Resize();
|
||||
index = hash % _Buckets.Length;
|
||||
}
|
||||
num2 = _Count;
|
||||
_Count++;
|
||||
}
|
||||
_HashCodes[num2] = hash;
|
||||
_Next[num2] = _Buckets[index];
|
||||
_Keys[num2] = key;
|
||||
_Values[num2] = value;
|
||||
_Buckets[index] = num2;
|
||||
_Version++;
|
||||
|
||||
//if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(comparer))
|
||||
//{
|
||||
// comparer = (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer);
|
||||
// Resize(entries.Length, true);
|
||||
//}
|
||||
}
|
||||
|
||||
private void Initialize(int capacity)
|
||||
{
|
||||
int prime = PrimeHelper.GetPrime(capacity);
|
||||
|
||||
_Buckets = new int[prime];
|
||||
for (int i = 0; i < _Buckets.Length; i++)
|
||||
_Buckets[i] = -1;
|
||||
|
||||
_Keys = new TKey[prime];
|
||||
_Values = new TValue[prime];
|
||||
_HashCodes = new int[prime];
|
||||
_Next = new int[prime];
|
||||
|
||||
_FreeList = -1;
|
||||
}
|
||||
|
||||
private int FindIndex(TKey key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (_Buckets != null)
|
||||
{
|
||||
int hash = _Comparer.GetHashCode(key) & 2147483647;
|
||||
for (int i = _Buckets[hash % _Buckets.Length]; i >= 0; i = _Next[i])
|
||||
{
|
||||
if (_HashCodes[i] == hash && _Comparer.Equals(_Keys[i], key))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
int index = FindIndex(key);
|
||||
if (index >= 0)
|
||||
{
|
||||
value = _Values[index];
|
||||
return true;
|
||||
}
|
||||
value = default(TValue);
|
||||
return false;
|
||||
}
|
||||
private static class PrimeHelper
|
||||
{
|
||||
public static readonly int[] Primes = new int[]
|
||||
{
|
||||
3,
|
||||
7,
|
||||
11,
|
||||
17,
|
||||
23,
|
||||
29,
|
||||
37,
|
||||
47,
|
||||
59,
|
||||
71,
|
||||
89,
|
||||
107,
|
||||
131,
|
||||
163,
|
||||
197,
|
||||
239,
|
||||
293,
|
||||
353,
|
||||
431,
|
||||
521,
|
||||
631,
|
||||
761,
|
||||
919,
|
||||
1103,
|
||||
1327,
|
||||
1597,
|
||||
1931,
|
||||
2333,
|
||||
2801,
|
||||
3371,
|
||||
4049,
|
||||
4861,
|
||||
5839,
|
||||
7013,
|
||||
8419,
|
||||
10103,
|
||||
12143,
|
||||
14591,
|
||||
17519,
|
||||
21023,
|
||||
25229,
|
||||
30293,
|
||||
36353,
|
||||
43627,
|
||||
52361,
|
||||
62851,
|
||||
75431,
|
||||
90523,
|
||||
108631,
|
||||
130363,
|
||||
156437,
|
||||
187751,
|
||||
225307,
|
||||
270371,
|
||||
324449,
|
||||
389357,
|
||||
467237,
|
||||
560689,
|
||||
672827,
|
||||
807403,
|
||||
968897,
|
||||
1162687,
|
||||
1395263,
|
||||
1674319,
|
||||
2009191,
|
||||
2411033,
|
||||
2893249,
|
||||
3471899,
|
||||
4166287,
|
||||
4999559,
|
||||
5999471,
|
||||
7199369
|
||||
};
|
||||
|
||||
public static bool IsPrime(int candidate)
|
||||
{
|
||||
if ((candidate & 1) != 0)
|
||||
{
|
||||
int num = (int)Math.Sqrt((double)candidate);
|
||||
for (int i = 3; i <= num; i += 2)
|
||||
{
|
||||
if (candidate % i == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return candidate == 2;
|
||||
}
|
||||
|
||||
public static int GetPrime(int min)
|
||||
{
|
||||
if (min < 0)
|
||||
throw new ArgumentException("min < 0");
|
||||
|
||||
for (int i = 0; i < PrimeHelper.Primes.Length; i++)
|
||||
{
|
||||
int prime = PrimeHelper.Primes[i];
|
||||
if (prime >= min)
|
||||
return prime;
|
||||
}
|
||||
for (int i = min | 1; i < 2147483647; i += 2)
|
||||
{
|
||||
if (PrimeHelper.IsPrime(i) && (i - 1) % 101 != 0)
|
||||
return i;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
public static int ExpandPrime(int oldSize)
|
||||
{
|
||||
int num = 2 * oldSize;
|
||||
if (num > 2146435069 && 2146435069 > oldSize)
|
||||
{
|
||||
return 2146435069;
|
||||
}
|
||||
return PrimeHelper.GetPrime(num);
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return _Keys.Take(Count).ToArray(); }
|
||||
}
|
||||
|
||||
public ICollection<TValue> Values
|
||||
{
|
||||
get { return _Values.Take(Count).ToArray(); }
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
int index = FindIndex(item.Key);
|
||||
return index >= 0 &&
|
||||
EqualityComparer<TValue>.Default.Equals(_Values[index], item.Value);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
if (index < 0 || index > array.Length)
|
||||
throw new ArgumentOutOfRangeException(string.Format("index = {0} array.Length = {1}", index, array.Length));
|
||||
|
||||
if (array.Length - index < Count)
|
||||
throw new ArgumentException(string.Format("The number of elements in the dictionary ({0}) is greater than the available space from index to the end of the destination array {1}.", Count, array.Length));
|
||||
|
||||
for (int i = 0; i < _Count; i++)
|
||||
{
|
||||
if (_HashCodes[i] >= 0)
|
||||
array[index++] = new KeyValuePair<TKey, TValue>(_Keys[i], _Values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Remove(item.Key);
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
|
||||
{
|
||||
private readonly SerializableDictionary<TKey, TValue> _Dictionary;
|
||||
private int _Version;
|
||||
private int _Index;
|
||||
private KeyValuePair<TKey, TValue> _Current;
|
||||
|
||||
public KeyValuePair<TKey, TValue> Current
|
||||
{
|
||||
get { return _Current; }
|
||||
}
|
||||
|
||||
internal Enumerator(SerializableDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
_Dictionary = dictionary;
|
||||
_Version = dictionary._Version;
|
||||
_Current = default(KeyValuePair<TKey, TValue>);
|
||||
_Index = 0;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_Version != _Dictionary._Version)
|
||||
throw new InvalidOperationException(string.Format("Enumerator version {0} != Dictionary version {1}", _Version, _Dictionary._Version));
|
||||
|
||||
while (_Index < _Dictionary._Count)
|
||||
{
|
||||
if (_Dictionary._HashCodes[_Index] >= 0)
|
||||
{
|
||||
_Current = new KeyValuePair<TKey, TValue>(_Dictionary._Keys[_Index], _Dictionary._Values[_Index]);
|
||||
_Index++;
|
||||
return true;
|
||||
}
|
||||
_Index++;
|
||||
}
|
||||
|
||||
_Index = _Dictionary._Count + 1;
|
||||
_Current = default(KeyValuePair<TKey, TValue>);
|
||||
return false;
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
if (_Version != _Dictionary._Version)
|
||||
throw new InvalidOperationException(string.Format("Enumerator version {0} != Dictionary version {1}", _Version, _Dictionary._Version));
|
||||
|
||||
_Index = 0;
|
||||
_Current = default(KeyValuePair<TKey, TValue>);
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get { return Current; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DictionaryDrawer<TK, TV> : PropertyDrawer
|
||||
{
|
||||
private SerializableDictionary<TK, TV> _Dictionary;
|
||||
private bool _Foldout;
|
||||
private const float kButtonWidth = 18f;
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
CheckInitialize(property, label);
|
||||
if (_Foldout)
|
||||
return (_Dictionary.Count + 1) * 17f;
|
||||
return 17f;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
CheckInitialize(property, label);
|
||||
|
||||
position.height = 17f;
|
||||
|
||||
var foldoutRect = position;
|
||||
foldoutRect.width -= 2 * kButtonWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
EditorPrefs.SetBool(label.text, _Foldout);
|
||||
|
||||
var buttonRect = position;
|
||||
buttonRect.x = position.width - kButtonWidth + position.x;
|
||||
buttonRect.width = kButtonWidth + 2;
|
||||
|
||||
if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton))
|
||||
{
|
||||
AddNewItem();
|
||||
}
|
||||
|
||||
buttonRect.x -= kButtonWidth;
|
||||
|
||||
if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight))
|
||||
{
|
||||
ClearDictionary();
|
||||
}
|
||||
|
||||
if (!_Foldout)
|
||||
return;
|
||||
|
||||
foreach (var item in _Dictionary)
|
||||
{
|
||||
var key = item.Key;
|
||||
var value = item.Value;
|
||||
|
||||
position.y += 17f;
|
||||
|
||||
var keyRect = position;
|
||||
keyRect.width /= 2;
|
||||
keyRect.width -= 4;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newKey = DoField(keyRect, typeof(TK), key);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
try
|
||||
{
|
||||
_Dictionary.Remove(key);
|
||||
_Dictionary.Add(newKey, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.Log(e.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var valueRect = position;
|
||||
valueRect.x = position.width / 2 + 15;
|
||||
valueRect.width = keyRect.width - kButtonWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
value = DoField(valueRect, typeof(TV), value);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_Dictionary[key] = value;
|
||||
break;
|
||||
}
|
||||
|
||||
var removeRect = valueRect;
|
||||
removeRect.x = valueRect.xMax + 2;
|
||||
removeRect.width = kButtonWidth;
|
||||
if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight))
|
||||
{
|
||||
RemoveItem(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveItem(TK key)
|
||||
{
|
||||
_Dictionary.Remove(key);
|
||||
}
|
||||
|
||||
private void CheckInitialize(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (_Dictionary == null)
|
||||
{
|
||||
var target = property.serializedObject.targetObject;
|
||||
_Dictionary = fieldInfo.GetValue(target) as SerializableDictionary<TK, TV>;
|
||||
if (_Dictionary == null)
|
||||
{
|
||||
_Dictionary = new SerializableDictionary<TK, TV>();
|
||||
fieldInfo.SetValue(target, _Dictionary);
|
||||
}
|
||||
|
||||
_Foldout = EditorPrefs.GetBool(label.text);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, Func<Rect, object, object>> _Fields =
|
||||
new Dictionary<Type, Func<Rect, object, object>>()
|
||||
{
|
||||
{ typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) },
|
||||
{ typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) },
|
||||
{ typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) },
|
||||
{ typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) },
|
||||
{ typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) },
|
||||
{ typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) },
|
||||
{ typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) },
|
||||
{ typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) },
|
||||
};
|
||||
|
||||
private static T DoField<T>(Rect rect, Type type, T value)
|
||||
{
|
||||
Func<Rect, object, object> field;
|
||||
if (_Fields.TryGetValue(type, out field))
|
||||
return (T)field(rect, value);
|
||||
|
||||
if (type.IsEnum)
|
||||
return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value);
|
||||
|
||||
if (typeof(UnityObject).IsAssignableFrom(type))
|
||||
return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true);
|
||||
|
||||
UnityEngine.Debug.Log("Type is not supported: " + type);
|
||||
return value;
|
||||
}
|
||||
|
||||
private void ClearDictionary()
|
||||
{
|
||||
_Dictionary.Clear();
|
||||
}
|
||||
|
||||
private void AddNewItem()
|
||||
{
|
||||
TK key;
|
||||
if (typeof(TK) == typeof(string))
|
||||
key = (TK)(object)"";
|
||||
else key = default(TK);
|
||||
|
||||
var value = default(TV);
|
||||
try
|
||||
{
|
||||
_Dictionary.Add(key, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.Log(e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable] public class DictionaryOfTeamsAndNavPoints : SerializableDictionary<Team, NavPoint> { }
|
||||
[CustomPropertyDrawer(typeof(DictionaryOfTeamsAndNavPoints))]
|
||||
public class DictionaryOfTeamsAndNavPointsDrawer : DictionaryDrawer<Team, NavPoint> { }
|
11
Assets/Scripts/Utils/SerializableDictionary.cs.meta
generated
Executable file
11
Assets/Scripts/Utils/SerializableDictionary.cs.meta
generated
Executable file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: baaabca40bed4b845a14c4d2801350f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user