First commit for private source control. Older commits available on Github.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "AYellowpaper.SerializedCollections",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d525ad6bd40672747bde77962f1c401e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/AYellowpaper.SerializedCollections.asmdef
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1444c3990d36354e9d53f3797d31080
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
internal class DictionaryLookupTable<TKey, TValue> : IKeyable
|
||||
{
|
||||
private SerializedDictionary<TKey, TValue> _dictionary;
|
||||
private Dictionary<TKey, List<int>> _occurences = new Dictionary<TKey, List<int>>();
|
||||
|
||||
private static readonly List<int> EmptyList = new List<int>();
|
||||
|
||||
public IEnumerable Keys => _dictionary.Keys;
|
||||
|
||||
public DictionaryLookupTable(SerializedDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
_dictionary = dictionary;
|
||||
}
|
||||
|
||||
public IReadOnlyList<int> GetOccurences(object key)
|
||||
{
|
||||
if (key is TKey castKey && _occurences.TryGetValue(castKey, out var list))
|
||||
return list;
|
||||
|
||||
return EmptyList;
|
||||
}
|
||||
|
||||
public void RecalculateOccurences()
|
||||
{
|
||||
_occurences.Clear();
|
||||
|
||||
int count = _dictionary._serializedList.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var kvp = _dictionary._serializedList[i];
|
||||
if (!SerializedCollectionsUtility.IsValidKey(kvp.Key))
|
||||
continue;
|
||||
|
||||
if (!_occurences.ContainsKey(kvp.Key))
|
||||
_occurences.Add(kvp.Key, new List<int>() { i });
|
||||
else
|
||||
_occurences[kvp.Key].Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveKey(object key)
|
||||
{
|
||||
for (int i = _dictionary._serializedList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var dictKey = _dictionary._serializedList[i].Key;
|
||||
if (SerializedCollectionsUtility.KeysAreEqual(dictKey, key))
|
||||
_dictionary._serializedList.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
_dictionary._serializedList.RemoveAt(index);
|
||||
}
|
||||
|
||||
public object GetKeyAt(int index)
|
||||
{
|
||||
return _dictionary._serializedList[index];
|
||||
}
|
||||
|
||||
public int GetCount()
|
||||
{
|
||||
return _dictionary._serializedList.Count;
|
||||
}
|
||||
|
||||
public void RemoveDuplicates()
|
||||
{
|
||||
_dictionary._serializedList = _dictionary._serializedList
|
||||
.GroupBy(x => x.Key)
|
||||
.Where(x => SerializedCollectionsUtility.IsValidKey(x.Key))
|
||||
.Select(x => x.First()).ToList();
|
||||
}
|
||||
|
||||
public void AddKey(object key)
|
||||
{
|
||||
var entry = new SerializedKeyValuePair<TKey, TValue>();
|
||||
entry.Key = (TKey) key;
|
||||
_dictionary._serializedList.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff547989e6c74ca418db99a6a03aa653
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/LookupTables/DictionaryLookupTable.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
internal interface IKeyable
|
||||
{
|
||||
void RecalculateOccurences();
|
||||
IReadOnlyList<int> GetOccurences(object key);
|
||||
IEnumerable Keys { get; }
|
||||
|
||||
void AddKey(object key);
|
||||
void RemoveKey(object key);
|
||||
void RemoveAt(int index);
|
||||
object GetKeyAt(int index);
|
||||
int GetCount();
|
||||
void RemoveDuplicates();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 131781efcfa1f0c4a8f9480cc10f5699
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/LookupTables/IKeyable.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54ab7ca0599474d4281016b4f077172c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("AYellowpaper.SerializedCollections.Editor")]
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88ab3f65a23ff3a4697758e7a3ed3ac0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/Scripts/AssemblyInfo.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
public static class SerializedCollectionsUtility
|
||||
{
|
||||
public static bool IsValidKey(object obj)
|
||||
{
|
||||
// we catch this error if we are not on the main thread and simply return false as we assume the object is null
|
||||
try
|
||||
{
|
||||
return !(obj == null || (obj is Object unityObject && unityObject == null));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool KeysAreEqual<T>(T key, object otherKey)
|
||||
{
|
||||
return (object)key == otherKey || key.Equals(otherKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1da1a15cc1e6754fb099902045e4572
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/Scripts/SerializedCollectionsUtility.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,176 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
[System.Serializable]
|
||||
public class SerializedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
|
||||
{
|
||||
[SerializeField]
|
||||
internal List<SerializedKeyValuePair<TKey, TValue>> _serializedList = new List<SerializedKeyValuePair<TKey, TValue>>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
internal IKeyable LookupTable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_lookupTable == null)
|
||||
_lookupTable = new DictionaryLookupTable<TKey, TValue>(this);
|
||||
return _lookupTable;
|
||||
}
|
||||
}
|
||||
|
||||
private DictionaryLookupTable<TKey, TValue> _lookupTable;
|
||||
#endif
|
||||
|
||||
public SerializedDictionary() : base() {}
|
||||
|
||||
public SerializedDictionary(SerializedDictionary<TKey, TValue> serializedDictionary) : base(serializedDictionary)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
foreach (var kvp in serializedDictionary._serializedList)
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(kvp.Key, kvp.Value));
|
||||
#endif
|
||||
}
|
||||
|
||||
public SerializedDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary)
|
||||
{
|
||||
SyncDictionaryToBackingField_Editor();
|
||||
}
|
||||
|
||||
public SerializedDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(
|
||||
dictionary, comparer)
|
||||
{
|
||||
SyncDictionaryToBackingField_Editor();
|
||||
}
|
||||
|
||||
public SerializedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : base(collection)
|
||||
{
|
||||
SyncDictionaryToBackingField_Editor();
|
||||
}
|
||||
|
||||
public SerializedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection,
|
||||
IEqualityComparer<TKey> comparer) : base(collection, comparer)
|
||||
{
|
||||
SyncDictionaryToBackingField_Editor();
|
||||
}
|
||||
public SerializedDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }
|
||||
public SerializedDictionary(int capacity) : base(capacity) { }
|
||||
public SerializedDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer) { }
|
||||
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
private void SyncDictionaryToBackingField_Editor()
|
||||
{
|
||||
foreach (var kvp in this)
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(kvp.Key, kvp.Value));
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public new TValue this[TKey key]
|
||||
{
|
||||
get => base[key];
|
||||
set
|
||||
{
|
||||
base[key] = value;
|
||||
bool anyEntryWasFound = false;
|
||||
for (int i = 0; i < _serializedList.Count; i++)
|
||||
{
|
||||
var kvp = _serializedList[i];
|
||||
if (!SerializedCollectionsUtility.KeysAreEqual(key, kvp.Key))
|
||||
continue;
|
||||
anyEntryWasFound = true;
|
||||
kvp.Value = value;
|
||||
_serializedList[i] = kvp;
|
||||
}
|
||||
|
||||
if (!anyEntryWasFound)
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
public new void Add(TKey key, TValue value)
|
||||
{
|
||||
base.Add(key, value);
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
|
||||
public new void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
_serializedList.Clear();
|
||||
}
|
||||
|
||||
public new bool Remove(TKey key)
|
||||
{
|
||||
if (TryGetValue(key, out var value))
|
||||
{
|
||||
base.Remove(key);
|
||||
_serializedList.Remove(new SerializedKeyValuePair<TKey, TValue>(key, value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public new bool TryAdd(TKey key, TValue value)
|
||||
{
|
||||
if (base.TryAdd(key, value))
|
||||
{
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(key, value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only available in Editor. Add a key value pair, even if the key already exists in the dictionary.
|
||||
/// </summary>
|
||||
public void AddConflictAllowed(TKey key, TValue value)
|
||||
{
|
||||
if (!ContainsKey(key))
|
||||
base.Add(key, value);
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
#endif
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
base.Clear();
|
||||
|
||||
foreach (var kvp in _serializedList)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (SerializedCollectionsUtility.IsValidKey(kvp.Key) && !ContainsKey(kvp.Key))
|
||||
base.Add(kvp.Key, kvp.Value);
|
||||
#else
|
||||
Add(kvp.Key, kvp.Value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
LookupTable.RecalculateOccurences();
|
||||
#else
|
||||
_serializedList.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (UnityEditor.BuildPipeline.isBuildingPlayer)
|
||||
LookupTable.RemoveDuplicates();
|
||||
|
||||
// TODO: is there a better way to check if the dictionary was deserialized with reflection?
|
||||
if (_serializedList.Count == 0 && Count > 0)
|
||||
SyncDictionaryToBackingField_Editor();
|
||||
#else
|
||||
_serializedList.Clear();
|
||||
foreach (var kvp in this)
|
||||
_serializedList.Add(new SerializedKeyValuePair<TKey, TValue>(kvp.Key, kvp.Value));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfd467abf43f5944faa7fd0abcac2299
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/Scripts/SerializedDictionary.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class SerializedDictionaryAttribute : Attribute
|
||||
{
|
||||
public readonly string KeyName;
|
||||
public readonly string ValueName;
|
||||
|
||||
public SerializedDictionaryAttribute(string keyName = null, string valueName = null)
|
||||
{
|
||||
KeyName = keyName;
|
||||
ValueName = valueName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3aa354f515fef24c865758f92a293ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/Scripts/SerializedDictionaryAttribute.cs
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct SerializedKeyValuePair<TKey, TValue>
|
||||
{
|
||||
public TKey Key;
|
||||
public TValue Value;
|
||||
|
||||
public SerializedKeyValuePair(TKey key, TValue value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f808808de12544418e1f67eb1e8a78d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Runtime/Scripts/SerializedKeyValuePair.cs
|
||||
uploadId: 632226
|
||||
Reference in New Issue
Block a user