您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
108 行
3.2 KiB
108 行
3.2 KiB
using System;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Linq.Expressions;
|
|
|
|
namespace GraphProcessor
|
|
{
|
|
public delegate void CustomPortIODelegate(BaseNode node, List< SerializableEdge > edges);
|
|
|
|
public static class CustomPortIO
|
|
{
|
|
class PortIOPerField : Dictionary< string, CustomPortIODelegate > {}
|
|
class PortIOPerNode : Dictionary< Type, PortIOPerField > {}
|
|
|
|
static Dictionary< Type, List< Type > > assignableTypes = new Dictionary< Type, List< Type > >();
|
|
static PortIOPerNode customIOPortMethods = new PortIOPerNode();
|
|
|
|
static CustomPortIO()
|
|
{
|
|
LoadCustomPortMethods();
|
|
}
|
|
|
|
static void LoadCustomPortMethods()
|
|
{
|
|
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
|
|
|
foreach (var type in AppDomain.CurrentDomain.GetAllTypes())
|
|
{
|
|
if (type.IsAbstract || type.ContainsGenericParameters)
|
|
continue ;
|
|
if (!(type.IsSubclassOf(typeof(BaseNode))))
|
|
continue ;
|
|
|
|
var methods = type.GetMethods(bindingFlags);
|
|
|
|
foreach (var method in methods)
|
|
{
|
|
var portInputAttr = method.GetCustomAttribute< CustomPortInputAttribute >();
|
|
var portOutputAttr = method.GetCustomAttribute< CustomPortOutputAttribute >();
|
|
|
|
if (portInputAttr == null && portOutputAttr == null)
|
|
continue ;
|
|
|
|
var p1 = Expression.Parameter(typeof(BaseNode), "node");
|
|
var p2 = Expression.Parameter(typeof(List< SerializableEdge >), "edges");
|
|
|
|
var ex = Expression.Call(Expression.Convert(p1, type), method, p2);
|
|
|
|
var deleg = Expression.Lambda< CustomPortIODelegate >(ex, p1, p2).Compile();
|
|
|
|
if (deleg == null)
|
|
{
|
|
Debug.LogWarning("Can't use custom IO port function " + method + ": The method have to respect this format: " + typeof(CustomPortIODelegate));
|
|
continue ;
|
|
}
|
|
|
|
string fieldName = (portInputAttr == null) ? portOutputAttr.fieldName : portInputAttr.fieldName;
|
|
Type customType = (portInputAttr == null) ? portOutputAttr.outputType : portInputAttr.inputType;
|
|
Type fieldType = type.GetField(fieldName, bindingFlags).FieldType;
|
|
|
|
AddCustomIOMethod(type, fieldName, deleg);
|
|
|
|
AddAssignableTypes(customType, fieldType);
|
|
AddAssignableTypes(fieldType, customType);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static CustomPortIODelegate GetCustomPortMethod(Type nodeType, string fieldName)
|
|
{
|
|
PortIOPerField portIOPerField;
|
|
CustomPortIODelegate deleg;
|
|
|
|
customIOPortMethods.TryGetValue(nodeType, out portIOPerField);
|
|
|
|
if (portIOPerField == null)
|
|
return null;
|
|
|
|
portIOPerField.TryGetValue(fieldName, out deleg);
|
|
|
|
return deleg;
|
|
}
|
|
|
|
static void AddCustomIOMethod(Type nodeType, string fieldName, CustomPortIODelegate deleg)
|
|
{
|
|
if (!customIOPortMethods.ContainsKey(nodeType))
|
|
customIOPortMethods[nodeType] = new PortIOPerField();
|
|
|
|
customIOPortMethods[nodeType][fieldName] = deleg;
|
|
}
|
|
|
|
static void AddAssignableTypes(Type fromType, Type toType)
|
|
{
|
|
if (!assignableTypes.ContainsKey(fromType))
|
|
assignableTypes[fromType] = new List< Type >();
|
|
|
|
assignableTypes[fromType].Add(toType);
|
|
}
|
|
|
|
public static bool IsAssignable(Type input, Type output)
|
|
{
|
|
if (assignableTypes.ContainsKey(input))
|
|
return assignableTypes[input].Contains(output);
|
|
return false;
|
|
}
|
|
}
|
|
}
|