242 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace Unity.VisualScripting
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Represents a unit within a flow graph, defining its behavior, ports, connections, and visualization in the graph editor.
 | |
|     /// </summary>
 | |
|     public interface IUnit : IGraphElementWithDebugData
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Gets the flow graph to which this unit belongs.
 | |
|         /// </summary>
 | |
|         new FlowGraph graph { get; }
 | |
| 
 | |
|         #region Definition
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a value indicating whether this unit can be defined.
 | |
|         /// </summary>
 | |
|         bool canDefine { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a value indicating whether this unit is currently defined.
 | |
|         /// </summary>
 | |
|         bool isDefined { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a value indicating whether this unit failed to define.
 | |
|         /// </summary>
 | |
|         bool failedToDefine { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the exception that occurred during the definition process, if the unit failed to define.
 | |
|         /// </summary>
 | |
|         Exception definitionException { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Defines this unit by setting up its ports, connections, and other requirements.
 | |
|         /// </summary>
 | |
|         void Define();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Ensures that this unit is properly defined, invoking definition if necessary.
 | |
|         /// </summary>
 | |
|         void EnsureDefined();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Removes any unconnected invalid ports from this unit.
 | |
|         /// </summary>
 | |
|         void RemoveUnconnectedInvalidPorts();
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Default Values
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a dictionary of default values used by the unit.
 | |
|         /// The keys represent port names, and the values represent their corresponding defaults.
 | |
|         /// </summary>
 | |
|         Dictionary<string, object> defaultValues { get; }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Ports
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of control input ports for this unit.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<ControlInput> controlInputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of control output ports for this unit.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<ControlOutput> controlOutputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of value input ports for this unit.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<ValueInput> valueInputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of value output ports for this unit.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<ValueOutput> valueOutputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of invalid input ports for this unit, which represent connections with unresolved compatibility issues.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<InvalidInput> invalidInputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of invalid output ports for this unit, which represent connections with unresolved compatibility issues.
 | |
|         /// </summary>
 | |
|         IUnitPortCollection<InvalidOutput> invalidOutputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets all input ports (both valid and invalid) for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitInputPort> inputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets all output ports (both valid and invalid) for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitOutputPort> outputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the valid input ports for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitInputPort> validInputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the valid output ports for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitOutputPort> validOutputs { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets all ports (valid and invalid) for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitPort> ports { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the invalid ports for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitPort> invalidPorts { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the valid ports for this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitPort> validPorts { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Called to notify that ports in the unit have changed.
 | |
|         /// </summary>
 | |
|         void PortsChanged();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Event triggered when ports in the unit have changed.
 | |
|         /// </summary>
 | |
|         event Action onPortsChanged;
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Connections
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the collection of port-to-port relationships (or connections) in this unit.
 | |
|         /// </summary>
 | |
|         IConnectionCollection<IUnitRelation, IUnitPort, IUnitPort> relations { get; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets all connections associated with this unit.
 | |
|         /// </summary>
 | |
|         IEnumerable<IUnitConnection> connections { get; }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Analysis
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a value indicating whether this unit is the control root of its graph.
 | |
|         /// </summary>
 | |
|         bool isControlRoot { get; }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region Widget
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the position of this unit in the graph editor interface.
 | |
|         /// </summary>
 | |
|         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();
 | |
|         }
 | |
|     }
 | |
| }
 |