A game about forced loneliness, made by TACStudios
1using System.Collections.Generic; 2using System.Linq; 3 4namespace Unity.VisualScripting 5{ 6 public abstract class UnitPort<TValidOther, TInvalidOther, TExternalConnection> : IUnitPort 7 where TValidOther : IUnitPort 8 where TInvalidOther : IUnitPort 9 where TExternalConnection : IUnitConnection 10 { 11 protected UnitPort(string key) 12 { 13 Ensure.That(nameof(key)).IsNotNull(key); 14 15 this.key = key; 16 } 17 18 public IUnit unit { get; set; } 19 20 public string key { get; } 21 22 public IGraph graph => unit?.graph; 23 24 public IEnumerable<IUnitRelation> relations => 25 LinqUtility.Concat<IUnitRelation>(unit.relations.WithSource(this), 26 unit.relations.WithDestination(this)).Distinct(); 27 28 public abstract IEnumerable<TExternalConnection> validConnections { get; } 29 30 public abstract IEnumerable<InvalidConnection> invalidConnections { get; } 31 32 public abstract IEnumerable<TValidOther> validConnectedPorts { get; } 33 34 public abstract IEnumerable<TInvalidOther> invalidConnectedPorts { get; } 35 36 IEnumerable<IUnitConnection> IUnitPort.validConnections => validConnections.Cast<IUnitConnection>(); 37 38 public IEnumerable<IUnitConnection> connections => LinqUtility.Concat<IUnitConnection>(validConnections, invalidConnections); 39 40 public IEnumerable<IUnitPort> connectedPorts => LinqUtility.Concat<IUnitPort>(validConnectedPorts, invalidConnectedPorts); 41 42 public bool hasAnyConnection => hasValidConnection || hasInvalidConnection; 43 44 // Allow for more efficient overrides 45 46 public virtual bool hasValidConnection => validConnections.Any(); 47 48 public virtual bool hasInvalidConnection => invalidConnections.Any(); 49 50 private bool CanConnectTo(IUnitPort port) 51 { 52 Ensure.That(nameof(port)).IsNotNull(port); 53 54 return unit != null && // We belong to a unit 55 port.unit != null && // Port belongs to a unit 56 port.unit != unit && // that is different than the current one 57 port.unit.graph == unit.graph; // but is on the same graph. 58 } 59 60 public bool CanValidlyConnectTo(IUnitPort port) 61 { 62 return CanConnectTo(port) && port is TValidOther && CanConnectToValid((TValidOther)port); 63 } 64 65 public bool CanInvalidlyConnectTo(IUnitPort port) 66 { 67 return CanConnectTo(port) && port is TInvalidOther && CanConnectToInvalid((TInvalidOther)port); 68 } 69 70 public void ValidlyConnectTo(IUnitPort port) 71 { 72 Ensure.That(nameof(port)).IsNotNull(port); 73 74 if (!(port is TValidOther)) 75 { 76 throw new InvalidConnectionException(); 77 } 78 79 ConnectToValid((TValidOther)port); 80 } 81 82 public void InvalidlyConnectTo(IUnitPort port) 83 { 84 Ensure.That(nameof(port)).IsNotNull(port); 85 86 if (!(port is TInvalidOther)) 87 { 88 throw new InvalidConnectionException(); 89 } 90 91 ConnectToInvalid((TInvalidOther)port); 92 } 93 94 public void Disconnect() 95 { 96 while (validConnectedPorts.Any()) 97 { 98 DisconnectFromValid(validConnectedPorts.First()); 99 } 100 101 while (invalidConnectedPorts.Any()) 102 { 103 DisconnectFromInvalid(invalidConnectedPorts.First()); 104 } 105 } 106 107 public abstract bool CanConnectToValid(TValidOther port); 108 109 public bool CanConnectToInvalid(TInvalidOther port) 110 { 111 return true; 112 } 113 114 public abstract void ConnectToValid(TValidOther port); 115 116 public abstract void ConnectToInvalid(TInvalidOther port); 117 118 public abstract void DisconnectFromValid(TValidOther port); 119 120 public abstract void DisconnectFromInvalid(TInvalidOther port); 121 122 public abstract IUnitPort CompatiblePort(IUnit unit); 123 124 protected void ConnectInvalid(IUnitOutputPort source, IUnitInputPort destination) 125 { 126 var connection = unit.graph.invalidConnections.SingleOrDefault(c => c.source == source && c.destination == destination); 127 128 if (connection != null) 129 { 130 return; 131 } 132 133 unit.graph.invalidConnections.Add(new InvalidConnection(source, destination)); 134 } 135 136 protected void DisconnectInvalid(IUnitOutputPort source, IUnitInputPort destination) 137 { 138 var connection = unit.graph.invalidConnections.SingleOrDefault(c => c.source == source && c.destination == destination); 139 140 if (connection == null) 141 { 142 return; 143 } 144 145 unit.graph.invalidConnections.Remove(connection); 146 } 147 } 148}