From 2f69c4350def2043f87cf94b2db9fb9388b516c1 Mon Sep 17 00:00:00 2001 From: Simon Rodriguez Date: Sat, 1 May 2021 18:47:39 +0200 Subject: [PATCH 1/3] Added support for unitys FormerlySerializedAsAttribute. It reconnects ports that has the old name to its new name. --- Scripts/NodeDataCache.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index ba52e1b..e05d033 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -14,6 +14,7 @@ namespace XNode { if (!Initialized) BuildCache(); Dictionary staticPorts = new Dictionary(); + Dictionary formerlySerializedAs = new Dictionary(); Dictionary> removedPorts = new Dictionary>(); System.Type nodeType = node.GetType(); @@ -24,6 +25,11 @@ namespace XNode { for (int i = 0; i < typePortCache.Count; i++) { staticPorts.Add(typePortCache[i].fieldName, portDataCache[nodeType][i]); } + for (int i = 0; i < typePortCache.Count; i++) { + var fieldInfo = nodeType.GetField(typePortCache[i].fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + var attribute = fieldInfo.GetCustomAttributes(true).FirstOrDefault(x => x is UnityEngine.Serialization.FormerlySerializedAsAttribute) as UnityEngine.Serialization.FormerlySerializedAsAttribute; + if (attribute != null) formerlySerializedAs.Add(attribute.oldName, typePortCache[i].fieldName); + } } // Cleanup port dict - Remove nonexisting static ports - update static port types @@ -43,6 +49,11 @@ namespace XNode { } // If port doesn't exist anymore, remove it else if (port.IsStatic) { + //See if the field is tagged with FormerlySerializedAs, if so add the port with its new field name to removedPorts + // so it can be reconnected in missing ports stage. + string newName = null; + if (formerlySerializedAs.TryGetValue(port.fieldName, out newName)) removedPorts.Add(newName, port.GetConnections()); + port.ClearConnections(); ports.Remove(port.fieldName); } From 3287575dcd3d03152c24454b0d962bd1ee33159e Mon Sep 17 00:00:00 2001 From: Simon Rodriguez Date: Tue, 4 May 2021 08:29:16 +0200 Subject: [PATCH 2/3] moved reflection code to cache part in initialization --- Scripts/NodeDataCache.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index e05d033..7061f17 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -7,6 +7,7 @@ namespace XNode { /// Precaches reflection data in editor so we won't have to do it runtime public static class NodeDataCache { private static PortDataCache portDataCache; + private static Dictionary> formerlySerializedAsCache; private static bool Initialized { get { return portDataCache != null; } } /// Update static ports and dynamic ports managed by DynamicPortLists to reflect class fields. @@ -14,10 +15,12 @@ namespace XNode { if (!Initialized) BuildCache(); Dictionary staticPorts = new Dictionary(); - Dictionary formerlySerializedAs = new Dictionary(); Dictionary> removedPorts = new Dictionary>(); System.Type nodeType = node.GetType(); + Dictionary formerlySerializedAs = null; + if (formerlySerializedAsCache != null) formerlySerializedAsCache.TryGetValue(nodeType, out formerlySerializedAs); + List dynamicListPorts = new List(); List typePortCache; @@ -25,11 +28,6 @@ namespace XNode { for (int i = 0; i < typePortCache.Count; i++) { staticPorts.Add(typePortCache[i].fieldName, portDataCache[nodeType][i]); } - for (int i = 0; i < typePortCache.Count; i++) { - var fieldInfo = nodeType.GetField(typePortCache[i].fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - var attribute = fieldInfo.GetCustomAttributes(true).FirstOrDefault(x => x is UnityEngine.Serialization.FormerlySerializedAsAttribute) as UnityEngine.Serialization.FormerlySerializedAsAttribute; - if (attribute != null) formerlySerializedAs.Add(attribute.oldName, typePortCache[i].fieldName); - } } // Cleanup port dict - Remove nonexisting static ports - update static port types @@ -52,7 +50,7 @@ namespace XNode { //See if the field is tagged with FormerlySerializedAs, if so add the port with its new field name to removedPorts // so it can be reconnected in missing ports stage. string newName = null; - if (formerlySerializedAs.TryGetValue(port.fieldName, out newName)) removedPorts.Add(newName, port.GetConnections()); + if (formerlySerializedAs != null && formerlySerializedAs.TryGetValue(port.fieldName, out newName)) removedPorts.Add(newName, port.GetConnections()); port.ClearConnections(); ports.Remove(port.fieldName); @@ -188,6 +186,7 @@ namespace XNode { object[] attribs = fieldInfo[i].GetCustomAttributes(true); 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; + UnityEngine.Serialization.FormerlySerializedAsAttribute formerlySerializedAsAttribute = attribs.FirstOrDefault(x => x is UnityEngine.Serialization.FormerlySerializedAsAttribute) as UnityEngine.Serialization.FormerlySerializedAsAttribute; if (inputAttrib == null && outputAttrib == null) continue; @@ -196,6 +195,12 @@ namespace XNode { if (!portDataCache.ContainsKey(nodeType)) portDataCache.Add(nodeType, new List()); portDataCache[nodeType].Add(new NodePort(fieldInfo[i])); } + + if(formerlySerializedAsAttribute != null) { + if (formerlySerializedAsCache == null) formerlySerializedAsCache = new Dictionary>(); + if (!formerlySerializedAsCache.ContainsKey(nodeType)) formerlySerializedAsCache.Add(nodeType, new Dictionary()); + formerlySerializedAsCache[nodeType].Add(formerlySerializedAsAttribute.oldName, fieldInfo[i].Name); + } } } From e1b564db1c85f611f871f15f8935ec62c1226b55 Mon Sep 17 00:00:00 2001 From: Simon Rodriguez Date: Tue, 4 May 2021 08:38:25 +0200 Subject: [PATCH 3/3] added error handling --- Scripts/NodeDataCache.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index 7061f17..f865ab2 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -199,7 +199,9 @@ namespace XNode { if(formerlySerializedAsAttribute != null) { if (formerlySerializedAsCache == null) formerlySerializedAsCache = new Dictionary>(); if (!formerlySerializedAsCache.ContainsKey(nodeType)) formerlySerializedAsCache.Add(nodeType, new Dictionary()); - formerlySerializedAsCache[nodeType].Add(formerlySerializedAsAttribute.oldName, fieldInfo[i].Name); + + if (formerlySerializedAsCache[nodeType].ContainsKey(formerlySerializedAsAttribute.oldName)) Debug.LogError("Another FormerlySerializedAs with value '" + formerlySerializedAsAttribute.oldName + "' already exist on this node."); + else formerlySerializedAsCache[nodeType].Add(formerlySerializedAsAttribute.oldName, fieldInfo[i].Name); } } }