Просмотр исходного кода

fix compatibility with blender 4.2, socket definitions

turns out 5.0-only constraints cause problems in older blenders
and it also turns out, quite unexpectedly, that subclassing
socket definitions messes things up in the parent class. weird
maybe blender does that on purpose because it expects
parent classes to be abstract base classes (sort of)
Joseph Brandenburg 2 месяцев назад
Родитель
Сommit
6efb6b2edc
7 измененных файлов с 105 добавлено и 9 удалено
  1. 4 1
      base_definitions.py
  2. 1 1
      blender_manifest.toml
  3. 4 0
      link_nodes.py
  4. 20 1
      link_nodes_ui.py
  5. 1 0
      node_common.py
  6. 1 1
      ops_generate_tree.py
  7. 74 5
      socket_definitions.py

+ 4 - 1
base_definitions.py

@@ -83,7 +83,7 @@ def hash_tree(tree):
 
 
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MINOR=13
 MANTIS_VERSION_MINOR=13
-MANTIS_VERSION_SUB=0
+MANTIS_VERSION_SUB=1
 
 
 class MantisTree(NodeTree):
 class MantisTree(NodeTree):
     '''A custom node tree type that will show up in the editor type list'''
     '''A custom node tree type that will show up in the editor type list'''
@@ -576,6 +576,9 @@ class MantisNodeGroup(Node, MantisUINode):
 class GraphError(Exception):
 class GraphError(Exception):
     pass
     pass
 
 
+class BlenderVersionError(Exception):
+    pass
+
 def get_signature_from_edited_tree(node, context):
 def get_signature_from_edited_tree(node, context):
     sig_path=[None,]
     sig_path=[None,]
     for item in context.space_data.path[:-1]:
     for item in context.space_data.path[:-1]:

+ 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.13.0"
+version = "0.13.1"
 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>"

+ 4 - 0
link_nodes.py

@@ -921,6 +921,10 @@ class LinkGeometryAttribute(MantisLinkNode):
         self.set_traverse([("Input Relationship", "Output Relationship")])
         self.set_traverse([("Input Relationship", "Output Relationship")])
 
 
     def bRelationshipPass(self, bContext = None,):
     def bRelationshipPass(self, bContext = None,):
+        from bpy.app import version
+        from .base_definitions import BlenderVersionError
+        if version < (5,0,0):
+            raise BlenderVersionError("Geometry Attribute Constraint is supported only in Blender 5.0 or greater.")
         prepare_parameters(self)
         prepare_parameters(self)
         for xf in self.GetxForm():
         for xf in self.GetxForm():
             print
             print

+ 20 - 1
link_nodes_ui.py

@@ -439,7 +439,10 @@ class LinkGeometryAttribute(Node, LinkNode):
     """A node representing Blender's Geometry Attribute Constraint"""
     """A node representing Blender's Geometry Attribute Constraint"""
     bl_idname = "LinkGeometryAttribute"
     bl_idname = "LinkGeometryAttribute"
     bl_label = "Geometry Attribute"
     bl_label = "Geometry Attribute"
-    bl_icon = "CON_GEOMETRYATTRIBUTE"
+    if bpy.app.version >= (5,0,0):
+        bl_icon = "CON_GEOMETRYATTRIBUTE"
+    else:
+        bl_icon = "ERROR"
     initialized : bpy.props.BoolProperty(default = False)
     initialized : bpy.props.BoolProperty(default = False)
     mantis_node_class_name=bl_idname
     mantis_node_class_name=bl_idname
 
 
@@ -448,8 +451,24 @@ class LinkGeometryAttribute(Node, LinkNode):
         self.use_custom_color = True
         self.use_custom_color = True
         self.color = linkTransformColor
         self.color = linkTransformColor
         self.initialized = True
         self.initialized = True
+    
+    def draw_label(self):
+        if bpy.app.version < (5,0,0):
+            return "ERROR: ONLY SUPPORTED IN Blender 5.0 OR NEWER"
+        elif self.label: 
+            return self.label
+        return self.bl_label
+    
+    def update(self):
+        if bpy.app.version < (5,0,0):
+            self.color = Color((1.0, 0.15, 0.15,)).from_scene_linear_to_srgb()
+        elif self.color != linkTransformColor:
+            self.color = linkTransformColor
+
 
 
     def display_update(self, parsed_tree, context):
     def display_update(self, parsed_tree, context):
+        if bpy.app.version < (5,0,0):
+            return
         data_type = self.inputs['Data Type'].default_value
         data_type = self.inputs['Data Type'].default_value
         if self.inputs['Data Type'].is_linked:
         if self.inputs['Data Type'].is_linked:
             node_tree = context.space_data.path[0].node_tree
             node_tree = context.space_data.path[0].node_tree

+ 1 - 0
node_common.py

@@ -8,6 +8,7 @@ from collections.abc import Callable
 # 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
 
 
+
 #TODO: refactor the socket definitions so this becomes unnecessary.
 #TODO: refactor the socket definitions so this becomes unnecessary.
 def get_socket_value(node_socket):
 def get_socket_value(node_socket):
     value = None
     value = None

+ 1 - 1
ops_generate_tree.py

@@ -851,7 +851,7 @@ def do_generate_armature(armOb, context, node_tree, parent_node=None):
                 mr_node = node_tree.nodes.new("UtilityMetaRig")
                 mr_node = node_tree.nodes.new("UtilityMetaRig")
                 meta_rig_nodes[mr_node_name] = mr_node
                 meta_rig_nodes[mr_node_name] = mr_node
                 mr_node.inputs[0].search_prop=armOb
                 mr_node.inputs[0].search_prop=armOb
