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,8 @@
fileFormatVersion: 2
guid: 61c823205c2384c13b4d38c05194c1df
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,77 @@
using System;
namespace Unity.VisualScripting
{
/// <summary>
/// Creates a struct with its default initializer.
/// </summary>
[SpecialUnit]
public sealed class CreateStruct : Unit
{
[Obsolete(Serialization.ConstructorWarning)]
public CreateStruct() : base() { }
public CreateStruct(Type type) : base()
{
Ensure.That(nameof(type)).IsNotNull(type);
if (!type.IsStruct())
{
throw new ArgumentException($"Type {type} must be a struct.", nameof(type));
}
this.type = type;
}
[Serialize]
public Type type { get; internal set; }
// Shouldn't happen through normal use, but can happen
// if deserialization fails to find the type
// https://support.ludiq.io/communities/5/topics/1661-x
public override bool canDefine => type != null;
/// <summary>
/// The entry point to create the struct. You can
/// still get the return value without connecting this port.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The action to call once the struct has been created.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
/// <summary>
/// The created struct.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput output { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Enter);
exit = ControlOutput(nameof(exit));
output = ValueOutput(type, nameof(output), Create);
Succession(enter, exit);
}
private ControlOutput Enter(Flow flow)
{
flow.SetValue(output, Activator.CreateInstance(type));
return exit;
}
private object Create(Flow flow)
{
return Activator.CreateInstance(type);
}
}
}

View file

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

View file

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace Unity.VisualScripting
{
/// <summary>
/// Exposes all members of the type.
/// </summary>
[SpecialUnit]
public sealed class Expose : Unit, IAotStubbable
{
public Expose() : base() { }
public Expose(Type type) : base()
{
this.type = type;
}
[Serialize, Inspectable, TypeFilter(Enums = false)]
public Type type { get; set; }
[Serialize, Inspectable, UnitHeaderInspectable("Instance"), InspectorToggleLeft]
public bool instance { get; set; } = true;
[Serialize, Inspectable, UnitHeaderInspectable("Static"), InspectorToggleLeft]
public bool @static { get; set; } = true;
/// <summary>
/// The instance of the exposed type.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
[NullMeansSelf]
public ValueInput target { get; private set; }
[DoNotSerialize]
public Dictionary<ValueOutput, Member> members { get; private set; }
public override bool canDefine => type != null;
IEnumerable<object> IAotStubbable.aotStubs
{
get
{
if (members != null)
{
foreach (var member in members.Values)
{
if (member != null && member.isReflected)
{
yield return member.info;
}
}
}
}
}
protected override void Definition()
{
members = new Dictionary<ValueOutput, Member>();
var requiresTarget = false;
foreach (var member in type.GetMembers()
.Where(m => m is FieldInfo || m is PropertyInfo)
.Select(m => m.ToManipulator(type))
.DistinctBy(m => m.name) // To account for "new" duplicates
.Where(Include)
.OrderBy(m => m.requiresTarget ? 0 : 1)
.ThenBy(m => m.order))
{
var memberPort = ValueOutput(member.type, member.name, (flow) => GetValue(flow, member));
if (member.isPredictable)
{
memberPort.Predictable();
}
members.Add(memberPort, member);
if (member.requiresTarget)
{
requiresTarget = true;
}
}
if (requiresTarget)
{
target = ValueInput(type, nameof(target)).NullMeansSelf();
target.SetDefaultValue(type.PseudoDefault());
foreach (var member in members.Keys)
{
if (members[member].requiresTarget)
{
Requirement(target, member);
}
}
}
}
private bool Include(Member member)
{
if (!instance && member.requiresTarget)
{
return false;
}
if (!@static && !member.requiresTarget)
{
return false;
}
if (!member.isPubliclyGettable)
{
return false;
}
if (member.info.HasAttribute<ObsoleteAttribute>())
{
return false;
}
if (member.isIndexer)
{
return false;
}
// Pesky edit-mode only accessor that is only available in the editor,
// yet isn't marked by any special attribute to indicate it.
if (member.name == "runInEditMode" && member.declaringType == typeof(MonoBehaviour))
{
return false;
}
return true;
}
private object GetValue(Flow flow, Member member)
{
var target = member.requiresTarget ? flow.GetValue(this.target, member.targetType) : null;
return member.Get(target);
}
}
}

View file

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

View file

@ -0,0 +1,59 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Gets the value of a field or property via reflection.
/// </summary>
public sealed class GetMember : MemberUnit
{
public GetMember() { }
public GetMember(Member member) : base(member) { }
[DoNotSerialize]
[MemberFilter(Fields = true, Properties = true, WriteOnly = false)]
public Member getter
{
get
{
return member;
}
set
{
member = value;
}
}
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput value { get; private set; }
protected override void Definition()
{
base.Definition();
value = ValueOutput(member.type, nameof(value), Value);
if (member.isPredictable)
{
value.Predictable();
}
if (member.requiresTarget)
{
Requirement(target, value);
}
}
protected override bool IsMemberValid(Member member)
{
return member.isAccessor && member.isGettable;
}
private object Value(Flow flow)
{
var target = member.requiresTarget ? flow.GetValue(this.target, member.targetType) : null;
return member.Get(target);
}
}
}

View file

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

View file

