Changing Port Order With OverrideFieldOrder Loses Port Edge Type
So I have a couple layers of inheritance first. It looks like this: BaseNode > DynamicNode<T> > SequenceNode
In Dynamic node I'm creating ports on the fly with CustomPortBehavior and CustomPortInput. Everything works how you would expect except I'd prefer if the ports were reordered so I did by implementing the OverrideFieldOrder method. Essentially all I'm doing is reversing the original order. i.e. return base.OverrideFieldOrder(fields).Reverse();.
Also for some reason the property drawer for a float in DynamicNode is in the wrong place by default.
The order is reversed correctly but when creating a connection node in the menu it doesn't pickup up the correct type.
Before (Dragging&Dropping an edge):
After (Dragging&Dropping an edge):

The float itself does work before and after so I think it could be some kind of generic inheritance thing.
Code For DynamicNode<T>:
DynamicNode Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GraphProcessor;
using System.Linq;
using System.Reflection;
using System;
[System.Serializable]
public abstract class DynamicNode<T> : BaseNode
{
[Input("Action Data")]
public Dictionary<string, object> actionData = new Dictionary<string, object>();
[Input("Float Val"), SerializeField] public float floatVal;
[SerializeField, ExpandableSO, ValueChangedCallback(nameof(OnDataChanged))] public T data;
protected override void Process()
{
UpdateActionWithCustomPortData();
}
protected virtual void UpdateActionWithCustomPortData()
{
// We clone due to reference issues
Dictionary<string, object> actionDataClone = new Dictionary<string, object>(actionData);
foreach (var field in GetInputFieldsOfType())
{
if (!actionDataClone.ContainsKey(field.fieldInfo.Name))
{
field.fieldInfo.SetValue(data, default);
}
else
{
field.fieldInfo.SetValue(data, actionDataClone[field.fieldInfo.Name]);
}
}
actionData.Clear();
}
protected virtual void OnDataChanged(UnityEditor.SerializedProperty serializedProperty)
{
UpdatePortsForFieldLocal(nameof(actionData));
}
#region Reflection Generation Of Ports
private List<FieldPortInfo> GetInputFieldsOfType()
{
List<FieldPortInfo> foundInputFields = new List<FieldPortInfo>();
Type dataType = actionData != null ? data.GetType() : typeof(T);
foreach (var field in dataType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
foreach (var attribute in field.GetCustomAttributes(typeof(InputAttribute), true))
{
if (attribute.GetType() != typeof(InputAttribute)) continue;
foundInputFields.Add(new FieldPortInfo(field, attribute as InputAttribute));
break;
}
}
return foundInputFields;
}
[CustomPortInput(nameof(actionData), typeof(object))]
protected void PullInputs(List<SerializableEdge> connectedEdges)
{
if (actionData == null) actionData = new Dictionary<string, object>();
foreach (SerializableEdge t in connectedEdges)
{
actionData.Add(t.inputPortIdentifier, t.passThroughBuffer);
}
}
[CustomPortBehavior(nameof(actionData))]
protected IEnumerable<PortData> ActionDataBehaviour(List<SerializableEdge> edges)
{
foreach (var field in GetInputFieldsOfType())
{
yield return new PortData
{
displayName = field.inputAttribute.name,
displayType = field.fieldInfo.FieldType,
identifier = field.fieldInfo.Name,
acceptMultipleEdges = false,
};
}
}
public override IEnumerable<FieldInfo> OverrideFieldOrder(IEnumerable<FieldInfo> fields)
{
return base.OverrideFieldOrder(fields).Reverse();
// static long GetFieldInheritanceLevel(FieldInfo f)
// {
// int level = 0;
// var t = f.DeclaringType;
// while (t != null)
// {
// t = t.BaseType;
// level++;
// }
// return level;
// }
// // Order by MetadataToken and inheritance level to sync the order with the port order (make sure FieldDrawers are next to the correct port)
// return fields.OrderByDescending(f => (GetFieldInheritanceLevel(f) << 32) | (long)f.MetadataToken);
}
#endregion
}
public struct FieldPortInfo
{
public FieldInfo fieldInfo;
public InputAttribute inputAttribute;
public FieldPortInfo(FieldInfo fieldInfo, InputAttribute inputAttribute)
{
this.fieldInfo = fieldInfo;
this.inputAttribute = inputAttribute;
}
}