Ver Fonte

refactor socket templates in mantis classes

socket templates are now class attributes, and I got rid of most uses of
both set_traverse() and init_parameters() to save on function calls
Joseph Brandenburg há 2 semanas atrás
pai
commit
e6ed10fa3f

+ 26 - 8
base_definitions.py

@@ -923,13 +923,15 @@ class MantisNode:
         "hierarchy_dependencies", "dependencies",
         "unmet_hierarchy_dependency_count",
         "prepared", "executed", "execution_prepared",
-        "socket_templates", "mContext",
+        "mContext",
         "is_schema_prototype"
         )
-    node_type='UNINITIALIZED'
+    node_type = 'UNINITIALIZED'
+    socket_templates = None
     def __init__(self, signature : tuple,
                  base_tree : bpy.types.NodeTree,
-                 socket_templates : list[MantisSocketTemplate]=[],):
+                 socket_templates : list[MantisSocketTemplate]=[],
+                 additional_parameters :dict = {}, ):
         self.base_tree=base_tree
         self.signature = signature
         self.ui_signature = signature
@@ -943,7 +945,6 @@ class MantisNode:
         self.execution_prepared = False
         # execution_prepared is for tracking prep state in execution, so that I can avoid preparing nodes
         #  again without changing the readtree code much.
-        self.socket_templates = socket_templates
         self.mContext = None # for now I am gonna set this at runtime
         self.is_schema_prototype = False
         # I know it isn't "beautiful OOP" or whatever, but it is just easier
@@ -951,7 +952,7 @@ class MantisNode:
         # in the future I can refactor it, but it will require changes to 100+
         #  classes, instead of adding about 5 lines of code elsewhere.
         if self.socket_templates:
-            self.init_sockets()
+            self.init_sockets( additional_parameters )
 
     @property
     def name(self):
@@ -968,19 +969,36 @@ class MantisNode:
         self.executed = False
         self.execution_prepared = False
 
-    def init_sockets(self) -> None:
+    def init_sockets(self, additional_parameters : dict = {}) -> None:
         # Formerly I was doing this:
         # self.inputs.init_sockets(self.socket_templates)
         # self.outputs.init_sockets(self.socket_templates)
         # Since doing each one causes some redundancy, we'll just reimplement it
         # This is a highly used and therefore expensive function so we have to make small
         # optimizations like this, even tho it is ugly.
+        traverse_in, traverse_out = {}, {}
         for socket in self.socket_templates:
+            if socket.traverse_target:
+                if socket.is_input:
+                    traverse_in[socket.name] = socket.traverse_target
+                else:
+                    traverse_out[socket.name] = socket.traverse_target
             if socket.ui_only == True: continue # used in UI but not in generation
             if socket.is_input:
-                self.inputs[socket.name] = NodeSocket(is_input=True, name=socket.name, node=self)
+                self.inputs[socket.name] = NodeSocket(is_input=True, name=socket.name,
+                                    node=self,)
             else:
-                self.outputs[socket.name] = NodeSocket(is_input=False, name=socket.name, node=self)
+                self.outputs[socket.name] = NodeSocket(is_input=False, name=socket.name,
+                                    node=self,)
+            self.parameters[socket.name] = None
+        for traverse_owner, traverse_target in traverse_in.items():
+            self.inputs[traverse_owner].traverse_target = self.outputs[traverse_target]
+            self.inputs[traverse_owner].can_traverse = True
+        for traverse_owner, traverse_target in traverse_out.items():
+            self.outputs[traverse_owner].traverse_target = self.inputs[traverse_target]
+            self.outputs[traverse_owner].can_traverse = True
+        for key, value in additional_parameters.items():
+            self.parameters[key]=value
 
     def init_parameters(self, additional_parameters = {}) -> None:
         for socket in self.inputs:

+ 11 - 79
deformer_nodes.py

@@ -40,7 +40,8 @@ class MantisDeformerNode(MantisNode):
     def __init__(self, signature : tuple,
                  base_tree : NodeTree,
                  socket_templates : list[MantisSocketTemplate]=[]):
-        super().__init__(signature, base_tree, socket_templates)
+        super().__init__(signature, base_tree, socket_templates,
+                         additional_parameters= {"Name":None})
         self.prepared = True
         self.bObject=[]
     # we need evaluate_input to have the same behaviour as links.