@ -0,0 +1,270 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
/// <summary>
/// Invokes a method or a constructor via reflection.
/// </summary>
public sealed class InvokeMember : MemberUnit
{
public InvokeMember() : base() { }
public InvokeMember(Member member) : base(member) { }
private bool useExpandedParameters;
/// <summary>
/// Whether the target should be output to allow for chaining.
/// </summary>
[Serialize]
[InspectableIf(nameof(supportsChaining))]
public bool chainable { get; set; }
[DoNotSerialize]
public bool supportsChaining => member.requiresTarget;
[DoNotSerialize]
[MemberFilter(Methods = true, Constructors = true)]
public Member invocation
{
get { return member; }
set { member = value; }
}
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
[DoNotSerialize]
public Dictionary<int, ValueInput> inputParameters { get; private set; }
/// <summary>
/// The target object used when setting the value.
/// </summary>
[DoNotSerialize]
[PortLabel("Target")]
[PortLabelHidden]
public ValueOutput targetOutput { get; private set; }
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput result { get; private set; }
[DoNotSerialize]
public Dictionary<int, ValueOutput> outputParameters { get; private set; }
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
[DoNotSerialize]
private int parameterCount;
protected override void Definition()
{
base.Definition();
inputParameters = new Dictionary<int, ValueInput>();
outputParameters = new Dictionary<int, ValueOutput>();
useExpandedParameters = true;
enter = ControlInput(nameof(enter), Enter);
exit = ControlOutput(nameof(exit));
Succession(enter, exit);
if (member.requiresTarget)
{
Requirement(target, enter);
}
if (supportsChaining && chainable)
{
targetOutput = ValueOutput(member.targetType, nameof(targetOutput));
Assignment(enter, targetOutput);
}
if (member.isGettable)
{
result = ValueOutput(member.type, nameof(result), Result);
if (member.requiresTarget)
{
Requirement(target, result);
}
}
var parameterInfos = member.GetParameterInfos().ToArray();
parameterCount = parameterInfos.Length;
for (int parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
{
var parameterInfo = parameterInfos[parameterIndex];
var parameterType = parameterInfo.UnderlyingParameterType();
if (!parameterInfo.HasOutModifier())
{
var inputParameterKey = "%" + parameterInfo.Name;
var inputParameter = ValueInput(parameterType, inputParameterKey);
inputParameters.Add(parameterIndex, inputParameter);
inputParameter.SetDefaultValue(parameterInfo.PseudoDefaultValue());
if (parameterInfo.AllowsNull())
{
inputParameter.AllowsNull();
}
Requirement(inputParameter, enter);
if (member.isGettable)
{
Requirement(inputParameter, result);
}
}
if (parameterInfo.ParameterType.IsByRef || parameterInfo.IsOut)
{
var outputParameterKey = "&" + parameterInfo.Name;
var outputParameter = ValueOutput(parameterType, outputParameterKey);
outputParameters.Add(parameterIndex, outputParameter);
Assignment(enter, outputParameter);
useExpandedParameters = false;
}
}
if (inputParameters.Count > 5)
{
useExpandedParameters = false;
}
}
protected override bool IsMemberValid(Member member)
{
return member.isInvocable;
}
private object Invoke(object target, Flow flow)
{
if (useExpandedParameters)
{
switch (inputParameters.Count)
{
case 0:
return member.Invoke(target);
case 1:
return member.Invoke(target,
flow.GetConvertedValue(inputParameters[0]));
case 2:
return member.Invoke(target,
flow.GetConvertedValue(inputParameters[0]),
flow.GetConvertedValue(inputParameters[1]));
case 3:
return member.Invoke(target,
flow.GetConvertedValue(inputParameters[0]),
flow.GetConvertedValue(inputParameters[1]),
flow.GetConvertedValue(inputParameters[2]));
case 4:
return member.Invoke(target,
flow.GetConvertedValue(inputParameters[0]),
flow.GetConvertedValue(inputParameters[1]),
flow.GetConvertedValue(inputParameters[2]),
flow.GetConvertedValue(inputParameters[3]));
case 5:
return member.Invoke(target,
flow.GetConvertedValue(inputParameters[0]),
flow.GetConvertedValue(inputParameters[1]),
flow.GetConvertedValue(inputParameters[2]),
flow.GetConvertedValue(inputParameters[3]),
flow.GetConvertedValue(inputParameters[4]));
default:
throw new NotSupportedException();
}
}
else
{
var arguments = new object[parameterCount];
for (int parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
{
if (inputParameters.TryGetValue(parameterIndex, out var inputParameter))
{
arguments[parameterIndex] = flow.GetConvertedValue(inputParameter);
}
}
var result = member.Invoke(target, arguments);
for (int parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
{
if (outputParameters.TryGetValue(parameterIndex, out var outputParameter))
{
flow.SetValue(outputParameter, arguments[parameterIndex]);
}
}
return result;
}
}
private object GetAndChainTarget(Flow flow)
{
if (member.requiresTarget)
{
var target = flow.GetValue(this.target, member.targetType);
if (supportsChaining && chainable)
{
flow.SetValue(targetOutput, target);
}
return target;
}
return null;
}
private object Result(Flow flow)
{
var target = GetAndChainTarget(flow);
return Invoke(target, flow);
}
private ControlOutput Enter(Flow flow)
{
var target = GetAndChainTarget(flow);
var result = Invoke(target, flow);
if (this.result != null)
{
flow.SetValue(this.result, result);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
[SpecialUnit]
public abstract class MemberUnit : Unit, IAotStubbable
{
protected MemberUnit() : base() { }
protected MemberUnit(Member member) : this()
{
this.member = member;
}
[Serialize]
[MemberFilter(Fields = true, Properties = true, Methods = true, Constructors = true)]
public Member member { get; set; }
/// <summary>
/// The target object.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
[NullMeansSelf]
public ValueInput target { get; private set; }
public override bool canDefine => member != null;
protected override void Definition()
{
member.EnsureReflected();
if (!IsMemberValid(member))
{
throw new NotSupportedException("The member type is not valid for this unit.");
}
if (member.requiresTarget)
{
target = ValueInput(member.targetType, nameof(target));
target.SetDefaultValue(member.targetType.PseudoDefault());
if (typeof(UnityObject).IsAssignableFrom(member.targetType))
{
target.NullMeansSelf();
}
}
}
protected abstract bool IsMemberValid(Member member);
public override void Prewarm()
{
if (member != null && member.isReflected)
{
member.Prewarm();
}
}
IEnumerable<object> IAotStubbable.aotStubs
{
get
{
if (member != null && member.isReflected)
{
yield return member.info;
}
}
}
}
}

View file

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

View file

@ -0,0 +1,122 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Sets the value of a field or property via reflection.
/// </summary>
public sealed class SetMember : MemberUnit
{
public SetMember() : base() { }
public SetMember(Member member) : base(member) { }
/// <summary>
/// Whether the target should be output to allow for chaining.
/// </summary>
[Serialize]
[InspectableIf(nameof(supportsChaining))]
public bool chainable { get; set; }
[DoNotSerialize]
public bool supportsChaining => member.requiresTarget;
[DoNotSerialize]
[MemberFilter(Fields = true, Properties = true, ReadOnly = false)]
public Member setter
{
get => member;
set => member = value;
}
[DoNotSerialize]
[PortLabelHidden]
public ControlInput assign { get; private set; }
[DoNotSerialize]
[PortLabel("Value")]
[PortLabelHidden]
public ValueInput input { get; private set; }
[DoNotSerialize]
[PortLabel("Value")]
[PortLabelHidden]
public ValueOutput output { get; private set; }
/// <summary>
/// The target object used when setting the value.
/// </summary>
[DoNotSerialize]
[PortLabel("Target")]
[PortLabelHidden]
public ValueOutput targetOutput { get; private set; }
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput assigned { get; private set; }
protected override void Definition()
{
base.Definition();
assign = ControlInput(nameof(assign), Assign);
assigned = ControlOutput(nameof(assigned));
Succession(assign, assigned);
if (supportsChaining && chainable)
{
targetOutput = ValueOutput(member.targetType, nameof(targetOutput));
Assignment(assign, targetOutput);
}
output = ValueOutput(member.type, nameof(output));
Assignment(assign, output);
if (member.requiresTarget)
{
Requirement(target, assign);
}
input = ValueInput(member.type, nameof(input));
Requirement(input, assign);
if (member.allowsNull)
{
input.AllowsNull();
}
input.SetDefaultValue(member.type.PseudoDefault());
}
protected override bool IsMemberValid(Member member)
{
return member.isAccessor && member.isSettable;
}
private object GetAndChainTarget(Flow flow)
{
if (member.requiresTarget)
{
var target = flow.GetValue(this.target, member.targetType);
if (supportsChaining && chainable)
{
flow.SetValue(targetOutput, target);
}
return target;
}
return null;
}
private ControlOutput Assign(Flow flow)
{
var target = GetAndChainTarget(flow);
var value = flow.GetConvertedValue(input);
flow.SetValue(output, member.Set(target, value));
return assigned;
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3b0d8ccc2f7184e87956a482fb08d49b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,48 @@
using System.Collections;
using System.Linq;
namespace Unity.VisualScripting
{
/// <summary>
/// Counts all items in a collection or enumeration.
/// </summary>
[UnitCategory("Collections")]
public sealed class CountItems : Unit
{
/// <summary>
/// The collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput collection { get; private set; }
/// <summary>
/// The number of items contained in the collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput count { get; private set; }
protected override void Definition()
{
collection = ValueInput<IEnumerable>(nameof(collection));
count = ValueOutput(nameof(count), Count);
Requirement(collection, count);
}
public int Count(Flow flow)
{
var enumerable = flow.GetValue<IEnumerable>(collection);
if (enumerable is ICollection)
{
return ((ICollection)enumerable).Count;
}
else
{
return enumerable.Cast<object>().Count();
}
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe09e9cdabae047b9a8e6d245eec4ade
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Adds an item to a dictionary.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Add Item")]
[UnitOrder(2)]
public sealed class AddDictionaryItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueInput dictionaryInput { get; private set; }
/// <summary>
/// The dictionary with the added element.
/// Note that the input dictionary is modified directly then returned.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueOutput dictionaryOutput { get; private set; }
/// <summary>
/// The key of the item to add.
/// </summary>
[DoNotSerialize]
public ValueInput key { get; private set; }
/// <summary>
/// The value of the item to add.
/// </summary>
[DoNotSerialize]
public ValueInput value { get; private set; }
/// <summary>
/// The action to execute once the item has been added.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Add);
dictionaryInput = ValueInput<IDictionary>(nameof(dictionaryInput));
key = ValueInput<object>(nameof(key));
value = ValueInput<object>(nameof(value));
dictionaryOutput = ValueOutput<IDictionary>(nameof(dictionaryOutput));
exit = ControlOutput(nameof(exit));
Requirement(dictionaryInput, enter);
Requirement(key, enter);
Requirement(value, enter);
Assignment(enter, dictionaryOutput);
Succession(enter, exit);
}
private ControlOutput Add(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(dictionaryInput);
var key = flow.GetValue<object>(this.key);
var value = flow.GetValue<object>(this.value);
flow.SetValue(dictionaryOutput, dictionary);
dictionary.Add(key, value);
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,69 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Clears all items from a dictionary.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Clear")]
[UnitOrder(4)]
[TypeIcon(typeof(RemoveDictionaryItem))]
public sealed class ClearDictionary : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueInput dictionaryInput { get; private set; }
/// <summary>
/// The cleared dictionary.
/// Note that the input dictionary is modified directly and then returned.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueOutput dictionaryOutput { get; private set; }
/// <summary>
/// The action to execute once the dictionary has been cleared.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Clear);
dictionaryInput = ValueInput<IDictionary>(nameof(dictionaryInput));
dictionaryOutput = ValueOutput<IDictionary>(nameof(dictionaryOutput));
exit = ControlOutput(nameof(exit));
Requirement(dictionaryInput, enter);
Assignment(enter, dictionaryOutput);
Succession(enter, exit);
}
private ControlOutput Clear(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(dictionaryInput);
flow.SetValue(dictionaryOutput, dictionary);
dictionary.Clear();
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,31 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Creates an empty dictionary.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitOrder(-1)]
[TypeIcon(typeof(IDictionary))]
[RenamedFrom("Bolt.CreateDitionary")]
public sealed class CreateDictionary : Unit
{
/// <summary>
/// The new empty dictionary.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput dictionary { get; private set; }
protected override void Definition()
{
dictionary = ValueOutput(nameof(dictionary), Create);
}
public IDictionary Create(Flow flow)
{
return new AotDictionary();
}
}
}

View file

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

View file

@ -0,0 +1,53 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Checks whether a dictionary contains the specified key.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Contains Key")]
[TypeIcon(typeof(IDictionary))]
public sealed class DictionaryContainsKey : Unit
{
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput dictionary { get; private set; }
/// <summary>
/// The key.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput key { get; private set; }
/// <summary>
/// Whether the list contains the item.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput contains { get; private set; }
protected override void Definition()
{
dictionary = ValueInput<IDictionary>(nameof(dictionary));
key = ValueInput<object>(nameof(key));
contains = ValueOutput(nameof(contains), Contains);
Requirement(dictionary, contains);
Requirement(key, contains);
}
private bool Contains(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(this.dictionary);
var key = flow.GetValue<object>(this.key);
return dictionary.Contains(key);
}
}
}

View file

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

View file

@ -0,0 +1,53 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Gets a dictionary item with the specified key.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Get Item")]
[UnitOrder(0)]
[TypeIcon(typeof(IDictionary))]
public sealed class GetDictionaryItem : Unit
{
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput dictionary { get; private set; }
/// <summary>
/// The key of the item.
/// </summary>
[DoNotSerialize]
public ValueInput key { get; private set; }
/// <summary>
/// The value of the item.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput value { get; private set; }
protected override void Definition()
{
dictionary = ValueInput<IDictionary>(nameof(dictionary));
key = ValueInput<object>(nameof(key));
value = ValueOutput(nameof(value), Get);
Requirement(dictionary, value);
Requirement(key, value);
}
private object Get(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(this.dictionary);
var key = flow.GetValue<object>(this.key);
return dictionary[key];
}
}
}

View file

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

View file

@ -0,0 +1,57 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Merges two or more dictionaries together.
/// </summary>
/// <remarks>
/// If the same key is found more than once, only the value
/// of the first dictionary with this key will be used.
/// </remarks>
[UnitCategory("Collections/Dictionaries")]
[UnitOrder(5)]
public sealed class MergeDictionaries : MultiInputUnit<IDictionary>
{
/// <summary>
/// The merged dictionary.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput dictionary { get; private set; }
protected override void Definition()
{
dictionary = ValueOutput(nameof(dictionary), Merge);
base.Definition();
foreach (var input in multiInputs)
{
Requirement(input, dictionary);
}
}
public IDictionary Merge(Flow flow)
{
var dictionary = new AotDictionary();
for (var i = 0; i < inputCount; i++)
{
var inputDictionary = flow.GetValue<IDictionary>(multiInputs[i]);
var enumerator = inputDictionary.GetEnumerator();
while (enumerator.MoveNext())
{
if (!dictionary.Contains(enumerator.Key))
{
dictionary.Add(enumerator.Key, enumerator.Value);
}
}
}
return dictionary;
}
}
}

View file

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

View file

@ -0,0 +1,77 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Removes a dictionary item with a specified key.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Remove Item")]
[UnitOrder(3)]
public sealed class RemoveDictionaryItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueInput dictionaryInput { get; private set; }
/// <summary>
/// The dictionary without the removed item.
/// Note that the input dictionary is modified directly and then returned.
/// </summary>
[DoNotSerialize]
[PortLabel("Dictionary")]
[PortLabelHidden]
public ValueOutput dictionaryOutput { get; private set; }
/// <summary>
/// The key of the item to remove.
/// </summary>
[DoNotSerialize]
public ValueInput key { get; private set; }
/// <summary>
/// The action to execute once the item has been removed.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Remove);
dictionaryInput = ValueInput<IDictionary>(nameof(dictionaryInput));
dictionaryOutput = ValueOutput<IDictionary>(nameof(dictionaryOutput));
key = ValueInput<object>(nameof(key));
exit = ControlOutput(nameof(exit));
Requirement(dictionaryInput, enter);
Requirement(key, enter);
Assignment(enter, dictionaryOutput);
Succession(enter, exit);
}
public ControlOutput Remove(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(dictionaryInput);
var key = flow.GetValue<object>(this.key);
flow.SetValue(dictionaryOutput, dictionary);
dictionary.Remove(key);
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,73 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Sets the value of a dictionary item with the specified key.
/// </summary>
[UnitCategory("Collections/Dictionaries")]
[UnitSurtitle("Dictionary")]
[UnitShortTitle("Set Item")]
[UnitOrder(1)]
[TypeIcon(typeof(IDictionary))]
public sealed class SetDictionaryItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The dictionary.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput dictionary { get; private set; }
/// <summary>
/// The key of the item to set.
/// </summary>
[DoNotSerialize]
public ValueInput key { get; private set; }
/// <summary>
/// The value to assign to the item.
/// </summary>
[DoNotSerialize]
public ValueInput value { get; private set; }
/// <summary>
/// The action to execute once the item has been assigned.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Set);
dictionary = ValueInput<IDictionary>(nameof(dictionary));
key = ValueInput<object>(nameof(key));
value = ValueInput<object>(nameof(value));
exit = ControlOutput(nameof(exit));
Requirement(dictionary, enter);
Requirement(key, enter);
Requirement(value, enter);
Succession(enter, exit);
}
public ControlOutput Set(Flow flow)
{
var dictionary = flow.GetValue<IDictionary>(this.dictionary);
var key = flow.GetValue<object>(this.key);
var value = flow.GetValue<object>(this.value);
dictionary[key] = value;
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,48 @@
using System.Collections;
using System.Linq;
namespace Unity.VisualScripting
{
/// <summary>
/// Returns the first item in a collection or enumeration.
/// </summary>
[UnitCategory("Collections")]
public sealed class FirstItem : Unit
{
/// <summary>
/// The collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput collection { get; private set; }
/// <summary>
/// The first item of the collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput firstItem { get; private set; }
protected override void Definition()
{
collection = ValueInput<IEnumerable>(nameof(collection));
firstItem = ValueOutput(nameof(firstItem), First);
Requirement(collection, firstItem);
}
public object First(Flow flow)
{
var enumerable = flow.GetValue<IEnumerable>(collection);
if (enumerable is IList)
{
return ((IList)enumerable)[0];
}
else
{
return enumerable.Cast<object>().First();
}
}
}
}

View file

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

View file

@ -0,0 +1,50 @@
using System.Collections;
using System.Linq;
namespace Unity.VisualScripting
{
/// <summary>
/// Returns the first item in a collection or enumeration.
/// </summary>
[UnitCategory("Collections")]
public sealed class LastItem : Unit
{
/// <summary>
/// The collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput collection { get; private set; }
/// <summary>
/// The last item of the collection.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput lastItem { get; private set; }
protected override void Definition()
{
collection = ValueInput<IEnumerable>(nameof(collection));
lastItem = ValueOutput(nameof(lastItem), First);
Requirement(collection, lastItem);
}
public object First(Flow flow)
{
var enumerable = flow.GetValue<IEnumerable>(collection);
if (enumerable is IList)
{
var list = (IList)enumerable;
return list[list.Count - 1];
}
else
{
return enumerable.Cast<object>().Last();
}
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 595933039dbdb4e7ca040caec13d06de
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,90 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Adds an item to a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Add Item")]
[UnitOrder(2)]
public sealed class AddListItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueInput listInput { get; private set; }
/// <summary>
/// The list with the added element.
/// Note that the input list is modified directly and then returned,
/// except if it is an array, in which case a new array with
/// the added element is returned instead.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueOutput listOutput { get; private set; }
/// <summary>
/// The item to add.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput item { get; private set; }
/// <summary>
/// The action to execute once the item has been added.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Add);
listInput = ValueInput<IList>(nameof(listInput));
item = ValueInput<object>(nameof(item));
listOutput = ValueOutput<IList>(nameof(listOutput));
exit = ControlOutput(nameof(exit));
Requirement(listInput, enter);
Requirement(item, enter);
Assignment(enter, listOutput);
Succession(enter, exit);
}
public ControlOutput Add(Flow flow)
{
var list = flow.GetValue<IList>(listInput);
var item = flow.GetValue<object>(this.item);
if (list is Array)
{
var resizableList = new ArrayList(list);
resizableList.Add(item);
flow.SetValue(listOutput, resizableList.ToArray(list.GetType().GetElementType()));
}
else
{
list.Add(item);
flow.SetValue(listOutput, list);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,79 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Clears all items from a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Clear")]
[UnitOrder(6)]
[TypeIcon(typeof(RemoveListItem))]
public sealed class ClearList : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueInput listInput { get; private set; }
/// <summary>
/// The cleared list.
/// Note that the input list is modified directly and then returned,
/// except if it is an array, in which case a new empty array
/// is returned instead.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueOutput listOutput { get; private set; }
/// <summary>
/// The action to execute once the list has been cleared.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Clear);
listInput = ValueInput<IList>(nameof(listInput));
listOutput = ValueOutput<IList>(nameof(listOutput));
exit = ControlOutput(nameof(exit));
Requirement(listInput, enter);
Assignment(enter, listOutput);
Succession(enter, exit);
}
public ControlOutput Clear(Flow flow)
{
var list = flow.GetValue<IList>(listInput);
if (list is Array)
{
flow.SetValue(listOutput, Array.CreateInstance(list.GetType().GetElementType(), 0));
}
else
{
list.Clear();
flow.SetValue(listOutput, list);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,58 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Creates a list from a number of item inputs.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitOrder(-1)]
[TypeIcon(typeof(IList))]
public sealed class CreateList : MultiInputUnit<object>
{
[DoNotSerialize]
protected override int minInputCount => 0;
[InspectorLabel("Elements")]
[UnitHeaderInspectable("Elements")]
[Inspectable]
public override int inputCount
{
get => base.inputCount;
set => base.inputCount = value;
}
/// <summary>
/// The created list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput list { get; private set; }
protected override void Definition()
{
list = ValueOutput(nameof(list), Create);
base.Definition();
foreach (var input in multiInputs)
{
Requirement(input, list);
}
InputsAllowNull();
}
public IList Create(Flow flow)
{
var list = new AotList();
for (var i = 0; i < inputCount; i++)
{
list.Add(flow.GetValue<object>(multiInputs[i]));
}
return list;
}
}
}

View file

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

View file

@ -0,0 +1,53 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Gets the item at the specified index of a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Get Item")]
[UnitOrder(0)]
[TypeIcon(typeof(IList))]
public sealed class GetListItem : Unit
{
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput list { get; private set; }
/// <summary>
/// The zero-based index.
/// </summary>
[DoNotSerialize]
public ValueInput index { get; private set; }
/// <summary>
/// The item.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput item { get; private set; }
protected override void Definition()
{
list = ValueInput<IList>(nameof(list));
index = ValueInput(nameof(index), 0);
item = ValueOutput(nameof(item), Get);
Requirement(list, item);
Requirement(index, item);
}
public object Get(Flow flow)
{
var list = flow.GetValue<IList>(this.list);
var index = flow.GetValue<int>(this.index);
return list[index];
}
}
}

View file

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

View file

@ -0,0 +1,98 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Inserts an item in a list at a specified index.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Insert Item")]
[UnitOrder(3)]
[TypeIcon(typeof(AddListItem))]
public sealed class InsertListItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueInput listInput { get; private set; }
/// <summary>
/// The list with the added element.
/// Note that the input list is modified directly and then returned,
/// except if it is an array, in which case a new array with
/// the added element is returned instead.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueOutput listOutput { get; private set; }
/// <summary>
/// The zero-based index at which to insert the item.
/// </summary>
[DoNotSerialize]
public ValueInput index { get; private set; }
/// <summary>
/// The item to insert.
/// </summary>
[DoNotSerialize]
public ValueInput item { get; private set; }
/// <summary>
/// The action to execute once the item has been inserted.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Insert);
listInput = ValueInput<IList>(nameof(listInput));
item = ValueInput<object>(nameof(item));
index = ValueInput(nameof(index), 0);
listOutput = ValueOutput<IList>(nameof(listOutput));
exit = ControlOutput(nameof(exit));
Requirement(listInput, enter);
Requirement(item, enter);
Requirement(index, enter);
Assignment(enter, listOutput);
Succession(enter, exit);
}
public ControlOutput Insert(Flow flow)
{
var list = flow.GetValue<IList>(listInput);
var index = flow.GetValue<int>(this.index);
var item = flow.GetValue<object>(this.item);
if (list is Array)
{
var resizableList = new ArrayList(list);
resizableList.Insert(index, item);
flow.SetValue(listOutput, resizableList.ToArray(list.GetType().GetElementType()));
}
else
{
list.Insert(index, item);
flow.SetValue(listOutput, list);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,53 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Checks whether a list contains the specified item.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Contains Item")]
[TypeIcon(typeof(IList))]
public sealed class ListContainsItem : Unit
{
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput list { get; private set; }
/// <summary>
/// The item.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput item { get; private set; }
/// <summary>
/// Whether the list contains the item.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput contains { get; private set; }
protected override void Definition()
{
list = ValueInput<IList>(nameof(list));
item = ValueInput<object>(nameof(item));
contains = ValueOutput(nameof(contains), Contains);
Requirement(list, contains);
Requirement(item, contains);
}
public bool Contains(Flow flow)
{
var list = flow.GetValue<IList>(this.list);
var item = flow.GetValue<object>(this.item);
return list.Contains(item);
}
}
}

View file

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

View file

@ -0,0 +1,43 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Merges two or more lists together.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitOrder(7)]
public sealed class MergeLists : MultiInputUnit<IEnumerable>
{
/// <summary>
/// The merged list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput list { get; private set; }
protected override void Definition()
{
list = ValueOutput(nameof(list), Merge);
base.Definition();
foreach (var input in multiInputs)
{
Requirement(input, list);
}
}
public IList Merge(Flow flow)
{
var list = new AotList();
for (var i = 0; i < inputCount; i++)
{
list.AddRange(flow.GetValue<IEnumerable>(multiInputs[i]));
}
return list;
}
}
}

View file

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

View file

@ -0,0 +1,89 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Removes the specified item from a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Remove Item")]
[UnitOrder(4)]
public sealed class RemoveListItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueInput listInput { get; private set; }
/// <summary>
/// The list without the removed item.
/// Note that the input list is modified directly and then returned,
/// except if it is an array, in which case a new array without the item
/// is returned instead.
/// </summary>
[DoNotSerialize]
[PortLabel("List")]
[PortLabelHidden]
public ValueOutput listOutput { get; private set; }
/// <summary>
/// The item to remove.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput item { get; private set; }
/// <summary>
/// The action to execute once the item has been removed.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Remove);
listInput = ValueInput<IList>(nameof(listInput));
listOutput = ValueOutput<IList>(nameof(listOutput));
item = ValueInput<object>(nameof(item));
exit = ControlOutput(nameof(exit));
Requirement(listInput, enter);
Requirement(item, enter);
Assignment(enter, listOutput);
Succession(enter, exit);
}
public ControlOutput Remove(Flow flow)
{
var list = flow.GetValue<IList>(listInput);
var item = flow.GetValue<object>(this.item);
if (list is Array)
{
var resizableList = new ArrayList(list);
resizableList.Remove(item);
flow.SetValue(listOutput, resizableList.ToArray(list.GetType().GetElementType()));
}
else
{
list.Remove(item);
flow.SetValue(listOutput, list);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,87 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Removes the item at the specified index of a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Remove Item At Index")]
[UnitOrder(5)]
[TypeIcon(typeof(RemoveListItem))]
public sealed class RemoveListItemAt : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput listInput { get; private set; }
/// <summary>
/// The list without the removed item.
/// Note that the input list is modified directly and then returned,
/// except if it is an array, in which case a new array without the item
/// is returned instead.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput listOutput { get; private set; }
/// <summary>
/// The zero-based index.
/// </summary>
[DoNotSerialize]
public ValueInput index { get; private set; }
/// <summary>
/// The action to execute once the item has been removed.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), RemoveAt);
listInput = ValueInput<IList>(nameof(listInput));
listOutput = ValueOutput<IList>(nameof(listOutput));
index = ValueInput(nameof(index), 0);
exit = ControlOutput(nameof(exit));
Requirement(listInput, enter);
Requirement(index, enter);
Assignment(enter, listOutput);
Succession(enter, exit);
}
public ControlOutput RemoveAt(Flow flow)
{
var list = flow.GetValue<IList>(listInput);
var index = flow.GetValue<int>(this.index);
if (list is Array)
{
var resizableList = new ArrayList(list);
resizableList.RemoveAt(index);
flow.SetValue(listOutput, resizableList.ToArray(list.GetType().GetElementType()));
}
else
{
list.RemoveAt(index);
flow.SetValue(listOutput, list);
}
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,73 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Sets the item at the specified index of a list.
/// </summary>
[UnitCategory("Collections/Lists")]
[UnitSurtitle("List")]
[UnitShortTitle("Set Item")]
[UnitOrder(1)]
[TypeIcon(typeof(IList))]
public sealed class SetListItem : Unit
{
/// <summary>
/// The entry point for the node.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The list.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput list { get; private set; }
/// <summary>
/// The zero-based index.
/// </summary>
[DoNotSerialize]
public ValueInput index { get; private set; }
/// <summary>
/// The item.
/// </summary>
[DoNotSerialize]
public ValueInput item { get; private set; }
/// <summary>
/// The action to execute once the item has been assigned.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Set);
list = ValueInput<IList>(nameof(list));
index = ValueInput(nameof(index), 0);
item = ValueInput<object>(nameof(item));
exit = ControlOutput(nameof(exit));
Requirement(list, enter);
Requirement(index, enter);
Requirement(item, enter);
Succession(enter, exit);
}
public ControlOutput Set(Flow flow)
{
var list = flow.GetValue<IList>(this.list);
var index = flow.GetValue<int>(this.index);
var item = flow.GetValue<object>(this.item);
list[index] = item;
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 295db730a69ce4455861615708163352
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,30 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Stops the execution of the current loop.
/// </summary>
[UnitTitle("Break Loop")]
[UnitCategory("Control")]
[UnitOrder(13)]
public class Break : Unit
{
/// <summary>
/// The entry point for the break.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Operation);
}
public ControlOutput Operation(Flow flow)
{
flow.BreakLoop();
return null;
}
}
}

View file

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

View file

@ -0,0 +1,60 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Caches the input so that all nodes connected to the output
/// retrieve the value only once.
/// </summary>
[UnitCategory("Control")]
[UnitOrder(15)]
public sealed class Cache : Unit
{
/// <summary>
/// The moment at which to cache the value.
/// The output value will only get updated when this gets triggered.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The value to cache when the node is entered.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput input { get; private set; }
/// <summary>
/// The cached value, as it was the last time this node was entered.
/// </summary>
[DoNotSerialize]
[PortLabel("Cached")]
[PortLabelHidden]
public ValueOutput output { get; private set; }
/// <summary>
/// The action to execute once the value has been cached.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Store);
input = ValueInput<object>(nameof(input));
output = ValueOutput<object>(nameof(output));
exit = ControlOutput(nameof(exit));
Requirement(input, enter);
Assignment(enter, output);
Succession(enter, exit);
}
private ControlOutput Store(Flow flow)
{
flow.SetValue(output, flow.GetValue(input));
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,127 @@
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Loops between a first and last index at a specified step.
/// </summary>
[UnitTitle("For Loop")]
[UnitCategory("Control")]
[UnitOrder(9)]
public sealed class For : LoopUnit
{
/// <summary>
/// The index at which to start the loop (inclusive).
/// </summary>
[PortLabel("First")]
[DoNotSerialize]
public ValueInput firstIndex { get; private set; }
/// <summary>
/// The index at which to end the loop (exclusive).
/// </summary>
[PortLabel("Last")]
[DoNotSerialize]
public ValueInput lastIndex { get; private set; }
/// <summary>
/// The value by which the index will be incremented (or decremented, if negative) after each loop.
/// </summary>
[DoNotSerialize]
public ValueInput step { get; private set; }
/// <summary>
/// The current index of the loop.
/// </summary>
[PortLabel("Index")]
[DoNotSerialize]
public ValueOutput currentIndex { get; private set; }
protected override void Definition()
{
firstIndex = ValueInput(nameof(firstIndex), 0);
lastIndex = ValueInput(nameof(lastIndex), 10);
step = ValueInput(nameof(step), 1);
currentIndex = ValueOutput<int>(nameof(currentIndex));
base.Definition();
Requirement(firstIndex, enter);
Requirement(lastIndex, enter);
Requirement(step, enter);
Assignment(enter, currentIndex);
}
private int Start(Flow flow, out int currentIndex, out int lastIndex, out bool ascending)
{
var firstIndex = flow.GetValue<int>(this.firstIndex);
lastIndex = flow.GetValue<int>(this.lastIndex);
ascending = firstIndex <= lastIndex;
currentIndex = firstIndex;
flow.SetValue(this.currentIndex, currentIndex);
return flow.EnterLoop();
}
private bool CanMoveNext(int currentIndex, int lastIndex, bool ascending)
{
if (ascending)
{
return currentIndex < lastIndex;
}
else
{
return currentIndex > lastIndex;
}
}
private void MoveNext(Flow flow, ref int currentIndex)
{
currentIndex += flow.GetValue<int>(step);
flow.SetValue(this.currentIndex, currentIndex);
}
protected override ControlOutput Loop(Flow flow)
{
var loop = Start(flow, out int currentIndex, out int lastIndex, out bool ascending);
var stack = flow.PreserveStack();
while (flow.LoopIsNotBroken(loop) && CanMoveNext(currentIndex, lastIndex, ascending))
{
flow.Invoke(body);
flow.RestoreStack(stack);
MoveNext(flow, ref currentIndex);
}
flow.DisposePreservedStack(stack);
flow.ExitLoop(loop);
return exit;
}
protected override IEnumerator LoopCoroutine(Flow flow)
{
var loop = Start(flow, out int currentIndex, out int lastIndex, out bool ascending);
var stack = flow.PreserveStack();
while (flow.LoopIsNotBroken(loop) && CanMoveNext(currentIndex, lastIndex, ascending))
{
yield return body;
flow.RestoreStack(stack);
MoveNext(flow, ref currentIndex);
}
flow.DisposePreservedStack(stack);
flow.ExitLoop(loop);
yield return exit;
}
}
}

View file

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

View file

@ -0,0 +1,175 @@
using System;
using System.Collections;
namespace Unity.VisualScripting
{
/// <summary>
/// Loops over each element of a collection.
/// </summary>
[UnitTitle("For Each Loop")]
[UnitCategory("Control")]
[UnitOrder(10)]
public class ForEach : LoopUnit
{
/// <summary>
/// The collection over which to loop.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput collection { get; private set; }
/// <summary>
/// The current index of the loop.
/// </summary>
[DoNotSerialize]
[PortLabel("Index")]
public ValueOutput currentIndex { get; private set; }
/// <summary>
/// The key of the current item of the loop.
/// </summary>
[DoNotSerialize]
[PortLabel("Key")]
public ValueOutput currentKey { get; private set; }
/// <summary>
/// The current item of the loop.
/// </summary>
[DoNotSerialize]
[PortLabel("Item")]
public ValueOutput currentItem { get; private set; }
[Serialize]
[Inspectable, UnitHeaderInspectable("Dictionary")]
[InspectorToggleLeft]
public bool dictionary { get; set; }
protected override void Definition()
{
base.Definition();
if (dictionary)
{
collection = ValueInput<IDictionary>(nameof(collection));
}
else
{
collection = ValueInput<IEnumerable>(nameof(collection));
}
currentIndex = ValueOutput<int>(nameof(currentIndex));
if (dictionary)
{
currentKey = ValueOutput<object>(nameof(currentKey));
}
currentItem = ValueOutput<object>(nameof(currentItem));
Requirement(collection, enter);
Assignment(enter, currentIndex);
Assignment(enter, currentItem);
if (dictionary)
{
Assignment(enter, currentKey);
}
}
private int Start(Flow flow, out IEnumerator enumerator, out IDictionaryEnumerator dictionaryEnumerator, out int currentIndex)
{
if (dictionary)
{
dictionaryEnumerator = flow.GetValue<IDictionary>(collection).GetEnumerator();
enumerator = dictionaryEnumerator;
}
else
{
enumerator = flow.GetValue<IEnumerable>(collection).GetEnumerator();
dictionaryEnumerator = null;
}
currentIndex = -1;
return flow.EnterLoop();
}
private bool MoveNext(Flow flow, IEnumerator enumerator, IDictionaryEnumerator dictionaryEnumerator, ref int currentIndex)
{
var result = enumerator.MoveNext();
if (result)
{
if (dictionary)
{
flow.SetValue(currentKey, dictionaryEnumerator.Key);
flow.SetValue(currentItem, dictionaryEnumerator.Value);
}
else
{
flow.SetValue(currentItem, enumerator.Current);
}
currentIndex++;
flow.SetValue(this.currentIndex, currentIndex);
}
return result;
}
protected override ControlOutput Loop(Flow flow)
{
var loop = Start(flow, out var enumerator, out var dictionaryEnumerator, out var currentIndex);
var stack = flow.PreserveStack();
try
{
while (flow.LoopIsNotBroken(loop) && MoveNext(flow, enumerator, dictionaryEnumerator, ref currentIndex))
{
flow.Invoke(body);
flow.RestoreStack(stack);
}
}
finally
{
(enumerator as IDisposable)?.Dispose();
}
flow.DisposePreservedStack(stack);
flow.ExitLoop(loop);
return exit;
}
protected override IEnumerator LoopCoroutine(Flow flow)
{
var loop = Start(flow, out var enumerator, out var dictionaryEnumerator, out var currentIndex);
var stack = flow.PreserveStack();
try
{
while (flow.LoopIsNotBroken(loop) && MoveNext(flow, enumerator, dictionaryEnumerator, ref currentIndex))
{
yield return body;
flow.RestoreStack(stack);
}
}
finally
{
(enumerator as IDisposable)?.Dispose();
}
flow.DisposePreservedStack(stack);
flow.ExitLoop(loop);
yield return exit;
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[TypeIconPriority]
public interface IBranchUnit : IUnit
{
ControlInput enter { get; }
}
}

View file

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

View file

@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[TypeIconPriority]
public interface ISelectUnit : IUnit
{
ValueOutput selection { get; }
}
}

View file

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

View file

@ -0,0 +1,57 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Branches flow by checking if a condition is true or false.
/// </summary>
[UnitCategory("Control")]
[UnitOrder(0)]
[RenamedFrom("Bolt.Branch")]
[RenamedFrom("Unity.VisualScripting.Branch")]
public sealed class If : Unit, IBranchUnit
{
/// <summary>
/// The entry point for the branch.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The condition to check.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput condition { get; private set; }
/// <summary>
/// The action to execute if the condition is true.
/// </summary>
[DoNotSerialize]
[PortLabel("True")]
public ControlOutput ifTrue { get; private set; }
/// <summary>
/// The action to execute if the condition is false.
/// </summary>
[DoNotSerialize]
[PortLabel("False")]
public ControlOutput ifFalse { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Enter);
condition = ValueInput<bool>(nameof(condition));
ifTrue = ControlOutput(nameof(ifTrue));
ifFalse = ControlOutput(nameof(ifFalse));
Requirement(condition, enter);
Succession(enter, ifTrue);
Succession(enter, ifFalse);
}
public ControlOutput Enter(Flow flow)
{
return flow.GetValue<bool>(condition) ? ifTrue : ifFalse;
}
}
}

View file

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

View file

@ -0,0 +1,40 @@
using System.Collections;
namespace Unity.VisualScripting
{
public abstract class LoopUnit : Unit
{
/// <summary>
/// The entry point for the loop.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The action to execute after the loop has been completed or broken.
/// </summary>
[DoNotSerialize]
public ControlOutput exit { get; private set; }
/// <summary>
/// The action to execute at each loop.
/// </summary>
[DoNotSerialize]
public ControlOutput body { get; private set; }
protected override void Definition()
{
enter = ControlInputCoroutine(nameof(enter), Loop, LoopCoroutine);
exit = ControlOutput(nameof(exit));
body = ControlOutput(nameof(body));
Succession(enter, body);
Succession(enter, exit);
}
protected abstract ControlOutput Loop(Flow flow);
protected abstract IEnumerator LoopCoroutine(Flow flow);
}
}

View file

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

View file

@ -0,0 +1,79 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Executes an action only once, and a different action afterwards.
/// </summary>
[UnitCategory("Control")]
[UnitOrder(14)]
public sealed class Once : Unit, IGraphElementWithData
{
public sealed class Data : IGraphElementData
{
public bool executed;
}
/// <summary>
/// The entry point for the action.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// Trigger to reset the once check.
/// </summary>
[DoNotSerialize]
public ControlInput reset { get; private set; }
/// <summary>
/// The action to execute the first time the unit is entered.
/// </summary>
[DoNotSerialize]
public ControlOutput once { get; private set; }
/// <summary>
/// The action to execute subsequently.
/// </summary>
[DoNotSerialize]
public ControlOutput after { get; private set; }
protected override void Definition()
{
enter = ControlInput(nameof(enter), Enter);
reset = ControlInput(nameof(reset), Reset);
once = ControlOutput(nameof(once));
after = ControlOutput(nameof(after));
Succession(enter, once);
Succession(enter, after);
}
public IGraphElementData CreateData()
{
return new Data();
}
public ControlOutput Enter(Flow flow)
{
var data = flow.stack.GetElementData<Data>(this);
if (!data.executed)
{
data.executed = true;
return once;
}
else
{
return after;
}
}
public ControlOutput Reset(Flow flow)
{
flow.stack.GetElementData<Data>(this).executed = false;
return null;
}
}
}

View file

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

View file

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
/// <summary>
/// Selects a value from a set by switching over an enum.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Select On Enum")]
[UnitShortTitle("Select")]
[UnitSubtitle("On Enum")]
[UnitOrder(7)]
[TypeIcon(typeof(ISelectUnit))]
public sealed class SelectOnEnum : Unit, ISelectUnit
{
[DoNotSerialize]
public Dictionary<object, ValueInput> branches { get; private set; }
/// <summary>
/// The value on which to select.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput selector { get; private set; }
/// <summary>
/// The selected value.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput selection { get; private set; }
[Serialize]
[Inspectable, UnitHeaderInspectable]
[TypeFilter(Enums = true, Classes = false, Interfaces = false, Structs = false, Primitives = false)]
public Type enumType { get; set; }
public override bool canDefine => enumType != null && enumType.IsEnum;
protected override void Definition()
{
branches = new Dictionary<object, ValueInput>();
selection = ValueOutput(nameof(selection), Branch).Predictable();
selector = ValueInput(enumType, nameof(selector));
Requirement(selector, selection);
foreach (var valueByName in EnumUtility.ValuesByNames(enumType))
{
var enumValue = valueByName.Value;
if (branches.ContainsKey(enumValue))
continue;
var branch = ValueInput<object>("%" + valueByName.Key).AllowsNull();
branches.Add(enumValue, branch);
Requirement(branch, selection);
}
}
public object Branch(Flow flow)
{
var selector = flow.GetValue(this.selector, enumType);
return flow.GetValue(branches[selector]);
}
}
}

View file

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

View file

@ -0,0 +1,72 @@
using System.Collections.Generic;
using UnityEngine;
namespace Unity.VisualScripting
{
/// <summary>
/// Selects a value from a set by matching it with an input flow.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Select On Flow")]
[UnitShortTitle("Select")]
[UnitSubtitle("On Flow")]
[UnitOrder(8)]
[TypeIcon(typeof(ISelectUnit))]
public sealed class SelectOnFlow : Unit, ISelectUnit
{
[SerializeAs(nameof(branchCount))]
private int _branchCount = 2;
[DoNotSerialize]
[Inspectable, UnitHeaderInspectable("Branches")]
public int branchCount
{
get => _branchCount;
set => _branchCount = Mathf.Clamp(value, 2, 10);
}
[DoNotSerialize]
public Dictionary<ControlInput, ValueInput> branches { get; private set; }
/// <summary>
/// Triggered when any selector is entered.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput exit { get; private set; }
/// <summary>
/// The selected value.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput selection { get; private set; }
protected override void Definition()
{
branches = new Dictionary<ControlInput, ValueInput>();
selection = ValueOutput<object>(nameof(selection));
exit = ControlOutput(nameof(exit));
for (int i = 0; i < branchCount; i++)
{
var branchValue = ValueInput<object>("value_" + i);
var branchControl = ControlInput("enter_" + i, (flow) => Select(flow, branchValue));
Requirement(branchValue, branchControl);
Assignment(branchControl, selection);
Succession(branchControl, exit);
branches.Add(branchControl, branchValue);
}
}
public ControlOutput Select(Flow flow, ValueInput branchValue)
{
flow.SetValue(selection, flow.GetValue(branchValue));
return exit;
}
}
}

View file

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

View file

@ -0,0 +1,14 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Selects a value from a set by switching over an integer.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Select On Integer")]
[UnitShortTitle("Select")]
[UnitSubtitle("On Integer")]
[UnitOrder(8)]
public class SelectOnInteger : SelectUnit<int>
{
}
}

View file

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

View file

@ -0,0 +1,30 @@
using System;
namespace Unity.VisualScripting
{
/// <summary>
/// Selects a value from a set by switching over a string.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Select On String")]
[UnitShortTitle("Select")]
[UnitSubtitle("On String")]
[UnitOrder(7)]
public class SelectOnString : SelectUnit<string>
{
[Serialize]
[Inspectable, UnitHeaderInspectable("Ignore Case")]
[InspectorToggleLeft]
public bool ignoreCase { get; set; }
protected override bool Matches(string a, string b)
{
if (string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b))
{
return true;
}
return string.Equals(a, b, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}
}
}

View file

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

View file

@ -0,0 +1,57 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Selects a value from a set by checking if a condition is true or false.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Select")]
[TypeIcon(typeof(ISelectUnit))]
[UnitOrder(6)]
public sealed class SelectUnit : Unit, ISelectUnit
{
/// <summary>
/// The condition to check.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput condition { get; private set; }
/// <summary>
/// The value to return if the condition is true.
/// </summary>
[DoNotSerialize]
[PortLabel("True")]
public ValueInput ifTrue { get; private set; }
/// <summary>
/// The value to return if the condition is false.
/// </summary>
[DoNotSerialize]
[PortLabel("False")]
public ValueInput ifFalse { get; private set; }
/// <summary>
/// The returned value.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput selection { get; private set; }
protected override void Definition()
{
condition = ValueInput<bool>(nameof(condition));
ifTrue = ValueInput<object>(nameof(ifTrue)).AllowsNull();
ifFalse = ValueInput<object>(nameof(ifFalse)).AllowsNull();
selection = ValueOutput(nameof(selection), Branch).Predictable();
Requirement(condition, selection);
Requirement(ifTrue, selection);
Requirement(ifFalse, selection);
}
public object Branch(Flow flow)
{
return flow.GetValue(flow.GetValue<bool>(condition) ? ifTrue : ifFalse);
}
}
}

