您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
161 行
4.2 KiB
161 行
4.2 KiB
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System.Reflection;
|
|
using System.Linq.Expressions;
|
|
using System;
|
|
|
|
namespace GraphProcessor
|
|
{
|
|
public class NodePort
|
|
{
|
|
|
|
public string fieldName;
|
|
public BaseNode owner;
|
|
List< SerializableEdge > edges = new List< SerializableEdge >();
|
|
Dictionary< SerializableEdge, PushDataDelegate > pushDataDelegates = new Dictionary< SerializableEdge, PushDataDelegate >();
|
|
List< SerializableEdge > edgeWithRemoteCustomIO = new List< SerializableEdge >();
|
|
|
|
CustomPortIODelegate customPortIOMethod;
|
|
FieldInfo ourValueField;
|
|
|
|
public delegate void PushDataDelegate();
|
|
|
|
public NodePort(BaseNode owner, string fieldName)
|
|
{
|
|
this.fieldName = fieldName;
|
|
this.owner = owner;
|
|
|
|
ourValueField = owner.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
customPortIOMethod = CustomPortIO.GetCustomPortMethod(owner.GetType(), fieldName);
|
|
}
|
|
|
|
public void Add(SerializableEdge edge)
|
|
{
|
|
if (!edges.Contains(edge))
|
|
edges.Add(edge);
|
|
|
|
if (edge.inputNode == owner)
|
|
{
|
|
if (edge.outputPort.customPortIOMethod != null)
|
|
edgeWithRemoteCustomIO.Add(edge);
|
|
}
|
|
else
|
|
{
|
|
if (edge.inputPort.customPortIOMethod != null)
|
|
edgeWithRemoteCustomIO.Add(edge);
|
|
}
|
|
|
|
//if we have a custom io implementation, we don't need
|
|
if (edge.inputPort.customPortIOMethod != null || edge.outputPort.customPortIOMethod != null)
|
|
return ;
|
|
|
|
PushDataDelegate edgeDelegate = CreatePushDataDelegateForEdge(edge);
|
|
|
|
if (edgeDelegate != null)
|
|
pushDataDelegates[edge] = edgeDelegate;
|
|
}
|
|
|
|
PushDataDelegate CreatePushDataDelegateForEdge(SerializableEdge edge)
|
|
{
|
|
try
|
|
{
|
|
//Creation of the delegate to move the data from the input node to the output node:
|
|
FieldInfo inputField = edge.inputNode.GetType().GetField(edge.trueInputFieldName, BindingFlags.Public | BindingFlags.Instance);
|
|
FieldInfo outputField = edge.outputNode.GetType().GetField(edge.trueOutputFieldName, BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
MemberExpression inputParamField = Expression.Field(Expression.Constant(edge.inputNode), inputField);
|
|
MemberExpression outputParamField = Expression.Field(Expression.Constant(edge.outputNode), outputField);
|
|
|
|
BinaryExpression assign = Expression.Assign(inputParamField, Expression.Convert(outputParamField, inputField.FieldType));
|
|
return Expression.Lambda< PushDataDelegate >(assign).Compile();
|
|
} catch (Exception e) {
|
|
Debug.LogError(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void Remove(SerializableEdge edge)
|
|
{
|
|
pushDataDelegates.Remove(edge);
|
|
edges.Remove(edge);
|
|
}
|
|
|
|
public List< SerializableEdge > GetEdges()
|
|
{
|
|
return edges;
|
|
}
|
|
|
|
//This method can only be called on output ports
|
|
public void PushData()
|
|
{
|
|
if (customPortIOMethod != null)
|
|
{
|
|
customPortIOMethod(owner, edges);
|
|
return ;
|
|
}
|
|
|
|
foreach (var pushDataDelegate in pushDataDelegates)
|
|
pushDataDelegate.Value();
|
|
|
|
if (edgeWithRemoteCustomIO.Count == 0)
|
|
return ;
|
|
|
|
//if there are custom IO implementation on the other ports, they'll need our value in the passThrough buffer
|
|
object ourValue = ourValueField.GetValue(owner);
|
|
foreach (var edge in edgeWithRemoteCustomIO)
|
|
edge.passThroughBuffer = ourValue;
|
|
}
|
|
|
|
public void PullData()
|
|
{
|
|
if (customPortIOMethod != null)
|
|
{
|
|
customPortIOMethod(owner, edges);
|
|
}
|
|
}
|
|
}
|
|
|
|
public abstract class NodePortContainer : List< NodePort >
|
|
{
|
|
protected BaseNode node;
|
|
|
|
public NodePortContainer(BaseNode node)
|
|
{
|
|
this.node = node;
|
|
}
|
|
|
|
public void Remove(SerializableEdge edge)
|
|
{
|
|
ForEach(p => p.Remove(edge));
|
|
}
|
|
|
|
public void Add(SerializableEdge edge)
|
|
{
|
|
string portFieldName = (edge.inputNode == node) ? edge.inputFieldName : edge.outputFieldName;
|
|
var port = this.FirstOrDefault(p => p.fieldName == portFieldName);
|
|
port.Add(edge);
|
|
}
|
|
}
|
|
|
|
public class NodeInputPortContainer : NodePortContainer
|
|
{
|
|
public NodeInputPortContainer(BaseNode node) : base(node) {}
|
|
|
|
public void PullDatas()
|
|
{
|
|
ForEach(p => p.PullData());
|
|
}
|
|
}
|
|
|
|
public class NodeOutputPortContainer : NodePortContainer
|
|
{
|
|
public NodeOutputPortContainer(BaseNode node) : base(node) {}
|
|
|
|
public void PushDatas()
|
|
{
|
|
ForEach(p => p.PushData());
|
|
}
|
|
}
|
|
}
|