UnityGame/Library/PackageCache/com.unity.visualscripting/Runtime/VisualScripting.Flow/Ports/UnitPort.cs
2024-10-27 10:53:47 +03:00

149 lines
4.7 KiB
C#

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);
}
}
}