@@ -81,12 +82,7 @@ def standard_modifier_bind(self, bContext=None, operator=None):
 class DeformerArmature(MantisDeformerNode):
     '''A node representing an armature deformer'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, DeformArmatureSockets)
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = DeformArmatureSockets
 
     def GetxForm(self, socket="Deformer"):
         if socket == "Deformer":
@@ -257,7 +253,6 @@ class DeformerArmature(MantisDeformerNode):
                 vg.add([p_index], weights[b_name]/max_pre_normalized_weight, 'REPLACE')
         armOb.data.pose_position = 'POSE'
     
-
     def bFinalize(self, bContext=None):
         prGreen("Executing Armature Deform Node")
         mod_name = self.evaluate_input("Name")
@@ -283,18 +278,10 @@ class DeformerArmature(MantisDeformerNode):
             # elif skin_method == "EXISTING_GROUPS":
             #     pass
 
-
 class DeformerHook(MantisDeformerNode):
     '''A node representing a hook deformer'''
     __slots__ = ()
-    
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, HookSockets)
-        # now set up the traverse target...
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = HookSockets
 
     def driver_for_radius(self, object, hook, index, influence, bezier=True):
         """ Creates a driver to control the radius of a curve point with the hook."""
@@ -420,15 +407,10 @@ class DeformerHook(MantisDeformerNode):
         # todo: this node should be able to take many indices in the future.
         # Also: I have a Geometry Nodes implementation of this I can use... maybe...
 
-
 class DeformerMorphTarget(MantisDeformerNode):
     '''A node representing an armature deformer'''
     __slots__ = ()
-    
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MorphTargetSockets)
-        self.init_parameters(additional_parameters={"Name":None})
-        self.prepared = True
+    socket_templates = MorphTargetSockets
     
     def GetxForm(self, trace_input="Object"):
         trace = trace_single_line(self, trace_input)
@@ -437,7 +419,6 @@ class DeformerMorphTarget(MantisDeformerNode):
                 return node
         raise GraphError("%s is not connected to an upstream xForm" % self)
 
-
     def bRelationshipPass(self, bContext = None,):
         prGreen("Executing Morph Target Node")
 
@@ -462,34 +443,16 @@ class DeformerMorphTarget(MantisDeformerNode):
         self.parameters["Name"] = ob # this is redundant but it's OK since accessing the mt is tedious
         self.executed = True
 
-
-
 class DeformerMorphTargetDeform(MantisDeformerNode):
     '''A node representing an armature deformer'''
     __slots__ = ()
-    
+    socket_templates = MorphTargetDeformSockets
 
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree)
-        inputs = [
-            "Deformer",
-            "Use Shape Key",
-            "Use Offset",
-        ]
-        outputs = [
-          "Deformer",
-        ]
-        self.outputs.init_sockets(outputs)
-        self.inputs.init_sockets(inputs)
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+        super().__init__(signature, base_tree, self.socket_templates)
         self.executed = True
         setup_custom_property_inputs_outputs(self)
     
-    # bpy.data.node_groups["Morph Deform.045"].nodes["Named Attribute.020"].data_type = 'FLOAT_VECTOR'
-    # bpy.context.object.add_rest_position_attribute = True
-
     def reset_execution(self):
         return super().reset_execution()
         self.executed=True
@@ -707,19 +670,10 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
             else:
                 self.gen_morph_target_modifier(xf, bContext)
 
-
-
 class DeformerSurfaceDeform(MantisDeformerNode):
     '''A node representing an surface deform modifier'''
     __slots__ = ()
-    
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SurfaceDeformSockets)
-        # now set up the traverse target...
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = SurfaceDeformSockets
 
     def GetxForm(self, socket="Deformer"):
         if socket == "Deformer":
@@ -747,18 +701,10 @@ class DeformerSurfaceDeform(MantisDeformerNode):
         from bpy import ops
         standard_modifier_bind(self, bContext, ops.object.surfacedeform_bind)
 
-
 class DeformerMeshDeform(MantisDeformerNode):
     '''A node representing a mesh deform modifier'''
     __slots__ = ()
-    
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MeshDeformSockets)
-        # now set up the traverse target...
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = MeshDeformSockets
 
     def GetxForm(self, socket="Deformer"):
         if socket == "Deformer":
@@ -789,14 +735,7 @@ class DeformerMeshDeform(MantisDeformerNode):
 class DeformerLatticeDeform(MantisDeformerNode):
     '''A node representing a lattice deform modifier'''
     __slots__ = ()
-    
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LatticeDeformSockets)
-        # now set up the traverse target...
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = LatticeDeformSockets
 
     def GetxForm(self, socket="Deformer"):
         if socket == "Deformer":
@@ -823,14 +762,7 @@ class DeformerLatticeDeform(MantisDeformerNode):
 class DeformerSmoothCorrectiveDeform(MantisDeformerNode):
     '''A node representing a corrective smooth deform modifier'''
     __slots__ = ()
-    
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SmoothDeformSockets)
-        # now set up the traverse target...
-        self.init_parameters(additional_parameters={"Name":None})
-        self.set_traverse([("Deformer", "Deformer")])
-        self.prepared = True
+    socket_templates = SmoothDeformSockets
 
     def GetxForm(self, socket="Deformer"):
         if socket == "Deformer":

+ 2 - 3
deformer_socket_templates.py

@@ -26,11 +26,10 @@ DeformArmatureSockets = [
                            blender_property='use_bone_envelopes'),
     UseVertexGroups := ST(name="Use Vertex Groups", bl_idname="BooleanSocket", is_input=True, default_value=True,
                            blender_property='use_vertex_groups'),
-    DeformerInput := ST(name="Deformer", bl_idname="DeformerSocket", is_input=True),
+    DeformerInput := ST(name="Deformer", bl_idname="DeformerSocket", is_input=True, traverse_target='Deformer'),
     CopySkinWeightsFrom := ST(name="Copy Skin Weights From", bl_idname="xFormSocket", is_input=True, hide=True),
     SkinningMethod := ST(name="Skinning Method", bl_idname="EnumSkinning", is_input=True),
-    DeformerOutput := ST(name="Deformer", bl_idname="DeformerSocket", is_input=False),
-
+    DeformerOutput := ST(name="Deformer", bl_idname="DeformerSocket", is_input=False, traverse_target='Deformer'),
 ]
 
 HookSockets= [

+ 1 - 0
execution/readtree.py

@@ -105,6 +105,7 @@ def gen_mantis_nodes(base_tree, current_tree, tree_path_names, mContext, all_man
                 sig = (None, *tree_path_names, ui_node.bl_idname)
                 if local_mantis_nodes.get(sig):
                     continue # already made
+            print (mantis_class)
             mantis_node = mantis_class( sig , base_tree)
             local_mantis_nodes[sig] = mantis_node; all_mantis_nodes[sig] = mantis_node
             mantis_node.ui_signature = (*mantis_node.ui_signature[:-1], ui_node.name) # just to ensure it points to a real node.

+ 2 - 2
internal_nodes.py

@@ -119,8 +119,8 @@ class NoOpNode(MantisNode):
     node_type = 'UTILITY'
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
-        self.inputs.init_sockets(["Input"])
-        self.outputs.init_sockets(["Output"])
+        self.inputs['Input'] = NodeSocket(is_input=True, node=self, name='Input')
+        self.outputs['Output'] = NodeSocket(is_input=False, node=self, name='Output')
         self.init_parameters()
         self.set_traverse([("Input", "Output")])
         self.prepared, self.executed = True, True

+ 28 - 108
link_nodes.py

@@ -45,9 +45,9 @@ class MantisLinkNode(MantisNode):
     __slots__ = ()
     node_type = 'LINK'
     def __init__(self, signature : tuple,
-                 base_tree : NodeTree,
-                 socket_templates : list[SockTemplate]=[]):
-        super().__init__(signature, base_tree, socket_templates)
+                 base_tree : NodeTree,):
+        super().__init__(signature, base_tree, self.socket_templates,
+                         additional_parameters={'Name':None})
         self.prepared = True; self.bObject=[]
 
     def bTransformPass(self, bContext=None):
@@ -138,11 +138,8 @@ class MantisLinkNode(MantisNode):
 class LinkInherit(MantisLinkNode):
     '''A node representing inheritance'''
     __slots__ = ()
+    socket_templates = LinkInheritSockets
 
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkInheritSockets)
-        self.init_parameters()
-        self.set_traverse([('Parent', 'Inheritance')])
 
     def bTransformPass(self, bContext=None):
         parent_xForm_info = get_parent_xForm_info(self, 'Parent')
@@ -159,13 +156,8 @@ class LinkInherit(MantisLinkNode):
 
 class LinkCopyLocation(MantisLinkNode):
     '''A node representing Copy Location'''
-
-    def __init__(self, signature : tuple,
-                 base_tree : NodeTree,):
-        super().__init__(signature, base_tree, LinkCopyLocationSockets)
-        additional_parameters = { "Name":None }
-        self.init_parameters(additional_parameters=additional_parameters)
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    __slots__ = ()
+    socket_templates = LinkCopyLocationSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -186,12 +178,7 @@ class LinkCopyLocation(MantisLinkNode):
 class LinkCopyRotation(MantisLinkNode):
     '''A node representing Copy Rotation'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkCopyRotationSockets)
-        additional_parameters = { "Name":None }
-        self.init_parameters(additional_parameters=additional_parameters)
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkCopyRotationSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -221,12 +208,7 @@ class LinkCopyRotation(MantisLinkNode):
 class LinkCopyScale(MantisLinkNode):
     '''A node representing Copy Scale'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkCopyScaleSockets)
-        additional_parameters = { "Name":None }
-        self.init_parameters(additional_parameters=additional_parameters)
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkCopyScaleSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -248,12 +230,7 @@ class LinkCopyScale(MantisLinkNode):
 class LinkCopyTransforms(MantisLinkNode):
     '''A node representing Copy Transfoms'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkCopyTransformsSockets)
