Эх сурвалжийг харах

Improve ops_generate_tree efficiency

Improves the efficiency of ops_generate_tree.py by removing sorting code and executing in order of parenting
Replaces the do_after queue with a set to prevent duplicate jobs
Adds a Meta Rig node for each bone.
Joseph Brandenburg 8 сар өмнө
parent
commit
115e685035
1 өөрчлөгдсөн 149 нэмэгдсэн , 134 устгасан
  1. 149 134
      ops_generate_tree.py

+ 149 - 134
ops_generate_tree.py

@@ -399,7 +399,7 @@ def setup_vp_settings(bone_node, pb, do_after, node_tree):
                 node_tree.links.new(shape_xform_n.outputs["xForm"], bone_node.inputs['Custom Object xForm Override'])
                 break
         else: # make it a task
-            do_after.append( ("Custom Object xForm Override", bone_node.name , shape_xform_ob.name ) )
+            do_after.add( ("Custom Object xForm Override", bone_node.name , shape_xform_ob.name ) )
     # all the above should be in a function.
 
 
@@ -742,15 +742,18 @@ def do_generate_armature(context, node_tree):
         armature.location = ( 0, 0)
         
         
-        do_after = []
+        do_after = set()
+
+        meta_rig_nodes = {}
         
         
+        bones = []
         for root in armOb.data.bones:
             if root.parent is None:
                 iter_start= time()
-                lines = []
-                lines = walk_edit_bone(armOb, root)
-                lines.append([]) # add the root itself HACK ugly
+                # lines = []
+                # lines = walk_edit_bone(armOb, root)
+                # lines.append([]) # add the root itself HACK ugly
                 milestone=time()
                 prPurple("got the bone paths", time() - milestone); milestone=time()
                 # set up some properties:
@@ -762,146 +765,158 @@ def do_generate_armature(context, node_tree):
                 
                 # do short lines first bc longer lines rely on their results
                 sort_by_len = lambda elem : len(elem)
-                lines.sort(key=sort_by_len)
+                # lines.sort(key=sort_by_len)
+                bones.extend([root])
+
+
+            
+        # for bone_path in lines:
+        for bone in bones:
+            # prGreen("for bone_path in lines", time() - milestone); milestone=time()
+            # first go through the bone path and find relevant information
+            # bone = get_bone_from_path(root, bone_path)
+            bone_node = node_tree.nodes.new("xFormBoneNode")
+            bone_node.inputs["Name"].default_value = bone.name
+            bone_node.name, bone_node.label = bone.name, bone.name
+            matrix = bone.matrix_local.copy()
+            bone_node.inputs["Matrix"].default_value = [
+                    matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
+                    matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
+                    matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3], # last element is bone length, for mantis
+                    matrix[3][0], matrix[3][1], matrix[3][2], bone.length ] #matrix[3][3], ]
+            mr_node_name = armOb.name+":"+bone.name
+            if not (mr_node:= meta_rig_nodes.get(mr_node_name)):    
+                mr_node = node_tree.nodes.new("UtilityMetaRig")
+                meta_rig_nodes[mr_node_name] = mr_node
+                mr_node.inputs[0].search_prop=armOb
+                mr_node.inputs[1].search_prop=armOb
+                mr_node.inputs[1].bone=bone.name
+                mr_node.inputs[1].default_value=bone.name
+            node_tree.links.new(input=mr_node.outputs[0], output=bone_node.inputs["Matrix"])
+            x_distance, y_distance = 0, 0
+            pb = armOb.pose.bones[bone.name]
+            possible_parent_nodes = []
+            
+            if bone.parent: # not a root
+                possible_parent_nodes = bone_inherit_node.get(bone.parent.name)
+                # Set the parent
+                parent_node = None
                 
