A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections; 3using System.Collections.Generic; 4using System.Linq; 5 6namespace Unity.VisualScripting 7{ 8 public sealed class ControlInput : UnitPort<ControlOutput, IUnitOutputPort, ControlConnection>, IUnitControlPort, IUnitInputPort 9 { 10 public ControlInput(string key, Func<Flow, ControlOutput> action) : base(key) 11 { 12 Ensure.That(nameof(action)).IsNotNull(action); 13 14 this.action = action; 15 } 16 17 public ControlInput(string key, Func<Flow, IEnumerator> coroutineAction) : base(key) 18 { 19 Ensure.That(nameof(coroutineAction)).IsNotNull(coroutineAction); 20 21 this.coroutineAction = coroutineAction; 22 } 23 24 public ControlInput(string key, Func<Flow, ControlOutput> action, Func<Flow, IEnumerator> coroutineAction) : base(key) 25 { 26 Ensure.That(nameof(action)).IsNotNull(action); 27 Ensure.That(nameof(coroutineAction)).IsNotNull(coroutineAction); 28 29 this.action = action; 30 this.coroutineAction = coroutineAction; 31 } 32 33 public bool supportsCoroutine => coroutineAction != null; 34 35 public bool requiresCoroutine => action == null; 36 37 internal readonly Func<Flow, ControlOutput> action; 38 39 internal readonly Func<Flow, IEnumerator> coroutineAction; 40 41 public override IEnumerable<ControlConnection> validConnections => unit?.graph?.controlConnections.WithDestination(this) ?? Enumerable.Empty<ControlConnection>(); 42 43 public override IEnumerable<InvalidConnection> invalidConnections => unit?.graph?.invalidConnections.WithDestination(this) ?? Enumerable.Empty<InvalidConnection>(); 44 45 public override IEnumerable<ControlOutput> validConnectedPorts => validConnections.Select(c => c.source); 46 47 public override IEnumerable<IUnitOutputPort> invalidConnectedPorts => invalidConnections.Select(c => c.source); 48 49 public bool isPredictable 50 { 51 get 52 { 53 using (var recursion = Recursion.New(1)) 54 { 55 return IsPredictable(recursion); 56 } 57 } 58 } 59 60 public bool IsPredictable(Recursion recursion) 61 { 62 if (!hasValidConnection) 63 { 64 return true; 65 } 66 67 if (!recursion?.TryEnter(this) ?? false) 68 { 69 return false; 70 } 71 72 var isPredictable = validConnectedPorts.All(cop => cop.IsPredictable(recursion)); 73 74 recursion?.Exit(this); 75 76 return isPredictable; 77 } 78 79 public bool couldBeEntered 80 { 81 get 82 { 83 if (!isPredictable) 84 { 85 throw new NotSupportedException(); 86 } 87 88 if (!hasValidConnection) 89 { 90 return false; 91 } 92 93 return validConnectedPorts.Any(cop => cop.couldBeEntered); 94 } 95 } 96 97 public override bool CanConnectToValid(ControlOutput port) 98 { 99 return true; 100 } 101 102 public override void ConnectToValid(ControlOutput port) 103 { 104 var source = port; 105 var destination = this; 106 107 source.Disconnect(); 108 109 unit.graph.controlConnections.Add(new ControlConnection(source, destination)); 110 } 111 112 public override void ConnectToInvalid(IUnitOutputPort port) 113 { 114 ConnectInvalid(port, this); 115 } 116 117 public override void DisconnectFromValid(ControlOutput port) 118 { 119 var connection = validConnections.SingleOrDefault(c => c.source == port); 120 121 if (connection != null) 122 { 123 unit.graph.controlConnections.Remove(connection); 124 } 125 } 126 127 public override void DisconnectFromInvalid(IUnitOutputPort port) 128 { 129 DisconnectInvalid(port, this); 130 } 131 132 public override IUnitPort CompatiblePort(IUnit unit) 133 { 134 if (unit == this.unit) return null; 135 136 return unit.controlOutputs.FirstOrDefault(); 137 } 138 } 139}