-        additional_parameters = { "Name":None }
-        self.init_parameters(additional_parameters=additional_parameters)
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkCopyTransformsSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -274,11 +251,7 @@ class LinkCopyTransforms(MantisLinkNode):
 class LinkTransformation(MantisLinkNode):
     '''A node representing Copy Transfoms'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkTransformationSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkTransformationSockets
 
     def ui_modify_socket(self, ui_socket, socket_name=None):
         from_suffix, to_suffix = '', ''
@@ -346,10 +319,7 @@ class LinkTransformation(MantisLinkNode):
 
 class LinkLimitLocation(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkLimitLocationScaleSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkLimitLocationSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -368,10 +338,7 @@ class LinkLimitLocation(MantisLinkNode):
 
 class LinkLimitRotation(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkLimitRotationSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkLimitRotationSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -391,10 +358,7 @@ class LinkLimitRotation(MantisLinkNode):
 
 class LinkLimitScale(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkLimitLocationScaleSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkLimitScaleSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -414,10 +378,7 @@ class LinkLimitScale(MantisLinkNode):
 
 class LinkLimitDistance(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkLimitDistanceSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkLimitDistanceSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -439,10 +400,7 @@ class LinkLimitDistance(MantisLinkNode):
 
 class LinkStretchTo(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkStretchToSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkStretchToSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -465,11 +423,8 @@ class LinkStretchTo(MantisLinkNode):
 
 class LinkDampedTrack(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkDampedTrackSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
-
+    socket_templates = LinkDampedTrackSockets
+    
     def bRelationshipPass(self, context):
         prepare_parameters(self)
         for xf in self.GetxForm():
@@ -487,10 +442,7 @@ class LinkDampedTrack(MantisLinkNode):
 
 class LinkLockedTrack(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree,LinkLockedTrackSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkLockedTrackSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -509,10 +461,7 @@ class LinkLockedTrack(MantisLinkNode):
 
 class LinkTrackTo(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkTrackToSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkTrackToSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -531,10 +480,7 @@ class LinkTrackTo(MantisLinkNode):
 
 class LinkInheritConstraint(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkInheritConstraintSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkInheritConstraintSockets
 
     def bRelationshipPass(self, context):
         prepare_parameters(self)
@@ -555,10 +501,7 @@ class LinkInheritConstraint(MantisLinkNode):
 
 class LinkInverseKinematics(MantisLinkNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkInverseKinematicsSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkInverseKinematicsSockets
 
     def get_base_ik_bone(self, ik_bone):
         chain_length : int = (self.evaluate_input("Chain Length"))
@@ -735,7 +678,6 @@ class LinkInverseKinematics(MantisLinkNode):
                     constraint.mute = enabled_before
         super().bFinalize(bContext)
 
-
 def ik_report_error(pb, context, do_print=False):
     dg = context.view_layer.depsgraph
     dg.update()
@@ -755,12 +697,9 @@ def ik_report_error(pb, context, do_print=False):
 
 # This is kinda a weird design decision?
 class LinkDrivenParameter(MantisLinkNode):
-    __slots__ = ()
     '''A node representing an armature object'''
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkDrivenParameterSockets)
-        self.init_parameters(additional_parameters={ "Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    __slots__ = ()
+    socket_templates = LinkDrivenParameterSockets
 
     def bRelationshipPass(self, bContext = None,):
         prepare_parameters(self)
@@ -814,12 +753,7 @@ class LinkDrivenParameter(MantisLinkNode):
 class LinkArmature(MantisLinkNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree,):
-        super().__init__(signature, base_tree, LinkArmatureSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
-        setup_custom_property_inputs_outputs(self) # <-- this takes care of the runtime-added sockets
+    socket_templates = LinkArmatureSockets
 
     def bRelationshipPass(self, bContext = None,):
         prepare_parameters(self)
@@ -867,11 +801,7 @@ class LinkArmature(MantisLinkNode):
 class LinkSplineIK(MantisLinkNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LinkSplineIKSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkSplineIKSockets
 
     def bRelationshipPass(self, bContext = None,):
         prepare_parameters(self)
@@ -906,11 +836,7 @@ class LinkSplineIK(MantisLinkNode):
 class LinkFloor(MantisLinkNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree,):
-        super().__init__(signature, base_tree, LinkFloorSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkFloorSockets
 
     def bRelationshipPass(self, bContext = None,):
         prepare_parameters(self)
@@ -931,10 +857,7 @@ class LinkFloor(MantisLinkNode):
 class LinkShrinkWrap(MantisLinkNode):
     '''A node representing a shrinkwrap relationship.'''
     __slots__ = ()
-    def __init__(self, signature, base_tree,):
-        super().__init__(signature, base_tree, LinkShrinkWrapSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkShrinkWrapSockets
 
     def bRelationshipPass(self, bContext = None,):
         prepare_parameters(self)
@@ -956,10 +879,7 @@ class LinkShrinkWrap(MantisLinkNode):
 class LinkGeometryAttribute(MantisLinkNode):
     '''A node representing a geometry attribute relationship.'''
     __slots__ = ()
-    def __init__(self, signature, base_tree,):
-        super().__init__(signature, base_tree, LinkGeometryAttributeSockets)
-        self.init_parameters(additional_parameters={"Name":None })
-        self.set_traverse([("Input Relationship", "Output Relationship")])
+    socket_templates = LinkGeometryAttributeSockets
 
     def bRelationshipPass(self, bContext = None,):
         from bpy.app import version

+ 2 - 2
link_nodes_ui.py

@@ -183,7 +183,7 @@ class LinkLimitLocationNode(Node, LinkNode):
     bl_icon = 'CON_LOCLIMIT'
     mantis_node_class_name=bl_idname
     category_color=linkTransformColor
-    socket_templates = LinkLimitLocationScaleSockets
+    socket_templates = LinkLimitLocationSockets
 
 class LinkLimitScaleNode(Node, LinkNode):
     '''A node representing Limit Scale'''
@@ -192,7 +192,7 @@ class LinkLimitScaleNode(Node, LinkNode):
     bl_icon = 'CON_SIZELIMIT'
     mantis_node_class_name=bl_idname
     category_color=linkTransformColor
-    socket_templates = LinkLimitLocationScaleSockets
+    socket_templates = LinkLimitScaleSockets
 
 class LinkLimitRotationNode(Node, LinkNode):
     '''A node representing Limit Rotation'''

+ 10 - 6
link_socket_templates.py

@@ -6,7 +6,8 @@ from .misc_nodes_socket_templates import SplineIndexTemplate
 # Socket Templates we will reuse:
 # inputs:
 InputRelationshipTemplate : SockTemplate = SockTemplate(
-    name="Input Relationship", is_input=True,  bl_idname='RelationshipSocket', )
+    name="Input Relationship", is_input=True,  bl_idname='RelationshipSocket',
+    traverse_target='Output Relationship')
 TargetTemplate : SockTemplate = SockTemplate(
     name="Target", is_input=True,  bl_idname='xFormSocket', )
 Head_Tail_Template : SockTemplate = SockTemplate(
@@ -78,7 +79,8 @@ TrackAxisTemplate= SockTemplate(name="Track Axis", bl_idname="EnumTrackAxis",
 
 # outputs:
 OutputRelationshipTemplate : SockTemplate = SockTemplate(
-    name="Output Relationship", is_input=False,  bl_idname='RelationshipSocket', )
+    name="Output Relationship", is_input=False,  bl_idname='RelationshipSocket',
+    traverse_target='Input Relationship')
 
 
 LinkInheritSockets = [
@@ -88,8 +90,10 @@ LinkInheritSockets = [
                  bl_idname='EnumInheritScale',    default_value="FULL",),
     SockTemplate(name="Connected",        is_input=True,
                  bl_idname='BooleanSocket',       default_value=False,),
-    SockTemplate(name="Parent",           is_input=True,   bl_idname='xFormSocket',),
-    SockTemplate(name="Inheritance",      is_input=False,  bl_idname='RelationshipSocket',),
+    SockTemplate(name="Parent",           is_input=True,   bl_idname='xFormSocket',
+                 traverse_target='Inheritance'),
+    SockTemplate(name="Inheritance",      is_input=False,  bl_idname='RelationshipSocket',
+                 traverse_target='Parent'),
 ]
 
 
@@ -206,7 +210,7 @@ LinkTransformationSockets = [
     OutputRelationshipTemplate,
 ]
 
-LinkLimitLocationScaleSockets = [
+LinkLimitLocationSockets = [
     InputRelationshipTemplate,
     *LimitAxesSocketTemplates, # we generated these ahead of time in a list
     AffectTransformTemplate,
@@ -226,7 +230,7 @@ LinkLimitRotationSockets = [
     OutputRelationshipTemplate,
 ]
 
-LinkLimitLocationScaleSockets = [
+LinkLimitScaleSockets = [
     InputRelationshipTemplate,
     *LimitAxesSocketTemplates, # we generated these ahead of time in a list
     AffectTransformTemplate,

+ 1 - 1
mantis_dataclasses.py

@@ -5,7 +5,7 @@ from typing import List, Any, Tuple, Optional
 class MantisSocketTemplate():
     name             : str = field(default="")
     bl_idname        : str = field(default="")
-    traverse_target  : str = field(default="")
+    traverse_target  : Optional[str] = field(default=None)
     identifier       : str = field(default="")
     display_shape    : str = field(default="") # for arrays
     category         : str = field(default="") # for use in display update

+ 3 - 9
math_nodes.py

@@ -53,10 +53,8 @@ def math_operation(operation, a, b):
 class MathStaticInt(MantisNode):
     '''A node representing an integer math operation'''
     __slots__ = ()
+    socket_templates = StaticIntSockets
     node_type = "UTILITY"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, StaticIntSockets)
-        self.init_parameters()
 
     def bPrepare(self, bContext = None,):
         a = self.evaluate_input("Int A"); b = self.evaluate_input("Int B")
@@ -67,10 +65,8 @@ class MathStaticInt(MantisNode):
 class MathStaticFloat(MantisNode):
     '''A node representing a float math operation'''
     __slots__ = ()
+    socket_templates = StaticFloatSockets
     node_type = "UTILITY"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, StaticFloatSockets)
-        self.init_parameters()
 
     def bPrepare(self, bContext = None,):
         a = self.evaluate_input("Float A"); b = self.evaluate_input("Float B")
@@ -81,10 +77,8 @@ class MathStaticFloat(MantisNode):
 class MathStaticVector(MantisNode):
     '''A node representing a vector math operation'''
     __slots__ = ()
+    socket_templates = StaticVectorSockets
     node_type = "UTILITY"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, StaticVectorSockets)
-        self.init_parameters()
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector

+ 79 - 207
misc_nodes.py

@@ -209,8 +209,8 @@ class MantisMiscNode(MantisNode):
 class SimpleInputNode(MantisMiscNode):
     __slots__ = ()
     node_type = 'UTILITY'
-    def __init__(self, signature, base_tree, socket_templates=[]):
-        super().__init__(signature, base_tree, socket_templates)
+    def __init__(self, signature, base_tree, socket_templates=[], additional_parameters={}):
+        super().__init__(signature, base_tree, socket_templates, additional_parameters)
         self.prepared, self.executed = True, True
 
 #*#-------------------------------#++#-------------------------------#*#
@@ -220,77 +220,52 @@ class SimpleInputNode(MantisMiscNode):
 class InputFloat(SimpleInputNode):
     '''A node representing float input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputFloatSockets)
-        self.init_parameters()
+    socket_templates = InputFloatSockets
 
 class InputIntNode(SimpleInputNode):
     '''A node representing integer input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputIntSockets)
-        self.init_parameters()
+    socket_templates = InputIntSockets
 
 class InputVector(SimpleInputNode):
     '''A node representing vector input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputVectorSockets)
-        self.init_parameters()
+    socket_templates = InputVectorSockets
 
 class InputBoolean(SimpleInputNode):
     '''A node representing boolean input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputBooleanSockets)
-        self.init_parameters()
+    socket_templates = InputBooleanSockets
 
 class InputBooleanThreeTuple(SimpleInputNode):
     '''A node representing a tuple of three booleans'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputBooleanThreeTupleSockets)
-        self.init_parameters()
+    socket_templates = InputBooleanThreeTupleSockets
 
 class InputRotationOrder(SimpleInputNode):
     '''A node representing string input for rotation order'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputRotationOrderSockets)
-        self.init_parameters()
+    socket_templates = InputRotationOrderSockets
 
 class InputTransformSpace(SimpleInputNode):
     '''A node representing string input for transform space'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputTransformSpaceSockets)
-        self.init_parameters()
+    socket_templates = InputTransformSpaceSockets
 
 class InputString(SimpleInputNode):
     '''A node representing string input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputStringSockets)
-        self.init_parameters()
+    socket_templates = InputStringSockets
 
 class InputMatrix(SimpleInputNode):
     '''A node representing axis-angle quaternion input'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputMatrixSockets)
-        self.init_parameters()
+    socket_templates = InputMatrixSockets
 
 class InputThemeBoneColorSets(SimpleInputNode):
     '''A node representing the theme's colors'''
     __slots__ = ()
+    socket_templates = None
 
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
@@ -302,7 +277,6 @@ class InputThemeBoneColorSets(SimpleInputNode):
             ))
         self.outputs.init_sockets(outputs)
         self.init_parameters()
-        # we'll go ahead and fill them here
 
     def fill_parameters(self, ui_node=None):
         if not ui_node:
@@ -315,8 +289,7 @@ class InputThemeBoneColorSets(SimpleInputNode):
 class InputColorSetPallete(SimpleInputNode):
     '''A node representing the theme's colors'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree)
+    socket_templates = None
 
     def fill_parameters(self, ui_node=None):
         if not ui_node:
@@ -335,10 +308,8 @@ class InputColorSetPallete(SimpleInputNode):
 
 class UtilityCustomProperty(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, UtilityCustomPropertySockets)
-        self.init_parameters()
-    # this should output a dataclass containing custom prop info
+    socket_templates = UtilityCustomPropertySockets
+    # TODO this should output a dataclass containing custom prop info
     # then the xForm will use it to assign custom properties
 
     def bPrepare(self, bContext=None):
@@ -382,10 +353,7 @@ class UtilityCustomProperty(MantisMiscNode):
 class UtilityMatrixFromCurve(MantisMiscNode):
     '''Get a matrix from a curve'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixFromCurveSockets)