View file

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

View file

@ -0,0 +1,84 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
[TypeIcon(typeof(ISelectUnit))]
public abstract class SelectUnit<T> : Unit, ISelectUnit
{
// Using L<KVP> instead of Dictionary to allow null key
[DoNotSerialize]
public List<KeyValuePair<T, ValueInput>> branches { get; private set; }
[Inspectable, Serialize]
public List<T> options { get; set; } = new List<T>();
/// <summary>
/// The value on which to select.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput selector { get; private set; }
/// <summary>
/// The output value to return if the selector doesn't match any other option.
/// </summary>
[DoNotSerialize]
public ValueInput @default { get; private set; }
/// <summary>
/// The selected value.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueOutput selection { get; private set; }
public override bool canDefine => options != null;
protected override void Definition()
{
selection = ValueOutput(nameof(selection), Result).Predictable();
selector = ValueInput<T>(nameof(selector));
Requirement(selector, selection);
branches = new List<KeyValuePair<T, ValueInput>>();
foreach (var option in options)
{
var key = "%" + option;
if (!valueInputs.Contains(key))
{
var branch = ValueInput<object>(key).AllowsNull();
branches.Add(new KeyValuePair<T, ValueInput>(option, branch));
Requirement(branch, selection);
}
}
@default = ValueInput<object>(nameof(@default));
Requirement(@default, selection);
}
protected virtual bool Matches(T a, T b)
{
return Equals(a, b);
}
public object Result(Flow flow)
{
var selector = flow.GetValue<T>(this.selector);
foreach (var branch in branches)
{
if (Matches(branch.Key, selector))
{
return flow.GetValue(branch.Value);
}
}
return flow.GetValue(@default);
}
}
}

