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,139 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public sealed class ControlInput : UnitPort<ControlOutput, IUnitOutputPort, ControlConnection>, IUnitControlPort, IUnitInputPort
{
public ControlInput(string key, Func<Flow, ControlOutput> action) : base(key)
{
Ensure.That(nameof(action)).IsNotNull(action);
this.action = action;
}
public ControlInput(string key, Func<Flow, IEnumerator> coroutineAction) : base(key)
{
Ensure.That(nameof(coroutineAction)).IsNotNull(coroutineAction);
this.coroutineAction = coroutineAction;
}
public ControlInput(string key, Func<Flow, ControlOutput> action, Func<Flow, IEnumerator> coroutineAction) : base(key)
{
Ensure.That(nameof(action)).IsNotNull(action);
Ensure.That(nameof(coroutineAction)).IsNotNull(coroutineAction);
this.action = action;
this.coroutineAction = coroutineAction;
}
public bool supportsCoroutine => coroutineAction != null;
public bool requiresCoroutine => action == null;
internal readonly Func<Flow, ControlOutput> action;
internal readonly Func<Flow, IEnumerator> coroutineAction;
public override IEnumerable<ControlConnection> validConnections => unit?.graph?.controlConnections.WithDestination(this) ?? Enumerable.Empty<ControlConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => unit?.graph?.invalidConnections.WithDestination(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<ControlOutput> validConnectedPorts => validConnections.Select(c => c.source);
public override IEnumerable<IUnitOutputPort> invalidConnectedPorts => invalidConnections.Select(c => c.source);
public bool isPredictable
{
get
{
using (var recursion = Recursion.New(1))
{
return IsPredictable(recursion);
}
}
}
public bool IsPredictable(Recursion recursion)
{
if (!hasValidConnection)
{
return true;
}
if (!recursion?.TryEnter(this) ?? false)
{
return false;
}
var isPredictable = validConnectedPorts.All(cop => cop.IsPredictable(recursion));
recursion?.Exit(this);
return isPredictable;
}
public bool couldBeEntered
{
get
{
if (!isPredictable)
{
throw new NotSupportedException();
}
if (!hasValidConnection)
{
return false;
}
return validConnectedPorts.Any(cop => cop.couldBeEntered);
}
}
public override bool CanConnectToValid(ControlOutput port)
{
return true;
}
public override void ConnectToValid(ControlOutput port)
{
var source = port;
var destination = this;
source.Disconnect();
unit.graph.controlConnections.Add(new ControlConnection(source, destination));
}
public override void ConnectToInvalid(IUnitOutputPort port)
{
ConnectInvalid(port, this);
}
public override void DisconnectFromValid(ControlOutput port)
{
var connection = validConnections.SingleOrDefault(c => c.source == port);
if (connection != null)
{
unit.graph.controlConnections.Remove(connection);
}
}
public override void DisconnectFromInvalid(IUnitOutputPort port)
{
DisconnectInvalid(port, this);
}
public override IUnitPort CompatiblePort(IUnit unit)
{
if (unit == this.unit) return null;
return unit.controlOutputs.FirstOrDefault();
}
}
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public sealed class ControlInputDefinition : ControlPortDefinition, IUnitInputPortDefinition { }
}

View file

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

