1
0
mirror of https://github.com/Siccity/xNode.git synced 2026-03-26 22:49:02 +08:00

!O(Dynamic Port List) 默认实现存在潜规则,删除了潜规则

This commit is contained in:
Icarus 2019-11-28 03:48:25 +08:00
parent 1fece9c7c5
commit 413f4e2f52
2 changed files with 60 additions and 69 deletions

View File

@ -6,6 +6,7 @@ using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEditorInternal; using UnityEditorInternal;
using UnityEngine; using UnityEngine;
using XNode;
namespace XNodeEditor { namespace XNodeEditor {
/// <summary> xNode-specific version of <see cref="EditorGUILayout"/> </summary> /// <summary> xNode-specific version of <see cref="EditorGUILayout"/> </summary>
@ -302,23 +303,19 @@ namespace XNodeEditor {
/// <param name="connectionType">Connection type of added dynamic ports</param> /// <param name="connectionType">Connection type of added dynamic ports</param>
/// <param name="inputTypeConstraintBaseType">当<see cref="io"/>为<see cref="IO.Input"/>并且<see cref="typeConstraint"/>为<see cref="TypeConstraint.Inherited"/>时可用</param> /// <param name="inputTypeConstraintBaseType">当<see cref="io"/>为<see cref="IO.Input"/>并且<see cref="typeConstraint"/>为<see cref="TypeConstraint.Inherited"/>时可用</param>
/// <param name="onCreation">Called on the list on creation. Use this if you want to customize the created ReorderableList</param> /// <param name="onCreation">Called on the list on creation. Use this if you want to customize the created ReorderableList</param>
public static void DynamicPortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None,Type inputTypeConstraintBaseType = null, Action<ReorderableList> onCreation = null) { public static void DynamicPortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io,
XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple,
XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None,Type inputTypeConstraintBaseType = null,
Action<ReorderableList> onCreation = null) {
XNode.Node node = serializedObject.targetObject as XNode.Node; XNode.Node node = serializedObject.targetObject as XNode.Node;
var indexedPorts = node.DynamicPorts.Select(x => { var indexedPorts = node.DynamicPorts;
string[] split = x.fieldName.Split(' ');
if (split != null && split.Length == 2 && split[0] == fieldName) { List<XNode.NodePort> dynamicPorts = indexedPorts.ToList();
int i = -1;
if (int.TryParse(split[1], out i)) {
return new { index = i, port = x };
}
}
return new { index = -1, port = (XNode.NodePort) null };
}).Where(x => x.port != null);
List<XNode.NodePort> dynamicPorts = indexedPorts.OrderBy(x => x.index).Select(x => x.port).ToList();
ReorderableList list = null; ReorderableList list = null;
Dictionary<string, ReorderableList> rlc; Dictionary<string, ReorderableList> rlc;
//todo rename no update cache -- 2019年11月28日03点00分
if (reorderableListCache.TryGetValue(serializedObject.targetObject, out rlc)) { if (reorderableListCache.TryGetValue(serializedObject.targetObject, out rlc)) {
if (!rlc.TryGetValue(fieldName, out list)) list = null; if (!rlc.TryGetValue(fieldName, out list)) list = null;
} }
@ -340,16 +337,22 @@ namespace XNodeEditor {
string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName); string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName);
list.drawElementCallback = list.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => { (Rect rect, int index, bool isActive, bool isFocused) =>
XNode.NodePort port = node.GetPort(fieldName + " " + index); {
if (hasArrayData) { XNode.NodePort port = (NodePort) list.list[index];
if (hasArrayData)
{
if (arrayData.arraySize <= index) { if (arrayData.arraySize <= index) {
EditorGUI.LabelField(rect, "Array[" + index + "] data out of range"); EditorGUI.LabelField(rect, "Array[" + index + "] data out of range");
return; return;
} }
SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index);
EditorGUI.PropertyField(rect, itemData, true); EditorGUI.PropertyField(rect, itemData, true);
} else EditorGUI.LabelField(rect, port != null ? port.fieldName : ""); }
else
EditorGUI.LabelField(rect, port != null ? port.fieldName : "");
if (port != null) { if (port != null) {
Vector2 pos = rect.position + (port.IsOutput?new Vector2(rect.width + 6, 0) : new Vector2(-36, 0)); Vector2 pos = rect.position + (port.IsOutput?new Vector2(rect.width + 6, 0) : new Vector2(-36, 0));
NodeEditorGUILayout.PortField(pos, port); NodeEditorGUILayout.PortField(pos, port);
@ -363,58 +366,43 @@ namespace XNodeEditor {
return EditorGUI.GetPropertyHeight(itemData); return EditorGUI.GetPropertyHeight(itemData);
} else return EditorGUIUtility.singleLineHeight; } else return EditorGUIUtility.singleLineHeight;
}; };
list.drawHeaderCallback = list.drawHeaderCallback =
(Rect rect) => { (Rect rect) => {
EditorGUI.LabelField(rect, label); EditorGUI.LabelField(rect, label);
}; };
list.onSelectCallback = list.onSelectCallback =
(ReorderableList rl) => { (ReorderableList rl) => {
reorderableListIndex = rl.index; reorderableListIndex = rl.index;
}; };
list.onReorderCallback =
(ReorderableList rl) => {
// Move up list.onReorderCallbackWithDetails = (reorderableList, index, newIndex) =>
if (rl.index > reorderableListIndex) { {
for (int i = reorderableListIndex; i < rl.index; ++i) { var port = serializedObject.FindProperty(Node.PortFieldName);
XNode.NodePort port = node.GetPort(fieldName + " " + i); SerializedProperty keys = port.FindPropertyRelative(Node.KeysFieldName);
XNode.NodePort nextPort = node.GetPort(fieldName + " " + (i + 1)); SerializedProperty values = port.FindPropertyRelative(Node.ValuesFieldName);
port.SwapConnections(nextPort); var count = 0;
// Swap cached positions to mitigate twitching foreach (var nodePort in node.Ports)
Rect rect = NodeEditorWindow.current.portConnectionPoints[port]; {
NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort]; if (!reorderableList.list.Contains(nodePort))
NodeEditorWindow.current.portConnectionPoints[nextPort] = rect; {
} count++;
continue;
} }
// Move down
else { //list after May exist dynamic node so break
for (int i = reorderableListIndex; i > rl.index; --i) { break;
XNode.NodePort port = node.GetPort(fieldName + " " + i); }
XNode.NodePort nextPort = node.GetPort(fieldName + " " + (i - 1));
port.SwapConnections(nextPort); index += count;
newIndex += count;
keys.MoveArrayElement(index, newIndex);
values.MoveArrayElement(index, newIndex);
};
// Swap cached positions to mitigate twitching
Rect rect = NodeEditorWindow.current.portConnectionPoints[port];
NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort];
NodeEditorWindow.current.portConnectionPoints[nextPort] = rect;
}
}
// Apply changes
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
// Move array data if there is any
if (hasArrayData) {
arrayData.MoveArrayElement(reorderableListIndex, rl.index);
}
// Apply changes
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
NodeEditorWindow.current.Repaint();
EditorApplication.delayCall += NodeEditorWindow.current.Repaint;
};
list.onAddCallback = list.onAddCallback =
(ReorderableList rl) => { (ReorderableList rl) => {
// Add dynamic port postfixed with an index number // Add dynamic port postfixed with an index number
@ -432,19 +420,11 @@ namespace XNodeEditor {
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
}; };
list.onRemoveCallback = list.onRemoveCallback =
(ReorderableList rl) => { (ReorderableList rl) =>
{
var indexedPorts = node.DynamicPorts.Select(x => { var indexedPorts = node.DynamicPorts;
string[] split = x.fieldName.Split(' '); dynamicPorts = indexedPorts.ToList();
if (split != null && split.Length == 2 && split[0] == fieldName) {
int i = -1;
if (int.TryParse(split[1], out i)) {
return new { index = i, port = x };
}
}
return new { index = -1, port = (XNode.NodePort) null };
}).Where(x => x.port != null);
dynamicPorts = indexedPorts.OrderBy(x => x.index).Select(x => x.port).ToList();
int index = rl.index; int index = rl.index;

View File

@ -111,6 +111,12 @@ namespace XNode {
/// <summary> It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> </summary> /// <summary> It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> </summary>
[SerializeField] private NodePortDictionary ports = new NodePortDictionary(); [SerializeField] private NodePortDictionary ports = new NodePortDictionary();
#if UNITY_EDITOR
public const string PortFieldName = nameof(ports);
public const string KeysFieldName = NodePortDictionary.KeyFieldName;
public const string ValuesFieldName = NodePortDictionary.ValueFieldName;
#endif
/// <summary> Used during node instantiation to fix null/misconfigured graph during OnEnable/Init. Set it before instantiating a node. Will automatically be unset during OnEnable </summary> /// <summary> Used during node instantiation to fix null/misconfigured graph during OnEnable/Init. Set it before instantiating a node. Will automatically be unset during OnEnable </summary>
public static NodeGraph graphHotfix; public static NodeGraph graphHotfix;
@ -366,6 +372,11 @@ namespace XNode {
[SerializeField] private List<string> keys = new List<string>(); [SerializeField] private List<string> keys = new List<string>();
[SerializeField] private List<NodePort> values = new List<NodePort>(); [SerializeField] private List<NodePort> values = new List<NodePort>();
#if UNITY_EDITOR
public const string KeyFieldName = nameof(keys);
public const string ValueFieldName = nameof(values);
#endif
public void OnBeforeSerialize() { public void OnBeforeSerialize() {
keys.Clear(); keys.Clear();
values.Clear(); values.Clear();