View file

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

View file

@ -0,0 +1,90 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEngine;
namespace Unity.VisualScripting
{
/// <summary>
/// Executes the output ports in order.
/// </summary>
[UnitCategory("Control")]
[UnitOrder(13)]
public sealed class Sequence : Unit
{
[SerializeAs(nameof(outputCount))]
private int _outputCount = 2;
/// <summary>
/// The entry point for the sequence.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
[DoNotSerialize]
[Inspectable, InspectorLabel("Steps"), UnitHeaderInspectable("Steps")]
public int outputCount
{
get => _outputCount;
set => _outputCount = Mathf.Clamp(value, 1, 10);
}
[DoNotSerialize]
public ReadOnlyCollection<ControlOutput> multiOutputs { get; private set; }
protected override void Definition()
{
enter = ControlInputCoroutine(nameof(enter), Enter, EnterCoroutine);
var _multiOutputs = new List<ControlOutput>();
multiOutputs = _multiOutputs.AsReadOnly();
for (var i = 0; i < outputCount; i++)
{
var output = ControlOutput(i.ToString());
Succession(enter, output);
_multiOutputs.Add(output);
}
}
private ControlOutput Enter(Flow flow)
{
var stack = flow.PreserveStack();
foreach (var output in multiOutputs)
{
flow.Invoke(output);
flow.RestoreStack(stack);
}
flow.DisposePreservedStack(stack);
return null;
}
private IEnumerator EnterCoroutine(Flow flow)
{
var stack = flow.PreserveStack();
foreach (var output in multiOutputs)
{
yield return output;
flow.RestoreStack(stack);
}
flow.DisposePreservedStack(stack);
}
public void CopyFrom(Sequence source)
{
base.CopyFrom(source);
outputCount = source.outputCount;
}
}
}