View file

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public sealed class ControlOutput : UnitPort<ControlInput, IUnitInputPort, ControlConnection>, IUnitControlPort, IUnitOutputPort
{
public ControlOutput(string key) : base(key) { }
public override IEnumerable<ControlConnection> validConnections => unit?.graph?.controlConnections.WithSource(this) ?? Enumerable.Empty<ControlConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => unit?.graph?.invalidConnections.WithSource(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<ControlInput> validConnectedPorts => validConnections.Select(c => c.destination);
public override IEnumerable<IUnitInputPort> invalidConnectedPorts => invalidConnections.Select(c => c.destination);
public bool isPredictable
{
get
{
using (var recursion = Recursion.New(1))
{
return IsPredictable(recursion);
}
}
}
public bool IsPredictable(Recursion recursion)
{
if (unit.isControlRoot)
{
return true;
}
if (!recursion?.TryEnter(this) ?? false)
{
return false;
}
var isPredictable = unit.relations.WithDestination(this).Where(r => r.source is ControlInput).All(r => ((ControlInput)r.source).IsPredictable(recursion));
recursion?.Exit(this);
return isPredictable;
}
public bool couldBeEntered
{
get
{
if (!isPredictable)
{
throw new NotSupportedException();
}
if (unit.isControlRoot)
{
return true;
}
return unit.relations.WithDestination(this).Where(r => r.source is ControlInput).Any(r => ((ControlInput)r.source).couldBeEntered);
}
}
public ControlConnection connection => unit.graph?.controlConnections.SingleOrDefaultWithSource(this);
public override bool hasValidConnection => connection != null;
public override bool CanConnectToValid(ControlInput port)
{
return true;
}
public override void ConnectToValid(ControlInput port)
{
var source = this;
var destination = port;
source.Disconnect();
unit.graph.controlConnections.Add(new ControlConnection(source, destination));
}
public override void ConnectToInvalid(IUnitInputPort port)
{
ConnectInvalid(this, port);
}
public override void DisconnectFromValid(ControlInput port)
{
var connection = validConnections.SingleOrDefault(c => c.destination == port);
if (connection != null)
{
unit.graph.controlConnections.Remove(connection);
}
}
public override void DisconnectFromInvalid(IUnitInputPort port)
{
DisconnectInvalid(this, port);
}
public override IUnitPort CompatiblePort(IUnit unit)
{
if (unit == this.unit) return null;
return unit.controlInputs.FirstOrDefault();
}
}
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public sealed class ControlOutputDefinition : ControlPortDefinition, IUnitOutputPortDefinition { }
}

View file

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

View file

@ -0,0 +1,5 @@
namespace Unity.VisualScripting
{
public abstract class ControlPortDefinition : UnitPortDefinition, IUnitControlPortDefinition
{ }
}

View file

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

View file

@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
public interface IUnitControlPort : IUnitPort
{
bool isPredictable { get; }
bool couldBeEntered { get; }
}
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface IUnitControlPortDefinition : IUnitPortDefinition { }
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface IUnitInputPort : IUnitPort { }
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface IUnitInputPortDefinition : IUnitPortDefinition { }
}

View file

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

View file

@ -0,0 +1,6 @@
namespace Unity.VisualScripting
{
public interface IUnitInvalidPort : IUnitPort
{
}
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface IUnitOutputPort : IUnitPort { }
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface IUnitOutputPortDefinition : IUnitPortDefinition { }
}

View file

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

View file

@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public interface IUnitPort : IGraphItem
{
IUnit unit { get; set; }
string key { get; }
IEnumerable<IUnitRelation> relations { get; }
IEnumerable<IUnitConnection> validConnections { get; }
IEnumerable<InvalidConnection> invalidConnections { get; }
IEnumerable<IUnitConnection> connections { get; }
IEnumerable<IUnitPort> connectedPorts { get; }
bool hasAnyConnection { get; }
bool hasValidConnection { get; }
bool hasInvalidConnection { get; }
bool CanInvalidlyConnectTo(IUnitPort port);
bool CanValidlyConnectTo(IUnitPort port);
void InvalidlyConnectTo(IUnitPort port);
void ValidlyConnectTo(IUnitPort port);
void Disconnect();
IUnitPort CompatiblePort(IUnit unit);
}
}

View file

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

View file

@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public interface IUnitPortCollection<TPort> : IKeyedCollection<string, TPort> where TPort : IUnitPort
{
TPort Single();
}
}

View file

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

View file