-                for bone_path in lines:
-                    prGreen("for bone_path in lines", time() - milestone); milestone=time()
-                    # first go through the bone path and find relevant information
-                    bone = get_bone_from_path(root, bone_path)
-                    bone_node = node_tree.nodes.new("xFormBoneNode")
-                    bone_node.inputs["Name"].default_value = bone.name
-                    bone_node.name, bone_node.label = bone.name, bone.name
-                    matrix = bone.matrix_local.copy()
-                    bone_node.inputs["Matrix"].default_value = [
-                           matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
-                           matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
-                           matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3], # last element is bone length, for mantis
-                           matrix[3][0], matrix[3][1], matrix[3][2], bone.length ] #matrix[3][3], ]
-                    x_distance, y_distance = 0, 0
-                    pb = armOb.pose.bones[bone.name]
-                    possible_parent_nodes = []
-                    
-                    if bone_path: # not a root
-                        x_distance, y_distance = len(bone_path), bone_path[-1]
-                        possible_parent_nodes = bone_inherit_node.get(bone.parent.name)
-                        # Set the parent
-                        parent_node = None
-                        
-                        if not (possible_parent_nodes):
-                            parent_node = create_inheritance_node(pb, bone.parent.name, bone_inherit_node, node_tree)
-                        else:
-                            for ppn in possible_parent_nodes:
-                                # check if it has the right connected, inherit scale, inherit rotation
-                                if ppn.inputs["Connected"].default_value  != pb.bone.use_connect:
-                                    continue
-                                if ppn.inputs["Inherit Scale"].default_value != pb.bone.inherit_scale:
-                                    continue
-                                if ppn.inputs["Inherit Rotation"].default_value != pb.bone.use_inherit_rotation:
-                                    continue
-                                parent_node = ppn; break
-                            else:
-                                parent_node = create_inheritance_node(pb, bone.parent.name, bone_inherit_node, node_tree)
-                        
-                        print("Got parent node", time() - milestone); milestone=time()
-                        if parent_node is None:
-                            raise RuntimeError("No parent node?")
-                    else: # This is a root
-                        prOrange("else this is a root",time() - milestone); milestone=time()
-                        parent_node = node_tree.nodes.new("linkInherit")
-                        # root_child = node_tree.nodes.new("linkInherit")
-                        node_tree.links.new(parent_node.outputs["Inheritance"], bone_node.inputs['Relationship'])
-                        # node_tree.links.new(bone_node.outputs["xForm Out"], root_child.inputs['Parent'])
-                        node_tree.links.new(armature.outputs["xForm Out"], parent_node.inputs['Parent'])
+                if not (possible_parent_nodes):
+                    parent_node = create_inheritance_node(pb, bone.parent.name, bone_inherit_node, node_tree)
+                else:
+                    for ppn in possible_parent_nodes:
+                        # check if it has the right connected, inherit scale, inherit rotation
+                        if ppn.inputs["Connected"].default_value  != pb.bone.use_connect:
+                            continue
+                        if ppn.inputs["Inherit Scale"].default_value != pb.bone.inherit_scale:
+                            continue
+                        if ppn.inputs["Inherit Rotation"].default_value != pb.bone.use_inherit_rotation:
+                            continue
+                        parent_node = ppn; break
+                    else:
+                        parent_node = create_inheritance_node(pb, bone.parent.name, bone_inherit_node, node_tree)
                 
-                        parent_node.inputs["Inherit Rotation"].default_value = True
-                        parent_node.location = (200, 0)
-                        bone_node.location = (400, 0)
-                        # root_child.location = (600, 0)
-                        
-                        # bone_inherit_node[bone_node.name]=[root_child]
-                    
+                print("Got parent node", time() - milestone); milestone=time()
+                if parent_node is None:
+                    raise RuntimeError("No parent node?")
+            else: # This is a root
+                prOrange("else this is a root",time() - milestone); milestone=time()
+                parent_node = node_tree.nodes.new("linkInherit")
+                # root_child = node_tree.nodes.new("linkInherit")
+                node_tree.links.new(parent_node.outputs["Inheritance"], bone_node.inputs['Relationship'])
+                # node_tree.links.new(bone_node.outputs["xForm Out"], root_child.inputs['Parent'])
+                node_tree.links.new(armature.outputs["xForm Out"], parent_node.inputs['Parent'])
+        
+                parent_node.inputs["Inherit Rotation"].default_value = True
+                parent_node.location = (200, 0)
+                bone_node.location = (400, 0)
+                # root_child.location = (600, 0)
+                
+                # bone_inherit_node[bone_node.name]=[root_child]
+            
 
