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}