using System; using System.Collections.Generic; using System.Linq; namespace Unity.VisualScripting { public sealed class ValueOutput : UnitPort, IUnitValuePort, IUnitOutputPort { public ValueOutput(string key, Type type, Func getValue) : base(key) { Ensure.That(nameof(type)).IsNotNull(type); Ensure.That(nameof(getValue)).IsNotNull(getValue); this.type = type; this.getValue = getValue; } public ValueOutput(string key, Type type) : base(key) { Ensure.That(nameof(type)).IsNotNull(type); this.type = type; } internal readonly Func getValue; internal Func canPredictValue; public bool supportsPrediction => canPredictValue != null; public bool supportsFetch => getValue != null; public Type type { get; } public override IEnumerable validConnections => unit?.graph?.valueConnections.WithSource(this) ?? Enumerable.Empty(); public override IEnumerable invalidConnections => unit?.graph?.invalidConnections.WithSource(this) ?? Enumerable.Empty(); public override IEnumerable validConnectedPorts => validConnections.Select(c => c.destination); public override IEnumerable invalidConnectedPorts => invalidConnections.Select(c => c.destination); public override bool CanConnectToValid(ValueInput port) { var source = this; var destination = port; return source.type.IsConvertibleTo(destination.type, false); } public override void ConnectToValid(ValueInput port) { var source = this; var destination = port; destination.Disconnect(); unit.graph.valueConnections.Add(new ValueConnection(source, destination)); } public override void ConnectToInvalid(IUnitInputPort port) { ConnectInvalid(this, port); } public override void DisconnectFromValid(ValueInput port) { var connection = validConnections.SingleOrDefault(c => c.destination == port); if (connection != null) { unit.graph.valueConnections.Remove(connection); } } public override void DisconnectFromInvalid(IUnitInputPort port) { DisconnectInvalid(this, port); } public ValueOutput PredictableIf(Func condition) { Ensure.That(nameof(condition)).IsNotNull(condition); canPredictValue = condition; return this; } public ValueOutput Predictable() { canPredictValue = (flow) => true; return this; } public override IUnitPort CompatiblePort(IUnit unit) { if (unit == this.unit) return null; return unit.CompatibleValueInput(type); } } }