Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class ControlConnection : UnitConnection<ControlOutput, ControlInput>, IUnitConnection
|
||||
{
|
||||
[Obsolete(Serialization.ConstructorWarning)]
|
||||
public ControlConnection() : base() { }
|
||||
|
||||
public ControlConnection(ControlOutput source, ControlInput destination) : base(source, destination)
|
||||
{
|
||||
if (source.hasValidConnection)
|
||||
{
|
||||
throw new InvalidConnectionException("Control output ports do not support multiple connections.");
|
||||
}
|
||||
}
|
||||
|
||||
#region Ports
|
||||
|
||||
public override ControlOutput source => sourceUnit.controlOutputs[sourceKey];
|
||||
|
||||
public override ControlInput destination => destinationUnit.controlInputs[destinationKey];
|
||||
|
||||
IUnitOutputPort IConnection<IUnitOutputPort, IUnitInputPort>.source => source;
|
||||
|
||||
IUnitInputPort IConnection<IUnitOutputPort, IUnitInputPort>.destination => destination;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependencies
|
||||
|
||||
public override bool sourceExists => sourceUnit.controlOutputs.Contains(sourceKey);
|
||||
|
||||
public override bool destinationExists => destinationUnit.controlInputs.Contains(destinationKey);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b71fe733d92c1489cb3c89d5841ea222
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
/* Implementation notes:
|
||||
*
|
||||
* IUnitConnection cannot implement IConnection<IUnitOutputPort, IUnitInputPort> because
|
||||
* the compiler will be overly strict and complain that types may unify.
|
||||
* https://stackoverflow.com/questions/7664790
|
||||
*
|
||||
* Additionally, using contravariance for the type parameters will compile but
|
||||
* fail at runtime, because Unity's Mono version does not properly support variance,
|
||||
* even though it's supposed to be a CLR feature since .NET 1.1.
|
||||
* https://forum.unity3d.com/threads/398665/
|
||||
* https://github.com/jacobdufault/fullinspector/issues/9
|
||||
*
|
||||
* Therefore, the only remaining solution is to re-implement source and destination
|
||||
* manually. This introduces ambiguity, as the compiler will warn, but it's fine
|
||||
* if the implementations point both members to the same actual object.
|
||||
*/
|
||||
|
||||
public interface IUnitConnection : IConnection<IUnitOutputPort, IUnitInputPort>, IGraphElementWithDebugData
|
||||
{
|
||||
new FlowGraph graph { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dc809ec21d2bf44b983265840a5ed2f4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IUnitConnectionDebugData : IGraphElementDebugData
|
||||
{
|
||||
int lastInvokeFrame { get; set; }
|
||||
|
||||
float lastInvokeTime { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9239efc28f45f4c848294b936db9bfa0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,4 @@
|
|||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IUnitRelation : IConnection<IUnitPort, IUnitPort> { }
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 20177830b472f40faa7374d0861ddad0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class InvalidConnection : UnitConnection<IUnitOutputPort, IUnitInputPort>, IUnitConnection
|
||||
{
|
||||
[Obsolete(Serialization.ConstructorWarning)]
|
||||
public InvalidConnection() : base() { }
|
||||
|
||||
public InvalidConnection(IUnitOutputPort source, IUnitInputPort destination) : base(source, destination) { }
|
||||
|
||||
public override void AfterRemove()
|
||||
{
|
||||
base.AfterRemove();
|
||||
source.unit.RemoveUnconnectedInvalidPorts();
|
||||
destination.unit.RemoveUnconnectedInvalidPorts();
|
||||
}
|
||||
|
||||
#region Ports
|
||||
|
||||
public override IUnitOutputPort source => sourceUnit.outputs.Single(p => p.key == sourceKey);
|
||||
|
||||
public override IUnitInputPort destination => destinationUnit.inputs.Single(p => p.key == destinationKey);
|
||||
|
||||
public IUnitOutputPort validSource => sourceUnit.validOutputs.Single(p => p.key == sourceKey);
|
||||
|
||||
public IUnitInputPort validDestination => destinationUnit.validInputs.Single(p => p.key == destinationKey);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependencies
|
||||
|
||||
public override bool sourceExists => sourceUnit.outputs.Any(p => p.key == sourceKey);
|
||||
|
||||
public override bool destinationExists => destinationUnit.inputs.Any(p => p.key == destinationKey);
|
||||
|
||||
public bool validSourceExists => sourceUnit.validOutputs.Any(p => p.key == sourceKey);
|
||||
|
||||
public bool validDestinationExists => destinationUnit.validInputs.Any(p => p.key == destinationKey);
|
||||
|
||||
public override bool HandleDependencies()
|
||||
{
|
||||
// Replace the invalid connection with a valid connection if it can be created instead.
|
||||
if (validSourceExists && validDestinationExists && validSource.CanValidlyConnectTo(validDestination))
|
||||
{
|
||||
validSource.ValidlyConnectTo(validDestination);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the invalid ports to the units if need be
|
||||
if (!sourceExists)
|
||||
{
|
||||
sourceUnit.invalidOutputs.Add(new InvalidOutput(sourceKey));
|
||||
}
|
||||
|
||||
if (!destinationExists)
|
||||
{
|
||||
destinationUnit.invalidInputs.Add(new InvalidInput(destinationKey));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f564c98f800f2453595d4c4e261215ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,151 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
/* Implementation note:
|
||||
* Using an abstract base class works as a type unification workaround.
|
||||
* https://stackoverflow.com/questions/22721763
|
||||
* https://stackoverflow.com/a/7664919
|
||||
*
|
||||
* However, this forces us to use concrete classes for connections
|
||||
* instead of interfaces. In other words, no IControlConnection / IValueConnection.
|
||||
* If we did use interfaces, there would be ambiguity that needs to be resolved
|
||||
* at every reference to the source or destination.
|
||||
*
|
||||
* However, using a disambiguator hack seems to confuse even recent Mono runtime versions of Unity
|
||||
* and breaks its vtable. Sometimes, method pointers are just plain wrong.
|
||||
* I'm guessing this is specifically due to InvalidConnection, which actually
|
||||
* does unify the types; what the C# warning warned about.
|
||||
* https://stackoverflow.com/q/50051657/154502
|
||||
*
|
||||
* THEREFORE, IUnitConnection has to be implemented at the concrete class level,
|
||||
* because at that point the type unification warning is moot, because the type arguments are
|
||||
* provided.
|
||||
*/
|
||||
|
||||
public abstract class UnitConnection<TSourcePort, TDestinationPort> : GraphElement<FlowGraph>, IConnection<TSourcePort, TDestinationPort>
|
||||
where TSourcePort : class, IUnitOutputPort
|
||||
where TDestinationPort : class, IUnitInputPort
|
||||
{
|
||||
[Obsolete(Serialization.ConstructorWarning)]
|
||||
protected UnitConnection() { }
|
||||
|
||||
protected UnitConnection(TSourcePort source, TDestinationPort destination)
|
||||
{
|
||||
Ensure.That(nameof(source)).IsNotNull(source);
|
||||
Ensure.That(nameof(destination)).IsNotNull(destination);
|
||||
|
||||
if (source.unit.graph != destination.unit.graph)
|
||||
{
|
||||
throw new NotSupportedException("Cannot create connections across graphs.");
|
||||
}
|
||||
|
||||
if (source.unit == destination.unit)
|
||||
{
|
||||
throw new InvalidConnectionException("Cannot create connections on the same unit.");
|
||||
}
|
||||
|
||||
sourceUnit = source.unit;
|
||||
sourceKey = source.key;
|
||||
destinationUnit = destination.unit;
|
||||
destinationKey = destination.key;
|
||||
}
|
||||
|
||||
public virtual IGraphElementDebugData CreateDebugData()
|
||||
{
|
||||
return new UnitConnectionDebugData();
|
||||
}
|
||||
|
||||
#region Ports
|
||||
|
||||
[Serialize]
|
||||
protected IUnit sourceUnit { get; private set; }
|
||||
|
||||
[Serialize]
|
||||
protected string sourceKey { get; private set; }
|
||||
|
||||
[Serialize]
|
||||
protected IUnit destinationUnit { get; private set; }
|
||||
|
||||
[Serialize]
|
||||
protected string destinationKey { get; private set; }
|
||||
|
||||
[DoNotSerialize]
|
||||
public abstract TSourcePort source { get; }
|
||||
|
||||
[DoNotSerialize]
|
||||
public abstract TDestinationPort destination { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependencies
|
||||
|
||||
public override int dependencyOrder => 1;
|
||||
|
||||
public abstract bool sourceExists { get; }
|
||||
|
||||
public abstract bool destinationExists { get; }
|
||||
|
||||
protected void CopyFrom(UnitConnection<TSourcePort, TDestinationPort> source)
|
||||
{
|
||||
base.CopyFrom(source);
|
||||
}
|
||||
|
||||
public override bool HandleDependencies()
|
||||
{
|
||||
// Replace the connection with an invalid connection if the ports are either missing or incompatible.
|
||||
// If the ports are missing, create invalid ports if required.
|
||||
|
||||
var valid = true;
|
||||
IUnitOutputPort source;
|
||||
IUnitInputPort destination;
|
||||
|
||||
if (!sourceExists)
|
||||
{
|
||||
if (!sourceUnit.invalidOutputs.Contains(sourceKey))
|
||||
{
|
||||
sourceUnit.invalidOutputs.Add(new InvalidOutput(sourceKey));
|
||||
}
|
||||
|
||||
source = sourceUnit.invalidOutputs[sourceKey];
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = this.source;
|
||||
}
|
||||
|
||||
if (!destinationExists)
|
||||
{
|
||||
if (!destinationUnit.invalidInputs.Contains(destinationKey))
|
||||
{
|
||||
destinationUnit.invalidInputs.Add(new InvalidInput(destinationKey));
|
||||
}
|
||||
|
||||
destination = destinationUnit.invalidInputs[destinationKey];
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
destination = this.destination;
|
||||
}
|
||||
|
||||
if (!source.CanValidlyConnectTo(destination))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid && source.CanInvalidlyConnectTo(destination))
|
||||
{
|
||||
source.InvalidlyConnectTo(destination);
|
||||
|
||||
Debug.LogWarning($"Could not load connection between '{source.key}' of '{sourceUnit}' and '{destination.key}' of '{destinationUnit}'.");
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a8cc9b6e18b84c82a16ca1d5ae11643
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class UnitConnectionDebugData : IUnitConnectionDebugData
|
||||
{
|
||||
public int lastInvokeFrame { get; set; }
|
||||
|
||||
public float lastInvokeTime { get; set; }
|
||||
|
||||
public Exception runtimeException { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5b33449365cf844e986fad5c887be657
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class UnitRelation : IUnitRelation
|
||||
{
|
||||
public UnitRelation(IUnitPort source, IUnitPort destination)
|
||||
{
|
||||
Ensure.That(nameof(source)).IsNotNull(source);
|
||||
Ensure.That(nameof(destination)).IsNotNull(destination);
|
||||
|
||||
if (source.unit != destination.unit)
|
||||
{
|
||||
throw new NotSupportedException("Cannot create relations across units.");
|
||||
}
|
||||
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public IUnitPort source { get; }
|
||||
|
||||
public IUnitPort destination { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3617e416d65b4e44842280c042df8a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class ValueConnection : UnitConnection<ValueOutput, ValueInput>, IUnitConnection
|
||||
{
|
||||
public class DebugData : UnitConnectionDebugData
|
||||
{
|
||||
public object lastValue { get; set; }
|
||||
|
||||
public bool assignedLastValue { get; set; }
|
||||
}
|
||||
|
||||
public override IGraphElementDebugData CreateDebugData()
|
||||
{
|
||||
return new DebugData();
|
||||
}
|
||||
|
||||
[Obsolete(Serialization.ConstructorWarning)]
|
||||
public ValueConnection() : base() { }
|
||||
|
||||
public ValueConnection(ValueOutput source, ValueInput destination) : base(source, destination)
|
||||
{
|
||||
if (destination.hasValidConnection)
|
||||
{
|
||||
throw new InvalidConnectionException("Value input ports do not support multiple connections.");
|
||||
}
|
||||
|
||||
if (!source.type.IsConvertibleTo(destination.type, false))
|
||||
{
|
||||
throw new InvalidConnectionException($"Cannot convert from '{source.type}' to '{destination.type}'.");
|
||||
}
|
||||
}
|
||||
|
||||
#region Ports
|
||||
|
||||
public override ValueOutput source => sourceUnit.valueOutputs[sourceKey];
|
||||
|
||||
public override ValueInput destination => destinationUnit.valueInputs[destinationKey];
|
||||
|
||||
IUnitOutputPort IConnection<IUnitOutputPort, IUnitInputPort>.source => source;
|
||||
|
||||
IUnitInputPort IConnection<IUnitOutputPort, IUnitInputPort>.destination => destination;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependencies
|
||||
|
||||
public override bool sourceExists => sourceUnit.valueOutputs.Contains(sourceKey);
|
||||
|
||||
public override bool destinationExists => destinationUnit.valueInputs.Contains(destinationKey);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b74709ab7c4674a84903b44120fcb9fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue