Browse Source

Add: option to Use Offset in Morph Deform

also fixed bug in Armature Deform with incorrect context when selecting
or deselecting pose bones via bpy.ops.
Joseph Brandenburg 10 months ago
parent
commit
7ef6b11076
5 changed files with 47 additions and 19 deletions
  1. 7 4
      __init__.py
  2. 3 1
      base_definitions.py
  3. 1 1
      blender_manifest.toml
  4. 26 11
      deformer_containers.py
  5. 10 2
      deformer_definitions.py

+ 7 - 4
__init__.py

@@ -17,7 +17,7 @@ from .utilities import prRed
 
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MINOR=9
-MANTIS_VERSION_SUB=7
+MANTIS_VERSION_SUB=8
 
 
 classLists = [module.TellClasses() for module in [
@@ -118,6 +118,8 @@ utility_category = [
         NodeItem("MathStaticFloat"),
         NodeItem("MathStaticVector"),
         NodeItem("UtilityCatStrings"),
+        NodeItem("UtilityGeometryOfXForm"),
+        NodeItem("UtilityNameOfXForm"),
         NodeItem("UtilityCombineThreeBool"),
         NodeItem("UtilityCombineVector"),
         NodeItem("UtilityIntToString"),
@@ -261,13 +263,14 @@ def version_update_handler(filename):
                         if (n.bl_idname, socket.identifier) in SOCKETS_REMOVED:
                             print(f"INFO: removing socket {socket.identifier} of node {n.name} of type {n.bl_idname} because it has been deprecated.")
                             n.outputs.remove(socket)
-                    for bl_idname, in_out, socket_type, socket_name, index in SOCKETS_ADDED:
+                    for bl_idname, in_out, socket_type, socket_name, index, use_multi_input, default_val in SOCKETS_ADDED:
                         if n.bl_idname != bl_idname:
                             continue
                         if in_out == 'INPUT' and n.inputs.get(socket_name) is None:
                             print(f"INFO: adding socket \"{socket_name}\" of type {socket_type} to node {n.name} of type {n.bl_idname}.")
-                            s = n.inputs.new(socket_type, socket_name)
-                            # n.inputs.move(len(n.inputs), index)
+                            s = n.inputs.new(socket_type, socket_name, use_multi_input=use_multi_input)
+                            s.default_value = default_val
+                            n.inputs.move(len(n.inputs), index)
                 
                 
 

+ 3 - 1
base_definitions.py

@@ -356,7 +356,9 @@ SOCKETS_REMOVED=[("UtilityDriverVariable","Transform Channel"),
                  ("xFormRootNode","World Out"),
                  ("UtilitySwitch","xForm")]
 SOCKETS_RENAMED=[]
-SOCKETS_ADDED=[("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Shape Key", 1),]
+                # NODE CLASS NAME             IN_OUT    SOCKET TYPE     SOCKET NAME     INDEX   MULTI     DEFAULT
+SOCKETS_ADDED=[("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Shape Key", 1,      False,    False),
+               ("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Offset", 2,         False,     True),]
 
 # replace names with bl_idnames for reading the tree and solving schemas.
 replace_types = ["NodeGroupInput", "NodeGroupOutput", "SchemaIncomingConnection",

+ 1 - 1
blender_manifest.toml

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

+ 26 - 11
deformer_containers.py

@@ -207,18 +207,22 @@ class DeformerArmature:
                                   'active_pose_bone':deform_bones[0],
                                   'selected_pose_bones':deform_bones,}
             #
-            with bContext.temp_override(**{'active_object':armOb}):
-                bpy.ops.object.mode_set(mode='POSE')
-                bpy.ops.pose.select_all(action='SELECT')
+            # with bContext.temp_override(**{'active_object':armOb}):
+            #     bpy.ops.object.mode_set(mode='POSE')
+            #     bpy.ops.pose.select_all(action='SELECT')
+            for b in armOb.data.bones:
+                b.select = True
             with bContext.temp_override(**context_override):
                 bpy.ops.paint.weight_paint_toggle()
                 bpy.ops.paint.weight_from_bones(type='AUTOMATIC')
                 bpy.ops.paint.weight_paint_toggle()
+            for b in armOb.data.bones:
+                b.select = False
                 #
-            with bContext.temp_override(**{'active_object':armOb}):
-                bpy.ops.object.mode_set(mode='POSE')
-                bpy.ops.pose.select_all(action='DESELECT') 
-                bpy.ops.object.mode_set(mode='OBJECT')
+            # with bContext.temp_override(**{'active_object':armOb}):
+            #     bpy.ops.object.mode_set(mode='POSE')
+            #     bpy.ops.pose.select_all(action='DESELECT') 
+            #     bpy.ops.object.mode_set(mode='OBJECT')
             # TODO: modify Blender to make this available as a Python API function.
         elif skin_method == "EXISTING_GROUPS":
             pass
@@ -371,6 +375,7 @@ class DeformerMorphTargetDeform:
         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), }
@@ -378,7 +383,9 @@ class DeformerMorphTargetDeform:
           "Name"                : None,
           "Deformer"            : None,
           "Deformer"            : None,
-          "Use Shape Key"       : 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"])
@@ -425,7 +432,8 @@ class DeformerMorphTargetDeform:
         rest_position = ng.nodes.new("GeometryNodeInputNamedAttribute")
         rest_position.inputs["Name"].default_value="rest_position"
         rest_position.data_type = 'FLOAT_VECTOR'
-        # rest_position = position
+        if self.evaluate_input("Use Offset") == False:
+            rest_position = position
         add_these = []
 
         props_sockets={}
@@ -496,13 +504,20 @@ class DeformerMorphTargetDeform:
         # prev_node = ng.nodes.new("ShaderNodeVectorMath"); prev_node.operation="SUBTRACT"
         # ng.links.new(position.outputs[0], output=prev_node.inputs[0])
         # ng.links.new(rest_position.outputs[0], output=prev_node.inputs[1])
-        prev_node = ng.nodes.new("FunctionNodeInputVector")
+
+        if self.evaluate_input("Use Offset") == True:
+            prev_node = ng.nodes.new("FunctionNodeInputVector")
+        else:
+            prev_node = position
         for i, node in enumerate(add_these):
             add = ng.nodes.new("ShaderNodeVectorMath"); add.operation="ADD"
             ng.links.new(prev_node.outputs[0], output=add.inputs[0])
             ng.links.new(node.outputs[0], output=add.inputs[1])
             prev_node = add
-        ng.links.new(add.outputs[0], output=set_position.inputs["Offset"])
+        if self.evaluate_input("Use Offset") == True:
+            ng.links.new(add.outputs[0], output=set_position.inputs["Offset"])
+        else:
+            ng.links.new(add.outputs[0], output=set_position.inputs["Position"])
         
         from .utilities import SugiyamaGraph
         SugiyamaGraph(ng, 12)

+ 10 - 2
deformer_definitions.py

@@ -124,6 +124,8 @@ class DeformerMorphTargetDeform(Node, DeformerNode):
         self.id_data.do_live_update = False
         self.inputs.new('DeformerSocket', 'Deformer', )
         self.inputs.new('BooleanSocket', 'Use Shape Key', )
+        s = self.inputs.new('BooleanSocket', 'Use Offset', )
+        s.default_value = True
         self.inputs.new('WildcardSocket', '', identifier='__extend__')
         self.outputs.new('DeformerSocket', "Deformer")
         self.update()
@@ -132,6 +134,7 @@ class DeformerMorphTargetDeform(Node, DeformerNode):
         if self.id_data.is_executing:
             return # so that we don't update it while saving/loading the tree
         self.initialized = False
+        # use_offset = self.inputs["Use Offset"].default_value
         input_map = get_socket_maps(self)[0]
         # checc to see if targets have been removed... then modify the input map if necessary
         targets_deleted = 0 # this should usually be either 0 or 1
@@ -150,6 +153,8 @@ class DeformerMorphTargetDeform(Node, DeformerNode):
         self.inputs.clear()
         self.inputs.new('DeformerSocket', 'Deformer', )
         self.inputs.new('BooleanSocket', 'Use Shape Key', )
+        self.inputs.new('BooleanSocket', 'Use Offset', )
+        # s.default_value = use_offset
         # have to do this manually to avoid making things harder elsewhere
         # input_map
         for i in range(self.num_targets):
@@ -157,18 +162,21 @@ class DeformerMorphTargetDeform(Node, DeformerNode):
             self.inputs.new("FloatSocket", "Value."+str(i).zfill(3))
         # if self.num_targets > 0:
         simple_do_relink(self, input_map, in_out='INPUT')
-        if len(self.inputs)<2 or self.inputs[-1].bl_idname not in ["WildcardSocket"]:
+        if self.inputs[-1].bl_idname not in ["WildcardSocket"]:
             self.inputs.new('WildcardSocket', '', identifier='__extend__')
         self.initialized = True
     
     def display_update(self, parsed_tree, context):
         if self.inputs["Deformer"].is_linked:
-            if self.inputs["Deformer"].links[0].from_node.bl_idname != self.bl_idname:
+            if self.inputs["Deformer"].links[0].from_node.bl_idname not in [self.bl_idname, "NodeGroupInput"]:
                 self.inputs["Use Shape Key"].default_value = False
                 self.inputs["Use Shape Key"].hide = True
             elif self.inputs["Deformer"].links[0].from_node.inputs["Use Shape Key"].default_value == False:
                 self.inputs["Use Shape Key"].default_value = False
                 self.inputs["Use Shape Key"].hide = True
+        if self.inputs["Use Offset"] == False:
+                self.inputs["Use Shape Key"].hide = True
+                self.inputs["Use Shape Key"].default_value = False
 
 
 # TODO: there is no reason for this to be a separate node!