Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 260e630c5c1b1af42991291f6de23ede
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 89f0fbd77bac24f9dad0f8c81e7822c5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public abstract class Cloner<T> : ICloner
|
||||
{
|
||||
protected Cloner() { }
|
||||
|
||||
public abstract bool Handles(Type type);
|
||||
|
||||
void ICloner.BeforeClone(Type type, object original)
|
||||
{
|
||||
BeforeClone(type, (T)original);
|
||||
}
|
||||
|
||||
public virtual void BeforeClone(Type type, T original) { }
|
||||
|
||||
object ICloner.ConstructClone(Type type, object original)
|
||||
{
|
||||
return ConstructClone(type, (T)original);
|
||||
}
|
||||
|
||||
public virtual T ConstructClone(Type type, T original)
|
||||
{
|
||||
return (T)Activator.CreateInstance(type, true);
|
||||
}
|
||||
|
||||
void ICloner.FillClone(Type type, ref object clone, object original, CloningContext context)
|
||||
{
|
||||
var _instance = (T)clone;
|
||||
FillClone(type, ref _instance, (T)original, context);
|
||||
clone = _instance;
|
||||
}
|
||||
|
||||
public virtual void FillClone(Type type, ref T clone, T original, CloningContext context) { }
|
||||
|
||||
void ICloner.AfterClone(Type type, object clone)
|
||||
{
|
||||
AfterClone(type, (T)clone);
|
||||
}
|
||||
|
||||
public virtual void AfterClone(Type type, T clone) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50985218b7f8c4670b61869830f5ff7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c562f70f440ba462ba456f970152ebb1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class AnimationCurveCloner : Cloner<AnimationCurve>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return type == typeof(AnimationCurve);
|
||||
}
|
||||
|
||||
public override AnimationCurve ConstructClone(Type type, AnimationCurve original)
|
||||
{
|
||||
return new AnimationCurve();
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref AnimationCurve clone, AnimationCurve original, CloningContext context)
|
||||
{
|
||||
for (int i = 0; i < clone.length; i++)
|
||||
{
|
||||
clone.RemoveKey(i);
|
||||
}
|
||||
|
||||
foreach (var key in original.keys)
|
||||
{
|
||||
clone.AddKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f94de5bcee76742e2adc9ac35bfbcede
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class ArrayCloner : Cloner<Array>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return type.IsArray;
|
||||
}
|
||||
|
||||
public override Array ConstructClone(Type type, Array original)
|
||||
{
|
||||
return Array.CreateInstance(type.GetElementType(), 0);
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref Array clone, Array original, CloningContext context)
|
||||
{
|
||||
var length = original.GetLength(0);
|
||||
|
||||
clone = Array.CreateInstance(type.GetElementType(), length);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
clone.SetValue(Cloning.Clone(context, original.GetValue(i)), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a7f87d6d28e64ed9b331c4d12c46937
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class DictionaryCloner : Cloner<IDictionary>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return typeof(IDictionary).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref IDictionary clone, IDictionary original, CloningContext context)
|
||||
{
|
||||
// No support for instance preservation here, but none in FS either, so it shouldn't matter
|
||||
|
||||
var originalEnumerator = original.GetEnumerator();
|
||||
|
||||
while (originalEnumerator.MoveNext())
|
||||
{
|
||||
var originalKey = originalEnumerator.Key;
|
||||
var originalValue = originalEnumerator.Value;
|
||||
|
||||
var cloneKey = Cloning.Clone(context, originalKey);
|
||||
var cloneValue = Cloning.Clone(context, originalValue);
|
||||
|
||||
clone.Add(cloneKey, cloneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb2273f662a444114949392f30936c92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.VisualScripting.FullSerializer;
|
||||
using Unity.VisualScripting.FullSerializer.Internal;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class EnumerableCloner : Cloner<IEnumerable>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return typeof(IEnumerable).IsAssignableFrom(type) && !typeof(IList).IsAssignableFrom(type) && GetAddMethod(type) != null;
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref IEnumerable clone, IEnumerable original, CloningContext context)
|
||||
{
|
||||
var addMethod = GetAddMethod(type);
|
||||
|
||||
if (addMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot instantiate enumerable type '{type}' because it does not provide an add method.");
|
||||
}
|
||||
|
||||
// No way to preserve instances here
|
||||
|
||||
foreach (var item in original)
|
||||
{
|
||||
addMethod.Invoke(item, Cloning.Clone(context, item));
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, IOptimizedInvoker> addMethods = new Dictionary<Type, IOptimizedInvoker>();
|
||||
|
||||
private IOptimizedInvoker GetAddMethod(Type type)
|
||||
{
|
||||
if (!addMethods.ContainsKey(type))
|
||||
{
|
||||
var addMethod = fsReflectionUtility.GetInterface(type, typeof(ICollection<>))?.GetDeclaredMethod("Add") ??
|
||||
type.GetFlattenedMethod("Add") ??
|
||||
type.GetFlattenedMethod("Push") ??
|
||||
type.GetFlattenedMethod("Enqueue");
|
||||
|
||||
addMethods.Add(type, addMethod?.Prewarm());
|
||||
}
|
||||
|
||||
return addMethods[type];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6d1033b3313d4b48a5985fa78ec5621
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Unity.VisualScripting.FullSerializer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class FakeSerializationCloner : ReflectedCloner
|
||||
{
|
||||
public fsConfig config { get; set; } = new fsConfig();
|
||||
|
||||
public override void BeforeClone(Type type, object original)
|
||||
{
|
||||
(original as ISerializationCallbackReceiver)?.OnBeforeSerialize();
|
||||
}
|
||||
|
||||
public override void AfterClone(Type type, object clone)
|
||||
{
|
||||
(clone as ISerializationCallbackReceiver)?.OnAfterDeserialize();
|
||||
}
|
||||
|
||||
protected override IEnumerable<MemberInfo> GetMembers(Type type)
|
||||
{
|
||||
return fsMetaType.Get(config, type).Properties.Select(p => p._memberInfo);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d112c25d2373f447a965ce5f734e2a67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,17 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class FieldsCloner : ReflectedCloner
|
||||
{
|
||||
protected override bool IncludeField(FieldInfo field)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool IncludeProperty(PropertyInfo property)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3a95ea3668ca49bba7f93586f8e08ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class ListCloner : Cloner<IList>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return typeof(IList).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref IList clone, IList original, CloningContext context)
|
||||
{
|
||||
if (context.tryPreserveInstances)
|
||||
{
|
||||
for (int i = 0; i < original.Count; i++)
|
||||
{
|
||||
var originalItem = original[i];
|
||||
|
||||
if (i < clone.Count)
|
||||
{
|
||||
// The clone has at least as many items, we can try to preserve its instances.
|
||||
var cloneItem = clone[i];
|
||||
Cloning.CloneInto(context, ref cloneItem, originalItem);
|
||||
clone[i] = cloneItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The clone has less items than the original, we have to add a new item.
|
||||
clone.Add(Cloning.Clone(context, originalItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoiding foreach to avoid enumerator allocation
|
||||
|
||||
for (int i = 0; i < original.Count; i++)
|
||||
{
|
||||
var originalItem = original[i];
|
||||
|
||||
clone.Add(Cloning.Clone(context, originalItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cfddb429b323a4b0eb5bbfb7c5ef6ac0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public abstract class ReflectedCloner : Cloner<object>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return false; // Should only be used as a fallback cloner
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref object clone, object original, CloningContext context)
|
||||
{
|
||||
if (PlatformUtility.supportsJit)
|
||||
{
|
||||
foreach (var accessor in GetOptimizedAccessors(type))
|
||||
{
|
||||
if (context.tryPreserveInstances)
|
||||
{
|
||||
var cloneProperty = accessor.GetValue(clone);
|
||||
Cloning.CloneInto(context, ref cloneProperty, accessor.GetValue(original));
|
||||
accessor.SetValue(clone, cloneProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
accessor.SetValue(clone, Cloning.Clone(context, accessor.GetValue(original)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var accessor in GetAccessors(type))
|
||||
{
|
||||
if (accessor is FieldInfo)
|
||||
{
|
||||
var field = (FieldInfo)accessor;
|
||||
|
||||
if (context.tryPreserveInstances)
|
||||
{
|
||||
var cloneProperty = field.GetValue(clone);
|
||||
Cloning.CloneInto(context, ref cloneProperty, field.GetValue(original));
|
||||
field.SetValue(clone, cloneProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
field.SetValue(clone, Cloning.Clone(context, field.GetValue(original)));
|
||||
}
|
||||
}
|
||||
else if (accessor is PropertyInfo)
|
||||
{
|
||||
var property = (PropertyInfo)accessor;
|
||||
|
||||
if (context.tryPreserveInstances)
|
||||
{
|
||||
var cloneProperty = property.GetValue(clone, null);
|
||||
Cloning.CloneInto(context, ref cloneProperty, property.GetValue(original, null));
|
||||
property.SetValue(clone, cloneProperty, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
property.SetValue(clone, Cloning.Clone(context, property.GetValue(original, null)), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, MemberInfo[]> accessors = new Dictionary<Type, MemberInfo[]>();
|
||||
|
||||
private MemberInfo[] GetAccessors(Type type)
|
||||
{
|
||||
if (!accessors.ContainsKey(type))
|
||||
{
|
||||
accessors.Add(type, GetMembers(type).ToArray());
|
||||
}
|
||||
|
||||
return accessors[type];
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, IOptimizedAccessor[]> optimizedAccessors = new Dictionary<Type, IOptimizedAccessor[]>();
|
||||
|
||||
private IOptimizedAccessor[] GetOptimizedAccessors(Type type)
|
||||
{
|
||||
if (!optimizedAccessors.ContainsKey(type))
|
||||
{
|
||||
var list = new List<IOptimizedAccessor>();
|
||||
|
||||
foreach (var member in GetMembers(type))
|
||||
{
|
||||
if (member is FieldInfo)
|
||||
{
|
||||
list.Add(((FieldInfo)member).Prewarm());
|
||||
}
|
||||
else if (member is PropertyInfo)
|
||||
{
|
||||
list.Add(((PropertyInfo)member).Prewarm());
|
||||
}
|
||||
}
|
||||
|
||||
optimizedAccessors.Add(type, list.ToArray());
|
||||
}
|
||||
|
||||
return optimizedAccessors[type];
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<MemberInfo> GetMembers(Type type)
|
||||
{
|
||||
var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
|
||||
return LinqUtility.Concat<MemberInfo>
|
||||
(
|
||||
type.GetFields(bindingFlags).Where(IncludeField),
|
||||
type.GetProperties(bindingFlags).Where(IncludeProperty)
|
||||
);
|
||||
}
|
||||
|
||||
protected virtual bool IncludeField(FieldInfo field)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool IncludeProperty(PropertyInfo property)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9171b20d783a745a78171a47606f8843
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using UnityObject = UnityEngine.Object;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public static class Cloning
|
||||
{
|
||||
static Cloning()
|
||||
{
|
||||
cloners.Add(arrayCloner);
|
||||
cloners.Add(dictionaryCloner);
|
||||
cloners.Add(enumerableCloner);
|
||||
cloners.Add(listCloner);
|
||||
cloners.Add(animationCurveCloner);
|
||||
}
|
||||
|
||||
// Cloning has to be really fast, and skippable takes a while.
|
||||
private static readonly Dictionary<Type, bool> skippable = new Dictionary<Type, bool>();
|
||||
|
||||
public static HashSet<ICloner> cloners { get; } = new HashSet<ICloner>();
|
||||
|
||||
public static ArrayCloner arrayCloner { get; } = new ArrayCloner();
|
||||
public static DictionaryCloner dictionaryCloner { get; } = new DictionaryCloner();
|
||||
public static EnumerableCloner enumerableCloner { get; } = new EnumerableCloner();
|
||||
public static ListCloner listCloner { get; } = new ListCloner();
|
||||
public static AnimationCurveCloner animationCurveCloner { get; } = new AnimationCurveCloner();
|
||||
|
||||
public static FieldsCloner fieldsCloner { get; } = new FieldsCloner();
|
||||
public static FakeSerializationCloner fakeSerializationCloner { get; } = new FakeSerializationCloner();
|
||||
|
||||
public static object Clone(this object original, ICloner fallbackCloner, bool tryPreserveInstances)
|
||||
{
|
||||
using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
|
||||
{
|
||||
return Clone(context, original);
|
||||
}
|
||||
}
|
||||
|
||||
public static T Clone<T>(this T original, ICloner fallbackCloner, bool tryPreserveInstances)
|
||||
{
|
||||
return (T)Clone((object)original, fallbackCloner, tryPreserveInstances);
|
||||
}
|
||||
|
||||
public static object CloneViaFakeSerialization(this object original)
|
||||
{
|
||||
return original.Clone(fakeSerializationCloner, true);
|
||||
}
|
||||
|
||||
public static T CloneViaFakeSerialization<T>(this T original)
|
||||
{
|
||||
return (T)CloneViaFakeSerialization((object)original);
|
||||
}
|
||||
|
||||
internal static object Clone(CloningContext context, object original)
|
||||
{
|
||||
object clone = null;
|
||||
CloneInto(context, ref clone, original);
|
||||
return clone;
|
||||
}
|
||||
|
||||
internal static void CloneInto(CloningContext context, ref object clone, object original)
|
||||
{
|
||||
if (original == null)
|
||||
{
|
||||
clone = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var type = original.GetType();
|
||||
|
||||
if (Skippable(type))
|
||||
{
|
||||
clone = original;
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.clonings.ContainsKey(original))
|
||||
{
|
||||
clone = context.clonings[original];
|
||||
return;
|
||||
}
|
||||
|
||||
var cloner = GetCloner(original, type, context.fallbackCloner);
|
||||
|
||||
if (clone == null)
|
||||
{
|
||||
clone = cloner.ConstructClone(type, original);
|
||||
}
|
||||
|
||||
context.clonings.Add(original, clone);
|
||||
cloner.BeforeClone(type, original);
|
||||
cloner.FillClone(type, ref clone, original, context);
|
||||
cloner.AfterClone(type, clone);
|
||||
context.clonings[original] = clone; // In case the reference changed, for example in arrays
|
||||
}
|
||||
|
||||
[CanBeNull]
|
||||
public static ICloner GetCloner(object original, Type type)
|
||||
{
|
||||
if (original is ISpecifiesCloner cloneableVia)
|
||||
{
|
||||
return cloneableVia.cloner;
|
||||
}
|
||||
|
||||
return cloners.FirstOrDefault(cloner => cloner.Handles(type));
|
||||
}
|
||||
|
||||
private static ICloner GetCloner(object original, Type type, ICloner fallbackCloner)
|
||||
{
|
||||
var cloner = GetCloner(original, type);
|
||||
|
||||
if (cloner != null)
|
||||
return cloner;
|
||||
|
||||
Ensure.That(nameof(fallbackCloner)).IsNotNull(fallbackCloner);
|
||||
|
||||
return fallbackCloner;
|
||||
}
|
||||
|
||||
private static bool Skippable(Type type)
|
||||
{
|
||||
bool result;
|
||||
|
||||
if (!skippable.TryGetValue(type, out result))
|
||||
{
|
||||
result = type.IsValueType || // Value types are copied on assignment, so no cloning is necessary
|
||||
type == typeof(string) || // Strings have copy on write semantics as well, but aren't value types
|
||||
typeof(Type).IsAssignableFrom(type) || // Types are guaranteed to be singletons. Using inheritance because MonoType/RuntimeType extend Type
|
||||
typeof(UnityObject).IsAssignableFrom(type); // Unity objects act as pure references
|
||||
|
||||
skippable.Add(type, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: caccb2b4912fd42848baed54c72fcaec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class CloningContext : IPoolable, IDisposable
|
||||
{
|
||||
public Dictionary<object, object> clonings { get; } = new Dictionary<object, object>(ReferenceEqualityComparer.Instance);
|
||||
|
||||
public ICloner fallbackCloner { get; private set; }
|
||||
|
||||
public bool tryPreserveInstances { get; private set; }
|
||||
|
||||
private bool disposed;
|
||||
|
||||
void IPoolable.New()
|
||||
{
|
||||
disposed = false;
|
||||
}
|
||||
|
||||
void IPoolable.Free()
|
||||
{
|
||||
disposed = true;
|
||||
clonings.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(ToString());
|
||||
}
|
||||
|
||||
GenericPool<CloningContext>.Free(this);
|
||||
}
|
||||
|
||||
public static CloningContext New(ICloner fallbackCloner, bool tryPreserveInstances)
|
||||
{
|
||||
var context = GenericPool<CloningContext>.New(() => new CloningContext());
|
||||
context.fallbackCloner = fallbackCloner;
|
||||
context.tryPreserveInstances = tryPreserveInstances;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 006f225b9646c461aa078fc0b336581e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface ICloner
|
||||
{
|
||||
bool Handles(Type type);
|
||||
object ConstructClone(Type type, object original);
|
||||
void BeforeClone(Type type, object original);
|
||||
void FillClone(Type type, ref object clone, object original, CloningContext context);
|
||||
void AfterClone(Type type, object clone);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9b7b894041594292acd8c04daf20f83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface ISpecifiesCloner
|
||||
{
|
||||
ICloner cloner { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c30372978c88446b390054f403f3e0ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bbe380d5d8ee54393b29ed8756019c95
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
// Making this inherit OrderedDictionary for now because metadata
|
||||
// doesn't work well for unordered dictionaries. The ideal solution
|
||||
// would be to rework the MetadataDictionaryAdaptor to not require
|
||||
// the index at all, then make this inherit Dictionary<object, object>
|
||||
|
||||
public sealed class AotDictionary : OrderedDictionary
|
||||
{
|
||||
public AotDictionary() : base() { }
|
||||
public AotDictionary(IEqualityComparer comparer) : base(comparer) { }
|
||||
public AotDictionary(int capacity) : base(capacity) { }
|
||||
public AotDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { }
|
||||
|
||||
[Preserve]
|
||||
public static void AotStubs()
|
||||
{
|
||||
var dictionary = new AotDictionary();
|
||||
|
||||
dictionary.Add(default(object), default(object));
|
||||
dictionary.Remove(default(object));
|
||||
var item = dictionary[default(object)];
|
||||
dictionary[default(object)] = default(object);
|
||||
dictionary.Contains(default(object));
|
||||
dictionary.Clear();
|
||||
var count = dictionary.Count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f097bbb63a5fa43369651ebaf0812b0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
|||
using System.Collections;
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class AotList : ArrayList
|
||||
{
|
||||
public AotList() : base() { }
|
||||
public AotList(int capacity) : base(capacity) { }
|
||||
public AotList(ICollection c) : base(c) { }
|
||||
|
||||
[Preserve]
|
||||
public static void AotStubs()
|
||||
{
|
||||
var list = new AotList();
|
||||
|
||||
list.Add(default(object));
|
||||
list.Remove(default(object));
|
||||
var item = list[default(int)];
|
||||
list[default(int)] = default(object);
|
||||
list.Contains(default(object));
|
||||
list.Clear();
|
||||
var count = list.Count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a8adccab0e6b44bfa9204ceaad999770
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class DebugDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
|
||||
{
|
||||
private readonly Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return dictionary[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
Debug($"Set: {key} => {value}");
|
||||
dictionary[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
object IDictionary.this[object key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[(TKey)key];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[(TKey)key] = (TValue)value;
|
||||
}
|
||||
}
|
||||
|
||||
public string label { get; set; } = "Dictionary";
|
||||
|
||||
public bool debug { get; set; } = false;
|
||||
|
||||
public int Count => dictionary.Count;
|
||||
|
||||
object ICollection.SyncRoot => ((ICollection)dictionary).SyncRoot;
|
||||
|
||||
bool ICollection.IsSynchronized => ((ICollection)dictionary).IsSynchronized;
|
||||
|
||||
ICollection IDictionary.Values => ((IDictionary)dictionary).Values;
|
||||
|
||||
bool IDictionary.IsReadOnly => ((IDictionary)dictionary).IsReadOnly;
|
||||
|
||||
bool IDictionary.IsFixedSize => ((IDictionary)dictionary).IsFixedSize;
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).IsReadOnly;
|
||||
|
||||
public ICollection<TKey> Keys => dictionary.Keys;
|
||||
|
||||
ICollection IDictionary.Keys => ((IDictionary)dictionary).Keys;
|
||||
|
||||
public ICollection<TValue> Values => dictionary.Values;
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection)dictionary).CopyTo(array, index);
|
||||
}
|
||||
|
||||
private void Debug(string message)
|
||||
{
|
||||
if (!debug)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
message = $"[{label}] {message}";
|
||||
}
|
||||
|
||||
UnityEngine.Debug.Log(message + "\n");
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)dictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
void IDictionary.Remove(object key)
|
||||
{
|
||||
Remove((TKey)key);
|
||||
}
|
||||
|
||||
bool IDictionary.Contains(object key)
|
||||
{
|
||||
return ContainsKey((TKey)key);
|
||||
}
|
||||
|
||||
void IDictionary.Add(object key, object value)
|
||||
{
|
||||
Add((TKey)key, (TValue)value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Debug("Clear");
|
||||
dictionary.Clear();
|
||||
}
|
||||
|
||||
IDictionaryEnumerator IDictionary.GetEnumerator()
|
||||
{
|
||||
return ((IDictionary)dictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return dictionary.Contains(item);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Add(item);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
((ICollection<KeyValuePair<TKey, TValue>>)dictionary).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Remove(item);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
Debug($"Add: {key} => {value}");
|
||||
dictionary.Add(key, value);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
Debug($"Remove: {key}");
|
||||
return dictionary.Remove(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
return dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 41ca2a75f36964ef7a3a443f34ba6874
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class FlexibleDictionary<TKey, TValue> : Dictionary<TKey, TValue>
|
||||
{
|
||||
public new TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return base[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (ContainsKey(key))
|
||||
{
|
||||
base[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0f23d5c6cf81d46a99f18c2f734bdccc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class GuidCollection<T> : KeyedCollection<Guid, T>, IKeyedCollection<Guid, T> where T : IIdentifiable
|
||||
{
|
||||
protected override Guid GetKeyForItem(T item)
|
||||
{
|
||||
return item.guid;
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
Ensure.That(nameof(item)).IsNotNull(item);
|
||||
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, T item)
|
||||
{
|
||||
Ensure.That(nameof(item)).IsNotNull(item);
|
||||
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
|
||||
public bool TryGetValue(Guid key, out T value)
|
||||
{
|
||||
if (Dictionary == null)
|
||||
{
|
||||
value = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
return Dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 106fdba61aee041bb848696298f2a0cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IKeyedCollection<TKey, TItem> : ICollection<TItem>
|
||||
{
|
||||
TItem this[TKey key] { get; }
|
||||
TItem this[int index] { get; } // For allocation free enumerators
|
||||
bool TryGetValue(TKey key, out TItem value);
|
||||
bool Contains(TKey key);
|
||||
bool Remove(TKey key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 838e8a6e5d50f44d6988900179976bf1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IMergedCollection<T> : ICollection<T>
|
||||
{
|
||||
bool Includes<TI>() where TI : T;
|
||||
bool Includes(Type elementType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 954150586dd10405f91f4be9407eeff1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface INotifiedCollectionItem
|
||||
{
|
||||
void BeforeAdd();
|
||||
|
||||
void AfterAdd();
|
||||
|
||||
void BeforeRemove();
|
||||
|
||||
void AfterRemove();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca4bb37a65b7748358d2789431d7aa49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface INotifyCollectionChanged<T>
|
||||
{
|
||||
event Action<T> ItemAdded;
|
||||
|
||||
event Action<T> ItemRemoved;
|
||||
|
||||
event Action CollectionChanged;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: db8af6900bbbd4c77818f39666021768
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IProxyableNotifyCollectionChanged<T>
|
||||
{
|
||||
bool ProxyCollectionChange { get; set; }
|
||||
|
||||
void BeforeAdd(T item);
|
||||
|
||||
void AfterAdd(T item);
|
||||
|
||||
void BeforeRemove(T item);
|
||||
|
||||
void AfterRemove(T item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 067acbd60a2494a05954d63584e9b346
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,62 @@
|
|||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
/*============================================================
|
||||
**
|
||||
** Interface: ISet
|
||||
**
|
||||
** <OWNER>kimhamil</OWNER>
|
||||
**
|
||||
**
|
||||
** Purpose: Base interface for all generic sets.
|
||||
**
|
||||
**
|
||||
===========================================================*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic collection that guarantees the uniqueness of its elements, as defined
|
||||
/// by some comparer. It also supports basic set operations such as Union, Intersection,
|
||||
/// Complement and Exclusive Complement.
|
||||
/// </summary>
|
||||
public interface ISet<T> : ICollection<T>
|
||||
{
|
||||
//Add ITEM to the set, return true if added, false if duplicate
|
||||
new bool Add(T item);
|
||||
|
||||
//Transform this set into its union with the IEnumerable<T> other
|
||||
void UnionWith(IEnumerable<T> other);
|
||||
|
||||
//Transform this set into its intersection with the IEnumberable<T> other
|
||||
void IntersectWith(IEnumerable<T> other);
|
||||
|
||||
//Transform this set so it contains no elements that are also in other
|
||||
void ExceptWith(IEnumerable<T> other);
|
||||
|
||||
//Transform this set so it contains elements initially in this or in other, but not both
|
||||
void SymmetricExceptWith(IEnumerable<T> other);
|
||||
|
||||
//Check if this set is a subset of other
|
||||
bool IsSubsetOf(IEnumerable<T> other);
|
||||
|
||||
//Check if this set is a superset of other
|
||||
bool IsSupersetOf(IEnumerable<T> other);
|
||||
|
||||
//Check if this set is a subset of other, but not the same as it
|
||||
bool IsProperSupersetOf(IEnumerable<T> other);
|
||||
|
||||
//Check if this set is a superset of other, but not the same as it
|
||||
bool IsProperSubsetOf(IEnumerable<T> other);
|
||||
|
||||
//Check if this set has any elements in common with other
|
||||
bool Overlaps(IEnumerable<T> other);
|
||||
|
||||
//Check if this set contains the same and only the same elements as other
|
||||
bool SetEquals(IEnumerable<T> other);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e8bad27d2153d44cba7a1fa7e451d5e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,150 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class MergedCollection<T> : IMergedCollection<T>
|
||||
{
|
||||
public MergedCollection()
|
||||
{
|
||||
collections = new Dictionary<Type, ICollection<T>>();
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, ICollection<T>> collections;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
count += collection.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public void Include<TI>(ICollection<TI> collection) where TI : T
|
||||
{
|
||||
collections.Add(typeof(TI), new VariantCollection<T, TI>(collection));
|
||||
}
|
||||
|
||||
public bool Includes<TI>() where TI : T
|
||||
{
|
||||
return Includes(typeof(TI));
|
||||
}
|
||||
|
||||
public bool Includes(Type implementationType)
|
||||
{
|
||||
return GetCollectionForType(implementationType, false) != null;
|
||||
}
|
||||
|
||||
public ICollection<TI> ForType<TI>() where TI : T
|
||||
{
|
||||
return ((VariantCollection<T, TI>)GetCollectionForType(typeof(TI))).implementation;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
foreach (var item in collection)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ICollection<T> GetCollectionForItem(T item)
|
||||
{
|
||||
Ensure.That(nameof(item)).IsNotNull(item);
|
||||
|
||||
return GetCollectionForType(item.GetType());
|
||||
}
|
||||
|
||||
private ICollection<T> GetCollectionForType(Type type, bool throwOnFail = true)
|
||||
{
|
||||
if (collections.ContainsKey(type))
|
||||
{
|
||||
return collections[type];
|
||||
}
|
||||
|
||||
foreach (var collectionByType in collections)
|
||||
{
|
||||
if (collectionByType.Key.IsAssignableFrom(type))
|
||||
{
|
||||
return collectionByType.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnFail)
|
||||
{
|
||||
throw new InvalidOperationException($"No sub-collection available for type '{type}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return GetCollectionForItem(item).Contains(item);
|
||||
}
|
||||
|
||||
public virtual void Add(T item)
|
||||
{
|
||||
GetCollectionForItem(item).Add(item);
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
collection.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Remove(T item)
|
||||
{
|
||||
return GetCollectionForItem(item).Remove(item);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
collection.CopyTo(array, arrayIndex + i);
|
||||
i += collection.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e0381bb4e0f05444598e51b5a33edf4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,320 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class MergedKeyedCollection<TKey, TItem> : IMergedCollection<TItem>
|
||||
{
|
||||
public MergedKeyedCollection() : base()
|
||||
{
|
||||
collections = new Dictionary<Type, IKeyedCollection<TKey, TItem>>();
|
||||
collectionsLookup = new Dictionary<Type, IKeyedCollection<TKey, TItem>>();
|
||||
}
|
||||
|
||||
protected readonly Dictionary<Type, IKeyedCollection<TKey, TItem>> collections;
|
||||
|
||||
// Used for performance optimization when finding the right collection for a type
|
||||
protected readonly Dictionary<Type, IKeyedCollection<TKey, TItem>> collectionsLookup;
|
||||
|
||||
public TItem this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
foreach (var collectionByType in collections)
|
||||
{
|
||||
if (collectionByType.Value.Contains(key))
|
||||
{
|
||||
return collectionByType.Value[key];
|
||||
}
|
||||
}
|
||||
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (var collectionByType in collections)
|
||||
{
|
||||
count += collectionByType.Value.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public bool Includes<TSubItem>() where TSubItem : TItem
|
||||
{
|
||||
return Includes(typeof(TSubItem));
|
||||
}
|
||||
|
||||
public bool Includes(Type elementType)
|
||||
{
|
||||
return GetCollectionForType(elementType, false) != null;
|
||||
}
|
||||
|
||||
public IKeyedCollection<TKey, TSubItem> ForType<TSubItem>() where TSubItem : TItem
|
||||
{
|
||||
return ((VariantKeyedCollection<TItem, TSubItem, TKey>)GetCollectionForType(typeof(TSubItem))).implementation;
|
||||
}
|
||||
|
||||
public virtual void Include<TSubItem>(IKeyedCollection<TKey, TSubItem> collection) where TSubItem : TItem
|
||||
{
|
||||
var type = typeof(TSubItem);
|
||||
var variantCollection = new VariantKeyedCollection<TItem, TSubItem, TKey>(collection);
|
||||
collections.Add(type, variantCollection);
|
||||
collectionsLookup.Add(type, variantCollection);
|
||||
}
|
||||
|
||||
protected IKeyedCollection<TKey, TItem> GetCollectionForItem(TItem item)
|
||||
{
|
||||
Ensure.That(nameof(item)).IsNotNull(item);
|
||||
|
||||
return GetCollectionForType(item.GetType());
|
||||
}
|
||||
|
||||
protected IKeyedCollection<TKey, TItem> GetCollectionForType(Type type, bool throwOnFail = true)
|
||||
{
|
||||
Ensure.That(nameof(type)).IsNotNull(type);
|
||||
|
||||
if (collectionsLookup.TryGetValue(type, out var collection))
|
||||
{
|
||||
return collection;
|
||||
}
|
||||
|
||||
foreach (var collectionByType in collections)
|
||||
{
|
||||
if (collectionByType.Key.IsAssignableFrom(type))
|
||||
{
|
||||
collection = collectionByType.Value;
|
||||
collectionsLookup.Add(type, collection);
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnFail)
|
||||
{
|
||||
throw new InvalidOperationException($"No sub-collection available for type '{type}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected IKeyedCollection<TKey, TItem> GetCollectionForKey(TKey key, bool throwOnFail = true)
|
||||
{
|
||||
// Optim: avoid boxing here.
|
||||
// Ensure.That(nameof(key)).IsNotNull(key);
|
||||
|
||||
foreach (var collectionsByType in collections)
|
||||
{
|
||||
if (collectionsByType.Value.Contains(key))
|
||||
{
|
||||
return collectionsByType.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnFail)
|
||||
{
|
||||
throw new InvalidOperationException($"No sub-collection available for key '{key}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TItem value)
|
||||
{
|
||||
var collection = GetCollectionForKey(key, false);
|
||||
|
||||
value = default(TItem);
|
||||
|
||||
return collection != null && collection.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public virtual void Add(TItem item)
|
||||
{
|
||||
GetCollectionForItem(item).Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
collection.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(TItem item)
|
||||
{
|
||||
return GetCollectionForItem(item).Contains(item);
|
||||
}
|
||||
|
||||
public bool Remove(TItem item)
|
||||
{
|
||||
return GetCollectionForItem(item).Remove(item);
|
||||
}
|
||||
|
||||
public void CopyTo(TItem[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
foreach (var collection in collections.Values)
|
||||
{
|
||||
collection.CopyTo(array, arrayIndex + i);
|
||||
i += collection.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(TKey key)
|
||||
{
|
||||
return GetCollectionForKey(key, false) != null;
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return GetCollectionForKey(key).Remove(key);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<TItem>
|
||||
{
|
||||
private Dictionary<Type, IKeyedCollection<TKey, TItem>>.Enumerator collectionsEnumerator;
|
||||
private TItem currentItem;
|
||||
private IKeyedCollection<TKey, TItem> currentCollection;
|
||||
private int indexInCurrentCollection;
|
||||
private bool exceeded;
|
||||
|
||||
public Enumerator(MergedKeyedCollection<TKey, TItem> merged) : this()
|
||||
{
|
||||
collectionsEnumerator = merged.collections.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
// We just started, so we're not in a collection yet
|
||||
if (currentCollection == null)
|
||||
{
|
||||
// Try to find the first collection
|
||||
if (collectionsEnumerator.MoveNext())
|
||||
{
|
||||
// There is at least a collection, start with this one
|
||||
currentCollection = collectionsEnumerator.Current.Value;
|
||||
|
||||
if (currentCollection == null)
|
||||
{
|
||||
throw new InvalidOperationException("Merged sub collection is null.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is no collection at all, stop
|
||||
currentItem = default(TItem);
|
||||
exceeded = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're within the current collection
|
||||
if (indexInCurrentCollection < currentCollection.Count)
|
||||
{
|
||||
// We are, return this element and move to the next
|
||||
currentItem = currentCollection[indexInCurrentCollection];
|
||||
indexInCurrentCollection++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're beyond the current collection, but there may be more,
|
||||
// and because there may be many empty collections, we need to check
|
||||
// them all until we find an element, not just the next one
|
||||
while (collectionsEnumerator.MoveNext())
|
||||
{
|
||||
currentCollection = collectionsEnumerator.Current.Value;
|
||||
indexInCurrentCollection = 0;
|
||||
|
||||
if (currentCollection == null)
|
||||
{
|
||||
throw new InvalidOperationException("Merged sub collection is null.");
|
||||
}
|
||||
|
||||
if (indexInCurrentCollection < currentCollection.Count)
|
||||
{
|
||||
currentItem = currentCollection[indexInCurrentCollection];
|
||||
indexInCurrentCollection++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We're beyond all collections, stop
|
||||
currentItem = default(TItem);
|
||||
exceeded = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public TItem Current => currentItem;
|
||||
|
||||
Object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 520c9222b31ec4f5aa5951b64ab04a93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,252 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
// The advantage of this class is not to provide list accessors
|
||||
// for merged lists (which would be confusing), but rather that unlike
|
||||
// merged collection, it can provide a zero-allocation enumerator.
|
||||
|
||||
// OPTIM note: Dictionary<,>.Values allocated memory the first time, so avoid it if possible
|
||||
public class MergedList<T> : IMergedCollection<T>
|
||||
{
|
||||
public MergedList()
|
||||
{
|
||||
lists = new Dictionary<Type, IList<T>>();
|
||||
}
|
||||
|
||||
protected readonly Dictionary<Type, IList<T>> lists;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (var listByType in lists)
|
||||
{
|
||||
count += listByType.Value.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public virtual void Include<TI>(IList<TI> list) where TI : T
|
||||
{
|
||||
lists.Add(typeof(TI), new VariantList<T, TI>(list));
|
||||
}
|
||||
|
||||
public bool Includes<TI>() where TI : T
|
||||
{
|
||||
return Includes(typeof(TI));
|
||||
}
|
||||
|
||||
public bool Includes(Type elementType)
|
||||
{
|
||||
return GetListForType(elementType, false) != null;
|
||||
}
|
||||
|
||||
public IList<TI> ForType<TI>() where TI : T
|
||||
{
|
||||
return ((VariantList<T, TI>)GetListForType(typeof(TI))).implementation;
|
||||
}
|
||||
|
||||
protected IList<T> GetListForItem(T item)
|
||||
{
|
||||
Ensure.That(nameof(item)).IsNotNull(item);
|
||||
|
||||
return GetListForType(item.GetType());
|
||||
}
|
||||
|
||||
protected IList<T> GetListForType(Type type, bool throwOnFail = true)
|
||||
{
|
||||
if (lists.ContainsKey(type))
|
||||
{
|
||||
return lists[type];
|
||||
}
|
||||
|
||||
foreach (var listByType in lists)
|
||||
{
|
||||
if (listByType.Key.IsAssignableFrom(type))
|
||||
{
|
||||
return listByType.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnFail)
|
||||
{
|
||||
throw new InvalidOperationException($"No sub-collection available for type '{type}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return GetListForItem(item).Contains(item);
|
||||
}
|
||||
|
||||
public virtual void Add(T item)
|
||||
{
|
||||
GetListForItem(item).Add(item);
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
foreach (var listByType in lists)
|
||||
{
|
||||
listByType.Value.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Remove(T item)
|
||||
{
|
||||
return GetListForItem(item).Remove(item);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
foreach (var listByType in lists)
|
||||
{
|
||||
var list = listByType.Value;
|
||||
list.CopyTo(array, arrayIndex + i);
|
||||
i += list.Count;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<T>
|
||||
{
|
||||
private Dictionary<Type, IList<T>>.Enumerator listsEnumerator;
|
||||
private T currentItem;
|
||||
private IList<T> currentList;
|
||||
private int indexInCurrentList;
|
||||
private bool exceeded;
|
||||
|
||||
public Enumerator(MergedList<T> merged) : this()
|
||||
{
|
||||
listsEnumerator = merged.lists.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
// We just started, so we're not in a list yet
|
||||
if (currentList == null)
|
||||
{
|
||||
// Try to find the first list
|
||||
if (listsEnumerator.MoveNext())
|
||||
{
|
||||
// There is at least a list, start with this one
|
||||
currentList = listsEnumerator.Current.Value;
|
||||
|
||||
if (currentList == null)
|
||||
{
|
||||
throw new InvalidOperationException("Merged sub list is null.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is no list at all, stop
|
||||
currentItem = default(T);
|
||||
exceeded = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're within the current list
|
||||
if (indexInCurrentList < currentList.Count)
|
||||
{
|
||||
// We are, return this element and move to the next
|
||||
currentItem = currentList[indexInCurrentList];
|
||||
indexInCurrentList++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're beyond the current list, but there may be more,
|
||||
// and because there may be many empty lists, we need to check
|
||||
// them all until we find an element, not just the next one
|
||||
while (listsEnumerator.MoveNext())
|
||||
{
|
||||
currentList = listsEnumerator.Current.Value;
|
||||
indexInCurrentList = 0;
|
||||
|
||||
if (currentList == null)
|
||||
{
|
||||
throw new InvalidOperationException("Merged sub list is null.");
|
||||
}
|
||||
|
||||
if (indexInCurrentList < currentList.Count)
|
||||
{
|
||||
currentItem = currentList[indexInCurrentList];
|
||||
indexInCurrentList++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We're beyond all lists, stop
|
||||
currentItem = default(T);
|
||||
exceeded = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public T Current => currentItem;
|
||||
|
||||
Object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 725c1ccd191c1427fb11a5eab7d26b3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public struct NoAllocEnumerator<T> : IEnumerator<T>
|
||||
{
|
||||
private readonly IList<T> list;
|
||||
private int index;
|
||||
private T current;
|
||||
private bool exceeded;
|
||||
|
||||
public NoAllocEnumerator(IList<T> list) : this()
|
||||
{
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (index < list.Count)
|
||||
{
|
||||
current = list[index];
|
||||
index++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = list.Count + 1;
|
||||
current = default(T);
|
||||
exceeded = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public T Current => current;
|
||||
|
||||
Object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 174d73813488e4011b9b46d8a59ae9d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public abstract class NonNullableCollection<T> : Collection<T>
|
||||
{
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> collection)
|
||||
{
|
||||
foreach (var item in collection)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23aff2603b7a04000a57f820b6f71951
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class NonNullableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
|
||||
{
|
||||
public NonNullableDictionary()
|
||||
{
|
||||
dictionary = new Dictionary<TKey, TValue>();
|
||||
}
|
||||
|
||||
public NonNullableDictionary(int capacity)
|
||||
{
|
||||
dictionary = new Dictionary<TKey, TValue>(capacity);
|
||||
}
|
||||
|
||||
public NonNullableDictionary(IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
dictionary = new Dictionary<TKey, TValue>(comparer);
|
||||
}
|
||||
|
||||
public NonNullableDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
this.dictionary = new Dictionary<TKey, TValue>(dictionary);
|
||||
}
|
||||
|
||||
public NonNullableDictionary(int capacity, IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
|
||||
}
|
||||
|
||||
public NonNullableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
this.dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
|
||||
}
|
||||
|
||||
private readonly Dictionary<TKey, TValue> dictionary;
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return dictionary[key];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
dictionary[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
object IDictionary.this[object key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary)dictionary)[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
((IDictionary)dictionary)[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => dictionary.Count;
|
||||
|
||||
public bool IsSynchronized => ((ICollection)dictionary).IsSynchronized;
|
||||
|
||||
public object SyncRoot => ((ICollection)dictionary).SyncRoot;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public ICollection<TKey> Keys => dictionary.Keys;
|
||||
|
||||
ICollection IDictionary.Values => ((IDictionary)dictionary).Values;
|
||||
|
||||
ICollection IDictionary.Keys => ((IDictionary)dictionary).Keys;
|
||||
|
||||
public ICollection<TValue> Values => dictionary.Values;
|
||||
|
||||
public bool IsFixedSize => ((IDictionary)dictionary).IsFixedSize;
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection)dictionary).CopyTo(array, index);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Add(item);
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
dictionary.Add(key, value);
|
||||
}
|
||||
|
||||
public void Add(object key, object value)
|
||||
{
|
||||
((IDictionary)dictionary).Add(key, value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
dictionary.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(object key)
|
||||
{
|
||||
return ((IDictionary)dictionary).Contains(key);
|
||||
}
|
||||
|
||||
IDictionaryEnumerator IDictionary.GetEnumerator()
|
||||
{
|
||||
return ((IDictionary)dictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
public void Remove(object key)
|
||||
{
|
||||
((IDictionary)dictionary).Remove(key);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Contains(item);
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
((ICollection<KeyValuePair<TKey, TValue>>)dictionary).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Remove(item);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return dictionary.Remove(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
return dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return dictionary.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 97fbaa55dfb0e45868ec8c2fc00466a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class NonNullableHashSet<T> : ISet<T>
|
||||
{
|
||||
public NonNullableHashSet()
|
||||
{
|
||||
set = new HashSet<T>();
|
||||
}
|
||||
|
||||
public NonNullableHashSet(IEqualityComparer<T> comparer)
|
||||
{
|
||||
set = new HashSet<T>(comparer);
|
||||
}
|
||||
|
||||
public NonNullableHashSet(IEnumerable<T> collection)
|
||||
{
|
||||
set = new HashSet<T>(collection);
|
||||
}
|
||||
|
||||
public NonNullableHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer)
|
||||
{
|
||||
set = new HashSet<T>(collection, comparer);
|
||||
}
|
||||
|
||||
private readonly HashSet<T> set;
|
||||
|
||||
public int Count => set.Count;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public bool Add(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return set.Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return set.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
set.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public void ExceptWith(IEnumerable<T> other)
|
||||
{
|
||||
set.ExceptWith(other);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return set.GetEnumerator();
|
||||
}
|
||||
|
||||
public void IntersectWith(IEnumerable<T> other)
|
||||
{
|
||||
set.IntersectWith(other);
|
||||
}
|
||||
|
||||
public bool IsProperSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
return set.IsProperSubsetOf(other);
|
||||
}
|
||||
|
||||
public bool IsProperSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
return set.IsProperSupersetOf(other);
|
||||
}
|
||||
|
||||
public bool IsSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
return set.IsSubsetOf(other);
|
||||
}
|
||||
|
||||
public bool IsSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
return set.IsSupersetOf(other);
|
||||
}
|
||||
|
||||
public bool Overlaps(IEnumerable<T> other)
|
||||
{
|
||||
return set.Overlaps(other);
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return set.Remove(item);
|
||||
}
|
||||
|
||||
public bool SetEquals(IEnumerable<T> other)
|
||||
{
|
||||
return set.SetEquals(other);
|
||||
}
|
||||
|
||||
public void SymmetricExceptWith(IEnumerable<T> other)
|
||||
{
|
||||
set.SymmetricExceptWith(other);
|
||||
}
|
||||
|
||||
public void UnionWith(IEnumerable<T> other)
|
||||
{
|
||||
set.UnionWith(other);
|
||||
}
|
||||
|
||||
void ICollection<T>.Add(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
((ICollection<T>)set).Add(item);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)set).GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d87db61d4949f45af99577f40b0ea695
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class NonNullableList<T> : IList<T>, IList
|
||||
{
|
||||
public NonNullableList()
|
||||
{
|
||||
list = new List<T>();
|
||||
}
|
||||
|
||||
public NonNullableList(int capacity)
|
||||
{
|
||||
list = new List<T>(capacity);
|
||||
}
|
||||
|
||||
public NonNullableList(IEnumerable<T> collection)
|
||||
{
|
||||
list = new List<T>(collection);
|
||||
}
|
||||
|
||||
private readonly List<T> list;
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return list[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
list[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
object IList.this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IList)list)[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
((IList)list)[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => list.Count;
|
||||
|
||||
public bool IsSynchronized => ((ICollection)list).IsSynchronized;
|
||||
|
||||
public object SyncRoot => ((ICollection)list).SyncRoot;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public bool IsFixedSize => ((IList)list).IsFixedSize;
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection)list).CopyTo(array, index);
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
public int Add(object value)
|
||||
{
|
||||
return ((IList)list).Add(value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(object value)
|
||||
{
|
||||
return ((IList)list).Contains(value);
|
||||
}
|
||||
|
||||
public int IndexOf(object value)
|
||||
{
|
||||
return ((IList)list).IndexOf(value);
|
||||
}
|
||||
|
||||
public void Insert(int index, object value)
|
||||
{
|
||||
((IList)list).Insert(index, value);
|
||||
}
|
||||
|
||||
public void Remove(object value)
|
||||
{
|
||||
((IList)list).Remove(value);
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return list.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return list.GetEnumerator();
|
||||
}
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return list.IndexOf(item);
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
list.Insert(index, item);
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return list.Remove(item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
list.RemoveAt(index);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return list.GetEnumerator();
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> collection)
|
||||
{
|
||||
foreach (var item in collection)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 43726dbe3dc9b43e7b7757fe847b033a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class VariantCollection<TBase, TImplementation> : ICollection<TBase> where TImplementation : TBase
|
||||
{
|
||||
public VariantCollection(ICollection<TImplementation> implementation)
|
||||
{
|
||||
if (implementation == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(implementation));
|
||||
}
|
||||
|
||||
this.implementation = implementation;
|
||||
}
|
||||
|
||||
public ICollection<TImplementation> implementation { get; private set; }
|
||||
|
||||
public int Count => implementation.Count;
|
||||
|
||||
public bool IsReadOnly => implementation.IsReadOnly;
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<TBase> GetEnumerator()
|
||||
{
|
||||
foreach (var i in implementation)
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
implementation.Add((TImplementation)item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
implementation.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return implementation.Contains((TImplementation)item);
|
||||
}
|
||||
|
||||
public bool Remove(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return implementation.Remove((TImplementation)item);
|
||||
}
|
||||
|
||||
public void CopyTo(TBase[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var implementationArray = new TImplementation[Count];
|
||||
implementation.CopyTo(implementationArray, 0);
|
||||
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
array[i + arrayIndex] = implementationArray[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 151f0a13a53cb44ae83db5361508f233
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,37 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class VariantKeyedCollection<TBase, TImplementation, TKey> :
|
||||
VariantCollection<TBase, TImplementation>,
|
||||
IKeyedCollection<TKey, TBase>
|
||||
where TImplementation : TBase
|
||||
{
|
||||
public VariantKeyedCollection(IKeyedCollection<TKey, TImplementation> implementation) : base(implementation)
|
||||
{
|
||||
this.implementation = implementation;
|
||||
}
|
||||
|
||||
public TBase this[TKey key] => implementation[key];
|
||||
|
||||
public new IKeyedCollection<TKey, TImplementation> implementation { get; private set; }
|
||||
|
||||
public bool TryGetValue(TKey key, out TBase value)
|
||||
{
|
||||
TImplementation implementationValue;
|
||||
var result = implementation.TryGetValue(key, out implementationValue);
|
||||
value = implementationValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Contains(TKey key)
|
||||
{
|
||||
return implementation.Contains(key);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return implementation.Remove(key);
|
||||
}
|
||||
|
||||
TBase IKeyedCollection<TKey, TBase>.this[int index] => implementation[index];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9e147a4fe5cb14a9cb1eae8b8c321dc0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class VariantList<TBase, TImplementation> : IList<TBase> where TImplementation : TBase
|
||||
{
|
||||
public VariantList(IList<TImplementation> implementation)
|
||||
{
|
||||
if (implementation == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(implementation));
|
||||
}
|
||||
|
||||
this.implementation = implementation;
|
||||
}
|
||||
|
||||
public TBase this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return implementation[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!(value is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
implementation[index] = (TImplementation)value;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<TImplementation> implementation { get; private set; }
|
||||
|
||||
public int Count => implementation.Count;
|
||||
|
||||
public bool IsReadOnly => implementation.IsReadOnly;
|
||||
|
||||
public void Add(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
implementation.Add((TImplementation)item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
implementation.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return implementation.Contains((TImplementation)item);
|
||||
}
|
||||
|
||||
public bool Remove(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return implementation.Remove((TImplementation)item);
|
||||
}
|
||||
|
||||
public void CopyTo(TBase[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var implementationArray = new TImplementation[Count];
|
||||
implementation.CopyTo(implementationArray, 0);
|
||||
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
array[i + arrayIndex] = implementationArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
public int IndexOf(TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return implementation.IndexOf((TImplementation)item);
|
||||
}
|
||||
|
||||
public void Insert(int index, TBase item)
|
||||
{
|
||||
if (!(item is TImplementation))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
implementation.Insert(index, (TImplementation)item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
implementation.RemoveAt(index);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<TBase> IEnumerable<TBase>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public NoAllocEnumerator<TBase> GetEnumerator()
|
||||
{
|
||||
return new NoAllocEnumerator<TBase>(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b5ebd1fa4eb6941199648d59aaab0b3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class WatchedList<T> : Collection<T>, INotifyCollectionChanged<T>
|
||||
{
|
||||
public event Action<T> ItemAdded;
|
||||
|
||||
public event Action<T> ItemRemoved;
|
||||
|
||||
public event Action CollectionChanged;
|
||||
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
ItemAdded?.Invoke(item);
|
||||
CollectionChanged?.Invoke();
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
if (index < Count)
|
||||
{
|
||||
var item = this[index];
|
||||
base.RemoveItem(index);
|
||||
ItemRemoved?.Invoke(item);
|
||||
CollectionChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
while (Count > 0)
|
||||
{
|
||||
RemoveItem(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4444c1ac4c2c24720ad9edd95152c1b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cd7f10104a033462da12776730ed1565
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class ConnectionCollection<TConnection, TSource, TDestination> : ConnectionCollectionBase<TConnection, TSource, TDestination, List<TConnection>>
|
||||
where TConnection : IConnection<TSource, TDestination>
|
||||
{
|
||||
public ConnectionCollection() : base(new List<TConnection>()) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 64f1445c587dc4e6580be74135961a4c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,234 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class ConnectionCollectionBase<TConnection, TSource, TDestination, TCollection> : IConnectionCollection<TConnection, TSource, TDestination>
|
||||
where TConnection : IConnection<TSource, TDestination>
|
||||
where TCollection : ICollection<TConnection>
|
||||
{
|
||||
public ConnectionCollectionBase(TCollection collection)
|
||||
{
|
||||
this.collection = collection;
|
||||
bySource = new Dictionary<TSource, List<TConnection>>();
|
||||
byDestination = new Dictionary<TDestination, List<TConnection>>();
|
||||
}
|
||||
|
||||
// Using lists instead of HashSet to allow access by index
|
||||
// instead of creating an enumeration and allocating memory
|
||||
// specifically for the "With*NoAlloc" methods, used
|
||||
// very often in flow graphs.
|
||||
private readonly Dictionary<TDestination, List<TConnection>> byDestination;
|
||||
private readonly Dictionary<TSource, List<TConnection>> bySource;
|
||||
protected readonly TCollection collection;
|
||||
|
||||
public IEnumerable<TConnection> this[TSource source] => WithSource(source);
|
||||
|
||||
public IEnumerable<TConnection> this[TDestination destination] => WithDestination(destination);
|
||||
|
||||
public int Count => collection.Count;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public IEnumerator<TConnection> GetEnumerator()
|
||||
{
|
||||
return collection.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerable<TConnection> WithSource(TSource source)
|
||||
{
|
||||
return WithSourceNoAlloc(source);
|
||||
}
|
||||
|
||||
public List<TConnection> WithSourceNoAlloc(TSource source)
|
||||
{
|
||||
Ensure.That(nameof(source)).IsNotNull(source);
|
||||
|
||||
if (bySource.TryGetValue(source, out var withSource))
|
||||
{
|
||||
return withSource;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Empty<TConnection>.list;
|
||||
}
|
||||
}
|
||||
|
||||
public TConnection SingleOrDefaultWithSource(TSource source)
|
||||
{
|
||||
Ensure.That(nameof(source)).IsNotNull(source);
|
||||
|
||||
if (bySource.TryGetValue(source, out var withSource))
|
||||
{
|
||||
if (withSource.Count == 1)
|
||||
{
|
||||
return withSource[0];
|
||||
}
|
||||
else if (withSource.Count == 0)
|
||||
{
|
||||
return default(TConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(TConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TConnection> WithDestination(TDestination destination)
|
||||
{
|
||||
return WithDestinationNoAlloc(destination);
|
||||
}
|
||||
|
||||
public List<TConnection> WithDestinationNoAlloc(TDestination destination)
|
||||
{
|
||||
Ensure.That(nameof(destination)).IsNotNull(destination);
|
||||
|
||||
if (byDestination.TryGetValue(destination, out var withDestination))
|
||||
{
|
||||
return withDestination;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Empty<TConnection>.list;
|
||||
}
|
||||
}
|
||||
|
||||
public TConnection SingleOrDefaultWithDestination(TDestination destination)
|
||||
{
|
||||
Ensure.That(nameof(destination)).IsNotNull(destination);
|
||||
|
||||
if (byDestination.TryGetValue(destination, out var withDestination))
|
||||
{
|
||||
if (withDestination.Count == 1)
|
||||
{
|
||||
return withDestination[0];
|
||||
}
|
||||
else if (withDestination.Count == 0)
|
||||
{
|
||||
return default(TConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(TConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(TConnection item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
if (item.source == null)
|
||||
{
|
||||
throw new ArgumentNullException("item.source");
|
||||
}
|
||||
|
||||
if (item.destination == null)
|
||||
{
|
||||
throw new ArgumentNullException("item.destination");
|
||||
}
|
||||
|
||||
BeforeAdd(item);
|
||||
collection.Add(item);
|
||||
AddToDictionaries(item);
|
||||
AfterAdd(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
collection.Clear();
|
||||
bySource.Clear();
|
||||
byDestination.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(TConnection item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return collection.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(TConnection[] array, int arrayIndex)
|
||||
{
|
||||
collection.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(TConnection item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
if (item.source == null)
|
||||
{
|
||||
throw new ArgumentNullException("item.source");
|
||||
}
|
||||
|
||||
if (item.destination == null)
|
||||
{
|
||||
throw new ArgumentNullException("item.destination");
|
||||
}
|
||||
|
||||
if (!collection.Contains(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BeforeRemove(item);
|
||||
collection.Remove(item);
|
||||
RemoveFromDictionaries(item);
|
||||
AfterRemove(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void BeforeAdd(TConnection item) { }
|
||||
protected virtual void AfterAdd(TConnection item) { }
|
||||
protected virtual void BeforeRemove(TConnection item) { }
|
||||
protected virtual void AfterRemove(TConnection item) { }
|
||||
|
||||
private void AddToDictionaries(TConnection item)
|
||||
{
|
||||
if (!bySource.ContainsKey(item.source))
|
||||
{
|
||||
bySource.Add(item.source, new List<TConnection>());
|
||||
}
|
||||
|
||||
bySource[item.source].Add(item);
|
||||
|
||||
if (!byDestination.ContainsKey(item.destination))
|
||||
{
|
||||
byDestination.Add(item.destination, new List<TConnection>());
|
||||
}
|
||||
|
||||
byDestination[item.destination].Add(item);
|
||||
}
|
||||
|
||||
private void RemoveFromDictionaries(TConnection item)
|
||||
{
|
||||
bySource[item.source].Remove(item);
|
||||
byDestination[item.destination].Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d7cff333251d4761a76a91d14e3fe51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class GraphConnectionCollection<TConnection, TSource, TDestination> :
|
||||
ConnectionCollectionBase<TConnection, TSource, TDestination, GraphElementCollection<TConnection>>,
|
||||
IGraphElementCollection<TConnection>
|
||||
where TConnection : IConnection<TSource, TDestination>, IGraphElement
|
||||
{
|
||||
public GraphConnectionCollection(IGraph graph) : base(new GraphElementCollection<TConnection>(graph))
|
||||
{
|
||||
// The issue of reusing GEC as the internal collection a CCB is that
|
||||
// the add / remove events will NOT be in sync with the CCB's dictionaries
|
||||
// if we just watched the collection's insertion.
|
||||
// Therefore, we must provide a way to let the CCB proxy its own events
|
||||
// and to disable our the GEC's events by default.
|
||||
collection.ProxyCollectionChange = true;
|
||||
}
|
||||
|
||||
TConnection IKeyedCollection<Guid, TConnection>.this[Guid key] => collection[key];
|
||||
|
||||
TConnection IKeyedCollection<Guid, TConnection>.this[int index] => collection[index];
|
||||
|
||||
public bool TryGetValue(Guid key, out TConnection value)
|
||||
{
|
||||
return collection.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public bool Contains(Guid key)
|
||||
{
|
||||
return collection.Contains(key);
|
||||
}
|
||||
|
||||
public bool Remove(Guid key)
|
||||
{
|
||||
if (Contains(key))
|
||||
{
|
||||
// Call base remove to remove from dictionaries as well
|
||||
return Remove(collection[key]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public event Action<TConnection> ItemAdded
|
||||
{
|
||||
add { collection.ItemAdded += value; }
|
||||
remove { collection.ItemAdded -= value; }
|
||||
}
|
||||
|
||||
public event Action<TConnection> ItemRemoved
|
||||
{
|
||||
add { collection.ItemRemoved += value; }
|
||||
remove { collection.ItemRemoved -= value; }
|
||||
}
|
||||
|
||||
public event Action CollectionChanged
|
||||
{
|
||||
add { collection.CollectionChanged += value; }
|
||||
remove { collection.CollectionChanged -= value; }
|
||||
}
|
||||
|
||||
protected override void BeforeAdd(TConnection item)
|
||||
{
|
||||
collection.BeforeAdd(item);
|
||||
}
|
||||
|
||||
protected override void AfterAdd(TConnection item)
|
||||
{
|
||||
collection.AfterAdd(item);
|
||||
}
|
||||
|
||||
protected override void BeforeRemove(TConnection item)
|
||||
{
|
||||
collection.BeforeRemove(item);
|
||||
}
|
||||
|
||||
protected override void AfterRemove(TConnection item)
|
||||
{
|
||||
collection.AfterRemove(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 650036ff826f64479bd924a78dab1057
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IConnection<out TSource, out TDestination>
|
||||
{
|
||||
TSource source { get; }
|
||||
TDestination destination { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9ef61ff81bd641b98e376b72a35e6d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IConnectionCollection<TConnection, TSource, TDestination> : ICollection<TConnection>
|
||||
where TConnection : IConnection<TSource, TDestination>
|
||||
{
|
||||
IEnumerable<TConnection> this[TSource source] { get; }
|
||||
IEnumerable<TConnection> this[TDestination destination] { get; }
|
||||
IEnumerable<TConnection> WithSource(TSource source);
|
||||
IEnumerable<TConnection> WithDestination(TDestination destination);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8b1b785745a7f45e7aeb8928f8301c7e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class InvalidConnectionException : Exception
|
||||
{
|
||||
public InvalidConnectionException() : base("") { }
|
||||
public InvalidConnectionException(string message) : base(message) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8dc2791b3a1a24557addbdc57a45b5bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fc4d9a317f2ee464887412e4b1ff834a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IDecoratorAttribute
|
||||
{
|
||||
Type type { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f5ba353976e54c5ca51dd1873135abe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3750d38b6e2f410894efd787f3a2c4e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d9533b5df35dc4eb1ae391f2b0f7fede
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,213 @@
|
|||
// Copyright Christophe Bertrand.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Unity.VisualScripting.AssemblyQualifiedNameParser
|
||||
{
|
||||
public class ParsedAssemblyQualifiedName
|
||||
{
|
||||
public string AssemblyDescriptionString { get; }
|
||||
|
||||
public string TypeName { get; private set; }
|
||||
|
||||
public string ShortAssemblyName { get; }
|
||||
|
||||
public string Version { get; }
|
||||
|
||||
public string Culture { get; }
|
||||
|
||||
public string PublicKeyToken { get; }
|
||||
|
||||
public List<ParsedAssemblyQualifiedName> GenericParameters { get; } = new List<ParsedAssemblyQualifiedName>();
|
||||
|
||||
public int GenericParameterCount { get; }
|
||||
|
||||
public ParsedAssemblyQualifiedName(string AssemblyQualifiedName)
|
||||
{
|
||||
var typeNameLength = AssemblyQualifiedName.Length;
|
||||
var hasAssemblyDescription = false;
|
||||
|
||||
var rootBlock = new Block();
|
||||
{
|
||||
var depth = 0;
|
||||
var currentBlock = rootBlock;
|
||||
|
||||
for (var index = 0; index < AssemblyQualifiedName.Length; ++index)
|
||||
{
|
||||
var c = AssemblyQualifiedName[index];
|
||||
|
||||
if (c == '[')
|
||||
{
|
||||
if (AssemblyQualifiedName[index + 1] == ']') // Array type // TODO (LAZLO): This won't detect multidimensional array, but FS can't handle them anyway
|
||||
{
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
typeNameLength = index;
|
||||
}
|
||||
|
||||
++depth;
|
||||
|
||||
var innerBlock = new Block
|
||||
{
|
||||
startIndex = index + 1,
|
||||
level = depth,
|
||||
parentBlock = currentBlock
|
||||
};
|
||||
|
||||
currentBlock.innerBlocks.Add(innerBlock);
|
||||
|
||||
currentBlock = innerBlock;
|
||||
}
|
||||
}
|
||||
else if (c == ']')
|
||||
{
|
||||
currentBlock.endIndex = index - 1;
|
||||
|
||||
if (AssemblyQualifiedName[currentBlock.startIndex] != '[')
|
||||
{
|
||||
currentBlock.parsedAssemblyQualifiedName = new ParsedAssemblyQualifiedName(AssemblyQualifiedName.Substring(currentBlock.startIndex, index - currentBlock.startIndex));
|
||||
|
||||
if (depth == 2)
|
||||
{
|
||||
GenericParameters.Add(currentBlock.parsedAssemblyQualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
currentBlock = currentBlock.parentBlock;
|
||||
--depth;
|
||||
}
|
||||
else if (depth == 0 && c == ',')
|
||||
{
|
||||
typeNameLength = index;
|
||||
hasAssemblyDescription = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TypeName = AssemblyQualifiedName.Substring(0, typeNameLength);
|
||||
|
||||
var tickIndex = TypeName.IndexOf('`');
|
||||
|
||||
if (tickIndex >= 0)
|
||||
{
|
||||
GenericParameterCount = int.Parse(TypeName.Substring(tickIndex + 1));
|
||||
TypeName = TypeName.Substring(0, tickIndex);
|
||||
}
|
||||
|
||||
if (hasAssemblyDescription)
|
||||
{
|
||||
AssemblyDescriptionString = AssemblyQualifiedName.Substring(typeNameLength + 2);
|
||||
|
||||
var parts = AssemblyDescriptionString.Split(',')
|
||||
.Select(x => x.Trim())
|
||||
.ToList();
|
||||
|
||||
Version = LookForPairThenRemove(parts, "Version");
|
||||
Culture = LookForPairThenRemove(parts, "Culture");
|
||||
PublicKeyToken = LookForPairThenRemove(parts, "PublicKeyToken");
|
||||
|
||||
if (parts.Count > 0)
|
||||
{
|
||||
ShortAssemblyName = parts[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Block
|
||||
{
|
||||
internal int startIndex;
|
||||
|
||||
internal int endIndex;
|
||||
|
||||
internal int level;
|
||||
|
||||
internal Block parentBlock;
|
||||
|
||||
internal readonly List<Block> innerBlocks = new List<Block>();
|
||||
|
||||
internal ParsedAssemblyQualifiedName parsedAssemblyQualifiedName;
|
||||
}
|
||||
|
||||
private static string LookForPairThenRemove(List<string> strings, string Name)
|
||||
{
|
||||
for (var istr = 0; istr < strings.Count; istr++)
|
||||
{
|
||||
var s = strings[istr];
|
||||
var i = s.IndexOf(Name);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
var i2 = s.IndexOf('=');
|
||||
|
||||
if (i2 > 0)
|
||||
{
|
||||
var ret = s.Substring(i2 + 1);
|
||||
strings.RemoveAt(istr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Replace(string oldTypeName, string newTypeName)
|
||||
{
|
||||
if (TypeName == oldTypeName)
|
||||
{
|
||||
TypeName = newTypeName;
|
||||
}
|
||||
|
||||
foreach (var genericParameter in GenericParameters)
|
||||
{
|
||||
genericParameter.Replace(oldTypeName, newTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
private string ToString(bool includeAssemblyDescription)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(TypeName);
|
||||
|
||||
if (GenericParameters.Count > 0)
|
||||
{
|
||||
sb.Append("`");
|
||||
|
||||
sb.Append(GenericParameterCount);
|
||||
|
||||
sb.Append("[[");
|
||||
|
||||
foreach (var genericParameter in GenericParameters)
|
||||
{
|
||||
sb.Append(genericParameter.ToString(true));
|
||||
}
|
||||
|
||||
sb.Append("]]");
|
||||
}
|
||||
|
||||
if (includeAssemblyDescription)
|
||||
{
|
||||
sb.Append(", ");
|
||||
|
||||
sb.Append(AssemblyDescriptionString);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d92a04ad12d04b89acd2055df01a8b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: febf30edd777246c5afbf74d55f387d7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d987e9d47d9a848d181e7806e6c9013f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50b35552dbca348bc84a9fcbd885547c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,51 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting.FullSerializer
|
||||
{
|
||||
partial class fsConverterRegistrar
|
||||
{
|
||||
public static AnimationCurve_DirectConverter Register_AnimationCurve_DirectConverter;
|
||||
}
|
||||
|
||||
public class AnimationCurve_DirectConverter : fsDirectConverter<AnimationCurve>
|
||||
{
|
||||
protected override fsResult DoSerialize(AnimationCurve model, Dictionary<string, fsData> serialized)
|
||||
{
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "keys", model.keys);
|
||||
result += SerializeMember(serialized, null, "preWrapMode", model.preWrapMode);
|
||||
result += SerializeMember(serialized, null, "postWrapMode", model.postWrapMode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref AnimationCurve model)
|
||||
{
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.keys;
|
||||
result += DeserializeMember(data, null, "keys", out t0);
|
||||
model.keys = t0;
|
||||
|
||||
var t1 = model.preWrapMode;
|
||||
result += DeserializeMember(data, null, "preWrapMode", out t1);
|
||||
model.preWrapMode = t1;
|
||||
|
||||
var t2 = model.postWrapMode;
|
||||
result += DeserializeMember(data, null, "postWrapMode", out t2);
|
||||
model.postWrapMode = t2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType)
|
||||
{
|
||||
return new AnimationCurve();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue