| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 | using System.Collections;using System.Collections.Generic;using UnityEngine;using GraphProcessor;using System.Linq;using System;[System.Serializable, NodeMenuItem("Utils/Relay")]public class RelayNode : BaseNode{	const string packIdentifier = "_Pack";	[HideInInspector]	public struct PackedRelayData	{		public List<object>	values;		public List<string>	names;		public List<Type>	types;	}	[Input(name = "In")]    public PackedRelayData	input;	[Output(name = "Out")]	public PackedRelayData	output;	public bool		unpackOutput = false;	public bool		packInput = false;	public int		inputEdgeCount = 0;	[System.NonSerialized]	int				outputIndex = 0;	SerializableType inputType = new SerializableType(typeof(object));	const int		k_MaxPortSize = 14;	protected override void Process()	{		outputIndex = 0;		output = input;	}	public override string layoutStyle => "GraphProcessorStyles/RelayNode";	[CustomPortInput(nameof(input), typeof(object), true)]	public void GetInputs(List< SerializableEdge > edges)	{		inputEdgeCount = edges.Count;		// If the relay is only connected to another relay:		if (edges.Count == 1 && edges.First().outputNode.GetType() == typeof(RelayNode))		{			if (edges.First().passThroughBuffer != null)				input = (PackedRelayData)edges.First().passThroughBuffer;		}		else		{			input.values = edges.Select(e => e.passThroughBuffer).ToList();			input.names = edges.Select(e => e.outputPort.portData.displayName).ToList();			input.types = edges.Select(e => e.outputPort.portData.displayType ?? e.outputPort.fieldInfo.FieldType).ToList();		}	}	[CustomPortOutput(nameof(output), typeof(object), true)]	public void PushOutputs(List< SerializableEdge > edges, NodePort outputPort)	{		if (inputPorts.Count == 0)			return;		var inputPortEdges = inputPorts[0].GetEdges();		if (outputPort.portData.identifier != packIdentifier && outputIndex >= 0 && (unpackOutput || inputPortEdges.Count == 1))		{			if (output.values == null)				return;			// When we unpack the output, there is one port per type of data in output			// That means that this function will be called the same number of time than the output port count			// Thus we use a class field to keep the index.			object data = output.values[outputIndex++];			foreach (var edge in edges)			{				var inputRelay = edge.inputNode as RelayNode;				edge.passThroughBuffer = inputRelay != null && !inputRelay.packInput ? output : data;			}		}		else		{			foreach (var edge in edges)				edge.passThroughBuffer = output;		}	}	[CustomPortBehavior(nameof(input))]	IEnumerable< PortData > InputPortBehavior(List< SerializableEdge > edges)	{		// When the node is initialized, the input ports is empty because it's this function that generate the ports		int sizeInPixel = 0;		if (inputPorts.Count != 0)		{			// Add the size of all input edges:			var inputEdges = inputPorts[0]?.GetEdges();			sizeInPixel = inputEdges.Sum(e => Mathf.Max(0, e.outputPort.portData.sizeInPixel - 8));		}				if (edges.Count == 1 && !packInput)			inputType.type = edges[0].outputPort.portData.displayType;		else			inputType.type = typeof(object);		yield return new PortData {			displayName = "",			displayType = inputType.type,			identifier = "0",			acceptMultipleEdges = true,			sizeInPixel = Mathf.Min(k_MaxPortSize, sizeInPixel + 8),		};	}	[CustomPortBehavior(nameof(output))]	IEnumerable< PortData > OutputPortBehavior(List< SerializableEdge > edges)	{		if (inputPorts.Count == 0)		{			// Default dummy port to avoid having a relay without any output:			yield return new PortData {				displayName = "",				displayType = typeof(object),				identifier = "0",				acceptMultipleEdges = true,			};			yield break;		}		var inputPortEdges = inputPorts[0].GetEdges();		var underlyingPortData = GetUnderlyingPortDataList();		if (unpackOutput && inputPortEdges.Count == 1)		{			yield return new PortData			{				displayName = "Pack",				identifier = packIdentifier,				displayType = inputType.type,				acceptMultipleEdges = true,				sizeInPixel = Mathf.Min(k_MaxPortSize, Mathf.Max(underlyingPortData.Count, 1) + 7), // TODO: function			};			// We still keep the packed data as output when unpacking just in case we want to continue the relay after unpacking			for (int i = 0; i < underlyingPortData.Count; i++)			{				yield return new PortData {					displayName = underlyingPortData?[i].name ?? "",					displayType = underlyingPortData?[i].type ?? typeof(object),					identifier = i.ToString(),					acceptMultipleEdges = true,					sizeInPixel = 0,				};			}		}		else		{			yield return new PortData {				displayName = "",				displayType = inputType.type,				identifier = "0",				acceptMultipleEdges = true,				sizeInPixel = Mathf.Min(k_MaxPortSize, Mathf.Max(underlyingPortData.Count, 1) + 7),			};		}	}	static List<(Type, string)> s_empty = new List<(Type, string)>();	public List<(Type type, string name)> GetUnderlyingPortDataList()	{		// get input edges:		if (inputPorts.Count == 0)			return s_empty;		var inputEdges = GetNonRelayEdges();		if (inputEdges != null)			return inputEdges.Select(e => (e.outputPort.portData.displayType ?? e.outputPort.fieldInfo.FieldType, e.outputPort.portData.displayName)).ToList();		return s_empty;	}	public List<SerializableEdge> GetNonRelayEdges()	{		var inputEdges = inputPorts?[0]?.GetEdges();		// Iterate until we don't have a relay node in input		while (inputEdges.Count == 1 && inputEdges.First().outputNode.GetType() == typeof(RelayNode))			inputEdges = inputEdges.First().outputNode.inputPorts[0]?.GetEdges();		return inputEdges;	}}
 |