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;
- }
- }
|