mirror of
https://github.com/Siccity/xNode.git
synced 2025-12-20 09:16:01 +08:00
Internal NodePorts now uses dicts instead of lists. This is faster and more manageable. Added instance ports. Added Node.Ports, Node.Outputs, Node.Inputs, Node.InstanceOutputs, Node.InstanceInputs Changed public GetInputByFieldName to GetInputValue and GetInputPort
102 lines
4.1 KiB
C#
102 lines
4.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
/// <summary> Precaches reflection data in editor so we won't have to do it runtime </summary>
|
|
public static class NodeDataCache {
|
|
private static PortDataCache portDataCache;
|
|
private static bool Initialized { get { return portDataCache != null; } }
|
|
|
|
/// <summary> Update static ports to reflect class fields. </summary>
|
|
public static void UpdatePorts(Node node, Dictionary<string, NodePort> ports) {
|
|
if (!Initialized) BuildCache();
|
|
|
|
Dictionary<string, NodePort> staticPorts = new Dictionary<string, NodePort>();
|
|
System.Type nodeType = node.GetType();
|
|
|
|
if (!portDataCache.ContainsKey(nodeType)) return;
|
|
for (int i = 0; i < portDataCache[nodeType].Count; i++) {
|
|
staticPorts.Add(portDataCache[nodeType][i].fieldName, portDataCache[nodeType][i]);
|
|
}
|
|
|
|
// Cleanup port dict - Remove nonexisting static ports - update static port types
|
|
foreach (NodePort port in ports.Values) {
|
|
if (staticPorts.ContainsKey(port.fieldName)) {
|
|
NodePort staticPort = staticPorts[port.fieldName];
|
|
if (port.IsDynamic || port.direction != staticPort.direction) ports.Remove(port.fieldName);
|
|
else port.type = staticPort.type;
|
|
} else {
|
|
ports.Remove(port.fieldName);
|
|
}
|
|
}
|
|
// Add missing ports
|
|
foreach (NodePort staticPort in staticPorts.Values) {
|
|
if (!ports.ContainsKey(staticPort.fieldName)) {
|
|
ports.Add(staticPort.fieldName, new NodePort(staticPort, node));
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildCache() {
|
|
portDataCache = new PortDataCache();
|
|
System.Type baseType = typeof(Node);
|
|
Assembly assembly = Assembly.GetAssembly(baseType);
|
|
System.Type[] nodeTypes = assembly.GetTypes().Where(t =>
|
|
!t.IsAbstract &&
|
|
baseType.IsAssignableFrom(t)
|
|
).ToArray();
|
|
|
|
for (int i = 0; i < nodeTypes.Length; i++) {
|
|
CachePorts(nodeTypes[i]);
|
|
}
|
|
}
|
|
|
|
private static void CachePorts(System.Type nodeType) {
|
|
System.Reflection.FieldInfo[] fieldInfo = nodeType.GetFields();
|
|
for (int i = 0; i < fieldInfo.Length; i++) {
|
|
|
|
//Get InputAttribute and OutputAttribute
|
|
object[] attribs = fieldInfo[i].GetCustomAttributes(false);
|
|
Node.InputAttribute inputAttrib = attribs.FirstOrDefault(x => x is Node.InputAttribute) as Node.InputAttribute;
|
|
Node.OutputAttribute outputAttrib = attribs.FirstOrDefault(x => x is Node.OutputAttribute) as Node.OutputAttribute;
|
|
|
|
if (inputAttrib == null && outputAttrib == null) continue;
|
|
|
|
if (inputAttrib != null && outputAttrib != null) Debug.LogError("Field " + fieldInfo + " cannot be both input and output.");
|
|
else {
|
|
if (!portDataCache.ContainsKey(nodeType)) portDataCache.Add(nodeType, new List<NodePort>());
|
|
portDataCache[nodeType].Add(new NodePort(fieldInfo[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
private class PortDataCache : Dictionary<System.Type, List<NodePort>>, ISerializationCallbackReceiver {
|
|
[SerializeField] private List<System.Type> keys = new List<System.Type>();
|
|
[SerializeField] private List<List<NodePort>> values = new List<List<NodePort>>();
|
|
|
|
// save the dictionary to lists
|
|
public void OnBeforeSerialize() {
|
|
keys.Clear();
|
|
values.Clear();
|
|
foreach (var pair in this) {
|
|
keys.Add(pair.Key);
|
|
values.Add(pair.Value);
|
|
}
|
|
}
|
|
|
|
// load dictionary from lists
|
|
public void OnAfterDeserialize() {
|
|
this.Clear();
|
|
|
|
if (keys.Count != values.Count)
|
|
throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable."));
|
|
|
|
for (int i = 0; i < keys.Count; i++)
|
|
this.Add(keys[i], values[i]);
|
|
}
|
|
}
|
|
} |