Gameplay Ingredients是一组用于 Unity 游戏的运行时和编辑器工具:一组脚本的集合,可在制作游戏和原型时简化简单的任务。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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