using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace VketCloudGUITools.Runtime { [System.Serializable] public class SerializableDictionary : IDictionary, ISerializationCallbackReceiver where TKeyValuePair : SerializableKeyValuePair, new() { Dictionary _innerDictionary = new Dictionary(); [SerializeField] List _keyValuePairs = new List(); public void Add(TKey key, TValue value) { ((IDictionary)_innerDictionary).Add(key, value); } public bool ContainsKey(TKey key) { return ((IDictionary)_innerDictionary).ContainsKey(key); } public bool Remove(TKey key) { return ((IDictionary)_innerDictionary).Remove(key); } public bool TryGetValue(TKey key, out TValue value) { return ((IDictionary)_innerDictionary).TryGetValue(key, out value); } public TValue this[TKey key] { get => ((IDictionary)_innerDictionary)[key]; set => ((IDictionary)_innerDictionary)[key] = value; } public ICollection Keys => ((IDictionary)_innerDictionary).Keys; public ICollection Values => ((IDictionary)_innerDictionary).Values; public void Add(KeyValuePair item) { ((ICollection>)_innerDictionary).Add(item); } public void Clear() { ((ICollection>)_innerDictionary).Clear(); } public bool Contains(KeyValuePair item) { return ((ICollection>)_innerDictionary).Contains(item); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)_innerDictionary).CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { var retval = ((ICollection>)_innerDictionary).Remove(item); return retval; } public int Count => ((ICollection>)_innerDictionary).Count; public bool IsReadOnly => ((ICollection>)_innerDictionary).IsReadOnly; public IEnumerator> GetEnumerator() { return ((IEnumerable>)_innerDictionary).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_innerDictionary).GetEnumerator(); } public void OnBeforeSerialize() { DictionaryToList(); } public void OnAfterDeserialize() { ListToDictionary(); } private void DictionaryToList() { _keyValuePairs.Clear(); foreach (var kv in _innerDictionary) { var skv = new TKeyValuePair() { Key = kv.Key, Value = kv.Value }; _keyValuePairs.Add(skv); } } private void ListToDictionary() { int count = _keyValuePairs.Count; for (int i = 0; i < _keyValuePairs.Count; ++i) { _innerDictionary.Add(_keyValuePairs[i].Key, _keyValuePairs[i].Value); } } } [System.Serializable] public class SerializableKeyValuePair { public TKey Key; public TValue Value; public SerializableKeyValuePair() { } public SerializableKeyValuePair(TKey _key, TValue _value) { Key = _key; Value = _value; } public SerializableKeyValuePair(KeyValuePair pair) { Key = pair.Key; Value = pair.Value; } } [System.Serializable] public class SerializableDictionaryStringBool : SerializableDictionary { } [System.Serializable] public class SerializableKeyValuePairStringBool : SerializableKeyValuePair { } [System.Serializable] public class SerializableDictionaryStringInt : SerializableDictionary { } [System.Serializable] public class SerializableKeyValuePairStringInt : SerializableKeyValuePair { } [System.Serializable] public class SerializableDictionaryStringFloat : SerializableDictionary { } [System.Serializable] public class SerializableKeyValuePairStringFloat : SerializableKeyValuePair { } [System.Serializable] public class SerializableDictionaryStringString : SerializableDictionary { } [System.Serializable] public class SerializableKeyValuePairStringString : SerializableKeyValuePair { } [System.Serializable] public class SerializableDictionaryStringIntArray : SerializableDictionary { } [System.Serializable] public class SerializableKeyValuePairStringIntArray : SerializableKeyValuePair { } [System.Serializable] public class SerializableDictionaryStringObject : IDictionary, ISerializationCallbackReceiver { Dictionary _innerDictionary = new Dictionary(); [SerializeField] SerializableDictionaryStringBool _boolDictionary = new SerializableDictionaryStringBool(); [SerializeField] SerializableDictionaryStringInt _intDictionary = new SerializableDictionaryStringInt(); [SerializeField] SerializableDictionaryStringFloat _floatDictionary = new SerializableDictionaryStringFloat(); [SerializeField] SerializableDictionaryStringString _stringDictionary = new SerializableDictionaryStringString(); [SerializeField] SerializableDictionaryStringIntArray _intArrayDictionary = new SerializableDictionaryStringIntArray(); // Unity のSerializeはFieldに対しnullが指定できない。Listの要素数でNull/非Nullを区別する回避策を行う [SerializeField] List _recuesiveDictionary = new List(); public void Add(string key, object value) { ((IDictionary)_innerDictionary).Add(key, value); } public bool ContainsKey(string key) { return ((IDictionary)_innerDictionary).ContainsKey(key); } public bool Remove(string key) { return ((IDictionary)_innerDictionary).Remove(key); } public bool TryGetValue(string key, out object value) { return ((IDictionary)_innerDictionary).TryGetValue(key, out value); } public object this[string key] { get => ((IDictionary)_innerDictionary)[key]; set => ((IDictionary)_innerDictionary)[key] = value; } public ICollection Keys => ((IDictionary)_innerDictionary).Keys; public ICollection Values => ((IDictionary)_innerDictionary).Values; public void Add(KeyValuePair item) { ((ICollection>)_innerDictionary).Add(item); } public void Clear() { ((ICollection>)_innerDictionary).Clear(); } public bool Contains(KeyValuePair item) { return ((ICollection>)_innerDictionary).Contains(item); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)_innerDictionary).CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { return ((ICollection>)_innerDictionary).Remove(item); } public int Count => ((ICollection>)_innerDictionary).Count; public bool IsReadOnly => ((ICollection>)_innerDictionary).IsReadOnly; public IEnumerator> GetEnumerator() { return ((IEnumerable>)_innerDictionary).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_innerDictionary).GetEnumerator(); } public void OnBeforeSerialize() { DictionaryToList(); } public void OnAfterDeserialize() { ListToDictionary(); } private void DictionaryToList() { _boolDictionary.Clear(); _intDictionary.Clear(); _floatDictionary.Clear(); _stringDictionary.Clear(); _intArrayDictionary.Clear(); _recuesiveDictionary.Clear(); foreach (var kv in _innerDictionary) { if (kv.Value == null) { continue; } else if (kv.Value is bool) { _boolDictionary.Add(kv.Key, (bool)kv.Value); } else if (kv.Value is int) { _intDictionary.Add(kv.Key, (int)kv.Value); } else if (kv.Value is float) { _floatDictionary.Add(kv.Key, (float)kv.Value); } else if (kv.Value is string) { _stringDictionary.Add(kv.Key, (string)kv.Value); } else if (kv.Value is int[]) { _intArrayDictionary.Add(kv.Key, (int[])kv.Value); } else if (kv.Value is Dictionary) { if (_recuesiveDictionary.Count == 0) { _recuesiveDictionary.Add(new SerializableDictionaryStringObject()); } _recuesiveDictionary[0].DictionaryToList(); _recuesiveDictionary[0].Add(kv.Key, (Dictionary)kv.Value); } } } private void ListToDictionary() { _innerDictionary.Clear(); foreach (var kv in _boolDictionary) { _innerDictionary.Add(kv.Key, kv.Value); } foreach (var kv in _intDictionary) { _innerDictionary.Add(kv.Key, kv.Value); } foreach (var kv in _floatDictionary) { _innerDictionary.Add(kv.Key, kv.Value); } foreach (var kv in _stringDictionary) { _innerDictionary.Add(kv.Key, kv.Value); } foreach (var kv in _intArrayDictionary) { _innerDictionary.Add(kv.Key, kv.Value); } if (_recuesiveDictionary.Count > 0) { _recuesiveDictionary[0].ListToDictionary(); foreach (var kv in _recuesiveDictionary[0]) { _innerDictionary.Add(kv.Key, kv.Value); } } } public void ForceSerialize() { DictionaryToList(); } } }