-        self.init_parameters()
+    socket_templates = MatrixFromCurveSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Matrix
@@ -467,10 +435,7 @@ class UtilityMatrixFromCurve(MantisMiscNode):
 class UtilityPointFromCurve(MantisMiscNode):
     '''Get a point from a curve'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, PointFromCurveSockets)
-        self.init_parameters()
+    socket_templates = PointFromCurveSockets
 
     def bPrepare(self, bContext = None,):
         import bpy
@@ -501,10 +466,7 @@ class UtilityPointFromCurve(MantisMiscNode):
 class UtilityMatricesFromCurve(MantisMiscNode):
     '''Get matrices from a curve'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatricesFromCurveSockets)
-        self.init_parameters()
+    socket_templates = MatricesFromCurveSockets
 
     def bPrepare(self, bContext = None,):
         import time
@@ -569,9 +531,7 @@ class UtilityMatricesFromCurve(MantisMiscNode):
 
 class UtilityNumberOfCurveSegments(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, NumberOfCurveSegmentsSockets)
-        self.init_parameters()
+    socket_templates = NumberOfCurveSegmentsSockets
 
     def bPrepare(self, bContext = None,):
         curve_name = self.evaluate_input("Curve")
@@ -586,9 +546,7 @@ class UtilityNumberOfCurveSegments(MantisMiscNode):
 
 class UtilityNumberOfSplines(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, NumberOfSplinesSockets)
-        self.init_parameters()
+    socket_templates = NumberOfSplinesSockets
 
     def bPrepare(self, bContext = None,):
         curve_name = self.evaluate_input("Curve")
@@ -598,9 +556,7 @@ class UtilityNumberOfSplines(MantisMiscNode):
 
 class UtilityMatrixFromCurveSegment(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixFromCurveSegmentSockets)
-        self.init_parameters()
+    socket_templates = MatrixFromCurveSegmentSockets
 
     def bPrepare(self, bContext = None,):
         import bpy
@@ -656,9 +612,7 @@ class UtilityMatrixFromCurveSegment(MantisMiscNode):
 
 class UtilityGetCurvePoint(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, GetCurvePointSockets)
-        self.init_parameters()
+    socket_templates = GetCurvePointSockets
 
     def bPrepare(self, bContext=None):
         import bpy
@@ -681,9 +635,7 @@ class UtilityGetCurvePoint(MantisMiscNode):
 
 class UtilityGetNearestFactorOnCurve(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, GetNearestFactorOnCurveSockets)
-        self.init_parameters()
+    socket_templates = GetNearestFactorOnCurveSockets
 
     def bPrepare(self, bContext = None,):
         import bpy
@@ -710,9 +662,9 @@ class UtilityGetNearestFactorOnCurve(MantisMiscNode):
 
 class UtilityKDChoosePoint(MantisMiscNode):
     __slots__ = ('rerouted')
+    socket_templates = KDChoosePointSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, KDChoosePointSockets)
-        self.init_parameters()
+        super().__init__(signature, base_tree, self.socket_templates)
         self.rerouted=[]
 
     def bPrepare(self, bContext = None,):
@@ -736,9 +688,9 @@ class UtilityKDChoosePoint(MantisMiscNode):
 
 class UtilityKDChooseXForm(MantisMiscNode):
     __slots__ = ('rerouted')
+    socket_templates = KDChooseXFormSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, KDChooseXFormSockets)
-        self.init_parameters()
+        super().__init__(signature, base_tree, self.socket_templates)
         self.rerouted=[]
 
     def bPrepare(self, bContext = None,):
@@ -774,10 +726,7 @@ class UtilityKDChooseXForm(MantisMiscNode):
 class UtilityMetaRig(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MetaRigSockets)
-        self.init_parameters()
+    socket_templates = MetaRigSockets
 
     def bPrepare(self, bContext = None,):
         #kinda clumsy, whatever
@@ -816,10 +765,7 @@ class UtilityMetaRig(MantisMiscNode):
 class UtilityBoneProperties(SimpleInputNode):
     '''A node representing a bone's gettable properties'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, BonePropertiesSockets)
-        self.init_parameters()
+    socket_templates = BonePropertiesSockets
 
     def fill_parameters(self, ui_node=None):
         return
@@ -828,11 +774,8 @@ class UtilityBoneProperties(SimpleInputNode):
 class UtilityDriverVariable(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
+    socket_templates = DriverVariableSockets
     node_type = "DRIVER"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, DriverVariableSockets)
-        self.init_parameters()    
-        self.prepared = True
 
     def reset_execution(self):
         super().reset_execution()
@@ -912,12 +855,13 @@ class UtilityDriverVariable(MantisMiscNode):
 class UtilityKeyframe(MantisMiscNode):
     '''A node representing a keyframe for a F-Curve'''
     __slots__ = ()
+    socket_templates = KeyframeSockets
     # TODO: try UTILITY type and remove setup_custom_property stuff
     node_type = "DRIVER" # MUST be run in Pose mode
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, KeyframeSockets)
-        additional_parameters = {"Keyframe":{}}
-        self.init_parameters( additional_parameters=additional_parameters)
+    def __init__(self, signature, base_tree,):
+        super().__init__(signature, base_tree, KeyframeSockets,
+                additional_parameters={"Keyframe":{}})
+        # TODO: i am not sure this is necessary anymore
         setup_custom_property_inputs_outputs(self)
 
     def bPrepare(self, bContext = None,):
@@ -934,11 +878,10 @@ class UtilityKeyframe(MantisMiscNode):
 class UtilityFCurve(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
+    socket_templates = FCurveSockets
 
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, FCurveSockets)
-        self.init_parameters()
-        setup_custom_property_inputs_outputs(self)
+        super().__init__(signature, base_tree, self.socket_templates)
         self.prepared = True
 
     def reset_execution(self):
@@ -961,14 +904,12 @@ class UtilityFCurve(MantisMiscNode):
 class UtilityDriver(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
+    socket_templates = DriverSockets
     node_type = "DRIVER" # MUST be run in Pose mode
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, DriverSockets)
         from .utilities.drivers import MantisDriver
-        additional_parameters = {
-          "Driver":MantisDriver(),
-        }
-        self.init_parameters(additional_parameters=additional_parameters)
+        super().__init__(signature, base_tree, self.socket_templates,
+            additional_parameters = {"Driver":MantisDriver(),})
         setup_custom_property_inputs_outputs(self)
         self.prepared = True
 
@@ -1016,14 +957,12 @@ class UtilityDriver(MantisMiscNode):
 class UtilitySwitch(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
+    socket_templates = SwitchSockets
     node_type = "DRIVER" # MUST be run in Pose mode
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SwitchSockets)
         from .utilities.drivers import MantisDriver
-        additional_parameters = {
-          "Driver":MantisDriver(),
-        }
-        self.init_parameters(additional_parameters=additional_parameters)
+        super().__init__(signature, base_tree, self.socket_templates,
+            additional_parameters={ "Driver":MantisDriver(), })
         self.prepared = True
 
     # NOTE: _index for interface consistency
@@ -1093,10 +1032,7 @@ class UtilitySwitch(MantisMiscNode):
 class UtilityCombineThreeBool(MantisMiscNode):
     '''A node for combining three booleans into a boolean three-tuple'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CombineThreeBoolSockets)
