Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Unity.VisualScripting
{
public static class CSharpNameUtility
{
private static readonly Dictionary<Type, string> primitives = new Dictionary<Type, string>
{
{ typeof(byte), "byte" },
{ typeof(sbyte), "sbyte" },
{ typeof(short), "short" },
{ typeof(ushort), "ushort" },
{ typeof(int), "int" },
{ typeof(uint), "uint" },
{ typeof(long), "long" },
{ typeof(ulong), "ulong" },
{ typeof(float), "float" },
{ typeof(double), "double" },
{ typeof(decimal), "decimal" },
{ typeof(string), "string" },
{ typeof(char), "char" },
{ typeof(bool), "bool" },
{ typeof(void), "void" },
{ typeof(object), "object" },
};
public static readonly Dictionary<string, string> operators = new Dictionary<string, string>
{
{ "op_Addition", "+" },
{ "op_Subtraction", "-" },
{ "op_Multiply", "*" },
{ "op_Division", "/" },
{ "op_Modulus", "%" },
{ "op_ExclusiveOr", "^" },
{ "op_BitwiseAnd", "&" },
{ "op_BitwiseOr", "|" },
{ "op_LogicalAnd", "&&" },
{ "op_LogicalOr", "||" },
{ "op_Assign", "=" },
{ "op_LeftShift", "<<" },
{ "op_RightShift", ">>" },
{ "op_Equality", "==" },
{ "op_GreaterThan", ">" },
{ "op_LessThan", "<" },
{ "op_Inequality", "!=" },
{ "op_GreaterThanOrEqual", ">=" },
{ "op_LessThanOrEqual", "<=" },
{ "op_MultiplicationAssignment", "*=" },
{ "op_SubtractionAssignment", "-=" },
{ "op_ExclusiveOrAssignment", "^=" },
{ "op_LeftShiftAssignment", "<<=" },
{ "op_ModulusAssignment", "%=" },
{ "op_AdditionAssignment", "+=" },
{ "op_BitwiseAndAssignment", "&=" },
{ "op_BitwiseOrAssignment", "|=" },
{ "op_Comma", "," },
{ "op_DivisionAssignment", "/=" },
{ "op_Decrement", "--" },
{ "op_Increment", "++" },
{ "op_UnaryNegation", "-" },
{ "op_UnaryPlus", "+" },
{ "op_OnesComplement", "~" },
};
private static readonly HashSet<char> illegalTypeFileNameCharacters = new HashSet<char>()
{
'<',
'>',
'?',
' ',
',',
':',
};
public static string CSharpName(this MemberInfo member, ActionDirection direction)
{
if (member is MethodInfo && ((MethodInfo)member).IsOperator())
{
return operators[member.Name] + " operator";
}
if (member is ConstructorInfo)
{
return "new " + member.DeclaringType.CSharpName();
}
if ((member is FieldInfo || member is PropertyInfo) && direction != ActionDirection.Any)
{
return $"{member.Name} ({direction.ToString().ToLower()})";
}
return member.Name;
}
public static string CSharpName(this Type type, bool includeGenericParameters = true)
{
return type.CSharpName(TypeQualifier.Name, includeGenericParameters);
}
public static string CSharpFullName(this Type type, bool includeGenericParameters = true)
{
return type.CSharpName(TypeQualifier.Namespace, includeGenericParameters);
}
public static string CSharpUniqueName(this Type type, bool includeGenericParameters = true)
{
return type.CSharpName(TypeQualifier.GlobalNamespace, includeGenericParameters);
}
public static string CSharpFileName(this Type type, bool includeNamespace, bool includeGenericParameters = false)
{
var fileName = type.CSharpName(includeNamespace ? TypeQualifier.Namespace : TypeQualifier.Name, includeGenericParameters);
if (!includeGenericParameters && type.IsGenericType && fileName.Contains('<'))
{
fileName = fileName.Substring(0, fileName.IndexOf('<'));
}
fileName = fileName.ReplaceMultiple(illegalTypeFileNameCharacters, '_')
.Trim('_')
.RemoveConsecutiveCharacters('_');
return fileName;
}
private static string CSharpName(this Type type, TypeQualifier qualifier, bool includeGenericParameters = true)
{
if (primitives.ContainsKey(type))
{
return primitives[type];
}
else if (type.IsGenericParameter)
{
return includeGenericParameters ? type.Name : "";
}
else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var nonNullable = Nullable.GetUnderlyingType(type);
var underlyingName = nonNullable.CSharpName(qualifier, includeGenericParameters);
return underlyingName + "?";
}
else
{
var name = type.Name;
if (type.IsGenericType && name.Contains('`'))
{
name = name.Substring(0, name.IndexOf('`'));
}
var genericArguments = (IEnumerable<Type>)type.GetGenericArguments();
if (type.IsNested)
{
name = type.DeclaringType.CSharpName(qualifier, includeGenericParameters) + "." + name;
if (type.DeclaringType.IsGenericType)
{
genericArguments.Skip(type.DeclaringType.GetGenericArguments().Length);
}
}
if (!type.IsNested)
{
if ((qualifier == TypeQualifier.Namespace || qualifier == TypeQualifier.GlobalNamespace) && type.Namespace != null)
{
name = type.Namespace + "." + name;
}
if (qualifier == TypeQualifier.GlobalNamespace)
{
name = "global::" + name;
}
}
if (genericArguments.Any())
{
name += "<";
name += string.Join(includeGenericParameters ? ", " : ",", genericArguments.Select(t => t.CSharpName(qualifier, includeGenericParameters)).ToArray());
name += ">";
}
return name;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09c9e2e5152e0495f86ddb8484d7e1bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,250 @@
using System;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public static class ComponentHolderProtocol
{
public static bool IsComponentHolderType(Type type)
{
Ensure.That(nameof(type)).IsNotNull(type);
return typeof(GameObject).IsAssignableFrom(type) || typeof(Component).IsAssignableFrom(type);
}
public static bool IsComponentHolder(this UnityObject uo)
{
return uo is GameObject || uo is Component;
}
public static GameObject GameObject(this UnityObject uo)
{
if (uo is GameObject)
{
return (GameObject)uo;
}
else if (uo is Component)
{
return ((Component)uo).gameObject;
}
else
{
return null;
}
}
public static T AddComponent<T>(this UnityObject uo) where T : Component
{
if (uo is GameObject)
{
return ((GameObject)uo).AddComponent<T>();
}
else if (uo is Component)
{
return ((Component)uo).gameObject.AddComponent<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T GetOrAddComponent<T>(this UnityObject uo) where T : Component
{
return uo.GetComponent<T>() ?? uo.AddComponent<T>();
}
public static T GetComponent<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponent<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponent<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T GetComponentInChildren<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentInChildren<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponentInChildren<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T GetComponentInParent<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentInParent<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponentInParent<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T[] GetComponents<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponents<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponents<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T[] GetComponentsInChildren<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentsInChildren<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponentsInChildren<T>();
}
else
{
throw new NotSupportedException();
}
}
public static T[] GetComponentsInParent<T>(this UnityObject uo)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentsInParent<T>();
}
else if (uo is Component)
{
return ((Component)uo).GetComponentsInParent<T>();
}
else
{
throw new NotSupportedException();
}
}
public static Component GetComponent(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponent(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponent(type);
}
else
{
throw new NotSupportedException();
}
}
public static Component GetComponentInChildren(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentInChildren(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponentInChildren(type);
}
else
{
throw new NotSupportedException();
}
}
public static Component GetComponentInParent(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentInParent(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponentInParent(type);
}
else
{
throw new NotSupportedException();
}
}
public static Component[] GetComponents(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponents(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponents(type);
}
else
{
throw new NotSupportedException();
}
}
public static Component[] GetComponentsInChildren(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentsInChildren(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponentsInChildren(type);
}
else
{
throw new NotSupportedException();
}
}
public static Component[] GetComponentsInParent(this UnityObject uo, Type type)
{
if (uo is GameObject)
{
return ((GameObject)uo).GetComponentsInParent(type);
}
else if (uo is Component)
{
return ((Component)uo).GetComponentsInParent(type);
}
else
{
throw new NotSupportedException();
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e5031b55827d74367b8d19a739ae45e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using UnityEngine;
namespace Unity.VisualScripting
{
[Singleton(Name = "Coroutine Runner", Automatic = true, Persistent = true)]
[AddComponentMenu("")]
[DisableAnnotation]
[IncludeInSettings(false)]
public sealed class CoroutineRunner : MonoBehaviour, ISingleton
{
private void Awake()
{
Singleton<CoroutineRunner>.Awake(this);
}
private void OnDestroy()
{
StopAllCoroutines();
Singleton<CoroutineRunner>.OnDestroy(this);
}
public static CoroutineRunner instance => Singleton<CoroutineRunner>.instance;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28cb3597f76b74b39b40b102825752e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
// For some reason, Enumerable.Empty<T>() seems to allocate 240b in Unity,
// even though Mono source seems to use a shared 0-length array instance.
// Maybe it's an old version's bug?
public static class Empty<T>
{
public static readonly T[] array = new T[0];
public static readonly List<T> list = new List<T>(0);
public static readonly HashSet<T> hashSet = new HashSet<T>();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cefc61f3b485d4f83b7932574b4b3130
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Unity.VisualScripting
{
public static class EnumUtility
{
public static bool HasFlag(this Enum value, Enum flag)
{
var lValue = Convert.ToInt64(value);
var lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) == lFlag;
}
public static Dictionary<string, Enum> ValuesByNames(Type enumType, bool obsolete = false)
{
Ensure.That(nameof(enumType)).IsNotNull(enumType);
IEnumerable<FieldInfo> fields = enumType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
if (!obsolete)
{
fields = fields.Where(f => !f.IsDefined(typeof(ObsoleteAttribute), false));
}
return fields.ToDictionary(f => f.Name, f => (Enum)f.GetValue(null));
}
public static Dictionary<string, T> ValuesByNames<T>(bool obsolete = false)
{
IEnumerable<FieldInfo> fields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
if (!obsolete)
{
fields = fields.Where(f => !f.IsDefined(typeof(ObsoleteAttribute), false));
}
return fields.ToDictionary(f => f.Name, f => (T)f.GetValue(null));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3314c51d5eca847faa3dca214bbb52cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,20 @@
using System;
using System.Reflection;
namespace Unity.VisualScripting
{
public static class ExceptionUtility
{
public static Exception Relevant(this Exception ex)
{
if (ex is TargetInvocationException)
{
return ex.InnerException;
}
else
{
return ex;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f804b6c44a294916b0052bae34a42b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,83 @@
namespace Unity.VisualScripting
{
public static class HashUtility
{
public static int GetHashCode<T>(T a)
{
return a?.GetHashCode() ?? 0;
}
public static int GetHashCode<T1, T2>(T1 a, T2 b)
{
unchecked
{
var hash = 17;
hash = hash * 23 + (a?.GetHashCode() ?? 0);
hash = hash * 23 + (b?.GetHashCode() ?? 0);
return hash;
}
}
public static int GetHashCode<T1, T2, T3>(T1 a, T2 b, T3 c)
{
unchecked
{
var hash = 17;
hash = hash * 23 + (a?.GetHashCode() ?? 0);
hash = hash * 23 + (b?.GetHashCode() ?? 0);
hash = hash * 23 + (c?.GetHashCode() ?? 0);
return hash;
}
}
public static int GetHashCode<T1, T2, T3, T4>(T1 a, T2 b, T3 c, T4 d)
{
unchecked
{
var hash = 17;
hash = hash * 23 + (a?.GetHashCode() ?? 0);
hash = hash * 23 + (b?.GetHashCode() ?? 0);
hash = hash * 23 + (c?.GetHashCode() ?? 0);
hash = hash * 23 + (d?.GetHashCode() ?? 0);
return hash;
}
}
public static int GetHashCode<T1, T2, T3, T4, T5>(T1 a, T2 b, T3 c, T4 d, T5 e)
{
unchecked
{
var hash = 17;
hash = hash * 23 + (a?.GetHashCode() ?? 0);
hash = hash * 23 + (b?.GetHashCode() ?? 0);
hash = hash * 23 + (c?.GetHashCode() ?? 0);
hash = hash * 23 + (d?.GetHashCode() ?? 0);
hash = hash * 23 + (e?.GetHashCode() ?? 0);
return hash;
}
}
public static int GetHashCodeAlloc(params object[] values)
{
unchecked
{
var hash = 17;
foreach (var value in values)
{
hash = hash * 23 + (value?.GetHashCode() ?? 0);
}
return hash;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38c7f6215a1b2469a877eed0cd55cf3d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,22 @@
using System;
namespace Unity.VisualScripting
{
public interface IGettable
{
object GetValue();
}
public static class XGettable
{
public static object GetValue(this IGettable gettable, Type type)
{
return ConversionUtility.Convert(gettable.GetValue(), type);
}
public static T GetValue<T>(this IGettable gettable)
{
return (T)gettable.GetValue(typeof(T));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9a0487fa0dbe4c4db50cd8d1bb03247
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using System;
namespace Unity.VisualScripting
{
public interface IIdentifiable
{
Guid guid { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b0efdfbd6ee674288a50819c81f48320
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public interface IInitializable
{
void Initialize();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d1ec6799af714a1aad300d02d85d3a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,239 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.VisualScripting
{
public static class LinqUtility
{
public static IEnumerable<T> Concat<T>(params IEnumerable[] enumerables)
{
foreach (var enumerable in enumerables.NotNull())
{
foreach (var item in enumerable.OfType<T>())
{
yield return item;
}
}
}
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
{
return items.GroupBy(property).Select(x => x.First());
}
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> enumerable)
{
return enumerable.Where(i => i != null);
}
public static IEnumerable<T> Yield<T>(this T t)
{
yield return t;
}
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> enumerable)
{
return new HashSet<T>(enumerable);
}
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
public static void AddRange(this IList list, IEnumerable items)
{
foreach (var item in items)
{
list.Add(item);
}
}
// NETUP: Replace with IReadOnlyCollection, IReadOnlyList
public static ICollection<T> AsReadOnlyCollection<T>(this IEnumerable<T> enumerable)
{
if (enumerable is ICollection<T>)
{
return (ICollection<T>)enumerable;
}
else
{
return enumerable.ToList().AsReadOnly();
}
}
public static IList<T> AsReadOnlyList<T>(this IEnumerable<T> enumerable)
{
if (enumerable is IList<T>)
{
return (IList<T>)enumerable;
}
else
{
return enumerable.ToList().AsReadOnly();
}
}
public static IEnumerable<T> Flatten<T>
(
this IEnumerable<T> source,
Func<T, IEnumerable<T>> childrenSelector
)
{
var flattenedList = source;
foreach (var element in source)
{
flattenedList = flattenedList.Concat(childrenSelector(element).Flatten(childrenSelector));
}
return flattenedList;
}
public static IEnumerable<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> groups)
{
HashSet<T> hashSet = null;
foreach (var group in groups)
{
if (hashSet == null)
{
hashSet = new HashSet<T>(group);
}
else
{
hashSet.IntersectWith(group);
}
}
return hashSet == null ? Enumerable.Empty<T>() : hashSet.AsEnumerable();
}
public static IEnumerable<T> OrderByDependencies<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getDependencies, bool throwOnCycle = true)
{
var sorted = new List<T>();
var visited = HashSetPool<T>.New();
foreach (var item in source)
{
OrderByDependenciesVisit(item, visited, sorted, getDependencies, throwOnCycle);
}
HashSetPool<T>.Free(visited);
return sorted;
}
private static void OrderByDependenciesVisit<T>(T item, HashSet<T> visited, List<T> sorted, Func<T, IEnumerable<T>> getDependencies, bool throwOnCycle)
{
if (!visited.Contains(item))
{
visited.Add(item);
foreach (var dependency in getDependencies(item))
{
OrderByDependenciesVisit(dependency, visited, sorted, getDependencies, throwOnCycle);
}
sorted.Add(item);
}
else
{
if (throwOnCycle && !sorted.Contains(item))
{
throw new InvalidOperationException("Cyclic dependency.");
}
}
}
public static IEnumerable<T> OrderByDependers<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getDependers, bool throwOnCycle = true)
{
// TODO: Optimize, or use another algorithm (Kahn's?)
// Convert dependers to dependencies
var dependencies = new Dictionary<T, HashSet<T>>();
foreach (var dependency in source)
{
foreach (var depender in getDependers(dependency))
{
if (!dependencies.ContainsKey(depender))
{
dependencies.Add(depender, new HashSet<T>());
}
dependencies[depender].Add(dependency);
}
}
return source.OrderByDependencies(depender =>
{
if (dependencies.ContainsKey(depender))
{
return dependencies[depender];
}
else
{
return Enumerable.Empty<T>();
}
}, throwOnCycle);
}
public static IEnumerable<T> Catch<T>(this IEnumerable<T> source, Action<Exception> @catch)
{
Ensure.That(nameof(source)).IsNotNull(source);
using (var enumerator = source.GetEnumerator())
{
bool success;
do
{
try
{
success = enumerator.MoveNext();
}
catch (OperationCanceledException)
{
yield break;
}
catch (Exception ex)
{
@catch?.Invoke(ex);
success = false;
}
if (success)
{
yield return enumerator.Current;
}
}
while (success);
}
}
public static IEnumerable<T> Catch<T>(this IEnumerable<T> source, ICollection<Exception> exceptions)
{
Ensure.That(nameof(exceptions)).IsNotNull(exceptions);
return source.Catch(exceptions.Add);
}
public static IEnumerable<T> CatchAsLogError<T>(this IEnumerable<T> source, string message)
{
return source.Catch((ex) => Debug.LogError(message + "\n" + ex.ToString()));
}
public static IEnumerable<T> CatchAsLogWarning<T>(this IEnumerable<T> source, string message)
{
return source.Catch((ex) => Debug.LogWarning(message + "\n" + ex.ToString()));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16c818a2cfc334b38b238142c08478ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public class OverrideStack<T>
{
public OverrideStack(T defaultValue)
{
_value = defaultValue;
getValue = () => _value;
setValue = (value) => _value = value;
}
public OverrideStack(Func<T> getValue, Action<T> setValue)
{
Ensure.That(nameof(getValue)).IsNotNull(getValue);
Ensure.That(nameof(setValue)).IsNotNull(setValue);
this.getValue = getValue;
this.setValue = setValue;
}
public OverrideStack(Func<T> getValue, Action<T> setValue, Action clearValue) : this(getValue, setValue)
{
Ensure.That(nameof(clearValue)).IsNotNull(clearValue);
this.clearValue = clearValue;
}
private readonly Func<T> getValue;
private readonly Action<T> setValue;
private readonly Action clearValue;
private T _value;
private readonly Stack<T> previous = new Stack<T>();
public T value
{
get
{
return getValue();
}
internal set
{
setValue(value);
}
}
public OverrideLayer<T> Override(T item)
{
return new OverrideLayer<T>(this, item);
}
public void BeginOverride(T item)
{
previous.Push(value);
value = item;
}
public void EndOverride()
{
if (previous.Count == 0)
{
throw new InvalidOperationException();
}
value = previous.Pop();
if (previous.Count == 0)
{
clearValue?.Invoke();
}
}
public static implicit operator T(OverrideStack<T> stack)
{
Ensure.That(nameof(stack)).IsNotNull(stack);
return stack.value;
}
}
public struct OverrideLayer<T> : IDisposable
{
public OverrideStack<T> stack { get; }
internal OverrideLayer(OverrideStack<T> stack, T item)
{
Ensure.That(nameof(stack)).IsNotNull(stack);
this.stack = stack;
stack.BeginOverride(item);
}
public void Dispose()
{
stack.EndOverride();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 648b9d6f371f74db398aa1e83ea0f383
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.VisualScripting
{
public class Recursion<T> : IPoolable, IDisposable
{
protected Recursion()
{
traversedOrder = new Stack<T>();
traversedCount = new Dictionary<T, int>();
}
private readonly Stack<T> traversedOrder;
private readonly Dictionary<T, int> traversedCount;
private bool disposed;
protected int maxDepth;
public void Enter(T o)
{
if (!TryEnter(o))
{
throw new StackOverflowException($"Max recursion depth of {maxDepth} has been exceeded. Consider increasing '{nameof(Recursion)}.{nameof(Recursion.defaultMaxDepth)}'.");
}
}
public bool TryEnter(T o)
{
if (disposed)
{
throw new ObjectDisposedException(ToString());
}
// Disable null check because it boxes o
// Ensure.That(nameof(o)).IsNotNull(o);
if (traversedCount.TryGetValue(o, out var depth))
{
if (depth < maxDepth)
{
traversedOrder.Push(o);
traversedCount[o]++;
return true;
}
else
{
return false;
}
}
else
{
traversedOrder.Push(o);
traversedCount.Add(o, 1);
return true;
}
}
public void Exit(T o)
{
if (traversedOrder.Count == 0)
{
throw new InvalidOperationException("Trying to exit an empty recursion stack.");
}
var current = traversedOrder.Peek();
if (!EqualityComparer<T>.Default.Equals(o, current))
{
throw new InvalidOperationException($"Exiting recursion stack in a non-consecutive order:\nProvided: {o} / Expected: {current}");
}
traversedOrder.Pop();
var newDepth = traversedCount[current]--;
if (newDepth == 0)
{
traversedCount.Remove(current);
}
}
public void Dispose()
{
if (disposed)
{
throw new ObjectDisposedException(ToString());
}
Free();
}
protected virtual void Free()
{
GenericPool<Recursion<T>>.Free(this);
}
void IPoolable.New()
{
disposed = false;
}
void IPoolable.Free()
{
disposed = true;
traversedCount.Clear();
traversedOrder.Clear();
}
public static Recursion<T> New()
{
return New(Recursion.defaultMaxDepth);
}
public static Recursion<T> New(int maxDepth)
{
if (!Recursion.safeMode)
{
return null;
}
if (maxDepth < 1)
{
throw new ArgumentException("Max recursion depth must be at least one.", nameof(maxDepth));
}
var recursion = GenericPool<Recursion<T>>.New(() => new Recursion<T>());
recursion.maxDepth = maxDepth;
return recursion;
}
}
public sealed class Recursion : Recursion<object>
{
private Recursion() : base() { }
public static int defaultMaxDepth { get; set; } = 100;
public static bool safeMode { get; set; }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void OnRuntimeMethodLoad()
{
safeMode = Application.isEditor || Debug.isDebugBuild;
}
protected override void Free()
{
GenericPool<Recursion>.Free(this);
}
public new static Recursion New()
{
return New(defaultMaxDepth);
}
public new static Recursion New(int maxDepth)
{
if (!safeMode)
{
return null;
}
if (maxDepth < 1)
{
throw new ArgumentException("Max recursion depth must be at least one.", nameof(maxDepth));
}
var recursion = GenericPool<Recursion>.New(() => new Recursion());
recursion.maxDepth = maxDepth;
return recursion;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d466a08d759134cb394b892eeaeabb85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Unity.VisualScripting
{
public static class ReferenceCollector
{
public static event Action onSceneUnloaded;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
SceneManager.sceneUnloaded += scene => onSceneUnloaded?.Invoke();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6641aaf2964f14d2ca96abe794c52929
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Unity.VisualScripting
{
// Implementation From Roslyn:
// http://source.roslyn.io/#microsoft.codeanalysis/InternalUtilities/ReferenceEqualityComparer.cs
public class ReferenceEqualityComparer : IEqualityComparer<object>
{
private ReferenceEqualityComparer() { }
bool IEqualityComparer<object>.Equals(object a, object b)
{
return a == b;
}
int IEqualityComparer<object>.GetHashCode(object a)
{
return GetHashCode(a);
}
public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer();
public static int GetHashCode(object a)
{
return RuntimeHelpers.GetHashCode(a);
}
}
public class ReferenceEqualityComparer<T> : IEqualityComparer<T>
{
private ReferenceEqualityComparer() { }
bool IEqualityComparer<T>.Equals(T a, T b)
{
return ReferenceEquals(a, b);
}
int IEqualityComparer<T>.GetHashCode(T a)
{
return GetHashCode(a);
}
public static readonly ReferenceEqualityComparer<T> Instance = new ReferenceEqualityComparer<T>();
public static int GetHashCode(T a)
{
return RuntimeHelpers.GetHashCode(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 473eee99af81e4e85b5a2048b267f9f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,449 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Unity.VisualScripting
{
public static class StringUtility
{
public static bool IsNullOrWhiteSpace(string s)
{
return s == null || s.Trim() == string.Empty;
}
public static string FallbackEmpty(string s, string fallback)
{
if (string.IsNullOrEmpty(s))
{
s = fallback;
}
return s;
}
public static string FallbackWhitespace(string s, string fallback)
{
if (IsNullOrWhiteSpace(s))
{
s = fallback;
}
return s;
}
public static void AppendLineFormat(this StringBuilder sb, string format, params object[] args)
{
sb.AppendFormat(format, args);
sb.AppendLine();
}
public static string ToSeparatedString(this IEnumerable enumerable, string separator)
{
return string.Join(separator, enumerable.Cast<object>().Select(o => o?.ToString() ?? "(null)").ToArray());
}
public static string ToCommaSeparatedString(this IEnumerable enumerable)
{
return ToSeparatedString(enumerable, ", ");
}
public static string ToLineSeparatedString(this IEnumerable enumerable)
{
return ToSeparatedString(enumerable, Environment.NewLine);
}
public static bool ContainsInsensitive(this string haystack, string needle)
{
return haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
}
public static IEnumerable<int> AllIndexesOf(this string haystack, string needle)
{
if (string.IsNullOrEmpty(needle))
{
yield break;
}
for (var index = 0; ; index += needle.Length)
{
index = haystack.IndexOf(needle, index, StringComparison.OrdinalIgnoreCase);
if (index == -1)
{
break;
}
yield return index;
}
}
public static string Filter(this string s, bool letters = true, bool numbers = true, bool whitespace = true, bool symbols = true, bool punctuation = true)
{
var sb = new StringBuilder();
foreach (var c in s)
{
if ((!letters && char.IsLetter(c)) ||
(!numbers && char.IsNumber(c)) ||
(!whitespace && char.IsWhiteSpace(c)) ||
(!symbols && char.IsSymbol(c)) ||
(!punctuation && char.IsPunctuation(c)))
{
continue;
}
sb.Append(c);
}
return sb.ToString();
}
public static string FilterReplace(this string s, char replacement, bool merge, bool letters = true, bool numbers = true, bool whitespace = true, bool symbols = true, bool punctuation = true)
{
var sb = new StringBuilder();
var wasFiltered = false;
foreach (var c in s)
{
if ((!letters && char.IsLetter(c)) ||
(!numbers && char.IsNumber(c)) ||
(!whitespace && char.IsWhiteSpace(c)) ||
(!symbols && char.IsSymbol(c)) ||
(!punctuation && char.IsPunctuation(c)))
{
if (!merge || !wasFiltered)
{
sb.Append(replacement);
}
wasFiltered = true;
}
else
{
sb.Append(c);
wasFiltered = false;
}
}
return sb.ToString();
}
public static string Prettify(this string s)
{
return s.FirstCharacterToUpper().SplitWords(' ');
}
public static bool IsWordDelimiter(char c)
{
return char.IsWhiteSpace(c) || char.IsSymbol(c) || char.IsPunctuation(c);
}
public static bool IsWordBeginning(char? previous, char current, char? next)
{
var isFirst = previous == null;
var isLast = next == null;
var isLetter = char.IsLetter(current);
var wasLetter = previous != null && char.IsLetter(previous.Value);
var isNumber = char.IsNumber(current);
var wasNumber = previous != null && char.IsNumber(previous.Value);
var isUpper = char.IsUpper(current);
var wasUpper = previous != null && char.IsUpper(previous.Value);
var isDelimiter = IsWordDelimiter(current);
var wasDelimiter = previous != null && IsWordDelimiter(previous.Value);
var willBeLower = next != null && char.IsLower(next.Value);
return
(!isDelimiter && isFirst) ||
(!isDelimiter && wasDelimiter) ||
(isLetter && wasLetter && isUpper && !wasUpper) || // camelCase => camel_Case
(isLetter && wasLetter && isUpper && wasUpper && !isLast && willBeLower) || // => ABBRWord => ABBR_Word
(isNumber && wasLetter) || // Vector3 => Vector_3
(isLetter && wasNumber && isUpper && willBeLower); // Word1Word => Word_1_Word, Word1word => Word_1word
}
public static bool IsWordBeginning(string s, int index)
{
Ensure.That(nameof(index)).IsGte(index, 0);
Ensure.That(nameof(index)).IsLt(index, s.Length);
var previous = index > 0 ? s[index - 1] : (char?)null;
var current = s[index];
var next = index < s.Length - 1 ? s[index + 1] : (char?)null;
return IsWordBeginning(previous, current, next);
}
public static string SplitWords(this string s, char separator)
{
var sb = new StringBuilder();
for (var i = 0; i < s.Length; i++)
{
var c = s[i];
if (i > 0 && IsWordBeginning(s, i))
{
sb.Append(separator);
}
sb.Append(c);
}
return sb.ToString();
}
public static string RemoveConsecutiveCharacters(this string s, char c)
{
var sb = new StringBuilder();
var previous = '\0';
foreach (var current in s)
{
if (current != c || current != previous)
{
sb.Append(current);
previous = current;
}
}
return sb.ToString();
}
public static string ReplaceMultiple(this string s, HashSet<char> haystacks, char replacement)
{
Ensure.That(nameof(haystacks)).IsNotNull(haystacks);
var sb = new StringBuilder();
foreach (var current in s)
{
if (haystacks.Contains(current))
{
sb.Append(replacement);
}
else
{
sb.Append(current);
}
}
return sb.ToString();
}
public static string Truncate(this string value, int maxLength, string suffix = "...")
{
return value.Length <= maxLength ? value : value.Substring(0, maxLength) + suffix;
}
public static string TrimEnd(this string source, string value)
{
if (!source.EndsWith(value))
{
return source;
}
return source.Remove(source.LastIndexOf(value));
}
public static string TrimStart(this string source, string value)
{
if (!source.StartsWith(value))
{
return source;
}
return source.Substring(value.Length);
}
public static string FirstCharacterToLower(this string s)
{
if (string.IsNullOrEmpty(s) || char.IsLower(s, 0))
{
return s;
}
return char.ToLowerInvariant(s[0]) + s.Substring(1);
}
public static string FirstCharacterToUpper(this string s)
{
if (string.IsNullOrEmpty(s) || char.IsUpper(s, 0))
{
return s;
}
return char.ToUpperInvariant(s[0]) + s.Substring(1);
}
public static string PartBefore(this string s, char c)
{
Ensure.That(nameof(s)).IsNotNull(s);
var index = s.IndexOf(c);
if (index > 0)
{
return s.Substring(0, index);
}
else
{
return s;
}
}
public static string PartAfter(this string s, char c)
{
Ensure.That(nameof(s)).IsNotNull(s);
var index = s.IndexOf(c);
if (index > 0)
{
return s.Substring(index + 1);
}
else
{
return s;
}
}
public static void PartsAround(this string s, char c, out string before, out string after)
{
Ensure.That(nameof(s)).IsNotNull(s);
var index = s.IndexOf(c);
if (index > 0)
{
before = s.Substring(0, index);
after = s.Substring(index + 1);
}
else
{
before = s;
after = null;
}
}
// Faster equivalents for chars
public static bool EndsWith(this string s, char c)
{
Ensure.That(nameof(s)).IsNotNull(s);
return s[s.Length - 1] == c;
}
public static bool StartsWith(this string s, char c)
{
Ensure.That(nameof(s)).IsNotNull(s);
return s[0] == c;
}
public static bool Contains(this string s, char c)
{
Ensure.That(nameof(s)).IsNotNull(s);
for (int i = 0; i < s.Length; i++)
{
if (s[i] == c)
{
return true;
}
}
return false;
}
public static string NullIfEmpty(this string s)
{
if (s == string.Empty)
{
return null;
}
else
{
return s;
}
}
public static string ToBinaryString(this int value)
{
return Convert.ToString(value, 2).PadLeft(8, '0');
}
public static string ToBinaryString(this long value)
{
return Convert.ToString(value, 2).PadLeft(16, '0');
}
public static string ToBinaryString(this Enum value)
{
return Convert.ToString(Convert.ToInt64(value), 2).PadLeft(16, '0');
}
public static int CountIndices(this string s, char c)
{
var count = 0;
foreach (var _c in s)
{
if (c == _c)
{
count++;
}
}
return count;
}
public static bool IsGuid(string value)
{
return guidRegex.IsMatch(value);
}
private static readonly Regex guidRegex = new Regex(@"[a-fA-F0-9]{8}(\-[a-fA-F0-9]{4}){3}\-[a-fA-F0-9]{12}");
public static string PathEllipsis(string s, int maxLength)
{
var ellipsis = "...";
if (s.Length < maxLength)
{
return s;
}
var fileName = Path.GetFileName(s);
var directory = Path.GetDirectoryName(s);
var maxDirectoryLength = maxLength - fileName.Length - ellipsis.Length;
if (maxDirectoryLength > 0)
{
return directory.Substring(0, maxDirectoryLength) + ellipsis + Path.DirectorySeparatorChar + fileName;
}
else
{
return ellipsis + Path.DirectorySeparatorChar + fileName;
}
}
public static string ToHexString(this byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", "");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61ab10f4687d1455da6d4845e21f5401
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public static class UnityObjectUtility
{
public static bool IsDestroyed(this UnityObject target)
{
// Checks whether a Unity object is not actually a null reference,
// but a rather destroyed native instance.
return !ReferenceEquals(target, null) && target == null;
}
public static bool IsUnityNull(this object obj)
{
// Checks whether an object is null or Unity pseudo-null
// without having to cast to UnityEngine.Object manually
return obj == null || ((obj is UnityObject) && ((UnityObject)obj) == null);
}
public static string ToSafeString(this UnityObject uo)
{
if (ReferenceEquals(uo, null))
{
return "(null)";
}
if (!UnityThread.allowsAPI)
{
return uo.GetType().Name;
}
if (uo == null)
{
return "(Destroyed)";
}
try
{
return uo.name;
}
catch (Exception ex)
{
return $"({ex.GetType().Name} in ToString: {ex.Message})";
}
}
public static string ToSafeString(this object obj)
{
if (obj == null)
{
return "(null)";
}
if (obj is UnityObject uo)
{
return uo.ToSafeString();
}
try
{
return obj.ToString();
}
catch (Exception ex)
{
return $"({ex.GetType().Name} in ToString: {ex.Message})";
}
}
public static T AsUnityNull<T>(this T obj) where T : UnityObject
{
// Converts a Unity pseudo-null to a real null, allowing for coalesce operators.
// e.g.: destroyedObject.AsUnityNull() ?? otherObject
if (obj == null)
{
return null;
}
return obj;
}
public static bool TrulyEqual(UnityObject a, UnityObject b)
{
// This method is required when checking two references
// against one another, where one of them might have been destroyed.
// It is not required when checking against null.
// This is because Unity does not compare alive state
// in the CompareBaseObjects method unless one of the two
// operators is actually the null literal.
// From the source:
/*
bool lhsIsNull = (object) lhs == null;
bool rhsIsNull = (object) rhs == null;
if (rhsIsNull && lhsIsNull)
return true;
if (rhsIsNull)
return !Object.IsNativeObjectAlive(lhs);
if (lhsIsNull)
return !Object.IsNativeObjectAlive(rhs);
return lhs.m_InstanceID == rhs.m_InstanceID;
*/
// As we can see, Object.IsNativeObjectAlive is not compared
// across the two objects unless one of the operands is actually null.
// But it can happen, for example when exiting play mode.
// If we stored a static reference to a scene object that was destroyed,
// the reference won't get cleared because assembly reloads don't happen
// when exiting playmode. But the instance ID of the object will stay
// the same, because it only gets reserialized. So if we compare our
// stale reference that was destroyed to a new reference to the object,
// it will return true, even though one reference is alive and the other isn't.
if (a != b)
{
return false;
}
if ((a == null) != (b == null))
{
return false;
}
return true;
}
public static IEnumerable<T> NotUnityNull<T>(this IEnumerable<T> enumerable) where T : UnityObject
{
return enumerable.Where(i => i != null);
}
public static IEnumerable<T> FindObjectsOfTypeIncludingInactive<T>()
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (scene.isLoaded)
{
foreach (var rootGameObject in scene.GetRootGameObjects())
{
foreach (var result in rootGameObject.GetComponentsInChildren<T>(true))
{
yield return result;
}
}
}
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85f4b970ba57b4bdd9b801cec11a183c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using UnityEngine;
namespace Unity.VisualScripting
{
public static class XColor
{
public static string ToHexString(this Color color)
{
return
((byte)(color.r * 255)).ToString("X2") +
((byte)(color.g * 255)).ToString("X2") +
((byte)(color.b * 255)).ToString("X2") +
((byte)(color.a * 255)).ToString("X2");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc7b71435e995493f8881e16f854d1cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: