Ver Fonte

Refactor & Optimize: UI classes now have a mantis class reference

This commit ends up saving ~10% time in the component_groups test file. (from ~1.1s to ~0.9s).
The biggest change is the fact that there is no costly lookup function finding mantis classes during
tree parsing. Now, the classes get a class reference assigned at init - even better, if the class reference
is not found, the class won't init and the addon will fail to load. Thus, it is also an effective error-
finding solution for the problem it solves.
The code is a little ugly, but not terribly so, and it provides a stopgap solution while I prepare the
much bigger change of generating UI classes programatically. So the ugliness is temporary.

There is also a tiny change in MantisNodeSocketCollection which removes a custom __setitem__
which, though harmless, was costing me precious milliseconds.

the change in schema_containers is formatting/cleanup.
Joseph Brandenburg há 7 meses atrás
pai
commit
e6a08d79b8

+ 25 - 9
base_definitions.py

@@ -23,6 +23,8 @@ def TellClasses():
 def error_popup_draw(self, context):
     self.layout.label(text="Error executing tree. See Console.")
 
+mantis_root = ".".join(__name__.split('.')[:-1]) # absolute HACK
+
 class MantisTree(NodeTree):
     '''A custom node tree type that will show up in the editor type list'''
     bl_idname = 'MantisTree'