-                mr_node.inputs[1].search_prop=armOb
+                mr_node.inputs[1].armature=armOb
                 mr_node.inputs[1].bone=bone.name
                 mr_node.inputs[1].bone=bone.name
                 mr_node.inputs[1].default_value=bone.name
                 mr_node.inputs[1].default_value=bone.name
             node_tree.links.new(input=mr_node.outputs[0], output=bone_node.inputs["Matrix"])
             node_tree.links.new(input=mr_node.outputs[0], output=bone_node.inputs["Matrix"])

+ 74 - 5
socket_definitions.py

@@ -1490,7 +1490,7 @@ class EnumMetaRigSocket(MantisSocket):
     '''Custom node socket type'''
     '''Custom node socket type'''
     bl_idname = 'EnumMetaRigSocket'
     bl_idname = 'EnumMetaRigSocket'
     bl_label = "Meta Rig"
     bl_label = "Meta Rig"
-
+    color_simple = cString
 
 
     search_prop:PointerProperty(type=bpy.types.Object, poll=poll_is_armature, update=update_metarig_armature)
     search_prop:PointerProperty(type=bpy.types.Object, poll=poll_is_armature, update=update_metarig_armature)
 
 
@@ -1505,9 +1505,8 @@ class EnumMetaRigSocket(MantisSocket):
                 self.search_prop=ob
                 self.search_prop=ob
 
 
     default_value  : StringProperty(name = "", get=get_default_value, set=set_default_value)
     default_value  : StringProperty(name = "", get=get_default_value, set=set_default_value)
-
-    color_simple = cString
     color : bpy.props.FloatVectorProperty(default=cString, size=4)
     color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    
     def draw(self, context, layout, node, text):
     def draw(self, context, layout, node, text):
         if self.is_output:
         if self.is_output:
             layout.label(text=self.name)
             layout.label(text=self.name)
@@ -1526,9 +1525,44 @@ class EnumMetaRigSocket(MantisSocket):
     def draw_color_simple(self):
     def draw_color_simple(self):
         return self.color_simple
         return self.color_simple
 
 
-class EnumArmature(EnumMetaRigSocket):
+# I donno why but I can't just subclass the above. hmm.so this is a duplicate
+class EnumArmature(MantisSocket):
     bl_idname = "EnumArmature"
     bl_idname = "EnumArmature"
     bl_label = "Armature"
     bl_label = "Armature"
+    color_simple = cString
+
+    search_prop:PointerProperty(type=bpy.types.Object, poll=poll_is_armature, update=update_metarig_armature)
+
+    def get_default_value(self):
+        if self.search_prop:
+            return self.search_prop.name
+        return ""
+
+    def set_default_value(self, value):
+        if ob:= bpy.data.objects.get(value):
+            if ob.type == 'ARMATURE':
+                self.search_prop=ob
+
+    default_value  : StringProperty(name = "", get=get_default_value, set=set_default_value)
+    color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    
+    def draw(self, context, layout, node, text):
+        if self.is_output:
+            layout.label(text=self.name)
+        elif not (self.is_linked):
+            layout.prop_search(data=self, property="search_prop", search_data=bpy.data, search_property="objects", text="", icon="OUTLINER_OB_ARMATURE", results_are_suggestions=True)
+        elif hasattr(self.node, "armature"):
+            layout.label(text=self.node.armature)
+            # TODO: we should actually use the parsed tree to query this info directly, since this socket may belong to a node group in/out
+            # which doesn't have this parameter. whatever.
+        else:
+            layout.label(text=self.name)
+
+    def draw_color(self, context, node):
+        return self.color
+    @classmethod
+    def draw_color_simple(self):
+        return self.color_simple
 
 
 def poll_is_curve(self, obj):
 def poll_is_curve(self, obj):
     return obj.type == "CURVE"
     return obj.type == "CURVE"
@@ -1613,10 +1647,45 @@ class EnumMetaBoneSocket(MantisSocket):
     def draw_color_simple(self):
     def draw_color_simple(self):
         return self.color_simple
         return self.color_simple
 
 
-class EnumExistingBoneSocket(EnumMetaBoneSocket):
+# I don't know why but I can't subclass the above and I had to duplicate it here
+class EnumExistingBoneSocket(MantisSocket): 
     '''Socket to Get a Bone from an object'''
     '''Socket to Get a Bone from an object'''
     bl_idname = 'EnumExistingBoneSocket'
     bl_idname = 'EnumExistingBoneSocket'
     bl_label = "Bone"
     bl_label = "Bone"
+    color_simple = cString
+
+    # this armature property is set by the parent node.
+    armature:PointerProperty(type=bpy.types.Object)
+    bone:StringProperty()
+
+    def populate_bones_list(self, context):
+        # just gonna hardcode the value
+        if (meta_rig := self.armature):
+            retList = []; i = -1
+            retList.append( ('NONE', '', '', 'NONE', i:=i+1 ) )
+            for b in meta_rig.data.bones:
+                retList.append( (b.name, b.name, "Bone to copy matrix from", "BONE_DATA", i:=i+1 ) )
+            return(retList)
+        return None
+
+    default_value  : StringProperty(name = "", update=update_metarig_posebone)
+
+    color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    def draw(self, context, layout, node, text):
+        if not (self.is_linked):
+            if self.armature is None:
+                layout.prop(self, "default_value", text="", icon="BONE_DATA",)
+            else:
+                SearchPBDraw(self, context, layout, node, text="")
+        else:
+            layout.label(text=self.node.pose_bone)
+
+    def draw_color(self, context, node):
+        return self.color
+    @classmethod
+    def draw_color_simple(self):
+        return self.color_simple
+
 
 
 # TODO: make it so that this makes an item for "missing" widgets
 # TODO: make it so that this makes an item for "missing" widgets
 # for when a widget is moved or deleted
 # for when a widget is moved or deleted