|  | @@ -2,30 +2,48 @@ from .utilities import prRed, prGreen, prPurple, prWhite, prOrange, \
 | 
	
		
			
				|  |  |                          wrapRed, wrapGreen, wrapPurple, wrapWhite, wrapOrange
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -# we need to reroute the incoming links to a new GroupInterface node
 | 
	
		
			
				|  |  | -# then we need to reroute the outgoing links from the GroupInterface
 | 
	
		
			
				|  |  | -# down into the tree -  or visa versa (NodeGroupOutput input to Group output)
 | 
	
		
			
				|  |  | +# this function is kind of confusing and is very important,
 | 
	
		
			
				|  |  | +# so it bears a full explanation: its purpose is to connect
 | 
	
		
			
				|  |  | +# the links going into a group to the nodes in that group.
 | 
	
		
			
				|  |  | +# FIRST we connect all the incoming links into the Group Node to
 | 
	
		
			
				|  |  | +# a Group Interface node that does nothing but mark the entrance.
 | 
	
		
			
				|  |  | +# Then, we connect all the outgoing links back to the nodes
 | 
	
		
			
				|  |  | +# that had incoming links, so the nodes OUTSIDE the Node Group
 | 
	
		
			
				|  |  | +# are connected directly to BOTH the GroupInterface and the
 | 
	
		
			
				|  |  | +# nodes INSIDE the node group.
 | 
	
		
			
				|  |  | +# we give the GroupInterface nodes an obscenely high
 | 
	
		
			
				|  |  | +# multi_input_sort_id so that they are always last.
 | 
	
		
			
				|  |  | +# but since these links are going IN, they shouldn't cause any problems.
 | 
	
		
			
				|  |  | +# the sub_sort_id is set here in case there are UI links which represent
 | 
	
		
			
				|  |  | +# multiple Mantis links - the mantis links are sorted within the UI links
 | 
	
		
			
				|  |  | +# and the UI links are sorted as normal, so all the links are in the right
 | 
	
		
			
				|  |  | +# order.... probably. BUG here?
 | 
	
		
			
				|  |  | +# I want the Group Interface nodes to be part of the hierarchy...
 | 
	
		
			
				|  |  | +# but I want to cut the links. hmmm what to do? Fix it if it causes problems.
 | 
	
		
			
				|  |  | +# solution to hypothetical BUG could be to do traversal on the links
 | 
	
		
			
				|  |  | +# instead of the sockets.
 | 
	
		
			
				|  |  |  def grp_node_reroute_common(in_node, out_node, interface):
 | 
	
		
			
				|  |  | +    from .base_definitions import links_sort_key
 | 
	
		
			
				|  |  |      for in_node_input in in_node.inputs:
 | 
	
		
			
				|  |  | +        i = 0
 | 
	
		
			
				|  |  | +        if len(in_node_input.links)>1: # sort here to ensure correct sub_sort_id
 | 
	
		
			
				|  |  | +            in_node_input.links.sort(key=links_sort_key)
 | 
	
		
			
				|  |  |          while (in_node_input.links):
 | 
	
		
			
				|  |  |              in_link = in_node_input.links.pop()
 | 
	
		
			
				|  |  |              from_node = in_link.from_node; from_socket = in_link.from_socket
 | 
	
		
			
				|  |  | -            # the inputs/outputs on the group and in/out nodes are IDs
 | 
	
		
			
				|  |  | -            from_node.outputs[from_socket].connect(
 | 
	
		
			
				|  |  | -                interface,in_node_input.name, sort_id = in_link.multi_input_sort_id)
 | 
	
		
			
				|  |  | -            in_link.die()
 | 
	
		
			
				|  |  | -            init_connections(from_node)
 | 
	
		
			
				|  |  | +            link = from_node.outputs[from_socket].connect(
 | 
	
		
			
				|  |  | +                interface,in_node_input.name, sort_id = 2**16, sub_sort_id=i)
 | 
	
		
			
				|  |  | +            i += 1; in_link.die()
 | 
	
		
			
				|  |  |      for out_node_output in out_node.outputs:
 | 
	
		
			
				|  |  |          while (out_node_output.links):
 | 
	
		
			
				|  |  |              out_link = out_node_output.links.pop()
 | 
	
		
			
				|  |  |              to_node = out_link.to_node; to_socket = out_link.to_socket
 | 
	
		
			
				|  |  | -            for l in interface.inputs[out_node_output.name].links:
 | 
	
		
			
				|  |  | -                interface.outputs[out_node_output.name].connect(
 | 
	
		
			
				|  |  | -                    to_node, to_socket, sort_id = l.multi_input_sort_id)
 | 
	
		
			
				|  |  | +            for j, l in enumerate(interface.inputs[out_node_output.name].links):
 | 
	
		
			
				|  |  | +                # we are connecting the link from the ORIGINAL output to the FINAL input.
 | 
	
		
			
				|  |  | +                link = l.from_node.outputs[l.from_socket].connect(
 | 
	
		
			
				|  |  | +                    to_node, to_socket, sort_id = out_link.multi_input_sort_id)
 | 
	
		
			
				|  |  | +                link.sub_sort_id = j
 | 
	
		
			
				|  |  |              out_link.die()
 | 
	
		
			
				|  |  | -            init_dependencies(to_node)
 | 
	
		
			
				|  |  | -    init_dependencies(interface); init_connections(interface)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def reroute_links_grp(group, all_nodes):
 | 
	
		
			
				|  |  |      from .internal_containers import GroupInterface
 | 
	
	
		
			
				|  | @@ -52,44 +70,35 @@ def reroute_links_grpout(group_output, all_nodes):
 | 
	
		
			
				|  |  |                   "(maybe you are running the tree from inside a node group?)")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  # FIXME I don't think these signatures are unique.
 | 
	
		
			
				|  |  | +# TODO this is a really silly and bad and also really dumb way to do this
 | 
	
		
			
				|  |  |  def insert_lazy_parents(nc):
 | 
	
		
			
				|  |  |      from .link_nodes import LinkInherit
 | 
	
		
			
				|  |  | -    from .base_definitions import NodeLink
 | 
	
		
			
				|  |  |      inherit_nc = None
 | 
	
		
			
				|  |  |      if nc.inputs["Relationship"].is_connected:
 | 
	
		
			
				|  |  | -        link = nc.inputs["Relationship"].links[0]
 | 
	
		
			
				|  |  | -        from_nc = link.from_node
 | 
	
		
			
				|  |  | -        if from_nc.node_type in ["XFORM"] and link.from_socket in ["xForm Out"]:
 | 
	
		
			
				|  |  | +        from .node_container_common import trace_single_line
 | 
	
		
			
				|  |  | +        node_line, last_socket = trace_single_line(nc, 'Relationship')
 | 
	
		
			
				|  |  | +        # if last_socket is from a valid XFORM, it is the relationship in
 | 
	
		
			
				|  |  | +        # because it was traversed from the xForm Out... so get the traverse target.
 | 
	
		
			
				|  |  | +        if last_socket.traverse_target is None:
 | 
	
		
			
				|  |  | +            return # this is not a valid lazy parent.
 | 
	
		
			
				|  |  | +        for other_node in node_line[1:]: # skip the first one, it is the same node
 | 
	
		
			
				|  |  | +            if other_node.node_type == 'LINK':
 | 
	
		
			
				|  |  | +                return # this one has a realtionship connection.
 | 
	
		
			
				|  |  | +            elif other_node.node_type == 'XFORM':
 | 
	
		
			
				|  |  | +                break
 | 
	
		
			
				|  |  | +        if other_node.node_type in ["XFORM"] and last_socket.traverse_target.name in ["xForm Out"]:
 | 
	
		
			
				|  |  | +            for link in other_node.outputs['xForm Out'].links:
 | 
	
		
			
				|  |  | +                if link.to_node == nc: link.die()
 | 
	
		
			
				|  |  |              inherit_nc = LinkInherit(("MANTIS_AUTOGENERATED", *nc.signature[1:], "LAZY_INHERIT"), nc.base_tree)
 | 
	
		
			
				|  |  | -            for from_link in from_nc.outputs["xForm Out"].links:
 | 
	
		
			
				|  |  | -                if from_link.to_node == nc and from_link.to_socket == "Relationship":
 | 
	
		
			
				|  |  | -                    break # this is it
 | 
	
		
			
				|  |  | -            from_link.to_node = inherit_nc; from_link.to_socket="Parent"
 | 
	
		
			
				|  |  | -            from_link.to_node.inputs[from_link.to_socket].is_linked=True
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            links=[]
 | 
	
		
			
				|  |  | -            while (nc.inputs["Relationship"].links):
 | 
	
		
			
				|  |  | -                to_link = nc.inputs["Relationship"].links.pop()
 | 
	
		
			
				|  |  | -                if to_link.from_node == from_nc and to_link.from_socket == "xForm Out":
 | 
	
		
			
				|  |  | -                    continue # don't keep this one
 | 
	
		
			
				|  |  | -                links.append(to_link)
 | 
	
		
			
				|  |  | -                to_link.from_node.outputs[from_link.from_socket].is_linked=True
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            nc.inputs["Relationship"].links=links
 | 
	
		
			
				|  |  | -            link=NodeLink(from_node=inherit_nc, from_socket="Inheritance", to_node=nc, to_socket="Relationship")
 | 
	
		
			
				|  |  | -            inherit_nc.inputs["Parent"].links.append(from_link)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            inherit_nc.parameters = {
 | 
	
		
			
				|  |  | -                                     "Parent":None,
 | 
	
		
			
				|  |  | -                                     "Inherit Rotation":True,
 | 
	
		
			
				|  |  | -                                     "Inherit Scale":'FULL',
 | 
	
		
			
				|  |  | -                                     "Connected":False,
 | 
	
		
			
				|  |  | -                                    }
 | 
	
		
			
				|  |  | +            l = other_node.outputs['xForm Out'].connect(inherit_nc, 'Parent')
 | 
	
		
			
				|  |  | +            l1 = inherit_nc.outputs['Inheritance'].connect(nc, 'Relationship')
 | 
	
		
			
				|  |  | +            inherit_nc.parameters = { "Parent":None,
 | 
	
		
			
				|  |  | +                                      "Inherit Rotation":True,
 | 
	
		
			
				|  |  | +                                      "Inherit Scale":'FULL',
 | 
	
		
			
				|  |  | +                                      "Connected":False, }
 | 
	
		
			
				|  |  |              # because the from node may have already been done.
 | 
	
		
			
				|  |  | -            init_connections(from_nc)
 | 
	
		
			
				|  |  | -            init_dependencies(from_nc)
 | 
	
		
			
				|  |  | -            init_connections(inherit_nc)
 | 
	
		
			
				|  |  | -            init_dependencies(inherit_nc)
 | 
	
		
			
				|  |  | +            init_connections(other_node); init_dependencies(other_node)
 | 
	
		
			
				|  |  | +            init_connections(inherit_nc); init_dependencies(inherit_nc)
 | 
	
		
			
				|  |  |      return inherit_nc
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** #
 | 
	
	
		
			
				|  | @@ -377,8 +386,6 @@ def parse_tree(base_tree, error_popups=False):
 | 
	
		
			
				|  |  |              dummy.reroute_links(dummy, all_mantis_nodes)
 | 
	
		
			
				|  |  |      prGreen(f"Pulling data from tree took {time.time() - data_start_time} seconds")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    # base_tree.parsed_tree = all_mantis_nodes # for debugging
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      start_time = time.time()
 | 
	
		
			
				|  |  |      solve_only_these = []; solve_only_these.extend(list(all_schema.values()))
 | 
	
		
			
				|  |  |      roots, array_nodes = [], []
 | 
	
	
		
			
				|  | @@ -661,7 +668,6 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
 | 
	
		
			
				|  |  |                      raise e
 | 
	
		
			
				|  |  |                  execution_failed = True; break
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          switch_mode(mode='OBJECT', objects=switch_me)
 | 
	
		
			
				|  |  |          # switch to pose mode here so that the nodes can use the final pose data
 | 
	
		
			
				|  |  |          # this will require them to update the depsgraph.
 | 
	
	
		
			
				|  | @@ -678,7 +684,6 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
 | 
	
		
			
				|  |  |                      raise e
 | 
	
		
			
				|  |  |                  execution_failed = True; break
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          # REST pose for deformer bind, so everything is in the rest position
 | 
	
		
			
				|  |  |          for ob in switch_me:
 | 
	
		
			
				|  |  |              ob.data.pose_position = 'REST'
 |