View file

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

View file

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
/// <summary>
/// Branches flow by switching over an enum.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Switch On Enum")]
[UnitShortTitle("Switch")]
[UnitSubtitle("On Enum")]
[UnitOrder(3)]
[TypeIcon(typeof(IBranchUnit))]
public sealed class SwitchOnEnum : Unit, IBranchUnit
{
[DoNotSerialize]
public Dictionary<Enum, ControlOutput> branches { get; private set; }
[Serialize]
[Inspectable, UnitHeaderInspectable]
[TypeFilter(Enums = true, Classes = false, Interfaces = false, Structs = false, Primitives = false)]
public Type enumType { get; set; }
/// <summary>
/// The entry point for the switch.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The enum value on which to switch.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput @enum { get; private set; }
public override bool canDefine => enumType != null && enumType.IsEnum;
protected override void Definition()
{
branches = new Dictionary<Enum, ControlOutput>();
enter = ControlInput(nameof(enter), Enter);
@enum = ValueInput(enumType, nameof(@enum));
Requirement(@enum, enter);
foreach (var valueByName in EnumUtility.ValuesByNames(enumType))
{
var enumName = valueByName.Key;
var enumValue = valueByName.Value;
// Just like in C#, duplicate switch labels for the same underlying value is prohibited
if (!branches.ContainsKey(enumValue))
{
var branch = ControlOutput("%" + enumName);
branches.Add(enumValue, branch);
Succession(enter, branch);
}
}
}
public ControlOutput Enter(Flow flow)
{
var @enum = (Enum)flow.GetValue(this.@enum, enumType);
if (branches.ContainsKey(@enum))
{
return branches[@enum];
}
else
{
return null;
}
}
}
}