@@ -139,10 +141,24 @@ class MantisUINode:
         MantisUINode objects will spawn one or more MantisNode objects when the graph is evaluated.
         The MantisNode objects will pull the data from the UI node and use it to generate the graph.
     """
+    mantis_node_library=''
+    mantis_node_class_name=''
+    mantis_class=None
     @classmethod
     def poll(cls, ntree):
         return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
                 
+    @classmethod
+    def set_mantis_class(self):
+        from importlib import import_module
+        # do not catch errors, they should cause a failure.
+        try:
+            module = import_module(self.mantis_node_library, package=mantis_root)
+            self.mantis_class=getattr(module, self.mantis_node_class_name)
+        except Exception as e:
+            print(self)
+            raise e
+
     def insert_link(self, link):
         context = bpy.context
         if context.space_data:
@@ -156,22 +172,26 @@ class MantisUINode:
                     node_tree.num_links+=1
         
             
-class SchemaUINode:
+class SchemaUINode(MantisUINode):
+    mantis_node_library='.schema_containers'
     @classmethod
     def poll(cls, ntree):
         return (ntree.bl_idname in ['SchemaTree'])
 
 class LinkNode(MantisUINode):
+    mantis_node_library='.link_containers'
     @classmethod
     def poll(cls, ntree):
         return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
-
+    
 class xFormNode(MantisUINode):
+    mantis_node_library='.xForm_containers'
     @classmethod
     def poll(cls, ntree):
         return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
 
 class DeformerNode(MantisUINode):
+    mantis_node_library='.deformer_containers'
     @classmethod
     def poll(cls, ntree):
         return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
@@ -406,13 +426,13 @@ class MantisNode:
         self.signature = signature
         self.inputs = MantisNodeSocketCollection(node=self, is_input=True)
         self.outputs = MantisNodeSocketCollection(node=self, is_input=False)
-        self.parameters = dict()
+        self.parameters = {}
+        self.drivers = {}
         self.node_type='UNINITIALIZED'
         self.hierarchy_connections, self.connections = [], []
         self.hierarchy_dependencies, self.dependencies = [], []
         self.prepared = False
         self.executed = False
-        self.drivers = {}
 
     def init_parameters(self, additional_parameters = {}):
         for socket in self.inputs:
@@ -658,11 +678,7 @@ class MantisNodeSocketCollection(dict):
         for socket in sockets:
             if not isinstance(socket, str): raise RuntimeError("NodeSocketCollection keys must be str.")
             self[socket] = NodeSocket(is_input=self.is_input, name=socket, node=self.node)
-
-    def __setitem__(self, key, value=None):
-        """Allows setting items using square brackets: obj[key] = value"""
-        super().__setitem__(key, value)
-    
+            
     def __delitem__(self, key):
         """Deletes a node socket by name, and all its links."""
         socket = self[key]

+ 8 - 1
deformer_definitions.py

@@ -29,6 +29,7 @@ class DeformerArmatureNode(Node, DeformerNode):
     bl_label = "Armature Deform"
     bl_icon = 'MOD_ARMATURE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         # self.inputs.new ("RelationshipSocket", "Input Relationship")
@@ -66,6 +67,7 @@ class DeformerHook(Node, DeformerNode):
     bl_label = "Hook Deform"
     bl_icon = 'HOOK'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new("DeformerSocket", "Deformer")
@@ -116,6 +118,7 @@ class DeformerMorphTargetDeform(Node, DeformerNode):
     bl_icon = 'MOD_ARMATURE'
     initialized : bpy.props.BoolProperty(default = False)
     num_targets : bpy.props.IntProperty(default = 0)
+    mantis_node_class_name=bl_idname
 
 
     def init(self, context):
@@ -183,6 +186,7 @@ class DeformerMorphTarget(Node, DeformerNode):
     bl_icon = 'SHAPEKEY_DATA'
     initialized : bpy.props.BoolProperty(default = False)
     num_targets : bpy.props.IntProperty(default = 0)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new('xFormSocket', "Relative to")
@@ -191,4 +195,7 @@ class DeformerMorphTarget(Node, DeformerNode):
         self.outputs.new('MorphTargetSocket', "Morph Target")
 
         self.initialized = True
-    
+
+# Set up the class property that ties the UI classes to the Mantis classes.
+for cls in TellClasses():
+    cls.set_mantis_class()

+ 25 - 18
link_definitions.py

@@ -1,6 +1,6 @@
 import bpy
 from bpy.types import NodeTree, Node, NodeSocket
-from .base_definitions import MantisUINode, LinkNode, GraphError
+from .base_definitions import LinkNode, GraphError
 from .utilities import (prRed, prGreen, prPurple, prWhite,
                               prOrange,
                               wrapRed, wrapGreen, wrapPurple, wrapWhite,
@@ -37,7 +37,6 @@ def default_traverse(self, socket):
             return self.outputs["Output Relationship"]
         return None
 
-
 from mathutils import Color # these colors were sampled from Blender's UI
 # TODO: maybe read the relevant colors from the Theme
 linkColor = Color((0.028034, 0.093164, 0.070379)).from_scene_linear_to_srgb()
@@ -55,6 +54,7 @@ class LinkInheritNode(Node, LinkNode):
     bl_label = "Inherit"
     bl_icon = 'CONSTRAINT_BONE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name="LinkInherit"
     
     
     # bone_prev : bpy.props.BoolProperty(default=False)
@@ -117,7 +117,7 @@ class LinkInverseKinematics(Node, LinkNode):
     bl_label = "Inverse Kinematics"
     bl_icon = 'CON_KINEMATIC'
     initialized : bpy.props.BoolProperty(default = False)
-    
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new('RelationshipSocket', "Input Relationship")
@@ -148,8 +148,8 @@ class LinkCopyLocationNode(Node, LinkNode):
     bl_idname = 'LinkCopyLocation'
     bl_label = "Copy Location"
     bl_icon = 'CON_LOCLIKE'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -176,8 +176,8 @@ class LinkCopyRotationNode(Node, LinkNode):
     bl_idname = 'LinkCopyRotation'
     bl_label = "Copy Rotation"
     bl_icon = 'CON_ROTLIKE'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -204,8 +204,8 @@ class LinkCopyScaleNode(Node, LinkNode):
     bl_idname = 'LinkCopyScale'
     bl_label = "Copy Scale"
     bl_icon = 'CON_SIZELIKE'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -235,8 +235,8 @@ class LinkInheritConstraintNode(Node, LinkNode):
     bl_idname = 'LinkInheritConstraint'
     bl_label = "Inherit (constraint)"
     bl_icon = 'CON_CHILDOF'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     # === Optional Functions ===
     def init(self, context):
@@ -263,9 +263,8 @@ class LinkCopyTransformNode(Node, LinkNode):
     bl_idname = 'LinkCopyTransforms'
     bl_label = "Copy Transform"
     bl_icon = 'CON_TRANSLIKE'
-    
     initialized : bpy.props.BoolProperty(default = False)
-
+    mantis_node_class_name=bl_idname
 
     # === Optional Functions ===
     def init(self, context):
@@ -292,8 +291,9 @@ class LinkStretchToNode(Node, LinkNode):
     bl_idname = 'LinkStretchTo'
     bl_label = "Stretch To"
     bl_icon = 'CON_STRETCHTO'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
+
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
         self.inputs.new ('FloatFactorSocket', "Head/Tail")
@@ -325,8 +325,9 @@ class LinkDampedTrackNode(Node, LinkNode):
     bl_idname = 'LinkDampedTrack'
     bl_label = "Damped Track"
     bl_icon = 'CON_TRACKTO'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
+
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
         self.inputs.new ('FloatFactorSocket', "Head/Tail")
@@ -350,8 +351,8 @@ class LinkLockedTrackNode(Node, LinkNode):
     bl_idname = 'LinkLockedTrack'
     bl_label = "Locked Track"
     bl_icon = 'CON_LOCKTRACK'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -377,8 +378,8 @@ class LinkTrackToNode(Node, LinkNode):
     bl_idname = 'LinkTrackTo'
     bl_label = "Track To"
     bl_icon = 'CON_TRACKTO'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -407,7 +408,7 @@ class LinkLimitLocationNode(Node, LinkNode):
     bl_idname = 'LinkLimitLocation'
     bl_label = "Limit Location"
     bl_icon = 'CON_LOCLIMIT'
-    
+    mantis_node_class_name=bl_idname
     initialized : bpy.props.BoolProperty(default = False)
 
     def init(self, context):
@@ -442,8 +443,8 @@ class LinkLimitScaleNode(Node, LinkNode):
     bl_idname = 'LinkLimitScale'
     bl_label = "Limit Scale"
     bl_icon = 'CON_SIZELIMIT'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -479,8 +480,8 @@ class LinkLimitRotationNode(Node, LinkNode):
     bl_idname = 'LinkLimitRotation'
     bl_label = "Limit Rotation"
     bl_icon = 'CON_ROTLIMIT'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     # === Optional Functions ===
     def init(self, context):
@@ -512,8 +513,8 @@ class LinkLimitDistanceNode(Node, LinkNode):
     bl_idname = 'LinkLimitDistance'
     bl_label = "Limit Distance"
     bl_icon = 'CON_DISTLIMIT'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new ('RelationshipSocket', "Input Relationship")
@@ -541,8 +542,8 @@ class LinkTransformationNode(Node, LinkNode):
     bl_idname = 'LinkTransformation'
     bl_label = "Transformation"
     bl_icon = 'CON_TRANSFORM'
-    
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         hide_me = []
@@ -619,6 +620,7 @@ class LinkArmatureNode(Node, LinkNode):
     bl_label = "Armature (Constraint)"
     bl_icon = "CON_ARMATURE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new ("RelationshipSocket", "Input Relationship")
@@ -651,6 +653,7 @@ class LinkSplineIKNode(Node, LinkNode):
     bl_label = "Spline IK"
     bl_icon = "CON_SPLINEIK"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new ("RelationshipSocket", "Input Relationship")
@@ -681,6 +684,7 @@ class LinkDrivenParameterNode(Node, LinkNode):
     bl_label = "Driven Parameter"
     bl_icon = "CONSTRAINT_BONE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new ( "RelationshipSocket", "Input Relationship" )
@@ -698,3 +702,6 @@ class LinkDrivenParameterNode(Node, LinkNode):
         self.use_custom_color = True
         self.color = driverColor
 
+# Set up the class property that ties the UI classes to the Mantis classes.
+for cls in TellClasses():
+    cls.set_mantis_class()

+ 9 - 1
math_definitions.py

@@ -24,6 +24,7 @@ class MathStaticInt(Node, MantisUINode):
     bl_label = "Static Int Math"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
 
     def init(self, context):
@@ -51,6 +52,7 @@ class MathStaticFloatNode(Node, MantisUINode):
     bl_label = "Static Float Math"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
 
     def init(self, context):
@@ -77,6 +79,7 @@ class MathStaticVectorNode(Node, MantisUINode):
     bl_label = "Static Vector Math"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MathVectorOperation", "Operation")
@@ -112,4 +115,9 @@ class MathStaticVectorNode(Node, MantisUINode):
                 self.inputs["Scalar A"].hide = False
             else:
                 self.inputs["Vector B"].hide = False
-                self.inputs["Scalar A"].hide = True
+                self.inputs["Scalar A"].hide = True
+
+# Set up the class property that ties the UI classes to the Mantis classes.
+for cls in TellClasses():
+    cls.mantis_node_library='.math_containers'
+    cls.set_mantis_class()

+ 50 - 28
nodes_generic.py

@@ -17,10 +17,7 @@ def TellClasses():
              InputRotationOrderNode,
              InputTransformSpaceNode,
              InputStringNode,
-             InputQuaternionNode,
-             InputQuaternionNodeAA,
              InputMatrixNode,
-             InputLayerMaskNode,
              # InputGeometryNode,
              InputExistingGeometryObjectNode,
              InputExistingGeometryDataNode,
@@ -75,6 +72,7 @@ class InputFloatNode(Node, MantisUINode):
     bl_label = "Float"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('FloatSocket', "Float Input").input = True
@@ -86,6 +84,7 @@ class InputIntNode(Node, MantisUINode):
     bl_label = "Integer"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.outputs.new('IntSocket', "Integer").input = True
@@ -97,6 +96,7 @@ class InputVectorNode(Node, MantisUINode):
     bl_label = "Vector"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('VectorSocket', "").input = True
@@ -108,6 +108,7 @@ class InputBooleanNode(Node, MantisUINode):
     bl_label = "Boolean"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('BooleanSocket', "").input = True
@@ -119,6 +120,7 @@ class InputBooleanThreeTupleNode(Node, MantisUINode):
     bl_label = "Boolean Vector"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('BooleanThreeTupleSocket', "")
@@ -130,6 +132,7 @@ class InputRotationOrderNode(Node, MantisUINode):
     bl_label = "Rotation Order"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('RotationOrderSocket', "").input = True
@@ -141,6 +144,7 @@ class InputTransformSpaceNode(Node, MantisUINode):
     bl_label = "Transform Space"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('TransformSpaceSocket', "").input = True
@@ -152,34 +156,11 @@ class InputStringNode(Node, MantisUINode):
     bl_label = "String"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.outputs.new('StringSocket', "").input = True
         self.initialized = True
-
-class InputQuaternionNode(Node, MantisUINode):
-    '''A node representing inheritance'''
-    bl_idname = 'InputQuaternionNode'
-    bl_label = "Quaternion"
-    bl_icon = 'NODE'
-    initialized : bpy.props.BoolProperty(default = False)
-
-    def init(self, context):
-        self.outputs.new('QuaternionSocket', "").input = True
-        self.initialized = True
-
-class InputQuaternionNodeAA(Node, MantisUINode):
-    '''A node representing inheritance'''
-    bl_idname = 'InputQuaternionNodeAA'
-    bl_label = "Axis Angle"
-    bl_icon = 'NODE'
-    initialized : bpy.props.BoolProperty(default = False)
-
-    def init(self, context):
-        self.outputs.new('QuaternionSocketAA', "").input = True
-        self.initialized = True
-
-
 class InputMatrixNode(Node, MantisUINode):
     '''A node representing inheritance'''
     bl_idname = 'InputMatrixNode'
@@ -190,6 +171,7 @@ class InputMatrixNode(Node, MantisUINode):
     third_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 1.0, 0.0,))
     fourth_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 0.0, 1.0,))
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def set_matrix(self):
         return (self.first_row[ 0], self.first_row[ 1], self.first_row[ 2], self.first_row[ 3],
@@ -239,6 +221,7 @@ class MetaRigMatrixNode(Node, MantisUINode):
     third_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 1.0, 0.0,))
     fourth_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 0.0, 1.0,))
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name="UtilityMetaRig"
 
     def set_matrix(self):
         return (self.first_row[ 0], self.first_row[ 1], self.first_row[ 2], self.first_row[ 3],
@@ -271,6 +254,7 @@ class UtilityMatrixFromCurve(Node, MantisUINode):
     bl_icon = "NODE"
     
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         curv = self.inputs.new("EnumCurveSocket", "Curve")
@@ -288,6 +272,7 @@ class UtilityPointFromCurve(Node, MantisUINode):
     bl_icon = "NODE"
     
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         curv = self.inputs.new("EnumCurveSocket", "Curve")
@@ -303,6 +288,7 @@ class UtilityMatricesFromCurve(Node, MantisUINode):
     bl_icon = "NODE"
     
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         curv = self.inputs.new("EnumCurveSocket", "Curve")
@@ -321,6 +307,7 @@ class UtilityMetaRigNode(Node, MantisUINode):
     armature:bpy.props.StringProperty()
     pose_bone:bpy.props.StringProperty()
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         armt = self.inputs.new("EnumMetaRigSocket", "Meta-Armature")
@@ -353,6 +340,7 @@ class UtilityBonePropertiesNode(Node, MantisUINode):
     bl_icon = "NODE"
     #bl_width_default = 250
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.outputs.new("ParameterStringSocket", "matrix")
@@ -375,6 +363,7 @@ class UtilityDriverVariableNode(Node, MantisUINode):
     bl_label = "Driver Variable"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     
     def init(self, context):
@@ -440,6 +429,7 @@ class UtilityFCurveNode(Node, MantisUINode):
     
     use_kf_nodes   : bpy.props.BoolProperty(default=True)
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("eFCrvExtrapolationMode", "Extrapolation Mode")
@@ -458,6 +448,7 @@ class UtilityDriverNode(Node, MantisUINode):
     bl_label = "Driver"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("EnumDriverType", "Driver Type")
@@ -490,6 +481,7 @@ class UtilitySwitchNode(Node, MantisUINode):
     bl_label = "Switch"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         # self.inputs.new("xFormSocket", "xForm")
@@ -505,6 +497,7 @@ class UtilityCombineThreeBoolNode(Node, MantisUINode):
     bl_label = "CombineThreeBool"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("BooleanSocket", "X")
@@ -519,6 +512,7 @@ class UtilityCombineVectorNode(Node, MantisUINode):
     bl_label = "CombineVector"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("FloatSocket", "X")
@@ -533,6 +527,7 @@ class UtilitySeparateVector(Node, MantisUINode):
     bl_label = "Separate Vector"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("VectorSocket", "Vector")
@@ -547,6 +542,7 @@ class UtilityCatStringsNode(Node, MantisUINode):
     bl_label = "Concatenate Strings"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("StringSocket", "String_1")
@@ -584,6 +580,7 @@ class InputLayerMaskNode(Node, MantisUINode):
     bl_label = "Layer Mask"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.outputs.new("LayerMaskInputSocket", "Layer Mask")
@@ -595,6 +592,7 @@ class InputExistingGeometryObjectNode(Node, MantisUINode):
     bl_label = "Existing Object"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     # We want Mantis to import widgets and stuff, so we hold a reference to the object
     object_reference : bpy.props.PointerProperty(type=bpy.types.Object,) 
     
@@ -617,6 +615,7 @@ class InputExistingGeometryDataNode(Node, MantisUINode):
     bl_label = "Existing Geometry"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("StringSocket", "Name")
@@ -629,6 +628,7 @@ class UtilityGeometryOfXForm(Node, MantisUINode):
     bl_label = "Geometry of xForm"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("xFormSocket", "xForm")
@@ -642,6 +642,7 @@ class UtilityNameOfXForm(Node, MantisUINode):
     bl_label = "Name of xForm"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("xFormSocket", "xForm")
@@ -654,6 +655,7 @@ class UtilityGetBoneLength(Node, MantisUINode):
     bl_label = "Get Bone Length"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Bone Matrix")
@@ -667,6 +669,7 @@ class UtilityPointFromBoneMatrix(Node, MantisUINode):
     bl_label = "Point from Bone Matrix"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Bone Matrix")
@@ -679,6 +682,7 @@ class UtilitySetBoneLength(Node, MantisUINode):
     bl_label = "Set Bone Matrix Length"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Bone Matrix")
@@ -694,6 +698,7 @@ class UtilityKeyframe(Node, MantisUINode):
     bl_label = "KeyFrame"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         # x and y
@@ -734,6 +739,7 @@ class UtilityBoneMatrixHeadTailFlip(Node, MantisUINode):
     bl_label = "Flip Head/Tail"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Bone Matrix")
@@ -746,6 +752,7 @@ class UtilityMatrixTransform(Node, MantisUINode):
     bl_label = "Matrix Transform"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Matrix 1")
@@ -759,6 +766,7 @@ class UtilityMatrixSetLocation(Node, MantisUINode):
     bl_label = "Set Matrix Location"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Matrix")
@@ -772,6 +780,7 @@ class UtilityMatrixGetLocation(Node, MantisUINode):
     bl_label = "Get Matrix Location"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Matrix")
@@ -784,6 +793,7 @@ class UtilityTransformationMatrix(Node, MantisUINode):
     bl_label = "Transformation Matrix"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         # first input is a transformation type - translation, rotation, or scale
@@ -828,6 +838,7 @@ class UtilitySetBoneMatrixTail(Node, MantisUINode):
     bl_label = "Set Bone Matrix Tail"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Matrix")
@@ -842,6 +853,7 @@ class UtilityMatrixFromXForm(Node, MantisUINode):
     bl_label = "Matrix of xForm"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("xFormSocket", "xForm")
@@ -854,6 +866,7 @@ class UtilityAxesFromMatrix(Node, MantisUINode):
     bl_label = "Axes of Matrix"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("MatrixSocket", "Matrix")
@@ -868,6 +881,7 @@ class UtilityIntToString(Node, MantisUINode):
     bl_label = "Number String"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         
@@ -883,6 +897,7 @@ class UtilityArrayGet(Node, MantisUINode):
     bl_label  = "Array Get"
     bl_icon   = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new('EnumArrayGetOptions', 'OoB Behaviour')
@@ -915,6 +930,7 @@ class UtilityCompare(Node, MantisUINode):
     bl_label = "Compare"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("WildcardSocket", "A")
@@ -946,6 +962,7 @@ class UtilityChoose(Node, MantisUINode):
     bl_label = "Choose"
     bl_icon = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         
@@ -987,15 +1004,20 @@ class UtilityChoose(Node, MantisUINode):
                 self.inputs['B'].color = link.from_socket.color
 
 
-
 class UtilityPrint(Node, MantisUINode):
     """A utility used to print arbitrary values."""
     bl_idname = "UtilityPrint"
     bl_label  = "Print"
     bl_icon   = "NODE"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new("WildcardSocket", "Input")
         self.initialized = True
     
+
+# Set up the class property that ties the UI classes to the Mantis classes.
+for cls in TellClasses():
+    cls.mantis_node_library='.misc_containers'
+    cls.set_mantis_class()

+ 5 - 0
primitives_definitions.py

@@ -17,6 +17,7 @@ class GeometryCirclePrimitive(Node, MantisUINode):
     bl_label = "Circle Primitive"
     bl_icon = 'NODE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name="CirclePrimitive"
 
     def init(self, context):
         self.inputs.new('StringSocket', "Name")
@@ -24,3 +25,7 @@ class GeometryCirclePrimitive(Node, MantisUINode):
         self.inputs.new('IntSocket', "Number of Points")
         self.outputs.new('GeometrySocket', "Circle")
         self.initialized = True
+
+for cls in TellClasses():
+    cls.mantis_node_library='.primitives_containers'
+    cls.set_mantis_class()

+ 12 - 12
readtree.py

@@ -1,7 +1,6 @@
 from .utilities import prRed, prGreen, prPurple, prWhite, prOrange, \
                         wrapRed, wrapGreen, wrapPurple, wrapWhite, wrapOrange
-from .utilities import get_node_prototype, class_for_mantis_prototype_node, \
-                        gen_nc_input_for_data
+from .utilities import  gen_nc_input_for_data
 
     
 
@@ -139,15 +138,7 @@ def gen_node_containers(base_tree, current_tree, tree_path_names, all_nc, local_
     for np in current_tree.nodes:
         if np.bl_idname in ["NodeFrame", "NodeReroute"]:
             continue # not a Mantis Node
-        if (nc_cls := class_for_mantis_prototype_node(np)):
-            sig = (None, *tree_path_names, np.name)
-            if np.bl_idname in replace_types:
-                sig = (None, *tree_path_names, np.bl_idname)
-                if local_nc.get(sig):
-                    continue # already made
-            nc = nc_cls( sig , base_tree)
-            local_nc[sig] = nc; all_nc[sig] = nc
-        elif np.bl_idname in ["NodeGroupInput", "NodeGroupOutput"]: # make a Dummy Node
+        if np.bl_idname in ["NodeGroupInput", "NodeGroupOutput"]: # make a Dummy Node
             # we only want ONE dummy in/out per tree_path, so use the bl_idname
             sig = (None, *tree_path_names, np.bl_idname)
             if not local_nc.get(sig):
@@ -165,6 +156,15 @@ def gen_node_containers(base_tree, current_tree, tree_path_names, all_nc, local_
             else:
                 group_nodes.append(nc)
                 schema_nodes[sig] = nc
+        # if it wasn't the types we ignore or the types we make a Dummy for, use this to catch all non-special cases.
+        elif (nc_cls := np.mantis_class):
+            sig = (None, *tree_path_names, np.name)
+            if np.bl_idname in replace_types:
+                sig = (None, *tree_path_names, np.bl_idname)
+                if local_nc.get(sig):
+                    continue # already made
+            nc = nc_cls( sig , base_tree)
+            local_nc[sig] = nc; all_nc[sig] = nc
         else:
             nc = None
             prRed(f"Can't make nc for.. {np.bl_idname}")
@@ -172,7 +172,7 @@ def gen_node_containers(base_tree, current_tree, tree_path_names, all_nc, local_
         if nc.signature[0] not in ['MANTIS_AUTOGENERATED'] and nc.node_type not in ['SCHEMA', 'DUMMY', 'DUMMY_SCHEMA']:
             nc.fill_parameters()
 
-def data_from_tree(base_tree, tree_path, dummy_nodes, all_nc, all_schema):
+def data_from_tree(base_tree, tree_path, dummy_nodes, all_nc, all_schema):#
     # TODO: it should be relatively easy to make this use a while loop instead of recursion.
     local_nc, group_nodes = {}, []
     tree_path_names = [tree.name for tree in tree_path if hasattr(tree, "name")]

+ 1 - 9
schema_containers.py

@@ -33,6 +33,7 @@ def schema_init_sockets(nc, is_input = True, in_out='INPUT', category=''):
                         node=nc)
     nc.init_parameters()
 
+
 class SchemaNode(MantisNode):
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
@@ -51,8 +52,6 @@ class SchemaIndex(SchemaNode):
         self.outputs.init_sockets(outputs)
         self.init_parameters()
 
-
-
 class SchemaArrayInput(SchemaNode):
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
@@ -69,24 +68,17 @@ class SchemaArrayInputGet(SchemaNode):
         self.inputs.init_sockets(inputs)
         schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
 
-
 class SchemaArrayOutput(SchemaNode):
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
         schema_init_sockets(self, is_input=True, in_out='OUTPUT', category='Array')
 
-
-        
-
 class SchemaConstInput(SchemaNode):
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
         schema_init_sockets(self, is_input=False, in_out='INPUT', category='Constant')
 
 
-
-
-
 class SchemaConstOutput(SchemaNode):
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)

+ 11 - 2
schema_definitions.py

@@ -34,6 +34,7 @@ class SchemaIndex(Node, SchemaUINode):
     bl_label = "Index"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.outputs.new("IntSocket", "Index")
@@ -47,6 +48,7 @@ class SchemaArrayInput(Node, SchemaUINode):
     bl_label = "Array Input"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.update()
@@ -71,6 +73,7 @@ class SchemaArrayInputGet(Node, SchemaUINode):
     bl_label = "Array Input at Index"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.inputs.new('EnumArrayGetOptions', 'OoB Behaviour')
@@ -97,6 +100,7 @@ class SchemaArrayOutput(Node, SchemaUINode):
     bl_label = "Array Output"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.update()
@@ -123,6 +127,7 @@ class SchemaConstInput(Node, SchemaUINode):
     bl_label = "Constant Input"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.update()
@@ -149,6 +154,7 @@ class SchemaConstOutput(Node, SchemaUINode):
     bl_label = "Constant Output"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.update()
@@ -180,10 +186,9 @@ class SchemaOutgoingConnection(Node, SchemaUINode):
     bl_label = "Outgoing Connection"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
-        # self.inputs.new('IntSocket', 'Valid From')
-        # self.inputs.new('IntSocket', 'Valid Until')
         self.update()
 
     def update(self):
@@ -210,6 +215,7 @@ class SchemaIncomingConnection(Node, SchemaUINode):
     bl_label = "Incoming Connection"
     bl_icon = 'GIZMO'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
 
     def init(self, context):
         self.update()
@@ -228,3 +234,6 @@ class SchemaIncomingConnection(Node, SchemaUINode):
             self.outputs.new('WildcardSocket', '', identifier='__extend__')
         self.initialized = True
 
+
+for cls in TellClasses():
+    cls.set_mantis_class()

+ 0 - 1
schema_solve.py

@@ -3,7 +3,6 @@ from .utilities import (prRed, prGreen, prPurple, prWhite,
                               wrapRed, wrapGreen, wrapPurple, wrapWhite,
                               wrapOrange,)
 from .utilities import init_connections, init_dependencies
-from .utilities import class_for_mantis_prototype_node
 from .base_definitions import SchemaUINode, GraphError, replace_types, custom_props_types
 from .node_container_common import setup_custom_props_from_np
 # a class that solves Schema nodes

+ 0 - 74
utilities.py

@@ -602,80 +602,6 @@ def project_point_to_plane(point, origin, normal):
 # stuff I should probably refactor!!
 ##################################################################################################
 
-# what in the cuss is this horrible abomination??
-def class_for_mantis_prototype_node(prototype_node):
-    """ This is a class which returns a class to instantiate for
-        the given prototype node."""
-    #from .node_container_classes import TellClasses
-    from . import xForm_containers, link_containers, misc_containers, primitives_containers, deformer_containers, math_containers, schema_containers
-    classes = {}
-    for module in [xForm_containers, link_containers, misc_containers, primitives_containers, deformer_containers, math_containers, schema_containers]:
-        for cls in module.TellClasses():
-            classes[cls.__name__] = cls
-    # I could probably do a string.replace() here
-    # But I actually think this is a bad idea since I might not
-    #  want to use this name convention in the future
-    #  this is easy enough for now, may refactor.
-    if prototype_node.bl_idname == 'xFormArmatureNode':
-        return classes["xFormArmature"]
-    elif prototype_node.bl_idname == 'xFormBoneNode':
-        return classes["xFormBone"]
-    elif prototype_node.bl_idname == 'xFormGeometryObject':
-        return classes["xFormGeometryObject"]
-    elif prototype_node.bl_idname == 'linkInherit':
-        return classes["LinkInherit"]
-    elif prototype_node.bl_idname == 'InputFloatNode':
-        return classes["InputFloat"]
-    elif prototype_node.bl_idname == 'InputVectorNode':
-        return classes["InputVector"]
-    elif prototype_node.bl_idname == 'InputBooleanNode':
-        return classes["InputBoolean"]
-    elif prototype_node.bl_idname == 'InputBooleanThreeTupleNode':
-        return classes["InputBooleanThreeTuple"]
-    elif prototype_node.bl_idname == 'InputRotationOrderNode':
-        return classes["InputRotationOrder"]
-    elif prototype_node.bl_idname == 'InputTransformSpaceNode':
-        return classes["InputTransformSpace"]
-    elif prototype_node.bl_idname == 'InputStringNode':
-        return classes["InputString"]
-    elif prototype_node.bl_idname == 'InputQuaternionNode':
-        return classes["InputQuaternion"]
-    elif prototype_node.bl_idname == 'InputQuaternionNodeAA':
-        return classes["InputQuaternionAA"]
-    elif prototype_node.bl_idname == 'InputMatrixNode':
-        return classes["InputMatrix"]
-    elif prototype_node.bl_idname == 'MetaRigMatrixNode':
-        return classes["InputMatrix"]
-    elif prototype_node.bl_idname == 'InputLayerMaskNode':
-        return classes["InputLayerMask"]
-    elif prototype_node.bl_idname == 'GeometryCirclePrimitive':
-        return classes["CirclePrimitive"]
-        
-    # every node before this point is not guarenteed to follow the pattern
-    # but every node not checked above does follow the pattern.
-    
-    try:
-        return classes[ prototype_node.bl_idname ]
-    except KeyError:
-        # prGreen(prototype_node.bl_idname)
-        # prWhite(classes.keys())
-        pass
-    
-    if prototype_node.bl_idname in [ 
-                                    "NodeReroute",
-                                    "NodeGroupInput",
-                                    "NodeGroupOutput",
-                                    "MantisNodeGroup",
-                                    "NodeFrame",
-                                    "MantisSchemaGroup",
-                                   ]:
-           return None
-    
-    prRed(prototype_node.bl_idname)
-    raise RuntimeError(wrapOrange("Failed to create node container for: ")+wrapRed("%s" % prototype_node.bl_idname))
-    return None
-
-
 # This is really, really stupid way to do this
 def gen_nc_input_for_data(socket):
     # Class List #TODO deduplicate

+ 7 - 0
xForm_definitions.py

@@ -162,6 +162,7 @@ class xFormBoneNode(Node, xFormNode):
     display_bb_settings : bpy.props.BoolProperty(default=False)
     socket_count : bpy.props.IntProperty()
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
     
     def init(self, context):
 
@@ -270,6 +271,7 @@ class xFormArmatureNode(Node, xFormNode):
     bl_label = "Armature"
     bl_icon = 'OUTLINER_OB_ARMATURE'
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname[:-4]
 
     def init(self, context):
         self.inputs.new('StringSocket', "Name")
@@ -301,6 +303,7 @@ class xFormGeometryObjectNode(Node, xFormNode):
     bl_label = "Geometry Object"
     bl_icon = "EMPTY_AXIS"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new('StringSocket', "Name")
@@ -334,6 +337,7 @@ class xFormObjectInstance(Node, xFormNode):
     bl_label = "Object Instance"
     bl_icon = "EMPTY_AXIS"
     initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
     
     def init(self, context):
         self.inputs.new('StringSocket', "Name")
@@ -361,3 +365,6 @@ class xFormObjectInstance(Node, xFormNode):
             self.inputs['Name'].display_text = ""
             if nc:
                 self.inputs['Name'].display_text = nc.evaluate_input("Name")
+
+for cls in TellClasses():
+    cls.set_mantis_class()