@ -0,0 +1,11 @@
namespace Unity.VisualScripting
{
public interface IUnitPortDefinition
{
string key { get; }
string label { get; }
string summary { get; }
bool hideLabel { get; }
bool isValid { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3152f3cff03649cab0bcea198d5bf3d
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 IUnitValuePort : IUnitPort
{
Type type { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5d3f06806b31e482b9cf45fc97d29fcb
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 IUnitValuePortDefinition : IUnitPortDefinition
{
Type type { get; }
}
}

View file

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

View file

@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public sealed class InvalidInput : UnitPort<IUnitOutputPort, IUnitOutputPort, InvalidConnection>, IUnitInvalidPort, IUnitInputPort
{
public InvalidInput(string key) : base(key) { }
public override IEnumerable<InvalidConnection> validConnections => unit?.graph?.invalidConnections.WithDestination(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => Enumerable.Empty<InvalidConnection>();
public override IEnumerable<IUnitOutputPort> validConnectedPorts => validConnections.Select(c => c.source);
public override IEnumerable<IUnitOutputPort> invalidConnectedPorts => invalidConnections.Select(c => c.source);
public override bool CanConnectToValid(IUnitOutputPort port)
{
return false;
}
public override void ConnectToValid(IUnitOutputPort port)
{
ConnectInvalid(port, this);
}
public override void ConnectToInvalid(IUnitOutputPort port)
{
ConnectInvalid(port, this);
}
public override void DisconnectFromValid(IUnitOutputPort port)
{
DisconnectInvalid(port, this);
}
public override void DisconnectFromInvalid(IUnitOutputPort port)
{
DisconnectInvalid(port, this);
}
public override IUnitPort CompatiblePort(IUnit unit)
{
return null;
}
}
}

View file

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

View file

@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public sealed class InvalidOutput : UnitPort<IUnitInputPort, IUnitInputPort, InvalidConnection>, IUnitInvalidPort, IUnitOutputPort
{
public InvalidOutput(string key) : base(key) { }
public override IEnumerable<InvalidConnection> validConnections => unit?.graph?.invalidConnections.WithSource(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => Enumerable.Empty<InvalidConnection>();
public override IEnumerable<IUnitInputPort> validConnectedPorts => validConnections.Select(c => c.destination);
public override IEnumerable<IUnitInputPort> invalidConnectedPorts => invalidConnections.Select(c => c.destination);
public override bool CanConnectToValid(IUnitInputPort port)
{
return false;
}
public override void ConnectToValid(IUnitInputPort port)
{
ConnectInvalid(this, port);
}
public override void ConnectToInvalid(IUnitInputPort port)
{
ConnectInvalid(this, port);
}
public override void DisconnectFromValid(IUnitInputPort port)
{
DisconnectInvalid(this, port);
}
public override void DisconnectFromInvalid(IUnitInputPort port)
{
DisconnectInvalid(this, port);
}
public override IUnitPort CompatiblePort(IUnit unit)
{
return null;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29dddc44cbcf54a8ea0ac623012344c1
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 sealed class MissingValuePortInputException : Exception
{
public MissingValuePortInputException(string key) : base($"Missing input value for '{key}'.") { }
}
}

View file

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

View file

@ -0,0 +1,148 @@
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public abstract class UnitPort<TValidOther, TInvalidOther, TExternalConnection> : IUnitPort
where TValidOther : IUnitPort
where TInvalidOther : IUnitPort
where TExternalConnection : IUnitConnection
{
protected UnitPort(string key)
{
Ensure.That(nameof(key)).IsNotNull(key);
this.key = key;
}
public IUnit unit { get; set; }
public string key { get; }
public IGraph graph => unit?.graph;
public IEnumerable<IUnitRelation> relations =>
LinqUtility.Concat<IUnitRelation>(unit.relations.WithSource(this),
unit.relations.WithDestination(this)).Distinct();
public abstract IEnumerable<TExternalConnection> validConnections { get; }
public abstract IEnumerable<InvalidConnection> invalidConnections { get; }
public abstract IEnumerable<TValidOther> validConnectedPorts { get; }
public abstract IEnumerable<TInvalidOther> invalidConnectedPorts { get; }
IEnumerable<IUnitConnection> IUnitPort.validConnections => validConnections.Cast<IUnitConnection>();
public IEnumerable<IUnitConnection> connections => LinqUtility.Concat<IUnitConnection>(validConnections, invalidConnections);
public IEnumerable<IUnitPort> connectedPorts => LinqUtility.Concat<IUnitPort>(validConnectedPorts, invalidConnectedPorts);
public bool hasAnyConnection => hasValidConnection || hasInvalidConnection;
// Allow for more efficient overrides
public virtual bool hasValidConnection => validConnections.Any();
public virtual bool hasInvalidConnection => invalidConnections.Any();
private bool CanConnectTo(IUnitPort port)
{
Ensure.That(nameof(port)).IsNotNull(port);
return unit != null && // We belong to a unit
port.unit != null && // Port belongs to a unit
port.unit != unit && // that is different than the current one
port.unit.graph == unit.graph; // but is on the same graph.
}
public bool CanValidlyConnectTo(IUnitPort port)
{
return CanConnectTo(port) && port is TValidOther && CanConnectToValid((TValidOther)port);
}
public bool CanInvalidlyConnectTo(IUnitPort port)
{
return CanConnectTo(port) && port is TInvalidOther && CanConnectToInvalid((TInvalidOther)port);
}
public void ValidlyConnectTo(IUnitPort port)
{
Ensure.That(nameof(port)).IsNotNull(port);
if (!(port is TValidOther))
{
throw new InvalidConnectionException();
}
ConnectToValid((TValidOther)port);
}
public void InvalidlyConnectTo(IUnitPort port)
{
Ensure.That(nameof(port)).IsNotNull(port);
if (!(port is TInvalidOther))
{
throw new InvalidConnectionException();
}
ConnectToInvalid((TInvalidOther)port);
}
public void Disconnect()
{
while (validConnectedPorts.Any())
{
DisconnectFromValid(validConnectedPorts.First());
}
while (invalidConnectedPorts.Any())
{
DisconnectFromInvalid(invalidConnectedPorts.First());
}
}
public abstract bool CanConnectToValid(TValidOther port);
public bool CanConnectToInvalid(TInvalidOther port)
{
return true;
}
public abstract void ConnectToValid(TValidOther port);
public abstract void ConnectToInvalid(TInvalidOther port);
public abstract void DisconnectFromValid(TValidOther port);
public abstract void DisconnectFromInvalid(TInvalidOther port);
public abstract IUnitPort CompatiblePort(IUnit unit);
protected void ConnectInvalid(IUnitOutputPort source, IUnitInputPort destination)
{
var connection = unit.graph.invalidConnections.SingleOrDefault(c => c.source == source && c.destination == destination);
if (connection != null)
{
return;
}
unit.graph.invalidConnections.Add(new InvalidConnection(source, destination));
}
protected void DisconnectInvalid(IUnitOutputPort source, IUnitInputPort destination)
{
var connection = unit.graph.invalidConnections.SingleOrDefault(c => c.source == source && c.destination == destination);
if (connection == null)
{
return;
}
unit.graph.invalidConnections.Remove(connection);
}
}
}

View file

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

View file

@ -0,0 +1,102 @@
using System;
using System.Collections.ObjectModel;
namespace Unity.VisualScripting
{
public sealed class UnitPortCollection<TPort> : KeyedCollection<string, TPort>, IUnitPortCollection<TPort>
where TPort : IUnitPort
{
public IUnit unit { get; }
public UnitPortCollection(IUnit unit)
{
this.unit = unit;
}
private void BeforeAdd(TPort port)
{
if (port.unit != null)
{
if (port.unit == unit)
{
throw new InvalidOperationException("Unit ports cannot be added multiple time to the same unit.");
}
else
{
throw new InvalidOperationException("Unit ports cannot be shared across units.");
}
}
port.unit = unit;
}
private void AfterAdd(TPort port)
{
unit.PortsChanged();
}
private void BeforeRemove(TPort port)
{
}
private void AfterRemove(TPort port)
{
port.unit = null;
unit.PortsChanged();
}
public TPort Single()
{
if (Count != 0)
{
throw new InvalidOperationException("Port collection does not have a single port.");
}
return this[0];
}
protected override string GetKeyForItem(TPort item)
{
return item.key;
}
public bool TryGetValue(string key, out TPort value)
{
if (Dictionary == null)
{
value = default(TPort);
return false;
}
return Dictionary.TryGetValue(key, out value);
}
protected override void InsertItem(int index, TPort item)
{
BeforeAdd(item);
base.InsertItem(index, item);
AfterAdd(item);
}
protected override void RemoveItem(int index)
{
var item = this[index];
BeforeRemove(item);
base.RemoveItem(index);
AfterRemove(item);
}
protected override void SetItem(int index, TPort item)
{
throw new NotSupportedException();
}
protected override void ClearItems()
{
while (Count > 0)
{
RemoveItem(0);
}
}
}
}

View file

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

View file

@ -0,0 +1,21 @@
namespace Unity.VisualScripting
{
public abstract class UnitPortDefinition : IUnitPortDefinition
{
[Serialize, Inspectable, InspectorDelayed]
[WarnBeforeEditing("Edit Port Key", "Changing the key of this definition will break any existing connection to this port. Are you sure you want to continue?", null, "")]
public string key { get; set; }
[Serialize, Inspectable]
public string label { get; set; }
[Serialize, Inspectable, InspectorTextArea]
public string summary { get; set; }
[Serialize, Inspectable]
public bool hideLabel { get; set; }
[DoNotSerialize]
public virtual bool isValid => !string.IsNullOrEmpty(key);
}
}

View file

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

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public sealed class ValueInput : UnitPort<ValueOutput, IUnitOutputPort, ValueConnection>, IUnitValuePort, IUnitInputPort
{
public ValueInput(string key, Type type) : base(key)
{
Ensure.That(nameof(type)).IsNotNull(type);
this.type = type;
}
public Type type { get; }
public bool hasDefaultValue => unit.defaultValues.ContainsKey(key);
public override IEnumerable<ValueConnection> validConnections => unit?.graph?.valueConnections.WithDestination(this) ?? Enumerable.Empty<ValueConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => unit?.graph?.invalidConnections.WithDestination(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<ValueOutput> validConnectedPorts => validConnections.Select(c => c.source);
public override IEnumerable<IUnitOutputPort> invalidConnectedPorts => invalidConnections.Select(c => c.source);
// Use for inspector metadata
[DoNotSerialize]
internal object _defaultValue
{
get
{
return unit.defaultValues[key];
}
set
{
unit.defaultValues[key] = value;
}
}
public bool nullMeansSelf { get; private set; }
public bool allowsNull { get; private set; }
public ValueConnection connection => unit.graph?.valueConnections.SingleOrDefaultWithDestination(this);
public override bool hasValidConnection => connection != null;
public void SetDefaultValue(object value)
{
Ensure.That(nameof(value)).IsOfType(value, type);
if (!SupportsDefaultValue(type))
{
return;
}
if (unit.defaultValues.ContainsKey(key))
{
unit.defaultValues[key] = value;
}
else
{
unit.defaultValues.Add(key, value);
}
}
public override bool CanConnectToValid(ValueOutput port)
{
var source = port;
var destination = this;
return source.type.IsConvertibleTo(destination.type, false);
}
public override void ConnectToValid(ValueOutput port)
{
var source = port;
var destination = this;
destination.Disconnect();
unit.graph.valueConnections.Add(new ValueConnection(source, destination));
}
public override void ConnectToInvalid(IUnitOutputPort port)
{
ConnectInvalid(port, this);
}
public override void DisconnectFromValid(ValueOutput port)
{
var connection = validConnections.SingleOrDefault(c => c.source == port);
if (connection != null)
{
unit.graph.valueConnections.Remove(connection);
}
}
public override void DisconnectFromInvalid(IUnitOutputPort port)
{
DisconnectInvalid(port, this);
}
public ValueInput NullMeansSelf()
{
if (ComponentHolderProtocol.IsComponentHolderType(type))
{
nullMeansSelf = true;
}
return this;
}
public ValueInput AllowsNull()
{
if (type.IsNullable())
{
allowsNull = true;
}
return this;
}
private static readonly HashSet<Type> typesWithDefaultValues = new HashSet<Type>()
{
typeof(Vector2),
typeof(Vector3),
typeof(Vector4),
typeof(Color),
typeof(AnimationCurve),
typeof(Rect),
typeof(Ray),
typeof(Ray2D),
typeof(Type),
#if PACKAGE_INPUT_SYSTEM_EXISTS
typeof(UnityEngine.InputSystem.InputAction),
#endif
};
public static bool SupportsDefaultValue(Type type)
{
return
typesWithDefaultValues.Contains(type) ||
typesWithDefaultValues.Contains(Nullable.GetUnderlyingType(type)) ||
type.IsBasic() ||
typeof(UnityObject).IsAssignableFrom(type);
}
public override IUnitPort CompatiblePort(IUnit unit)
{
if (unit == this.unit) return null;
return unit.CompatibleValueOutput(type);
}
}
}

View file

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

View file

@ -0,0 +1,67 @@
using System;
namespace Unity.VisualScripting
{
public sealed class ValueInputDefinition : ValuePortDefinition, IUnitInputPortDefinition
{
[SerializeAs(nameof(defaultValue))]
private object _defaultvalue;
[Inspectable]
[DoNotSerialize]
public override Type type
{
get
{
return base.type;
}
set
{
base.type = value;
if (!type.IsAssignableFrom(defaultValue))
{
if (ValueInput.SupportsDefaultValue(type))
{
_defaultvalue = type.PseudoDefault();
}
else
{
hasDefaultValue = false;
_defaultvalue = null;
}
}
}
}
[Serialize]
[Inspectable]
public bool hasDefaultValue { get; set; }
[DoNotSerialize]
[Inspectable]
public object defaultValue
{
get
{
return _defaultvalue;
}
set
{
if (type == null)
{
throw new InvalidOperationException("A type must be defined before setting the default value.");
}
if (!ValueInput.SupportsDefaultValue(type))
{
throw new InvalidOperationException("The selected type does not support default values.");
}
Ensure.That(nameof(value)).IsOfType(value, type);
_defaultvalue = value;
}
}
}
}

View file

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

View file

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public sealed class ValueOutput : UnitPort<ValueInput, IUnitInputPort, ValueConnection>, IUnitValuePort, IUnitOutputPort
{
public ValueOutput(string key, Type type, Func<Flow, object> getValue) : base(key)
{
Ensure.That(nameof(type)).IsNotNull(type);
Ensure.That(nameof(getValue)).IsNotNull(getValue);
this.type = type;
this.getValue = getValue;
}
public ValueOutput(string key, Type type) : base(key)
{
Ensure.That(nameof(type)).IsNotNull(type);
this.type = type;
}
internal readonly Func<Flow, object> getValue;
internal Func<Flow, bool> canPredictValue;
public bool supportsPrediction => canPredictValue != null;
public bool supportsFetch => getValue != null;
public Type type { get; }
public override IEnumerable<ValueConnection> validConnections => unit?.graph?.valueConnections.WithSource(this) ?? Enumerable.Empty<ValueConnection>();
public override IEnumerable<InvalidConnection> invalidConnections => unit?.graph?.invalidConnections.WithSource(this) ?? Enumerable.Empty<InvalidConnection>();
public override IEnumerable<ValueInput> validConnectedPorts => validConnections.Select(c => c.destination);
public override IEnumerable<IUnitInputPort> invalidConnectedPorts => invalidConnections.Select(c => c.destination);
public override bool CanConnectToValid(ValueInput port)
{
var source = this;
var destination = port;
return source.type.IsConvertibleTo(destination.type, false);
}
public override void ConnectToValid(ValueInput port)
{
var source = this;
var destination = port;
destination.Disconnect();
unit.graph.valueConnections.Add(new ValueConnection(source, destination));
}
public override void ConnectToInvalid(IUnitInputPort port)
{
ConnectInvalid(this, port);
}
public override void DisconnectFromValid(ValueInput port)
{
var connection = validConnections.SingleOrDefault(c => c.destination == port);
if (connection != null)
{
unit.graph.valueConnections.Remove(connection);
}
}
public override void DisconnectFromInvalid(IUnitInputPort port)
{
DisconnectInvalid(this, port);
}
public ValueOutput PredictableIf(Func<Flow, bool> condition)
{
Ensure.That(nameof(condition)).IsNotNull(condition);
canPredictValue = condition;
return this;
}
public ValueOutput Predictable()
{
canPredictValue = (flow) => true;
return this;
}
public override IUnitPort CompatiblePort(IUnit unit)
{
if (unit == this.unit) return null;
return unit.CompatibleValueInput(type);
}
}
}

View file

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

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public sealed class ValueOutputDefinition : ValuePortDefinition, IUnitOutputPortDefinition { }
}

View file

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

View file

@ -0,0 +1,27 @@
using System;
namespace Unity.VisualScripting
{
public abstract class ValuePortDefinition : UnitPortDefinition, IUnitValuePortDefinition
{
// For the virtual inheritors
[SerializeAs(nameof(_type))]
private Type _type { get; set; }
[Inspectable]
[DoNotSerialize]
public virtual Type type
{
get
{
return _type;
}
set
{
_type = value;
}
}
public override bool isValid => base.isValid && type != null;
}
}

View file

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