View file

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

View file

@ -0,0 +1,14 @@
namespace Unity.VisualScripting
{
/// <summary>
/// Branches flow by switching over an integer.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Switch On Integer")]
[UnitShortTitle("Switch")]
[UnitSubtitle("On Integer")]
[UnitOrder(5)]
public class SwitchOnInteger : SwitchUnit<int>
{
}
}

View file

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

View file

@ -0,0 +1,30 @@
using System;
namespace Unity.VisualScripting
{
/// <summary>
/// Branches flow by switching over a string.
/// </summary>
[UnitCategory("Control")]
[UnitTitle("Switch On String")]
[UnitShortTitle("Switch")]
[UnitSubtitle("On String")]
[UnitOrder(4)]
public class SwitchOnString : SwitchUnit<string>
{
[Serialize]
[Inspectable, UnitHeaderInspectable("Ignore Case")]
[InspectorToggleLeft]
public bool ignoreCase { get; set; }
protected override bool Matches(string a, string b)
{
if (string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b))
{
return true;
}
return string.Equals(a, b, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}
}
}

View file

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

View file

@ -0,0 +1,83 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
[TypeIcon(typeof(IBranchUnit))]
public abstract class SwitchUnit<T> : Unit, IBranchUnit
{
// Using L<KVP> instead of Dictionary to allow null key
[DoNotSerialize]
public List<KeyValuePair<T, ControlOutput>> branches { get; private set; }
[Inspectable, Serialize]
public List<T> options { get; set; } = new List<T>();
/// <summary>
/// The entry point for the switch.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The value on which to switch.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ValueInput selector { get; private set; }
/// <summary>
/// The branch to take if the input value does not match any other option.
/// </summary>
[DoNotSerialize]
public ControlOutput @default { get; private set; }
public override bool canDefine => options != null;
protected override void Definition()
{
enter = ControlInput(nameof(enter), Enter);
selector = ValueInput<T>(nameof(selector));
Requirement(selector, enter);
branches = new List<KeyValuePair<T, ControlOutput>>();
foreach (var option in options)
{
var key = "%" + option;
if (!controlOutputs.Contains(key))
{
var branch = ControlOutput(key);
branches.Add(new KeyValuePair<T, ControlOutput>(option, branch));
Succession(enter, branch);
}
}
@default = ControlOutput(nameof(@default));
Succession(enter, @default);
}
protected virtual bool Matches(T a, T b)
{
return Equals(a, b);
}
public ControlOutput Enter(Flow flow)
{
var selector = flow.GetValue<T>(this.selector);
foreach (var branch in branches)
{
if (Matches(branch.Key, selector))
{
return branch.Value;
}
}
return @default;
}
}
}

