浏览代码

Cleanup: All MantisNode classes now use a common __init__() function

Joseph Brandenburg 7 月之前
父节点
当前提交
9edb92fe0c
共有 15 个文件被更改,包括 1031 次插入1900 次删除
  1. 1 1
      __init__.py
  2. 248 74
      base_definitions.py
  3. 1 1
      blender_manifest.toml
  4. 62 113
      deformer_containers.py
  5. 6 26
      internal_containers.py
  6. 292 595
      link_containers.py
  7. 42 74
      math_containers.py
  8. 251 514
      misc_containers.py
  9. 2 116
      node_container_common.py
  10. 14 22
      primitives_containers.py
  11. 2 4
      readtree.py
  12. 46 127
      schema_containers.py
  13. 2 3
      schema_solve.py
  14. 1 1
      utilities.py
  15. 61 229
      xForm_containers.py

+ 1 - 1
__init__.py

@@ -17,7 +17,7 @@ from .utilities import prRed
 
 
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MINOR=9
 MANTIS_VERSION_MINOR=9
-MANTIS_VERSION_SUB=13
+MANTIS_VERSION_SUB=14
 
 
 classLists = [module.TellClasses() for module in [
 classLists = [module.TellClasses() for module in [
  link_definitions,
  link_definitions,

+ 248 - 74
base_definitions.py

@@ -131,80 +131,7 @@ class SchemaTree(NodeTree):
             
             
 
 
 
 
-#TODO: do a better job explaining how the following two classes relate.
-
-class MantisNode:
-    """
-        This class contains the basic interface for a Mantis Node.
-        A MantisNode is used internally by Mantis to represent the final evaluated node graph.
-        It gets generated with data from a MantisUINode when the graph is read.
-    """
-    def flush_links(self):
-        for inp in self.inputs.values():
-            inp.flush_links()
-        for out in self.outputs.values():
-            out.flush_links()
-    
-    def evaluate_input(self, input_name, index=0):
-        from .node_container_common import trace_single_line
-        if not (self.inputs.get(input_name)): # get the named parameter if there is no input
-            if input_name == 'Meta-Armature':
-                prOrange("beans are not frogs")
-            return self.parameters.get(input_name) # this will return None if the parameter does not exist.
-        # this trace() should give a key error if there is a problem
-        #  it is NOT handled here because it should NOT happen - so I want the error message.
-        trace = trace_single_line(self, input_name, index)
-        prop = trace[0][-1].parameters[trace[1].name] #trace[0] = the list of traced nodes; read its parameters
-        return prop
-    
-    def fill_parameters(self, ui_node=None):
-        from .utilities import get_node_prototype
-        from .node_container_common import get_socket_value
-        if not ui_node:
-            if ( (self.signature[0] in  ["MANTIS_AUTOGENERATED", "SCHEMA_AUTOGENERATED" ]) or 
-                (self.signature[-1] in ["NodeGroupOutput", "NodeGroupInput"]) ): # I think this is harmless
-                return None
-            else:
-                ui_node = get_node_prototype(self.signature, self.base_tree)
-            if not ui_node:
-                raise RuntimeError(wrapRed("No node prototype found for... %s" % ( [self.base_tree] + list(self.signature[1:]) ) ) )
-        for key in self.parameters.keys():
-            node_socket = ui_node.inputs.get(key)
-            if self.parameters[key] is not None: # the parameters are usually initialized as None.
-                continue # will be filled by the node itself
-            if not node_socket: #maybe the node socket has no name
-                if ( ( len(ui_node.inputs) == 0) and ( len(ui_node.outputs) == 1) ):
-                    # this is a simple input node.
-                    node_socket = ui_node.outputs[0]
-                elif key == 'Name': # for Links we just use the Node Label, or if there is no label, the name.
-                    self.parameters[key] = ui_node.label if ui_node.label else ui_node.name
-                    continue
-                else:
-                    pass
-            if node_socket:
-                if node_socket.bl_idname in  ['RelationshipSocket', 'xFormSocket']:
-                    continue
-                elif node_socket.is_linked and (not node_socket.is_output):
-                    pass # we will get the value from the link, because this is a linked input port.
-                # very importantly, we do not pass linked outputs- fill these because they are probably Input nodes.
-                elif hasattr(node_socket, "default_value"):
-                    if (value := get_socket_value(node_socket)) is not None:
-                        self.parameters[key] = value
-                        # TODO: try and remove the input if it is not needed (for performance speed)
-                    else:
-                        raise RuntimeError(wrapRed("No value found for " + self.__repr__() + " when filling out node parameters for " + ui_node.name + "::"+node_socket.name))
-                else:
-                    pass
-    
-    def bPrepare(self, bContext=None):
-        return
-    def bExecute(self, bContext=None):
-        return
-    def bFinalize(self, bContext=None):
-        return
-    def __repr__(self): 
-        return self.signature.__repr__()
-
+#TODO: do a better job explaining how MantisNode and MantisUINode relate.
 
 
 class MantisUINode:
 class MantisUINode:
     """
     """
@@ -465,3 +392,250 @@ to_name_filter = [
                    "Custom Object",
                    "Custom Object",
                    "Deform Bones",
                    "Deform Bones",
                  ]
                  ]
+
+
+
+class MantisNode:
+    """
+        This class contains the basic interface for a Mantis Node.
+        A MantisNode is used internally by Mantis to represent the final evaluated node graph.
+        It gets generated with data from a MantisUINode when the graph is read.
+    """
+    def __init__(self, signature, base_tree):
+        self.base_tree=base_tree
+        self.signature = signature
+        self.inputs = MantisNodeSocketCollection(node=self, is_input=True)
+        self.outputs = MantisNodeSocketCollection(node=self, is_input=False)
+        self.parameters = dict()
+        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:
+            self.parameters[socket.name] = None
+        for socket in self.outputs:
+            self.parameters[socket.name] = None
+        for key, value in additional_parameters.items():
+            self.parameters[key]=value
+    
+    def set_traverse(self, traversal_pairs = [(str, str)]):
+        for (a, b) in traversal_pairs:
+            self.inputs[a].set_traverse_target(self.outputs[b])
+            self.outputs[b].set_traverse_target(self.inputs[a])
+            
+
+    def flush_links(self):
+        for inp in self.inputs.values():
+            inp.flush_links()
+        for out in self.outputs.values():
+            out.flush_links()
+    
+    def evaluate_input(self, input_name, index=0):
+        from .node_container_common import trace_single_line
+        if not (self.inputs.get(input_name)): # get the named parameter if there is no input
+            if input_name == 'Meta-Armature':
+                prOrange("beans are not frogs")
+            return self.parameters.get(input_name) # this will return None if the parameter does not exist.
+        # this trace() should give a key error if there is a problem
+        #  it is NOT handled here because it should NOT happen - so I want the error message.
+        trace = trace_single_line(self, input_name, index)
+        prop = trace[0][-1].parameters[trace[1].name] #trace[0] = the list of traced nodes; read its parameters
+        return prop
+    
+    def fill_parameters(self, ui_node=None):
+        from .utilities import get_node_prototype
+        from .node_container_common import get_socket_value
+        if not ui_node:
+            if ( (self.signature[0] in  ["MANTIS_AUTOGENERATED", "SCHEMA_AUTOGENERATED" ]) or 
+                (self.signature[-1] in ["NodeGroupOutput", "NodeGroupInput"]) ): # I think this is harmless
+                return None
+            else:
+                ui_node = get_node_prototype(self.signature, self.base_tree)
+            if not ui_node:
+                raise RuntimeError(wrapRed("No node prototype found for... %s" % ( [self.base_tree] + list(self.signature[1:]) ) ) )
+        for key in self.parameters.keys():
+            node_socket = ui_node.inputs.get(key)
+            if self.parameters[key] is not None: # the parameters are usually initialized as None.
+                continue # will be filled by the node itself
+            if not node_socket: #maybe the node socket has no name
+                if ( ( len(ui_node.inputs) == 0) and ( len(ui_node.outputs) == 1) ):
+                    # this is a simple input node.
+                    node_socket = ui_node.outputs[0]
+                elif key == 'Name': # for Links we just use the Node Label, or if there is no label, the name.
+                    self.parameters[key] = ui_node.label if ui_node.label else ui_node.name
+                    continue
+                else:
+                    pass
+            if node_socket:
+                if node_socket.bl_idname in  ['RelationshipSocket', 'xFormSocket']:
+                    continue
+                elif node_socket.is_linked and (not node_socket.is_output):
+                    pass # we will get the value from the link, because this is a linked input port.
+                # very importantly, we do not pass linked outputs- fill these because they are probably Input nodes.
+                elif hasattr(node_socket, "default_value"):
+                    if (value := get_socket_value(node_socket)) is not None:
+                        self.parameters[key] = value
+                        # TODO: try and remove the input if it is not needed (for performance speed)
+                    else:
+                        raise RuntimeError(wrapRed("No value found for " + self.__repr__() + " when filling out node parameters for " + ui_node.name + "::"+node_socket.name))
+                else:
+                    pass
+    
+    def bPrepare(self, bContext=None):
+        return
+    def bExecute(self, bContext=None):
+        return
+    def bFinalize(self, bContext=None):
+        return
+    def __repr__(self): 
+        return self.signature.__repr__()
+
+
+
+
+# do I need this and the link class above?
+class DummyLink:
+    #gonna use this for faking links to keep the interface consistent
+    def __init__(self, from_socket, to_socket, nc_from=None, nc_to=None, original_from=None, multi_input_sort_id=0):
+        self.from_socket = from_socket
+        self.to_socket = to_socket
+        self.nc_from = nc_from
+        self.nc_to = nc_to
+        self.multi_input_sort_id = multi_input_sort_id
+        # self.from_node = from_socket.node
+        # self.to_node = to_socket.node
+        if (original_from):
+            self.original_from = original_from
+        else:
+            self.original_from = self.from_socket
+    def __repr__(self):
+        return(self.nc_from.__repr__()+":"+self.from_socket.name + " -> " + self.nc_to.__repr__()+":"+self.to_socket.name)
+
+
+class NodeLink:
+    from_node = None
+    from_socket = None
+    to_node = None
+    to_socket = None
+    
+    def __init__(self, from_node, from_socket, to_node, to_socket, multi_input_sort_id=0):
+        if from_node.signature == to_node.signature:
+            raise RuntimeError("Cannot connect a node to itself.")
+        self.from_node = from_node
+        self.from_socket = from_socket
+        self.to_node = to_node
+        self.to_socket = to_socket
+        self.from_node.outputs[self.from_socket].links.append(self)
+        # it is the responsibility of the node that uses these links to sort them correctly based on the sort_id
+        self.multi_input_sort_id = multi_input_sort_id
+        self.to_node.inputs[self.to_socket].links.append(self)
+        from .node_container_common import detect_hierarchy_link
+        self.is_hierarchy = detect_hierarchy_link(from_node, from_socket, to_node, to_socket,)
+        self.is_alive = True
+    
+    def __repr__(self):
+        return self.from_node.outputs[self.from_socket].__repr__() + " --> " + self.to_node.inputs[self.to_socket].__repr__()
+        # link_string =   # if I need to colorize output for debugging.
+        # if self.is_hierarchy:
+        #     return wrapOrange(link_string)
+        # else:
+        #     return wrapWhite(link_string)
+    
+    def die(self):
+        self.is_alive = False
+        self.to_node.inputs[self.to_socket].flush_links()
+        self.from_node.outputs[self.from_socket].flush_links()
+    
+    def insert_node(self, middle_node, middle_node_in, middle_node_out, re_init_hierarchy = True):
+        to_node = self.to_node
+        to_socket = self.to_socket
+        self.to_node = middle_node
+        self.to_socket = middle_node_in
+        middle_node.outputs[middle_node_out].connect(to_node, to_socket)
+        if re_init_hierarchy:
+            from .utilities import init_connections, init_dependencies
+            init_connections(self.from_node)
+            init_connections(middle_node)
+            init_dependencies(middle_node)
+            init_dependencies(to_node)
+
+class NodeSocket:
+    @property # this is a read-only property.
+    def is_linked(self):
+        return bool(self.links)
+        
+    def __init__(self, is_input = False,
+                 node = None, name = None,
+                 traverse_target = None):
+        self.can_traverse = False # to/from the other side of the parent node
+        self.traverse_target = None
+        self.node = node
+        self.name = name
+        self.is_input = is_input
+        self.links = []
+        if (traverse_target):
+            self.can_traverse = True
+        
+    def connect(self, node, socket, sort_id=0):
+        if  (self.is_input):
+            to_node   = self.node; from_node = node
+            to_socket = self.name; from_socket = socket
+        else:
+            from_node   = self.node; to_node   = node
+            from_socket = self.name; to_socket = socket
+        for l in from_node.outputs[from_socket].links:
+            if l.to_node==to_node and l.to_socket==to_socket:
+                return None
+        new_link = NodeLink(
+                from_node,
+                from_socket,
+                to_node,
+                to_socket,
+                sort_id)
+        return new_link
+    
+    def set_traverse_target(self, traverse_target):
+        self.traverse_target = traverse_target
+        self.can_traverse = True
+    
+    def flush_links(self):
+        """ Removes dead links from this socket."""
+        self.links = [l for l in self.links if l.is_alive]
+        
+    @property
+    def is_connected(self):
+        return len(self.links)>0
+    
+    
+    def __repr__(self):
+        return self.node.__repr__() + "::" + self.name
+
+class MantisNodeSocketCollection(dict):
+    def __init__(self, node, is_input=False):
+        self.is_input = is_input
+        self.node = node
+    
+    def init_sockets(self, sockets):
+        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"""
+        assert isinstance(key, str) and isinstance(value, NodeSocket), "Key must be a string and value must be NodeSocket"
+        super().__setitem__(key, value)
+    
+    def __delitem__(self, key):
+        """Deletes a node socket by name, and all its links."""
+        socket = self[key]
+        for l in socket.links:
+            l.die()
+        super().__delitem__(key)
+    
+    def __iter__(self):
+        """Makes the class iterable"""
+        return iter(self.values())

+ 1 - 1
blender_manifest.toml

@@ -3,7 +3,7 @@ schema_version = "1.0.0"
 # Example of manifest file for a Blender extension
 # Example of manifest file for a Blender extension
 # Change the values according to your extension
 # Change the values according to your extension
 id = "mantis"
 id = "mantis"
-version = "0.9.13"
+version = "0.9.14"
 name = "Mantis"
 name = "Mantis"
 tagline = "Mantis is a rigging nodes toolkit"
 tagline = "Mantis is a rigging nodes toolkit"
 maintainer = "Nodespaghetti <josephbburg@protonmail.com>"
 maintainer = "Nodespaghetti <josephbburg@protonmail.com>"

+ 62 - 113
deformer_containers.py

@@ -27,18 +27,6 @@ def trace_xForm_back(nc, socket):
                 return trace[ i ].bGetObject()
                 return trace[ i ].bGetObject()
         raise GraphError(wrapRed(f"No other object found for {nc}."))
         raise GraphError(wrapRed(f"No other object found for {nc}."))
 
 
-def default_evaluate_input(nc, input_name):
-    # duped from link_containers... should be common?
-    # should catch 'Target', 'Pole Target' and ArmatureConstraint targets, too
-    if ('Target' in input_name) and input_name != "Target Space":
-        socket = nc.inputs.get(input_name)
-        if socket.is_linked:
-            return socket.links[0].from_node
-        return None
-        
-    else:
-        return evaluate_input(nc, input_name)
-
 
 
 # semi-duplicated from link_containers
 # semi-duplicated from link_containers
 def GetxForm(nc):
 def GetxForm(nc):
@@ -52,44 +40,29 @@ class DeformerArmature(MantisNode):
     '''A node representing an armature deformer'''
     '''A node representing an armature deformer'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Input Relationship"     : NodeSocket(is_input = True, name = "Input Relationship", node = self,),
-          "Armature Object"        : NodeSocket(is_input = True, name = "Armature Object", node = self,),
-          "Blend Vertex Group"     : NodeSocket(is_input = True, name = "Blend Vertex Group", node = self),
-          "Invert Vertex Group"    : NodeSocket(is_input = True, name = "Invert Vertex Group", node = self),
-          "Preserve Volume"        : NodeSocket(is_input = True, name = "Preserve Volume", node = self),
-          "Use Multi Modifier"     : NodeSocket(is_input = True, name = "Use Multi Modifier", node = self),
-          "Use Envelopes"          : NodeSocket(is_input = True, name = "Use Envelopes", node = self),
-          "Use Vertex Groups"      : NodeSocket(is_input = True, name = "Use Vertex Groups", node = self),
-          "Skinning Method"        : NodeSocket(is_input = True, name = "Skinning Method", node = self),
-          "Deformer"               : NodeSocket(is_input = True, name = "Deformer", node = self),
-          "Copy Skin Weights From" : NodeSocket(is_input = True, name = "Copy Skin Weights From", node = self),
-        }
-        self.outputs = {
-          "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self), }
-        self.parameters = {
-          "Name"                   : None,
-          "Armature Object"        : None,
-          "Blend Vertex Group"     : None,
-          "Invert Vertex Group"    : None,
-          "Preserve Volume"        : None,
-          "Use Multi Modifier"     : None,
-          "Use Envelopes"          : None,
-          "Use Vertex Groups"      : None,
-          "Skinning Method"        : None,
-          "Deformer"               : None,
-          "Copy Skin Weights From" : None,
-        }
-        # now set up the traverse target...
-        self.inputs["Deformer"].set_traverse_target(self.outputs["Deformer"])
-        self.outputs["Deformer"].set_traverse_target(self.inputs["Deformer"])
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Input Relationship",
+            "Armature Object",
+            "Blend Vertex Group",
+            "Invert Vertex Group",
+            "Preserve Volume",
+            "Use Multi Modifier",
+            "Use Envelopes",
+            "Use Vertex Groups",
+            "Skinning Method",
+            "Deformer",
+            "Copy Skin Weights From"
+        ]
+        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.node_type = "LINK"
         self.node_type = "LINK"
-        self.hierarchy_connections, self.connections = [], []
-        self.hierarchy_dependencies, self.dependencies = [], []
         self.prepared = True
         self.prepared = True
-        self.executed = False
 
 
 
 
     def GetxForm(self, socket="Deformer"):
     def GetxForm(self, socket="Deformer"):
@@ -232,29 +205,22 @@ class DeformerHook(MantisNode):
     '''A node representing a hook deformer'''
     '''A node representing a hook deformer'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Hook Target"    : NodeSocket(is_input = True, name = "Hook Target", node = self,),
-          "Index"          : NodeSocket(is_input = True, name = "Index", node = self),
-          "Deformer"       : NodeSocket(is_input = True, name = "Deformer", node = self),
-        }
-        self.outputs = {
-          "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self), }
-        self.parameters = {
-          "Hook Target"     : None,
-          "Index"           : None,
-          "Deformer"        : None,
-          "Name"            : None,
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Hook Target",
+            "Index",
+            "Deformer",
+        ]
+        outputs = [
+          "Deformer"
+        ]
         # now set up the traverse target...
         # now set up the traverse target...
-        self.inputs["Deformer"].set_traverse_target(self.outputs["Deformer"])
-        self.outputs["Deformer"].set_traverse_target(self.inputs["Deformer"])
+        self.outputs.init_sockets(outputs)
+        self.inputs.init_sockets(inputs)
+        self.init_parameters(additional_parameters={"Name":None})
+        self.set_traverse([("Deformer", "Deformer")])
         self.node_type = "LINK"
         self.node_type = "LINK"
-        self.hierarchy_connections, self.connections = [], []
-        self.hierarchy_dependencies, self.dependencies = [], []
         self.prepared = True
         self.prepared = True
-        self.executed = False
 
 
 
 
 
 
@@ -303,33 +269,24 @@ class DeformerHook(MantisNode):
 class DeformerMorphTarget(MantisNode):
 class DeformerMorphTarget(MantisNode):
     '''A node representing an armature deformer'''
     '''A node representing an armature deformer'''
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Relative to"  : NodeSocket(is_input = True, name = "Relative To", node = self,),
-          "Object"       : NodeSocket(is_input = True, name = "Object", node = self,),
-          "Deformer"     : NodeSocket(is_input = True, name = "Deformer", node = self),
-          "Vertex Group" : NodeSocket(is_input = True, name = "Vertex Group", node = self),
-        }
-        self.outputs = {
-          "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self),
-          "Morph Target" : NodeSocket(is_input = False, name = "Morph Target", node=self), }
-        self.parameters = {
-          "Name"               : None,
-          "Relative to"        : None,
-          "Object"             : None,
-          "Morph Target"       : None,
-          "Deformer"           : None,
-          "Vertex Group"       : None,
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Relative to",
+            "Object",
+            "Deformer",
+            "Vertex Group",
+        ]
+        outputs = [
+          "Deformer",
+          "Morph Target",
+        ]
         # now set up the traverse target...
         # now set up the traverse target...
-        self.inputs["Deformer"].set_traverse_target(self.outputs["Deformer"])
-        self.outputs["Deformer"].set_traverse_target(self.inputs["Deformer"])
+        self.outputs.init_sockets(outputs)
+        self.inputs.init_sockets(inputs)
+        self.init_parameters(additional_parameters={"Name":None})
+        self.set_traverse([("Deformer", "Deformer")])
         self.node_type = "LINK"
         self.node_type = "LINK"
-        self.hierarchy_connections, self.connections = [], []
-        self.hierarchy_dependencies, self.dependencies = [], []
         self.prepared = True
         self.prepared = True
-        self.executed = False
     
     
     def GetxForm(self, trace_input="Object"):
     def GetxForm(self, trace_input="Object"):
         trace = trace_single_line(self, trace_input)
         trace = trace_single_line(self, trace_input)
@@ -369,28 +326,20 @@ class DeformerMorphTargetDeform(MantisNode):
     '''A node representing an armature deformer'''
     '''A node representing an armature deformer'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Deformer"            : NodeSocket(is_input = True, name = "Deformer", node = self),
-          "Use Shape Key"       : NodeSocket(is_input = True, name = "Use Shape Key", node = self),
-          "Use Offset"          : NodeSocket(is_input = True, name = "Use Offset", node = self),
-        }
-        self.outputs = {
-          "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self), }
-        self.parameters = {
-          "Name"                : None,
-          "Deformer"            : None,
-          "Deformer"            : None,
-          "Use Shape Key"       : None,
-          "Use Offset"          : None,
-          }
-        # now set up the traverse target...
-        self.inputs["Deformer"].set_traverse_target(self.outputs["Deformer"])
-        self.outputs["Deformer"].set_traverse_target(self.inputs["Deformer"])
+        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.node_type = "LINK"
         self.node_type = "LINK"
-        self.hierarchy_connections, self.connections = [], []
-        self.hierarchy_dependencies, self.dependencies = [], []
         self.prepared = True
         self.prepared = True
         self.executed = True
         self.executed = True
         self.bObject = None
         self.bObject = None

+ 6 - 26
internal_containers.py

@@ -5,12 +5,8 @@ from uuid import uuid4
 
 
 class DummyNode(MantisNode):
 class DummyNode(MantisNode):
     def __init__(self, signature, base_tree, prototype = None, natural_signature=None):
     def __init__(self, signature, base_tree, prototype = None, natural_signature=None):
-        self.signature = signature
-        self.base_tree = base_tree
+        super().__init__(signature, base_tree)
         self.prototype = prototype
         self.prototype = prototype
-        self.inputs={}
-        self.outputs={}
-        self.parameters = {}
         self.node_type = 'DUMMY'
         self.node_type = 'DUMMY'
         self.prepared = True
         self.prepared = True
         if prototype.bl_idname in ["MantisSchemaGroup"]:
         if prototype.bl_idname in ["MantisSchemaGroup"]:
@@ -32,33 +28,17 @@ class DummyNode(MantisNode):
             self.natural_signature=natural_signature
             self.natural_signature=natural_signature
         # This is necessary for Schema to work if there are multiple Schema nodes using the same Schema tree.
         # This is necessary for Schema to work if there are multiple Schema nodes using the same Schema tree.
         # this is ugly and I hate it.
         # this is ugly and I hate it.
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.executed = False
 
 
 
 
 class NoOpNode(MantisNode):
 class NoOpNode(MantisNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.signature = signature
-        self.base_tree = base_tree
-        self.inputs={
-          "Input"   : NodeSocket(is_input = True, name = "Input", node = self),
-        }
-        self.outputs = {
-          "Output" : NodeSocket(name = "Output", node=self),
-        }
-        self.parameters = {
-            "Input"  : None,
-            "Output" : None,
-        }
-        self.inputs["Input"].set_traverse_target(self.outputs["Output"])
-        self.outputs["Output"].set_traverse_target(self.inputs["Input"])
+        super().__init__(signature, base_tree)
+        self.inputs.init_sockets(["Input"])
+        self.outputs.init_sockets(["Output"])
+        self.init_parameters()
+        self.set_traverse([("Input", "Output")])
         self.node_type = 'UTILITY'
         self.node_type = 'UTILITY'
         self.prepared = True
         self.prepared = True
-        self.hierarchy_connections = [];  self.connections = []
-        self.hierarchy_dependencies = []; self.dependencies = []
         self.executed = True
         self.executed = True
     
     
     # this node is useful for me to insert in the tree and use for debugging especially connections.
     # this node is useful for me to insert in the tree and use for debugging especially connections.

文件差异内容过多而无法显示
+ 292 - 595
link_containers.py


+ 42 - 74
math_containers.py

@@ -1,5 +1,5 @@
 from .node_container_common import *
 from .node_container_common import *
-from .base_definitions import MantisNode
+from .base_definitions import MantisNode, NodeSocket
 
 
 def TellClasses():
 def TellClasses():
     return [
     return [
@@ -15,30 +15,20 @@ class MathStaticInt(MantisNode):
     '''A node representing an armature object'''
     '''A node representing an armature object'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.executed = False
-        self.signature = signature
-        self.inputs = {
-          "Operation" : NodeSocket(is_input = True, name = "Operation", node = self),
-          "Int A"   : NodeSocket(is_input = True, name = "Int A", node = self),
-          "Int B"   : NodeSocket(is_input = True, name = "Int B", node = self),
-        }
-        self.outputs = {
-          "Result Int" : NodeSocket(name = "Result Int", node=self),
-        }
-        self.parameters = {
-          "Operation":None,
-          "Int A":None, 
-          "Int B":None, 
-          "Result Int":None, 
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+          "Operation",
+          "Int A",
+          "Int B",
+        ]
+        outputs = [
+          "Result Int",
+        ]
+        additional_parameters = {}
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters(additional_parameters=additional_parameters)
         self.node_type = "UTILITY"
         self.node_type = "UTILITY"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = False
-        self.executed = False
 
 
     def bPrepare(self, bContext = None,):
     def bPrepare(self, bContext = None,):
         a = self.evaluate_input("Int A"); b = self.evaluate_input("Int B")
         a = self.evaluate_input("Int A"); b = self.evaluate_input("Int B")
@@ -73,30 +63,20 @@ class MathStaticFloat(MantisNode):
     '''A node representing an armature object'''
     '''A node representing an armature object'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.executed = False
-        self.signature = signature
-        self.inputs = {
-          "Operation" : NodeSocket(is_input = True, name = "Operation", node = self),
-          "Float A"   : NodeSocket(is_input = True, name = "Float A", node = self),
-          "Float B"   : NodeSocket(is_input = True, name = "Float B", node = self),
-        }
-        self.outputs = {
-          "Result Float" : NodeSocket(name = "Result Float", node=self),
-        }
-        self.parameters = {
-          "Operation":None,
-          "Float A":None, 
-          "Float B":None, 
-          "Result Float":None, 
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+          "Operation",
+          "Float A",
+          "Float B",
+        ]
+        outputs = [
+          "Result Float",
+        ]
+        additional_parameters = {}
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters(additional_parameters=additional_parameters)
         self.node_type = "UTILITY"
         self.node_type = "UTILITY"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = False
-        self.executed = False
 
 
     def bPrepare(self, bContext = None,):
     def bPrepare(self, bContext = None,):
         a = self.evaluate_input("Float A"); b = self.evaluate_input("Float B")
         a = self.evaluate_input("Float A"); b = self.evaluate_input("Float B")
@@ -136,34 +116,22 @@ class MathStaticVector(MantisNode):
     '''A node representing an armature object'''
     '''A node representing an armature object'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.executed = False
-        self.signature = signature
-        self.inputs = {
-          "Operation"  : NodeSocket(is_input = True, name = "Operation", node = self),
-          "Vector A"   : NodeSocket(is_input = True, name = "Vector A", node = self),
-          "Vector B"   : NodeSocket(is_input = True, name = "Vector B", node = self),
-          "Scalar A"   : NodeSocket(is_input = True, name = "Scalar A", node = self),
-        }
-        self.outputs = {
-          "Result Vector" : NodeSocket(name = "Result Vector", node=self),
-          "Result Float" : NodeSocket(name = "Result Float", node=self),
-        }
-        self.parameters = {
-          "Operation":None,
-          "Vector A":None, 
-          "Vector B":None, 
-          "Scalar A":None, 
-          "Result Vector":None, 
-          "Result Float":None, 
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+          "Operation",
+          "Vector A",
+          "Vector B",
+          "Scalar A",
+        ]
+        outputs = [
+          "Result Vector",
+          "Result Float",
+        ]
+        additional_parameters = {}
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters(additional_parameters=additional_parameters)
         self.node_type = "UTILITY"
         self.node_type = "UTILITY"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = False
-        self.executed = False
 
 
     def bPrepare(self, bContext = None,):
     def bPrepare(self, bContext = None,):
         from mathutils import Vector
         from mathutils import Vector

文件差异内容过多而无法显示
+ 251 - 514
misc_containers.py


+ 2 - 116
node_container_common.py

@@ -2,7 +2,7 @@ from .utilities import (prRed, prGreen, prPurple, prWhite,
                               prOrange,
                               prOrange,
                               wrapRed, wrapGreen, wrapPurple, wrapWhite,
                               wrapRed, wrapGreen, wrapPurple, wrapWhite,
                               wrapOrange,)
                               wrapOrange,)
-from .base_definitions import GraphError
+from .base_definitions import GraphError, NodeSocket
 # BE VERY CAREFUL
 # BE VERY CAREFUL
 # the x_containers files import * from this file
 # the x_containers files import * from this file
 # so all the top-level imports are carried over
 # so all the top-level imports are carried over
@@ -528,118 +528,4 @@ def detect_hierarchy_link(from_node, from_socket, to_node, to_socket,):
     return True
     return True
 
 
 #Dummy classes for logic with node containers, they are not meant to do
 #Dummy classes for logic with node containers, they are not meant to do
-#  each and every little thing the "real" Blender classes do.
-class NodeLink:
-    from_node = None
-    from_socket = None
-    to_node = None
-    to_socket = None
-    
-    def __init__(self, from_node, from_socket, to_node, to_socket, multi_input_sort_id=0):
-        if from_node.signature == to_node.signature:
-            raise RuntimeError("Cannot connect a node to itself.")
-        self.from_node = from_node
-        self.from_socket = from_socket
-        self.to_node = to_node
-        self.to_socket = to_socket
-        self.from_node.outputs[self.from_socket].links.append(self)
-        # it is the responsibility of the node that uses these links to sort them correctly based on the sort_id
-        self.multi_input_sort_id = multi_input_sort_id
-        self.to_node.inputs[self.to_socket].links.append(self)
-        self.is_hierarchy = detect_hierarchy_link(from_node, from_socket, to_node, to_socket,)
-        self.is_alive = True
-    
-    def __repr__(self):
-        return self.from_node.outputs[self.from_socket].__repr__() + " --> " + self.to_node.inputs[self.to_socket].__repr__()
-        # link_string =   # if I need to colorize output for debugging.
-        # if self.is_hierarchy:
-        #     return wrapOrange(link_string)
-        # else:
-        #     return wrapWhite(link_string)
-    
-    def die(self):
-        self.is_alive = False
-        self.to_node.inputs[self.to_socket].flush_links()
-        self.from_node.outputs[self.from_socket].flush_links()
-    
-    def insert_node(self, middle_node, middle_node_in, middle_node_out, re_init_hierarchy = True):
-        to_node = self.to_node
-        to_socket = self.to_socket
-        self.to_node = middle_node
-        self.to_socket = middle_node_in
-        middle_node.outputs[middle_node_out].connect(to_node, to_socket)
-        if re_init_hierarchy:
-            from .utilities import init_connections, init_dependencies
-            init_connections(self.from_node)
-            init_connections(middle_node)
-            init_dependencies(middle_node)
-            init_dependencies(to_node)
-
-class NodeSocket:
-    @property # this is a read-only property.
-    def is_linked(self):
-        return bool(self.links)
-        
-    def __init__(self, is_input = False,
-                 node = None, name = None,
-                 traverse_target = None):
-        self.can_traverse = False # to/from the other side of the parent node
-        self.traverse_target = None
-        self.node = node
-        self.name = name
-        self.is_input = is_input
-        self.links = []
-        if (traverse_target):
-            self.can_traverse = True
-        
-    def connect(self, node, socket, sort_id=0):
-        if  (self.is_input):
-            to_node   = self.node; from_node = node
-            to_socket = self.name; from_socket = socket
-        else:
-            from_node   = self.node; to_node   = node
-            from_socket = self.name; to_socket = socket
-        for l in from_node.outputs[from_socket].links:
-            if l.to_node==to_node and l.to_socket==to_socket:
-                return None
-        new_link = NodeLink(
-                from_node,
-                from_socket,
-                to_node,
-                to_socket,
-                sort_id)
-        return new_link
-    
-    def set_traverse_target(self, traverse_target):
-        self.traverse_target = traverse_target
-        self.can_traverse = True
-    
-    def flush_links(self):
-        self.links = [l for l in self.links if l.is_alive]
-        
-    @property
-    def is_connected(self):
-        return len(self.links)>0
-    
-    
-    def __repr__(self):
-        return self.node.__repr__() + "::" + self.name
-
-
-# do I need this and the link class above?
-class DummyLink:
-    #gonna use this for faking links to keep the interface consistent
-    def __init__(self, from_socket, to_socket, nc_from=None, nc_to=None, original_from=None, multi_input_sort_id=0):
-        self.from_socket = from_socket
-        self.to_socket = to_socket
-        self.nc_from = nc_from
-        self.nc_to = nc_to
-        self.multi_input_sort_id = multi_input_sort_id
-        # self.from_node = from_socket.node
-        # self.to_node = to_socket.node
-        if (original_from):
-            self.original_from = original_from
-        else:
-            self.original_from = self.from_socket
-    def __repr__(self):
-        return(self.nc_from.__repr__()+":"+self.from_socket.name + " -> " + self.nc_to.__repr__()+":"+self.to_socket.name)
+#  each and every little thing the "real" Blender classes do.

+ 14 - 22
primitives_containers.py

@@ -1,5 +1,5 @@
 from .node_container_common import *
 from .node_container_common import *
-from .base_definitions import MantisNode
+from .base_definitions import MantisNode, NodeSocket
 
 
 def TellClasses():
 def TellClasses():
     return [
     return [
@@ -17,29 +17,21 @@ class CirclePrimitive(MantisNode):
     '''A node representing a Circle Primitive mesh'''
     '''A node representing a Circle Primitive mesh'''
 
 
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Name"               : NodeSocket(is_input = True, name = "Name", node = self),
-          "Radius"             : NodeSocket(is_input = True, name = "Radius", node = self),
-          "Number of Points"   : NodeSocket(is_input = True, name = "Number of Points", node = self),
-        }
-        self.outputs = {
-          "Circle" : NodeSocket(is_input = False, name = "Circle", node=self),
-        }
-        self.parameters = {
-          "Name":None,
-          "Radius":None,
-          "Number of Points":None, 
-          "Circle":None, 
-        }
+        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)
         self.node_type = "UTILITY"
         self.node_type = "UTILITY"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
         self.prepared = True
         self.prepared = True
-        self.executed = False
 
 
 
 
 
 

+ 2 - 4
readtree.py

@@ -57,8 +57,7 @@ def reroute_links_grpin(nc, all_nc):
 # FIXME I don't think these signatures are unique.
 # FIXME I don't think these signatures are unique.
 def insert_lazy_parents(nc):
 def insert_lazy_parents(nc):
     from .link_containers import LinkInherit
     from .link_containers import LinkInherit
-    from .xForm_containers import xFormArmature
-    from .node_container_common import NodeLink
+    from .base_definitions import NodeLink
     inherit_nc = None
     inherit_nc = None
     if nc.inputs["Relationship"].is_connected:
     if nc.inputs["Relationship"].is_connected:
         link = nc.inputs["Relationship"].links[0]
         link = nc.inputs["Relationship"].links[0]
@@ -109,12 +108,11 @@ to_name_filter = [
 #                                  DATA FROM NODES                                  #
 #                                  DATA FROM NODES                                  #
 # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** #
 # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** #
 
 
-from .base_definitions import replace_types
+from .base_definitions import replace_types, NodeSocket
 
 
 # TODO: investigate whether I can set the properties in the downstream nodes directly.
 # TODO: investigate whether I can set the properties in the downstream nodes directly.
 #       I am doing this in Schema Solver and it seems to work quite efficiently.
 #       I am doing this in Schema Solver and it seems to work quite efficiently.
 def make_connections_to_ng_dummy(base_tree, tree_path_names, local_nc, all_nc, np):
 def make_connections_to_ng_dummy(base_tree, tree_path_names, local_nc, all_nc, np):
-    from .node_container_common import NodeSocket
     nc_to = local_nc[(None, *tree_path_names, np.name)]
     nc_to = local_nc[(None, *tree_path_names, np.name)]
     for inp in np.inputs:
     for inp in np.inputs:
         nc_from = None
         nc_from = None

+ 46 - 127
schema_containers.py

@@ -1,6 +1,6 @@
 from .node_container_common import *
 from .node_container_common import *
 from math import pi, tau
 from math import pi, tau
-from .base_definitions import MantisNode
+from .base_definitions import MantisNode, NodeSocket
 
 
 def TellClasses():
 def TellClasses():
     return [
     return [
@@ -15,7 +15,7 @@ def TellClasses():
     ]
     ]
 
 
 
 
-def init_parameters(nc, is_input = True, in_out='INPUT', category=''):
+def schema_init_sockets(nc, is_input = True, in_out='INPUT', category=''):
     from .utilities import tree_from_nc
     from .utilities import tree_from_nc
     parent_tree = tree_from_nc(nc.signature, nc.base_tree)
     parent_tree = tree_from_nc(nc.signature, nc.base_tree)
     if is_input:
     if is_input:
@@ -31,161 +31,80 @@ def init_parameters(nc, is_input = True, in_out='INPUT', category=''):
                         is_input=is_input,
                         is_input=is_input,
                         name=item.name,
                         name=item.name,
                         node=nc)
                         node=nc)
-                    nc.parameters[item.name] = None
+    nc.init_parameters()
 
 
-
-
-class SchemaIndex(MantisNode):
+class SchemaNode(MantisNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {
-          "Index" : NodeSocket(name = "Index", node=self),
-          "Schema Length" : NodeSocket(name = "Schema Length", node=self),
-        }
-        self.parameters = {
-          "Index":None,
-          "Schema Length":None,
-        }
+        super().__init__(signature, base_tree)
         self.node_type = 'SCHEMA'
         self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
         self.prepared = True
         self.prepared = True
         self.executed = True
         self.executed = True
 
 
 
 
+class SchemaIndex(SchemaNode):
+    def __init__(self, signature, base_tree):
+        super().__init__(signature, base_tree)
+        outputs = [
+          "Index",
+          "Schema Length",
+        ]
+        self.outputs.init_sockets(outputs)
+        self.init_parameters()
+
 
 
-class SchemaArrayInput(MantisNode):
+
+class SchemaArrayInput(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {}
-        self.parameters = {}
-        init_parameters(self, is_input=False, in_out='INPUT', category='Array')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
 
 
 
 
-class SchemaArrayInputGet(MantisNode):
+class SchemaArrayInputGet(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-            "OoB Behaviour"  :  NodeSocket(is_input = True, name = "OoB Behaviour", node = self),
-            "Index"          :  NodeSocket(is_input = True, name = "Index", node = self),
-        }
-        self.outputs = {}
-        self.parameters = {
-            "OoB Behaviour"  :  None,
-            "Index"          :  None,
-
-        }
-        init_parameters(self, is_input=False, in_out='INPUT', category='Array')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        inputs = [
+            "OoB Behaviour" ,
+            "Index"         ,
+        ]
+        self.inputs.init_sockets(inputs)
+        schema_init_sockets(self, is_input=False, in_out='INPUT', category='Array')
 
 
 
 
-class SchemaArrayOutput(MantisNode):
+class SchemaArrayOutput(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {}
-        self.parameters = {}
-        init_parameters(self, is_input=True, in_out='OUTPUT', category='Array')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        schema_init_sockets(self, is_input=True, in_out='OUTPUT', category='Array')
 
 
 
 
         
         
 
 
-class SchemaConstInput(MantisNode):
+class SchemaConstInput(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {}
-        self.parameters = {}
-        init_parameters(self, is_input=False, in_out='INPUT', category='Constant')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        schema_init_sockets(self, is_input=False, in_out='INPUT', category='Constant')
 
 
 
 
 
 
 
 
 
 
-class SchemaConstOutput(MantisNode):
+class SchemaConstOutput(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {"Expose when N==":NodeSocket(is_input=True, name="Expose when N==", node=self)}
-        self.outputs = {}
-        self.parameters = {"Expose when N==":None}
-        init_parameters(self, is_input=True, in_out='OUTPUT', category='Constant')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Expose when N==",
+        ]
+        self.inputs.init_sockets(inputs)
+        schema_init_sockets(self, is_input=True, in_out='OUTPUT', category='Constant')
 
 
 
 
         
         
-class SchemaOutgoingConnection(MantisNode):
+class SchemaOutgoingConnection(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {}
-        self.parameters = {}
-        init_parameters(self, is_input=True, in_out='INPUT', category='Connection')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
-
+        super().__init__(signature, base_tree)
+        schema_init_sockets(self, is_input=True, in_out='INPUT', category='Connection')
 
 
         
         
-class SchemaIncomingConnection(MantisNode):
+class SchemaIncomingConnection(SchemaNode):
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {}
-        self.outputs = {}
-        self.parameters = {}
-        init_parameters(self, is_input=False, in_out='OUTPUT', category='Connection')
-        self.node_type = 'SCHEMA'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = True
+        super().__init__(signature, base_tree)
+        schema_init_sockets(self, is_input=False, in_out='OUTPUT', category='Connection')

+ 2 - 3
schema_solve.py

@@ -285,7 +285,6 @@ class SchemaSolver:
         
         
         from .utilities import clear_reroutes
         from .utilities import clear_reroutes
         from .utilities import get_link_in_out, link_node_containers
         from .utilities import get_link_in_out, link_node_containers
-        from .node_container_common import DummyLink
 
 
         # if index_nc:
         # if index_nc:
         #     index_nc.parameters['Index']=index
         #     index_nc.parameters['Index']=index
@@ -388,9 +387,9 @@ class SchemaSolver:
                             nc_from = nc_cls(sig, self.node.base_tree)
                             nc_from = nc_cls(sig, self.node.base_tree)
                             # ugly! maybe even a HACK!
                             # ugly! maybe even a HACK!
                             nc_from.inputs = {}
                             nc_from.inputs = {}
-                            from .node_container_common import NodeSocket
+                            from .base_definitions import NodeSocket
                             nc_from.outputs = {link.from_socket.name:NodeSocket(name = link.from_socket.name, node=nc_from)}
                             nc_from.outputs = {link.from_socket.name:NodeSocket(name = link.from_socket.name, node=nc_from)}
-                            from .node_container_common import get_socket_value
+                            from .base_definitions import get_socket_value
                             nc_from.parameters = {link.from_socket.name:index}
                             nc_from.parameters = {link.from_socket.name:index}
                             frame_nc[sig]=nc_from
                             frame_nc[sig]=nc_from
                             from_node = nc_from
                             from_node = nc_from

+ 1 - 1
utilities.py

@@ -151,7 +151,7 @@ def socket_seek(start_link, links):
 # this creates fake links that have the same interface as Blender's
 # this creates fake links that have the same interface as Blender's
 # so that I can bypass Reroutes
 # so that I can bypass Reroutes
 def clear_reroutes(links):
 def clear_reroutes(links):
-    from .node_container_common import DummyLink
+    from .base_definitions import DummyLink
     kept_links, rerouted_starts = [], []
     kept_links, rerouted_starts = [], []
     rerouted = []
     rerouted = []
     all_links = links.copy()
     all_links = links.copy()

+ 61 - 229
xForm_containers.py

@@ -1,5 +1,5 @@
 from .node_container_common import *
 from .node_container_common import *
-from .base_definitions import MantisNode
+from .base_definitions import MantisNode, NodeSocket
 
 
 def TellClasses():
 def TellClasses():
              
              
@@ -27,34 +27,22 @@ class xFormArmature(MantisNode):
     bObject = None
     bObject = None
     
     
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-         "Name"           : NodeSocket(is_input = True, name = "Name", node = self),
-         "Rotation Order" : NodeSocket(is_input = True, name = "Rotation Order", node = self),
-         "Matrix"         : NodeSocket(is_input = True, name = "Matrix", node = self),
-         "Relationship"   : NodeSocket(is_input = True, name = "Relationship", node = self),
-        }
-        self.outputs = {
-         "xForm Out" : NodeSocket(name="xForm Out", node = self),
-        }
-        self.parameters = {
-         "Name":None,
-         "Rotation Order":None,
-         "Matrix":None,
-         "Relationship":None,
-        }
-        self.links = {} # leave this empty for now!
-        # now set up the traverse target...
-        self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
-        self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Name"           ,
+            "Rotation Order" ,
+            "Matrix"         ,
+            "Relationship"   ,
+        ]
+        outputs = [
+         "xForm Out",
+        ]
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters()
+        self.set_traverse([("Relationship", "xForm Out")])
         self.node_type = 'XFORM'
         self.node_type = 'XFORM'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
         self.prepared = True
         self.prepared = True
-        self.executed = False
 
 
     
     
     def bExecute(self, bContext = None,):
     def bExecute(self, bContext = None,):
@@ -220,149 +208,16 @@ class xFormBone(MantisNode):
     '''A node representing a bone in an armature'''
     '''A node representing a bone in an armature'''
     # DO: make a way to identify which armature this belongs to
     # DO: make a way to identify which armature this belongs to
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-         "Name"           : NodeSocket(is_input = True, name = "Name", node = self,),
-         "Rotation Order" : NodeSocket(is_input = True, name = "Rotation Order", node = self,),
-         "Matrix"         : NodeSocket(is_input = True, name = "Matrix", node = self,),
-         "Relationship"   : NodeSocket(is_input = True, name = "Relationship", node = self,),
-         # IK settings
-         "IK Stretch"     : NodeSocket(is_input = True, name = "IK Stretch", node = self,),
-         "Lock IK"        : NodeSocket(is_input = True, name = "Lock IK", node = self,),
-         "IK Stiffness"   : NodeSocket(is_input = True, name = "IK Stiffness", node = self,),
-         "Limit IK"       : NodeSocket(is_input = True, name = "Limit IK", node = self,),
-         "X Min"          : NodeSocket(is_input = True, name = "X Min", node = self,),
-         "X Max"          : NodeSocket(is_input = True, name = "X Max", node = self,),
-         "Y Min"          : NodeSocket(is_input = True, name = "Y Min", node = self,),
-         "Y Max"          : NodeSocket(is_input = True, name = "Y Max", node = self,),
-         "Z Min"          : NodeSocket(is_input = True, name = "Z Min", node = self,),
-         "Z Max"          : NodeSocket(is_input = True, name = "Z Max", node = self,),
-         # Visual stuff
-         "Bone Collection"                         : NodeSocket(is_input = True, name = "Bone Collection", node = self,),
-         "Hide"                               : NodeSocket(is_input = True, name = "Hide", node = self,),
-         "Custom Object"                      : NodeSocket(is_input = True, name = "Custom Object", node = self,),
-         "Custom Object xForm Override"       : NodeSocket(is_input = True, name = "Custom Object xForm Override", node = self,),
-         "Custom Object Scale to Bone Length" : NodeSocket(is_input = True, name = "Custom Object Scale to Bone Length", node = self,),
-         "Custom Object Wireframe"            : NodeSocket(is_input = True, name = "Custom Object Wireframe", node = self,),
-         "Custom Object Scale"                : NodeSocket(is_input = True, name = "Custom Object Scale", node = self,),
-         "Custom Object Translation"          : NodeSocket(is_input = True, name = "Custom Object Translation", node = self,),
-         "Custom Object Rotation"             : NodeSocket(is_input = True, name = "Custom Object Rotation", node = self,),
-         # Deform Stuff
-         "Deform"               : NodeSocket(is_input = True, name = "Deform", node = self,),
-         "Envelope Distance"    : NodeSocket(is_input = True, name = "Envelope Distance", node = self,),
-         "Envelope Weight"      : NodeSocket(is_input = True, name = "Envelope Weight", node = self,),
-         "Envelope Multiply"    : NodeSocket(is_input = True, name = "Envelope Multiply", node = self,),
-         "Envelope Head Radius" : NodeSocket(is_input = True, name = "Envelope Head Radius", node = self,),
-         "Envelope Tail Radius" : NodeSocket(is_input = True, name = "Envelope Tail Radius", node = self,),
-         # BBone stuff:
-         "BBone Segments" : NodeSocket(is_input = True, name = "BBone Segments", node=self,),
-         "BBone X Size" : NodeSocket(is_input = True, name = "BBone X Size", node=self,),
-         "BBone Z Size" : NodeSocket(is_input = True, name = "BBone Z Size", node=self,),
-         "BBone HQ Deformation" : NodeSocket(is_input = True, name = "BBone HQ Deformation", node=self,),
-         "BBone X Curve-In" : NodeSocket(is_input = True, name = "BBone X Curve-In", node=self,),
-         "BBone Z Curve-In" : NodeSocket(is_input = True, name = "BBone Z Curve-In", node=self,),
-         "BBone X Curve-Out" : NodeSocket(is_input = True, name = "BBone X Curve-Out", node=self,),
-         "BBone Z Curve-Out" : NodeSocket(is_input = True, name = "BBone Z Curve-Out", node=self,),
-         "BBone Roll-In" : NodeSocket(is_input = True, name = "BBone Roll-In", node=self,),
-         "BBone Roll-Out" : NodeSocket(is_input = True, name = "BBone Roll-Out", node=self,),
-         "BBone Inherit End Roll" : NodeSocket(is_input = True, name = "BBone Inherit End Roll", node=self,),
-         "BBone Scale-In" : NodeSocket(is_input = True, name = "BBone Scale-In", node=self,),
-         "BBone Scale-Out" : NodeSocket(is_input = True, name = "BBone Scale-Out", node=self,),
-         "BBone Ease-In" : NodeSocket(is_input = True, name = "BBone Ease-In", node=self,),
-         "BBone Ease-Out" : NodeSocket(is_input = True, name = "BBone Ease-Out", node=self,),
-         "BBone Easing" : NodeSocket(is_input = True, name = "BBone Easing", node=self,),
-         "BBone Start Handle Type" : NodeSocket(is_input = True, name = "BBone Start Handle Type", node=self,),
-         "BBone Custom Start Handle" : NodeSocket(is_input = True, name = "BBone Custom Start Handle", node=self,),
-         "BBone Start Handle Scale" : NodeSocket(is_input = True, name = "BBone Start Handle Scale", node=self,),
-         "BBone Start Handle Ease" : NodeSocket(is_input = True, name = "BBone Start Handle Ease", node=self,),
-         "BBone End Handle Type" : NodeSocket(is_input = True, name = "BBone End Handle Type", node=self,),
-         "BBone Custom End Handle" : NodeSocket(is_input = True, name = "BBone Custom End Handle", node=self,),
-         "BBone End Handle Scale" : NodeSocket(is_input = True, name = "BBone End Handle Scale", node=self,),
-         "BBone End Handle Ease" : NodeSocket(is_input = True, name = "BBone End Handle Ease", node=self,),
-
-         # locks
-         "Lock Location"    : NodeSocket(is_input = True, name = "Lock Location", node = self,),
-         "Lock Rotation" : NodeSocket(is_input = True, name = "Lock Rotation", node = self,),
-         "Lock Scale" : NodeSocket(is_input = True, name = "Lock Scale", node = self,),
-        }
-        self.outputs = {
-         "xForm Out"       : NodeSocket(name = "xForm Out", node = self),
-        }
-        self.parameters = {
-         "Name":None,
-         "Rotation Order":None,
-         "Matrix":None,
-         "Relationship":None,
-         # IK settings
-         "IK Stretch":None,
-         "Lock IK":None,
-         "IK Stiffness":None,
-         "Limit IK":None,
-         "X Min":None,
-         "X Max":None,
-         "Y Min":None,
-         "Y Max":None,
-         "Z Min":None,
-         "Z Max":None,
-         "Hide":None,
-         "Bone Collection":None,
-         "Hide":None,
-         "Custom Object":None,
-         "Custom Object xForm Override":None,
-         "Custom Object Scale to Bone Length":None,
-         "Custom Object Wireframe":None,
-         "Custom Object Scale":None,
-         "Custom Object Translation":None,
-         "Custom Object Rotation":None,
-         "Deform"               : None,
-         "Envelope Distance"    : None,
-         "Envelope Weight"      : None,
-         "Envelope Multiply"    : None,
-         "Envelope Head Radius" : None,
-         "Envelope Tail Radius" : None,
-         #
-         "BBone Segments"  : None,
-         "BBone X Size"  : None,
-         "BBone Z Size"  : None,
-         "BBone HQ Deformation"  : None,
-         "BBone X Curve-In"  : None,
-         "BBone Z Curve-In"  : None,
-         "BBone X Curve-Out"  : None,
-         "BBone Z Curve-Out"  : None,
-         "BBone Roll-In"  : None,
-         "BBone Roll-Out"  : None,
-         "BBone Inherit End Roll"  : None,
-         "BBone Scale-In"  : None,
-         "BBone Scale-Out"  : None,
-         "BBone Ease-In"  : None,
-         "BBone Ease-Out"  : None,
-         "BBone Easing"  : None,
-         "BBone Start Handle Type"  : None,
-         "BBone Custom Start Handle"  : None,
-         "BBone Start Handle Scale"  : None,
-         "BBone Start Handle Ease"  : None,
-         "BBone End Handle Type"  : None,
-         "BBone Custom End Handle"  : None,
-         "BBone End Handle Scale"  : None,
-         "BBone End Handle Ease"  : None,
-        #
-         "Lock Location"    : None,
-         "Lock Rotation" : None,
-         "Lock Scale" : None,
-        }
-        self.links = {} # leave this empty for now!
-        # now set up the traverse target...
-        self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
-        self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
+        super().__init__(signature, base_tree)
+        outputs = [
+         "xForm Out",
+        ]
+        self.inputs.init_sockets(bone_inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters()
+        self.set_traverse([("Relationship", "xForm Out")])
         self.node_type = 'XFORM'
         self.node_type = 'XFORM'
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
         self.prepared = True
         self.prepared = True
-        self.executed = False
-        self.input_length = len(self.inputs) # HACK HACK HACK 
         self.bObject=None
         self.bObject=None
     
     
     def bGetParentArmature(self):
     def bGetParentArmature(self):
@@ -541,8 +396,7 @@ class xFormBone(MantisNode):
         driver = None
         driver = None
         do_prints=False
         do_prints=False
 
 
-        # print (self.input_length)
-        # even worse hack coming
+        # detect custom inputs
         for i, inp in enumerate(self.inputs.values()):
         for i, inp in enumerate(self.inputs.values()):
             if inp.name in bone_inputs:
             if inp.name in bone_inputs:
                 continue
                 continue
@@ -731,48 +585,36 @@ class xFormBone(MantisNode):
             prRed ("Cannot get bone for %s" % self)
             prRed ("Cannot get bone for %s" % self)
             raise e
             raise e
 
 
-    def fill_parameters(self):
+    def fill_parameters(self, prototype=None):
         # this is the fill_parameters that is run if it isn't a schema
         # this is the fill_parameters that is run if it isn't a schema
         setup_custom_props(self)
         setup_custom_props(self)
-        super().fill_parameters()
+        super().fill_parameters(prototype)
         # otherwise we will do this from the schema 
         # otherwise we will do this from the schema 
         # LEGIBILITY TODO - why? explain this?
         # LEGIBILITY TODO - why? explain this?
 
 
 class xFormGeometryObject(MantisNode):
 class xFormGeometryObject(MantisNode):
     '''A node representing an armature object'''
     '''A node representing an armature object'''
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Name"           : NodeSocket(is_input = True, name = "Name", node = self),
-          "Geometry" : NodeSocket(is_input = True, name = "Geometry", node = self),
-          "Matrix"         : NodeSocket(is_input = True, name = "Matrix", node = self),
-          "Relationship"   : NodeSocket(is_input = True, name = "Relationship", node = self),
-          "Deformer"   : NodeSocket(is_input = True, name = "Relationship", node = self),
-          "Hide in Viewport"   : NodeSocket(is_input = True, name = "Hide in Viewport", node = self),
-          "Hide in Render"   : NodeSocket(is_input = True, name = "Hide in Render", node = self),
-        }
-        self.outputs = {
-          "xForm Out" : NodeSocket(is_input = False, name="xForm Out", node = self), }
-        self.parameters = {
-          "Name":None, 
-          "Geometry":None, 
-          "Matrix":None, 
-          "Relationship":None, 
-          "Deformer":None,
-          "Hide in Viewport":None,
-          "Hide in Render":None,
-        }
-        self.links = {} # leave this empty for now!
-        # now set up the traverse target...
-        self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
-        self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Name"             ,
+            "Geometry"         ,
+            "Matrix"           ,
+            "Relationship"     ,
+            "Deformer"         ,
+            "Hide in Viewport" ,
+            "Hide in Render"   ,
+        ]
+        outputs = [
+          "xForm Out",
+        ]
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters()
+        self.set_traverse([("Relationship", "xForm Out")])
         self.node_type = "XFORM"
         self.node_type = "XFORM"
         self.bObject = None
         self.bObject = None
-        self.prepared = False
-        self.executed = False
         self.has_shape_keys = False
         self.has_shape_keys = False
-        self.drivers = {}
 
 
     def bSetParent(self):
     def bSetParent(self):
         from bpy.types import Object
         from bpy.types import Object
@@ -866,39 +708,29 @@ class xFormGeometryObject(MantisNode):
 class xFormObjectInstance(MantisNode):
 class xFormObjectInstance(MantisNode):
     """Represents an instance of an existing geometry object."""
     """Represents an instance of an existing geometry object."""
     def __init__(self, signature, base_tree):
     def __init__(self, signature, base_tree):
-        self.base_tree=base_tree
-        self.signature = signature
-        self.inputs = {
-          "Name"             : NodeSocket(is_input = True, name = "Name", node = self),
-          "Source Object"    : NodeSocket(is_input = True, name = "Source Object", node = self),
-          "As Instance"      : NodeSocket(is_input = True, name = "As Instance", node = self),
-          "Matrix"           : NodeSocket(is_input = True, name = "Matrix", node = self),
-          "Relationship"     : NodeSocket(is_input = True, name = "Relationship", node = self),
-          "Deformer"         : NodeSocket(is_input = True, name = "Relationship", node = self),
-          "Hide in Viewport" : NodeSocket(is_input = True, name = "Hide in Viewport", node = self),
-          "Hide in Render"   : NodeSocket(is_input = True, name = "Hide in Render", node = self),
-        }
-        self.outputs = {
-          "xForm Out" : NodeSocket(is_input = False, name="xForm Out", node = self), }
-        self.parameters = {
-          "Name":None, 
-          "Source Object":None, 
-          "As Instance": None,
-          "Matrix":None, 
-          "Relationship":None, 
-          "Deformer":None,
-          "Hide in Viewport":None,
-          "Hide in Render":None,
-        }
+        super().__init__(signature, base_tree)
+        inputs = [
+            "Name"             ,
+            "Source Object"    ,
+            "As Instance"      ,
+            "Matrix"           ,
+            "Relationship"     ,
+            "Deformer"         ,
+            "Hide in Viewport" ,
+            "Hide in Render"   ,
+        ]
+        outputs = [
+          "xForm Out",
+        ]
+        self.inputs.init_sockets(inputs)
+        self.outputs.init_sockets(outputs)
+        self.init_parameters()
         self.links = {} # leave this empty for now!
         self.links = {} # leave this empty for now!
         # now set up the traverse target...
         # now set up the traverse target...
-        self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
-        self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
+        self.set_traverse([("Relationship", "xForm Out")])
         self.node_type = "XFORM"
         self.node_type = "XFORM"
         self.bObject = None
         self.bObject = None
-        self.prepared, self.executed = False, False
         self.has_shape_keys = False # Shape Keys will make a dupe so this is OK
         self.has_shape_keys = False # Shape Keys will make a dupe so this is OK
-        self.drivers = {}
 
 
     def bSetParent(self):
     def bSetParent(self):
         from bpy.types import Object
         from bpy.types import Object

部分文件因为文件数量过多而无法显示