-        self.init_parameters()
+    socket_templates = CombineThreeBoolSockets
 
     def reset_execution(self): # need to make sure any references are deleted
         super().reset_execution() # so we prepare the node again to reset them
@@ -1117,10 +1053,7 @@ class UtilityCombineThreeBool(MantisMiscNode):
 class UtilityCombineVector(MantisMiscNode):
     '''A node for combining three floats into a vector'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CombineVectorSockets)
-        self.init_parameters()
+    socket_templates = CombineVectorSockets
 
     def reset_execution(self): # need to make sure any references are deleted
         super().reset_execution() # so we prepare the node again to reset them
@@ -1141,10 +1074,7 @@ class UtilityCombineVector(MantisMiscNode):
 class UtilitySeparateVector(MantisMiscNode):
     '''A node for separating a vector into three floats'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SeparateVectorSockets)
-        self.init_parameters()
+    socket_templates = SeparateVectorSockets
 
     def bPrepare(self, bContext = None,):
         self.parameters["X"] = self.evaluate_input("Vector")[0]
@@ -1155,10 +1085,7 @@ class UtilitySeparateVector(MantisMiscNode):
 class UtilityCatStrings(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CatStringsSockets)
-        self.init_parameters()
+    socket_templates = CatStringsSockets
 
     def bPrepare(self, bContext = None,):
         self.parameters["OutputString"] = self.evaluate_input("String_1")+self.evaluate_input("String_2")
@@ -1168,10 +1095,8 @@ class UtilityCatStrings(MantisMiscNode):
 class InputWidget(MantisMiscNode):
     '''A node representing an existing object'''
     __slots__ = ()
+    socket_templates = InputWidgetSockets
     node_type = "XFORM"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputWidgetSockets)
-        self.init_parameters()
 
     def reset_execution(self):
         super().reset_execution()
@@ -1256,11 +1181,8 @@ class InputWidget(MantisMiscNode):
 class InputExistingGeometryObject(MantisMiscNode):
     '''A node representing an existing object'''
     __slots__ = ()
+    socket_templates = InputExistingGeometryObjectSockets
     node_type = "XFORM"
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputExistingGeometryObjectSockets)
-        self.init_parameters()
-        
 
     def reset_execution(self):
         super().reset_execution()
@@ -1283,10 +1205,10 @@ class InputExistingGeometryObject(MantisMiscNode):
 class InputExistingGeometryData(MantisMiscNode):
     '''A node representing existing object data'''
     __slots__ = ()
+    socket_templates = InputExistingGeometrySockets
 
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, InputExistingGeometrySockets)
-        self.init_parameters()
+        super().__init__(signature, base_tree, self.socket_templates)
         self.prepared = True; self.executed = True
 
     def reset_execution(self):
@@ -1307,6 +1229,7 @@ class InputExistingGeometryData(MantisMiscNode):
 class UtilityDeclareCollections(MantisMiscNode):
     '''A node to help manage bone collections'''
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree):
         # NOTE this one does not use socket template because it is special.
         # The user creates all the sockets for this one.
@@ -1335,10 +1258,7 @@ class UtilityDeclareCollections(MantisMiscNode):
 class UtilityCollectionJoin(MantisMiscNode):
     '''A node to help manage bone collections'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CollectionJoinSockets)
-        self.init_parameters()
-        self.prepared, self.executed = False, False
+    socket_templates = CollectionJoinSockets
 
     def reset_execution(self):
         super().reset_execution()
@@ -1365,10 +1285,7 @@ class UtilityCollectionJoin(MantisMiscNode):
 class UtilityCollectionHierarchy(MantisMiscNode):
     '''A node to help manage bone collections'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CollectionHierarchySockets)
-        self.init_parameters()
-        self.prepared, self.executed = False, False
+    socket_templates = CollectionHierarchySockets
 
     def reset_execution(self):
         super().reset_execution()
@@ -1390,11 +1307,10 @@ class UtilityCollectionHierarchy(MantisMiscNode):
 class UtilityGeometryOfXForm(MantisMiscNode):
     '''A node representing existing object data'''
     __slots__ = ()
+    socket_templates = GeometryOfXFormSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, GeometryOfXFormSockets)
-        self.init_parameters()
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree, self.socket_templates)
+        self.prepared = True; self.executed = True
 
     def reset_execution(self):
         super().reset_execution()
@@ -1416,9 +1332,7 @@ class UtilityGeometryOfXForm(MantisMiscNode):
 class UtilityNameOfXForm(MantisMiscNode):
     '''A node representing existing object data'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, NameOfXFormSockets)
-        self.init_parameters()
+    socket_templates = NameOfXFormSockets
 
     # mode for interface consistency
     def bPrepare(self, bContext = None,):
@@ -1432,10 +1346,7 @@ class UtilityNameOfXForm(MantisMiscNode):
 class UtilityGetBoneLength(MantisMiscNode):
     '''A node to get the length of a bone matrix'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, GetBoneLengthSockets)
-        self.init_parameters()
+    socket_templates = GetBoneLengthSockets
 
     def bPrepare(self, bContext = None,):
         if (l := self.evaluate_input("Bone Matrix")) is not None:
@@ -1448,10 +1359,7 @@ class UtilityGetBoneLength(MantisMiscNode):
 class UtilityPointFromBoneMatrix(MantisMiscNode):
     '''A node representing an armature object'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, PointFromBoneMatrixSockets)
-        self.init_parameters()
+    socket_templates = PointFromBoneMatrixSockets
 
     # TODO: find out why this is sometimes not ready at bPrepare phase
     def bPrepare(self, bContext = None,):
@@ -1465,10 +1373,7 @@ class UtilityPointFromBoneMatrix(MantisMiscNode):
 class UtilitySetBoneLength(MantisMiscNode):
     '''Sets the length of a Bone's matrix'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SetBoneLengthSockets)