View file

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

View file

@ -0,0 +1,65 @@
using System;
namespace Unity.VisualScripting
{
/// <summary>
/// Throws an exception.
/// </summary>
[UnitCategory("Control")]
[UnitOrder(16)]
public sealed class Throw : Unit
{
/// <summary>
/// Whether a custom exception object should be specified manually.
/// </summary>
[Serialize]
[Inspectable, UnitHeaderInspectable("Custom")]
[InspectorToggleLeft]
public bool custom { get; set; }
/// <summary>
/// The entry point to throw the exception.
/// </summary>
[DoNotSerialize]
[PortLabelHidden]
public ControlInput enter { get; private set; }
/// <summary>
/// The message of the exception.
/// </summary>
[DoNotSerialize]
public ValueInput message { get; private set; }
/// <summary>
/// The exception to throw.
/// </summary>
[DoNotSerialize]
public ValueInput exception { get; private set; }
protected override void Definition()
{
if (custom)
{
enter = ControlInput(nameof(enter), ThrowCustom);
exception = ValueInput<Exception>(nameof(exception));
Requirement(exception, enter);
}
else
{
enter = ControlInput(nameof(enter), ThrowMessage);
message = ValueInput(nameof(message), string.Empty);
Requirement(message, enter);
}
}
private ControlOutput ThrowCustom(Flow flow)
{
throw flow.GetValue<Exception>(exception);
}
private ControlOutput ThrowMessage(Flow flow)
{
throw new Exception(flow.GetValue<string>(message));
}
}
}

Some files were not shown because too many files have changed in this diff Show more