diff --git a/Scripts/Editor/NodeEditorGUILayout.cs b/Scripts/Editor/NodeEditorGUILayout.cs index b17fea3..8089265 100644 --- a/Scripts/Editor/NodeEditorGUILayout.cs +++ b/Scripts/Editor/NodeEditorGUILayout.cs @@ -45,7 +45,7 @@ namespace XNodeEditor { float spacePadding = 0; SpaceAttribute spaceAttribute; - if(NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out spaceAttribute)) spacePadding = spaceAttribute.height; + if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out spaceAttribute)) spacePadding = spaceAttribute.height; // If property is an input, display a regular property field and put a port handle on the left side if (port.direction == XNode.NodePort.IO.Input) { @@ -53,7 +53,7 @@ namespace XNodeEditor { XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected; XNode.Node.InputAttribute inputAttribute; bool instancePortList = false; - if (NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out inputAttribute)) { + if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out inputAttribute)) { instancePortList = inputAttribute.instancePortList; showBacking = inputAttribute.backingValue; } @@ -98,7 +98,7 @@ namespace XNodeEditor { XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected; XNode.Node.OutputAttribute outputAttribute; bool instancePortList = false; - if (NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out outputAttribute)) { + if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out outputAttribute)) { instancePortList = outputAttribute.instancePortList; showBacking = outputAttribute.backingValue; } diff --git a/Scripts/Editor/NodeEditorUtilities.cs b/Scripts/Editor/NodeEditorUtilities.cs index 0d98420..828207f 100644 --- a/Scripts/Editor/NodeEditorUtilities.cs +++ b/Scripts/Editor/NodeEditorUtilities.cs @@ -15,6 +15,9 @@ namespace XNodeEditor { /// C#'s Script Icon [The one MonoBhevaiour Scripts have]. private static Texture2D scriptIcon = (EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D); + /// Saves Attribute from Type+Field for faster lookup. Resets on recompiles. + private static Dictionary>> typeAttributes = new Dictionary>>(); + public static bool GetAttrib(Type classType, out T attribOut) where T : Attribute { object[] attribs = classType.GetCustomAttributes(typeof(T), false); return GetAttrib(attribs, out attribOut); @@ -45,6 +48,34 @@ namespace XNodeEditor { return false; } + public static bool GetCachedAttrib(Type classType, string fieldName, out T attribOut) where T : Attribute { + Dictionary> typeFields; + if (!typeAttributes.TryGetValue(classType, out typeFields)) { + typeFields = new Dictionary>(); + typeAttributes.Add(classType, typeFields); + } + + Dictionary typeTypes; + if(!typeFields.TryGetValue(fieldName, out typeTypes)) { + typeTypes = new Dictionary(); + typeFields.Add(fieldName, typeTypes); + } + + Attribute attr; + if (!typeTypes.TryGetValue(typeof(T), out attr)) { + if (GetAttrib(classType, fieldName, out attribOut)) typeTypes.Add(typeof(T), attribOut); + else typeTypes.Add(typeof(T), null); + } + + if(attr == null) { + attribOut = null; + return false; + } + + attribOut = attr as T; + return true; + } + /// Returns true if this can be casted to public static bool IsCastableTo(this Type from, Type to) { if (to.IsAssignableFrom(from)) return true;