first commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 260e630c5c1b1af42991291f6de23ede
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ffdd4c88c153a284e9574aaf8e695e65
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,59 @@
|
||||
#if UNITY_EDITOR && UNITY_2021_1_OR_NEWER
|
||||
#define CAN_USE_CUSTOM_HELP_URL
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
#if CAN_USE_CUSTOM_HELP_URL
|
||||
using UnityEditor.PackageManager;
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
class VisualScriptingHelpURLAttribute : HelpURLAttribute
|
||||
{
|
||||
const string k_BaseURL = "https://docs.unity3d.com/Packages/com.unity.visualscripting@";
|
||||
const string k_MidURL = "/api/";
|
||||
const string k_EndURL = ".html";
|
||||
const string k_FallbackVersion = "1.9";
|
||||
|
||||
static string s_PackageVersion;
|
||||
|
||||
static string PackageVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(s_PackageVersion))
|
||||
{
|
||||
var packageInfo = PackageInfo.FindForAssetPath("Packages/com.unity.visualscripting");
|
||||
s_PackageVersion = packageInfo == null ? k_FallbackVersion : GetMinorPackageVersionString(packageInfo.version);
|
||||
}
|
||||
|
||||
return s_PackageVersion;
|
||||
}
|
||||
}
|
||||
|
||||
// internal for test
|
||||
internal static string GetMinorPackageVersionString(string versionString)
|
||||
{
|
||||
var split = versionString.Split('.');
|
||||
return split.Length < 2 ? $"{split[0]}.0" : $"{split[0]}.{split[1]}";
|
||||
}
|
||||
|
||||
public VisualScriptingHelpURLAttribute(Type type)
|
||||
: base(HelpURL(type)) {}
|
||||
|
||||
static string HelpURL(Type type)
|
||||
{
|
||||
return $"{k_BaseURL}{PackageVersion}{k_MidURL}{type.FullName}{k_EndURL}";
|
||||
}
|
||||
}
|
||||
#else //HelpURL attribute is `sealed` in previous Unity versions
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
class VisualScriptingHelpURLAttribute : Attribute
|
||||
{
|
||||
public VisualScriptingHelpURLAttribute(Type type) { }
|
||||
}
|
||||
#endif
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3bcf9b19dcb40cdad778458b50003a8
|
||||
timeCreated: 1698171003
|
@@ -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,24 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
internal sealed class GradientCloner : Cloner<Gradient>
|
||||
{
|
||||
public override bool Handles(Type type)
|
||||
{
|
||||
return type == typeof(Gradient);
|
||||
}
|
||||
|
||||
public override Gradient ConstructClone(Type type, Gradient original)
|
||||
{
|
||||
return new Gradient();
|
||||
}
|
||||
|
||||
public override void FillClone(Type type, ref Gradient clone, Gradient original, CloningContext context)
|
||||
{
|
||||
clone.mode = original.mode;
|
||||
clone.SetKeys(original.colorKeys, original.alphaKeys);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 057253f1a89340aeb7283ea133acffeb
|
||||
timeCreated: 1678386566
|
@@ -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,143 @@
|
||||
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);
|
||||
cloners.Add(gradientCloner);
|
||||
}
|
||||
|
||||
// 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();
|
||||
internal static GradientCloner gradientCloner { get; } = new GradientCloner();
|
||||
|
||||
|
||||
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 new 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();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user