using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Unity.VisualScripting { /// /// Represents a unit within a flow graph, defining its behavior, ports, connections, and visualization in the graph editor. /// public interface IUnit : IGraphElementWithDebugData { /// /// Gets the flow graph to which this unit belongs. /// new FlowGraph graph { get; } #region Definition /// /// Gets a value indicating whether this unit can be defined. /// bool canDefine { get; } /// /// Gets a value indicating whether this unit is currently defined. /// bool isDefined { get; } /// /// Gets a value indicating whether this unit failed to define. /// bool failedToDefine { get; } /// /// Gets the exception that occurred during the definition process, if the unit failed to define. /// Exception definitionException { get; } /// /// Defines this unit by setting up its ports, connections, and other requirements. /// void Define(); /// /// Ensures that this unit is properly defined, invoking definition if necessary. /// void EnsureDefined(); /// /// Removes any unconnected invalid ports from this unit. /// void RemoveUnconnectedInvalidPorts(); #endregion #region Default Values /// /// Gets a dictionary of default values used by the unit. /// The keys represent port names, and the values represent their corresponding defaults. /// Dictionary defaultValues { get; } #endregion #region Ports /// /// Gets the collection of control input ports for this unit. /// IUnitPortCollection controlInputs { get; } /// /// Gets the collection of control output ports for this unit. /// IUnitPortCollection controlOutputs { get; } /// /// Gets the collection of value input ports for this unit. /// IUnitPortCollection valueInputs { get; } /// /// Gets the collection of value output ports for this unit. /// IUnitPortCollection valueOutputs { get; } /// /// Gets the collection of invalid input ports for this unit, which represent connections with unresolved compatibility issues. /// IUnitPortCollection invalidInputs { get; } /// /// Gets the collection of invalid output ports for this unit, which represent connections with unresolved compatibility issues. /// IUnitPortCollection invalidOutputs { get; } /// /// Gets all input ports (both valid and invalid) for this unit. /// IEnumerable inputs { get; } /// /// Gets all output ports (both valid and invalid) for this unit. /// IEnumerable outputs { get; } /// /// Gets the valid input ports for this unit. /// IEnumerable validInputs { get; } /// /// Gets the valid output ports for this unit. /// IEnumerable validOutputs { get; } /// /// Gets all ports (valid and invalid) for this unit. /// IEnumerable ports { get; } /// /// Gets the invalid ports for this unit. /// IEnumerable invalidPorts { get; } /// /// Gets the valid ports for this unit. /// IEnumerable validPorts { get; } /// /// Called to notify that ports in the unit have changed. /// void PortsChanged(); /// /// Event triggered when ports in the unit have changed. /// event Action onPortsChanged; #endregion #region Connections /// /// Gets the collection of port-to-port relationships (or connections) in this unit. /// IConnectionCollection relations { get; } /// /// Gets all connections associated with this unit. /// IEnumerable connections { get; } #endregion #region Analysis /// /// Gets a value indicating whether this unit is the control root of its graph. /// bool isControlRoot { get; } #endregion #region Widget /// /// Gets or sets the position of this unit in the graph editor interface. /// Vector2 position { get; set; } #endregion } public static class XUnit { public static ValueInput CompatibleValueInput(this IUnit unit, Type outputType) { Ensure.That(nameof(outputType)).IsNotNull(outputType); return unit.valueInputs .Where(valueInput => ConversionUtility.CanConvert(outputType, valueInput.type, false)) .OrderBy((valueInput) => { var exactType = outputType == valueInput.type; var free = !valueInput.hasValidConnection; if (free && exactType) { return 1; } else if (free) { return 2; } else if (exactType) { return 3; } else { return 4; } }).FirstOrDefault(); } public static ValueOutput CompatibleValueOutput(this IUnit unit, Type inputType) { Ensure.That(nameof(inputType)).IsNotNull(inputType); return unit.valueOutputs .Where(valueOutput => ConversionUtility.CanConvert(valueOutput.type, inputType, false)) .OrderBy((valueOutput) => { var exactType = inputType == valueOutput.type; var free = !valueOutput.hasValidConnection; if (free && exactType) { return 1; } else if (free) { return 2; } else if (exactType) { return 3; } else { return 4; } }).FirstOrDefault(); } } }