-                    bone_node.inputs["Lock Location"].default_value = pb.lock_location
-                    bone_node.inputs["Lock Rotation"].default_value = pb.lock_rotation
-                    bone_node.inputs["Lock Scale"].default_value    = pb.lock_scale
-
-                    setup_custom_properties(bone_node, pb)
-                    setup_ik_settings(bone_node, pb)
-                    setup_vp_settings(bone_node, pb, do_after, node_tree)
-                    setup_df_settings(bone_node, pb)
-
-                    # BBONES
-                    bone_node.inputs["BBone X Size"].default_value = pb.bone.bbone_x
-                    bone_node.inputs["BBone Z Size"].default_value = pb.bone.bbone_z
-                    bone_node.inputs["BBone Segments"].default_value = pb.bone.bbone_segments
-                    if pb.bone.bbone_mapping_mode == "CURVED":
-                        bone_node.inputs["BBone HQ Deformation"].default_value = True
-                    bone_node.inputs["BBone Start Handle Type"].default_value = pb.bone.bbone_handle_type_start
-                    bone_node.inputs["BBone End Handle Type"].default_value = pb.bone.bbone_handle_type_end
-                    bone_node.inputs["BBone Custom Start Handle"].default_value = pb.bone.bbone_handle_type_start
-                    bone_node.inputs["BBone Custom End Handle"].default_value = pb.bone.bbone_handle_type_end
-                    
-                    bone_node.inputs["BBone X Curve-In"].default_value = pb.bone.bbone_curveinx
-                    bone_node.inputs["BBone Z Curve-In"].default_value = pb.bone.bbone_curveinz
-                    bone_node.inputs["BBone X Curve-Out"].default_value = pb.bone.bbone_curveoutx
-                    bone_node.inputs["BBone Z Curve-Out"].default_value = pb.bone.bbone_curveoutz
+            bone_node.inputs["Lock Location"].default_value = pb.lock_location
+            bone_node.inputs["Lock Rotation"].default_value = pb.lock_rotation
+            bone_node.inputs["Lock Scale"].default_value    = pb.lock_scale
+
+            setup_custom_properties(bone_node, pb)
+            setup_ik_settings(bone_node, pb)
+            setup_vp_settings(bone_node, pb, do_after, node_tree)
+            setup_df_settings(bone_node, pb)
+
+            # BBONES
+            bone_node.inputs["BBone X Size"].default_value = pb.bone.bbone_x
+            bone_node.inputs["BBone Z Size"].default_value = pb.bone.bbone_z
+            bone_node.inputs["BBone Segments"].default_value = pb.bone.bbone_segments
+            if pb.bone.bbone_mapping_mode == "CURVED":
+                bone_node.inputs["BBone HQ Deformation"].default_value = True
+            bone_node.inputs["BBone Start Handle Type"].default_value = pb.bone.bbone_handle_type_start
+            bone_node.inputs["BBone End Handle Type"].default_value = pb.bone.bbone_handle_type_end
+            bone_node.inputs["BBone Custom Start Handle"].default_value = pb.bone.bbone_handle_type_start
+            bone_node.inputs["BBone Custom End Handle"].default_value = pb.bone.bbone_handle_type_end
+            
+            bone_node.inputs["BBone X Curve-In"].default_value = pb.bone.bbone_curveinx
+            bone_node.inputs["BBone Z Curve-In"].default_value = pb.bone.bbone_curveinz
+            bone_node.inputs["BBone X Curve-Out"].default_value = pb.bone.bbone_curveoutx
+            bone_node.inputs["BBone Z Curve-Out"].default_value = pb.bone.bbone_curveoutz
 
-                    prRed("BBone Implementation is not complete, expect errors and missing features for now")
+            prRed("BBone Implementation is not complete, expect errors and missing features for now")
 
+            
+            #
+            for c in pb.constraints:
+                prWhite("constraint %s for %s" % (c.name, pb.name), time() - milestone); milestone=time()
+                # make relationship nodes and set up links...
+                if ( c_node := create_relationship_node_for_constraint(node_tree, c)):
+                    c_node.label = c.name
+                    # this node definitely has a parent inherit node.
+                    c_node.location = parent_node.location; c_node.location.x += 200
                     
-                    #
-                    for c in pb.constraints:
-                        prWhite("constraint %s for %s" % (c.name, pb.name), time() - milestone); milestone=time()
-                        # make relationship nodes and set up links...
-                        if ( c_node := create_relationship_node_for_constraint(node_tree, c)):
-                            c_node.label = c.name
-                            # this node definitely has a parent inherit node.
-                            c_node.location = parent_node.location; c_node.location.x += 200
-                            
-                            try:
-                                node_tree.links.new(parent_node.outputs["Inheritance"], c_node.inputs['Input Relationship'])
-                            except KeyError: # not a inherit node anymore
-                                node_tree.links.new(parent_node.outputs["Output Relationship"], c_node.inputs['Input Relationship'])
-                            parent_node = c_node
-                            
-                            #Target Tasks:
-                            if (hasattr(c, "target") and not hasattr(c, "subtarget")):
-                                do_after.append( ("Object Target", c_node.name , c.target.name ) )
-                            if (hasattr(c, "subtarget")):
-                                if c.target and c.subtarget: # this node has a target, find the node associated with it... 
-                                    do_after.append( ("Target", c_node.name , c.subtarget ) )
-                                else:
-                                    do_after.append( ("Object Target", c_node.name , c.target.name ) )
-                            if (hasattr(c, "pole_subtarget")):
-                                if c.pole_target and c.pole_subtarget: # this node has a pole target, find the node associated with it... 
-                                    do_after.append( ("Pole Target", c_node.name , c.pole_subtarget ) )
-                            fill_parameters(c_node, c, context)
-                            if (hasattr(c, "targets")): # Armature Modifier, annoying.
-                                for i in range(len(c.targets)):
-                                    if (c.targets[i].subtarget):
-                                        do_after.append( ("Target."+str(i).zfill(3), c_node.name , c.targets[i].subtarget ) )
-                            # Driver Tasks
-                            if armOb.animation_data:
-                                for fc in armOb.animation_data.drivers:
-                                    pb_string = fc.data_path.split("[\"")[1]; pb_string = pb_string.split("\"]")[0]
-                                    try:
-                                        c_string = fc.data_path.split("[\"")[2]; c_string = c_string.split("\"]")[0]
-                                        do_after.append ( ("driver", bone_node.name, c_node.name) )
-                                    except IndexError: # the above expects .pose.bones["some name"].constraints["some constraint"]
-                                        do_after.append ( ("driver", bone_node.name, bone_node.name) ) # it's a property I guess
                     try:
-                        node_tree.links.new(parent_node.outputs["Inheritance"], bone_node.inputs['Relationship'])
-                    except KeyError: # may have changed, see above
-                        node_tree.links.new(parent_node.outputs["Output Relationship"], bone_node.inputs['Relationship'])
-                    bone_node.location = (400 + parent_node.location.x, -200*y_distance + parent_node.location.y)
-                    prPurple("iteration: ", time() - iter_start)
-                finished_drivers = set()
-                switches, driver_vars, fcurves, drivers = [],[],[],[]
+                        node_tree.links.new(parent_node.outputs["Inheritance"], c_node.inputs['Input Relationship'])
+                    except KeyError: # not a inherit node anymore
+                        node_tree.links.new(parent_node.outputs["Output Relationship"], c_node.inputs['Input Relationship'])
+                    parent_node = c_node
+                    
+                    #Target Tasks:
+                    if (hasattr(c, "target") and not hasattr(c, "subtarget")):
+                        do_after.add( ("Object Target", c_node.name , c.target.name ) )
+                    if (hasattr(c, "subtarget")):
+                        if c.target and c.subtarget: # this node has a target, find the node associated with it... 
+                            do_after.add( ("Target", c_node.name , c.subtarget ) )
+                        else:
+                            do_after.add( ("Object Target", c_node.name , c.target.name ) )
+                    if (hasattr(c, "pole_subtarget")):
+                        if c.pole_target and c.pole_subtarget: # this node has a pole target, find the node associated with it... 
+                            do_after.add( ("Pole Target", c_node.name , c.pole_subtarget ) )
+                    fill_parameters(c_node, c, context)
+                    if (hasattr(c, "targets")): # Armature Modifier, annoying.
+                        for i in range(len(c.targets)):
+                            if (c.targets[i].subtarget):
+                                do_after.add( ("Target."+str(i).zfill(3), c_node.name , c.targets[i].subtarget ) )
+                    # Driver Tasks
+                    if armOb.animation_data:
+                        for fc in armOb.animation_data.drivers:
+                            pb_string = fc.data_path.split("[\"")[1]; pb_string = pb_string.split("\"]")[0]
+                            try:
+                                c_string = fc.data_path.split("[\"")[2]; c_string = c_string.split("\"]")[0]
+                                do_after.add ( ("driver", bone_node.name, c_node.name) )
+                            except IndexError: # the above expects .pose.bones["some name"].constraints["some constraint"]
+                                do_after.add ( ("driver", bone_node.name, bone_node.name) ) # it's a property I guess
+            try:
+                node_tree.links.new(parent_node.outputs["Inheritance"], bone_node.inputs['Relationship'])
+            except KeyError: # may have changed, see above
+                node_tree.links.new(parent_node.outputs["Output Relationship"], bone_node.inputs['Relationship'])
+            prPurple("iteration: ", time() - iter_start)
+            bones.extend(bone.children)
+        finished_drivers = set()
+        switches, driver_vars, fcurves, drivers = [],[],[],[]
         
         # Now do the tasks.
         for (task, in_node_name, out_node_name) in do_after:
             prOrange(task, in_node_name, out_node_name)
-            prPurple(len(node_tree.nodes))
+            # prPurple(len(node_tree.nodes))
             if task in ['Object Target']:
                 in_node  = node_tree.nodes[ in_node_name ]
                 out_node= node_tree.nodes.new("InputExistingGeometryObject")