-        self.init_parameters()
+    socket_templates = SetBoneLengthSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1485,10 +1390,7 @@ class UtilitySetBoneLength(MantisMiscNode):
 class UtilityMatrixSetLocation(MantisMiscNode):
     '''Sets the location of a matrix'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixSetLocationSockets)
-        self.init_parameters()
+    socket_templates = MatrixSetLocationSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1503,9 +1405,7 @@ class UtilityMatrixSetLocation(MantisMiscNode):
 class UtilityMatrixGetLocation(MantisMiscNode):
     '''Gets the location of a matrix'''
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixGetLocationSockets)
-        self.init_parameters()
+    socket_templates = MatrixGetLocationSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1516,9 +1416,7 @@ class UtilityMatrixGetLocation(MantisMiscNode):
 class UtilityMatrixFromXForm(MantisMiscNode):
     """Returns the matrix of the given xForm node."""
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixFromXFormSockets)
-        self.init_parameters()
+    socket_templates = MatrixFromXFormSockets
 
     def GetxForm(self):
         trace = trace_single_line(self, "xForm")
@@ -1543,9 +1441,7 @@ class UtilityMatrixFromXForm(MantisMiscNode):
 class UtilityAxesFromMatrix(MantisMiscNode):
     """Returns the axes of the given matrix."""
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, AxesFromMatrixSockets)
-        self.init_parameters()
+    socket_templates = AxesFromMatrixSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1558,9 +1454,7 @@ class UtilityAxesFromMatrix(MantisMiscNode):
 
 class UtilityBoneMatrixHeadTailFlip(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, BoneMatrixHeadTailFlipSockets)
-        self.init_parameters()
+    socket_templates = BoneMatrixHeadTailFlipSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector, Matrix, Quaternion
@@ -1579,9 +1473,7 @@ class UtilityBoneMatrixHeadTailFlip(MantisMiscNode):
 
 class UtilityMatrixTransform(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixTransformSockets)
-        self.init_parameters()
+    socket_templates = MatrixTransformSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1597,9 +1489,7 @@ class UtilityMatrixTransform(MantisMiscNode):
 
 class UtilityMatrixInvert(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixInvertSockets)
-        self.init_parameters()
+    socket_templates = MatrixInvertSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
@@ -1618,9 +1508,7 @@ class UtilityMatrixInvert(MantisMiscNode):
 
 class UtilityMatrixCompose(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixComposeSockets)
-        self.init_parameters()
+    socket_templates = MatrixComposeSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Matrix, Vector
@@ -1645,9 +1533,7 @@ class UtilityMatrixCompose(MantisMiscNode):
 
 class UtilityMatrixAlignRoll(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, MatrixAlignRollSockets)
-        self.init_parameters()
+    socket_templates = MatrixAlignRollSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Vector, Matrix
@@ -1682,9 +1568,7 @@ class UtilityMatrixAlignRoll(MantisMiscNode):
 
 class UtilityTransformationMatrix(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, TransformationMatrixSockets)
-        self.init_parameters()
+    socket_templates = TransformationMatrixSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Matrix, Vector
@@ -1704,9 +1588,7 @@ class UtilityTransformationMatrix(MantisMiscNode):
 
 class UtilityIntToString(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, IntToStringSockets)
-        self.init_parameters()
+    socket_templates = IntToStringSockets
 
     def bPrepare(self, bContext = None,):
         number = self.evaluate_input("Number")
@@ -1717,9 +1599,9 @@ class UtilityIntToString(MantisMiscNode):
 
 class UtilityArrayGet(MantisMiscNode):
     __slots__ = ('rerouted')
+    socket_templates = ArrayGetSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, ArrayGetSockets)
-        self.init_parameters()
+        super().__init__(signature, base_tree, self.socket_templates)
         self.rerouted=[]
 
     def bPrepare(self, bContext = None,):
@@ -1745,9 +1627,7 @@ class UtilityArrayGet(MantisMiscNode):
 
 class UtilityArrayLength(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, UtilityArrayLengthSockets)
-        self.init_parameters()
+    socket_templates = UtilityArrayLengthSockets
 
     def bPrepare(self, bContext = None,):
         self.parameters["Length"] = len(self.inputs["Array"].links)
@@ -1755,9 +1635,7 @@ class UtilityArrayLength(MantisMiscNode):
 
 class UtilitySetBoneMatrixTail(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SetBoneMatrixTailSockets)
-        self.init_parameters()
+    socket_templates = SetBoneMatrixTailSockets
 
     def bPrepare(self, bContext = None,):
         from mathutils import Matrix
@@ -1769,9 +1647,7 @@ class UtilitySetBoneMatrixTail(MantisMiscNode):
 
 class UtilityCompare(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, CompareSockets)
-        self.init_parameters()
+    socket_templates = CompareSockets
 
     def bPrepare(self, bContext = None,):
         operation=self.evaluate_input("Comparison")
@@ -1802,9 +1678,7 @@ class UtilityCompare(MantisMiscNode):
 
 class UtilityChoose(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, ChooseSockets)
-        self.init_parameters()
+    socket_templates = ChooseSockets
 
     def reset_execution(self):
         prepared=self.prepared
@@ -1833,9 +1707,7 @@ class UtilityChoose(MantisMiscNode):
 
 class UtilityPrint(MantisMiscNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, PrintSockets)
-        self.init_parameters()
+    socket_templates = PrintSockets
 
     def bPrepare(self, bContext = None,):
         if my_input := self.evaluate_input("Input"):

+ 8 - 19
primitives_nodes.py

@@ -1,5 +1,6 @@
 from .utilities.node_common import *
 from .base_definitions import MantisNode, NodeSocket
+from .primitives_sockets import *
 
 def TellClasses():
     return [
@@ -16,8 +17,10 @@ class PrimitiveNode(MantisNode):
     __slots__ = ()
     node_type = "UTILITY"
     
-    def __init__(self, signature, base_tree, socket_templates=[]):
-        super().__init__(signature, base_tree, socket_templates)
+    def __init__(self, signature, base_tree, socket_templates=[],
+                 additional_parameters = {}):
+        super().__init__(signature, base_tree, socket_templates,
+                         additional_parameters)
         self.prepared = True
     
     def reset_execution(self):
@@ -27,21 +30,7 @@ class PrimitiveNode(MantisNode):
 class CirclePrimitive(PrimitiveNode):
     '''A node representing a Circle Primitive mesh'''
     __slots__ = ()
-
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree)
-        inputs = [
-          "Name",
-          "Radius",
-          "Number of Points",
-        ]
-        outputs = [
-          "Circle",
-        ]
-        additional_parameters = {}
-        self.inputs.init_sockets(inputs)
-        self.outputs.init_sockets(outputs)
-        self.init_parameters(additional_parameters=additional_parameters)
+    socket_templates = CirclePrimitiveSockets
 
     # mode is unused but needed for interface consistency
     def bGetObject(self, mode=''):
@@ -79,10 +68,10 @@ from .primitives_sockets import LatticeSockets
 class GeometryLattice(PrimitiveNode):
     '''A node representing a Circle Primitive mesh'''
     __slots__ = ()
+    socket_templates = LatticeSockets
 
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, LatticeSockets)
-        self.init_parameters(additional_parameters= {})
+        super().__init__(signature, base_tree, self.socket_templates)
         self.prepared = False
 
     def reset_execution(self):

+ 8 - 7
schema_nodes.py

@@ -30,7 +30,6 @@ def schema_init_sockets(mantis_node, is_input = True, in_out='INPUT', category='
             if item.parent and read_schema_type(item) == category:
                 if item.in_out == in_out:
                     sockets[item.name] = NodeSocket(is_input=is_input, name=item.name, node=mantis_node)
-    mantis_node.init_parameters()
 
 
 class SchemaNode(MantisNode):
@@ -50,12 +49,11 @@ class SchemaNode(MantisNode):
 
 class SchemaIndex(SchemaNode):
     __slots__ = ()
-    def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, SchemaIndexSockets)
-        self.init_parameters()
+    socket_templates = SchemaIndexSockets
 
 class SchemaArrayInput(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
         schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
@@ -63,24 +61,28 @@ class SchemaArrayInput(SchemaNode):
 
 class SchemaArrayInputGet(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree, SchemaArrayInputGetSockets)
         schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
 
 class SchemaArrayInputAll(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
         schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
 
 class SchemaArrayOutput(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     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):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree, parent_schema_node=None):
         super().__init__(signature, base_tree)
         if parent_schema_node:
@@ -92,14 +94,13 @@ class SchemaConstInput(SchemaNode):
                 if item.item_type == 'PANEL': continue
                 if item.in_out == 'INPUT':
                     sockets[item.name] = NodeSocket(is_input=False, node=self, name=item.name)
-            self.init_parameters()
-            
         else:
             schema_init_sockets(self, is_input=False, in_out='INPUT', category='Constant')
 
 
 class SchemaConstOutput(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree, parent_schema_node=None):
         super().__init__(signature, base_tree)
         sockets=self.inputs
@@ -112,7 +113,6 @@ class SchemaConstOutput(SchemaNode):
                 if item.item_type == 'PANEL': continue
                 if item.in_out == 'OUTPUT':
                     sockets[item.name] = NodeSocket(is_input=False, node=self, name=item.name)
-            self.init_parameters()
             self.parameters['Expose at Index"']=1
 
         else:
@@ -122,6 +122,7 @@ class SchemaConstOutput(SchemaNode):
         
 class SchemaOutgoingConnection(SchemaNode):
     __slots__ = ()
+    socket_templates = None
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree)
         schema_init_sockets(self, is_input=True, in_out='INPUT', category='Connection')

+ 17 - 24
xForm_nodes.py

@@ -69,8 +69,10 @@ def set_object_parent(node):
 class xFormNode(MantisNode):
     __slots__ = ()
     node_type = 'XFORM'
-    def __init__(self, signature, base_tree, socket_templates=[]):
-        super().__init__(signature, base_tree, socket_templates)
+    def __init__(self, signature, base_tree, socket_templates=[],
+                 additional_parameters={}):
+        super().__init__(signature, base_tree, socket_templates,
+                         additional_parameters)
         self.bObject=None
 
     # because new objects are created during prep phase
@@ -158,11 +160,10 @@ class xFormNode(MantisNode):
 class xFormArmature(xFormNode):
     '''A node representing an armature object'''
     __slots__ = ()
+    socket_templates = xFormArmatureSockets
 
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, xFormArmatureSockets)
-        self.init_parameters()
-        self.set_traverse([("Relationship", "xForm Out")])
+        super().__init__(signature, base_tree, self.socket_templates)
         setup_custom_property_inputs_outputs(self)
 
     def bPrepare(self, bContext=None):
@@ -279,15 +280,10 @@ class xFormArmature(xFormNode):
 class xFormBone(xFormNode):
     '''A node representing a bone in an armature'''
     __slots__ = ()
+    socket_templates = xFormBoneSockets
     # DO: make a way to identify which armature this belongs to
     def __init__(self, signature, base_tree):
         super().__init__(signature, base_tree, xFormBoneSockets)
-        # TODO: implement socket templates completely for Bone
-        # currently it is waiting on BBone and refactoring/cleanup.
-        # the socket templates are being used now but not for mantis node execution.
-        # because of edit/pose/objcet bone this will be a bit complex
-        self.init_parameters()
-        self.set_traverse([("Relationship", "xForm Out")])
         setup_custom_property_inputs_outputs(self)
 
     def bGetParentArmature(self):
@@ -528,11 +524,9 @@ class xFormBone(xFormNode):
 class xFormGeometryObject(xFormNode):
     '''A node representing an armature object'''
     __slots__ = ("has_shape_keys")
+    socket_templates = xFormGeometryObjectSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, xFormGeometryObjectSockets)
-        self.init_parameters()
-        self.set_traverse([("Relationship", "xForm Out")])
-        self.has_shape_keys = False
+        super().__init__(signature, base_tree, self.socket_templates)
         setup_custom_property_inputs_outputs(self)
 
     def bPrepare(self, bContext = None,):
@@ -640,12 +634,10 @@ class xFormGeometryObject(xFormNode):
 class xFormObjectInstance(xFormNode):
     """Represents an instance of an existing geometry object."""
     __slots__ = ("has_shape_keys")
+    socket_templates = xFormGeometryObjectInstanceSockets
+
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, xFormGeometryObjectInstanceSockets)
-        self.init_parameters()
-        # TODO: I think this field is a leftover from a test or something. see if it can be removed.
-        self.links = {} # leave this empty for now!
-        self.set_traverse([("Relationship", "xForm Out")])
+        super().__init__(signature, base_tree, self.socket_templates)
         self.has_shape_keys = False # Shape Keys will make a dupe so this is OK
         setup_custom_property_inputs_outputs(self)
 
@@ -740,9 +732,10 @@ class xFormObjectInstance(xFormNode):
 class xFormCurvePin(xFormNode):
     """An xForm pinned to a specific location on a curve."""
     __slots__ = ()
+    socket_templates = xFormCurvePinSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree,xFormCurvePinSockets)
-        self.init_parameters(additional_parameters={"Matrix":None})
+        super().__init__(signature, base_tree, self.socket_templates,
+            additional_parameters={"Matrix":None})
         setup_custom_property_inputs_outputs(self)
 
     def prep_driver_values(self, constraint):
@@ -881,9 +874,9 @@ class xFormCurvePin(xFormNode):
 class xFormGetBone(xFormNode):
     """Represents an instance of an existing geometry object."""
     __slots__ = ()
+    socket_templates = xFormGetBoneSockets
     def __init__(self, signature, base_tree):
-        super().__init__(signature, base_tree, xFormGetBoneSockets)
-        self.init_parameters()
+        super().__init__(signature, base_tree, self.socket_templates)
         # this is just a getter
         self.prepared=True; self.executed=True; self.execution_prepared=True
     

+ 5 - 3
xForm_socket_templates.py

@@ -14,7 +14,8 @@ xFormArmatureSockets=[
         name="Matrix", is_input=True,  bl_idname='MatrixSocket',
             blender_property='matrix_world' ),
     RelationshipInTemplate := SockTemplate(
-        name="Relationship", is_input=True,  bl_idname='RelationshipSocket', ),
+        name="Relationship", is_input=True,  bl_idname='RelationshipSocket',
+        traverse_target='xForm Out' ),
     ArmatureDisplayType := SockTemplate(name='Display Type', category='Display',
         default_value='OCTAHEDRAL', blender_property='display_type',
         min_bpy_version=(4,5,0), bl_idname='EnumArmatureDisplayType',  is_input=True,),
@@ -22,7 +23,8 @@ xFormArmatureSockets=[
         name="Custom Properties", is_input=True,  bl_idname='CustomPropSocket',
             use_multi_input=True, is_animatable=False, ),
     xFormOutTemplate := SockTemplate(
-        name="xForm Out", is_input=False,  bl_idname='xFormSocket', ),
+        name="xForm Out", is_input=False,  bl_idname='xFormSocket', 
+        traverse_target='Relationship' ),
 ]
 
 xFormGeometryObjectSockets=[
@@ -76,7 +78,7 @@ xFormCurvePinSockets = [
         name="Display Size", is_input=True,  bl_idname='FloatPositiveSocket',
         default_value=0.05, blender_property='empty_display_size'),
     CustomPropsTemplate,
-    xFormOutTemplate,
+    replace(xFormOutTemplate, traverse_target = None)
 ]
 
 xFormGetBoneSockets = [