1
0

8 Sitoutukset 9fba5be67f ... 6b48cb8702

Tekijä SHA1 Viesti Päivämäärä
  Joseph Brandenburg 6b48cb8702 cleanup clarity/consistency in __init__ 4 viikkoa sitten
  Joseph Brandenburg 1a78fbcf01 cleanup socket definitions 4 viikkoa sitten
  Joseph Brandenburg 72f16bd3e6 cleanup remove old commented lines 4 viikkoa sitten
  Joseph Brandenburg 3d5816e006 Fix? infinite Loop from Socket Update 4 viikkoa sitten
  Joseph Brandenburg d35aec39d1 Fix: versioning adds duplicate custom props input 4 viikkoa sitten
  Joseph Brandenburg 5762c39ef0 New Display Features for Bone, Armature 4 viikkoa sitten
  Joseph Brandenburg 15afceb101 temporarily hide BBone HQ Deformation socket 4 viikkoa sitten
  Joseph Brandenburg 6d2fdbd235 fix: driver check caused user errors 4 viikkoa sitten
9 muutettua tiedostoa jossa 225 lisäystä ja 514 poistoa
  1. 2 2
      __init__.py
  2. 6 0
      base_definitions.py
  3. 3 1
      mantis_dataclasses.py
  4. 59 473
      socket_definitions.py
  5. 0 5
      utilities/utilities.py
  6. 71 0
      versioning.py
  7. 30 17
      xForm_nodes.py
  8. 28 16
      xForm_nodes_ui.py
  9. 26 0
      xForm_socket_templates.py

+ 2 - 2
__init__.py

@@ -301,10 +301,10 @@ def do_version_update(node_tree):
         if hasattr(node, 'is_updating'):
             node.is_updating = True
     # start by doing tree versioning tasks
-    for affected_bl_idnames, task, arguments_needed in versioning_tasks:
+    for affected_bl_idnames, task, required_kwargs in versioning_tasks:
         if node_tree.bl_idname not in affected_bl_idnames: continue # this is a node task.
         arguments = {}
-        if 'tree' in arguments_needed:
+        if 'tree' in required_kwargs:
             arguments['tree']=node_tree
         task(**arguments)
     # run the updates that have no prerequisites

+ 6 - 0
base_definitions.py

@@ -785,8 +785,14 @@ class MantisNode:
     def gen_property_socket_map(self, prop_owner_group=None) -> dict:
         from .mantis_dataclasses import MantisSocketFiller
         from dataclasses import replace
+        from bpy.app import version as bpy_version
         props_sockets = {}
         for s_template in self.socket_templates:
+            if s_template.min_bpy_version:
+                if bpy_version < s_template.min_bpy_version:
+                    prPurple(f"Skipping socket {s_template.name} because "
+                             f"it requires Blender {s_template.min_bpy_version} or higher")
+                    continue # We can't set or drive this obviously.
             if prop_owner_group is not None and \
                     s_template.prop_owner_group != prop_owner_group:
                 continue # for composite objects like bones

+ 3 - 1
mantis_dataclasses.py

@@ -18,8 +18,10 @@ class MantisSocketTemplate():
     # this is a hint for the props_sockets system for complex situations
     #  where multiple blender objects own the properties, like e.g. bone/posebone
     prop_owner_group : str = field(default="")
-    # do? add versioning fields for Mantis, Blender version min/max
     is_animatable    : bool = field(default=True) # controls whether a driver is legal or not
+    # These attributes are for deprecated or new features in Blender
+    min_bpy_version  : Optional[tuple[int]] = field(default=None)
+    max_bpy_version  : Optional[tuple[int]] = field(default=None)
 
 @dataclass
 class xForm_info():

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 59 - 473
socket_definitions.py


+ 0 - 5
utilities/utilities.py

@@ -313,8 +313,6 @@ def update_interface(interface, name, in_out, sock_type, parent_name):
     else:
         raise RuntimeError(wrapRed("Cannot add interface item to tree without specifying type."))
 
-
-# D.node_groups['Rigging Nodes'].interface.new_socket('beans', description='the b word', socket_type='NodeSocketGeometry')
 #UGLY BAD REFACTOR
 def relink_socket_map_add_socket(node, socket_collection, item,  in_out=None,):
     from bpy.app import version as bpy_version
@@ -351,9 +349,6 @@ def relink_socket_map_add_socket(node, socket_collection, item,  in_out=None,):
     if read_schema_type(item) == 'Array': s.display_shape = 'SQUARE_DOT'
     elif node.bl_idname in ['MantisSchemaGroup'] and read_schema_type(item) == 'Constant':
         s.display_shape='CIRCLE_DOT'
-
-    # if item.parent.name == 'Array': s.display_shape = 'SQUARE_DOT'
-    # elif item.parent.name == 'Constant': s.display_shape='CIRCLE_DOT'
     return s
 
 # TODO REFACTOR THIS

+ 71 - 0
versioning.py

@@ -253,6 +253,8 @@ def up_0_13_0_new_custom_prop_node(*args, **kwargs):
     from .xForm_nodes_ui import xFormBoneNode
     socket_map_in, socket_map_out = get_socket_maps(node)
     if isinstance(node, xFormBoneNode):
+        if node.inputs.get('Custom Properties'):
+            return # already done here
         for custom_input in reversed(list(node.inputs)):
             if 'Parameter' not in custom_input.bl_idname:
                 continue
@@ -393,9 +395,11 @@ def update_fcurve_and_armature_node_to_multi_socket(*args, **kwargs):
                     toggle_updating.append(link.node)
                     was_updating[link.node.name] = link.node.is_updating
                     link.node.is_updating = True
+    socket_templates_original = node.socket_templates
     node.inputs.clear() # this is VERY DANGEROUS without the above
     add_me_sockets = [st for st in node.socket_templates if st.is_input == True]
     node.init_sockets(add_me_sockets)
+    node.socket_templates = socket_templates_original
     try:
         new_sockets_in = {}
         for convert_key in my_convert_keys:
@@ -438,6 +442,7 @@ def fix_bbone_default_scale_in_and_out(*args, **kwargs):
     if current_minor_version == 13 and current_sub_version >= 5: return# sub version must be 4 or less
     prPurple(f"Fixing BBone Settings for {tree.name}")
     live_updates = tree.do_live_update
+    tree.do_live_update = False
     bones = []
     for node in tree.nodes:
         if hasattr(node, 'is_updating'):
@@ -452,6 +457,71 @@ def fix_bbone_default_scale_in_and_out(*args, **kwargs):
         for node in tree.nodes:
             if hasattr(node, 'is_updating'):
                 node.is_updating = False
+        tree.do_live_update = live_updates
+
+# New display features, Display Type, new Custom Object gizmo/pivot stuff
+def add_new_display_features_v0_13_5(*args, **kwargs):
+    tree = kwargs['tree']
+    current_major_version = tree.mantis_version[0]
+    current_minor_version = tree.mantis_version[1]
+    current_sub_version = tree.mantis_version[2]
+    if  current_major_version > 0: return# major version must be 0
+    if current_minor_version >= 13: return# minor version must be 12 or less
+    if current_minor_version == 13 and current_sub_version >= 5: return# sub version must be 4 or less
+    prPurple(f"Adding new Display Features to {tree.name}")
+    live_updates = tree.do_live_update
+    tree.do_live_update = False
+    live_updates = tree.do_live_update
+    bones = []
+    armatures = []
+    for node in tree.nodes:
+        if hasattr(node, 'is_updating'):
+            node.is_updating = True
+        if node.bl_idname == 'xFormBoneNode':
+            bones.append(node)
+        if node.bl_idname == 'xFormArmatureNode':
+            armatures.append(node)
+    try:
+        for bone_node in bones:
+            # we'll just try this...
+            from .xForm_socket_templates import (BoneDisplayType,
+                                                 CustomObjectWireWidth,
+                                                 UseTransformAtCustomShape,
+                                                 UseTransformAroundCustomShape,
+                                                 xFormBoneSockets)
+            input_templates = ( BoneDisplayType,
+                                CustomObjectWireWidth,
+                                UseTransformAroundCustomShape,
+                                UseTransformAtCustomShape, )
+            bone_node.init_sockets(input_templates)
+            bone_node.socket_templates = xFormBoneSockets
+            for i, inp in enumerate(bone_node.inputs):
+                if inp.name == 'Custom Object xForm Override':
+                    # As confusing as this is, it is the least terrible way to do this
+                    # We add the sockets to the end, then move them from the end to the right place
+                    bone_node.inputs.move(len(bone_node.inputs)-1, i+1)
+                    bone_node.inputs.move(len(bone_node.inputs)-1, i+2)
+                    bone_node.inputs.move(len(bone_node.inputs)-1, i+3)
+                    bone_node.inputs.move(len(bone_node.inputs)-1, i+4)
+                    break
+        
+        for armature_node in armatures:
+            # we'll just try this...
+            from .xForm_socket_templates import (ArmatureDisplayType,
+                                                 xFormArmatureSockets)
+            input_templates = ( ArmatureDisplayType, )
+            armature_node.init_sockets(input_templates)
+            armature_node.socket_templates = xFormArmatureSockets
+            for i, inp in enumerate(armature_node.inputs):
+                if inp.name == 'Relationship':
+                    armature_node.inputs.move(len(armature_node.inputs)-1, i+1)
+                    break
+
+    finally:
+        for node in tree.nodes:
+            if hasattr(node, 'is_updating'):
+                node.is_updating = False
+        tree.do_live_update = live_updates
 
 # versioning tasks that involve Blender versions rather than Mantis versions:
 error_description_4_5_0_LTS = 'There is a bug in Blender 4.5.0 LTS, that is why these sockets are blue.'\
@@ -490,6 +560,7 @@ versioning_tasks = [
     (['UtilityFCurve', 'LinkArmature'],
            update_fcurve_and_armature_node_to_multi_socket, ['node']),
     (['MantisTree', 'SchemaTree'], fix_bbone_default_scale_in_and_out, ['tree']),
+    (['MantisTree', 'SchemaTree'], add_new_display_features_v0_13_5, ['tree']),
 ]
 
 

+ 30 - 17
xForm_nodes.py

@@ -79,23 +79,33 @@ class xFormNode(MantisNode):
 
     def check_drivers(self):
         for st in self.socket_templates:
-            if st.is_animatable == False:
-                socket = st.name
-                multi = st.use_multi_input
-                vector = isinstance(st.default_value, tuple)
-                # if single property
-                if not multi and not vector:
-                    has_driver = check_for_driver(self, socket)
-                elif not multi and vector:
-                    for i in range(len(st.default_value)):
-                        has_driver = check_for_driver(self, socket, i)
-                        if has_driver: break
-                elif multi:
-                    for i in range(len(self.inputs[socket].links)):
-                        has_driver = check_for_driver(self, socket, 0, i)
-                        if has_driver: break
-                if has_driver:
-                    raise GraphError(f"Error: Socket \"{socket}\" is not animatable and cannot be driven.")
+            try:
+                if st.is_animatable == False:
+                    socket = st.name
+                    multi = st.use_multi_input
+                    vector = isinstance(st.default_value, tuple)
+                    # if single property
+                    if not multi and not vector:
+                        has_driver = check_for_driver(self, socket)
+                    elif not multi and vector:
+                        for i in range(len(st.default_value)):
+                            has_driver = check_for_driver(self, socket, i)
+                            if has_driver: break
+                    elif multi:
+                        # TODO: this is a HACK, try and understand this later
+                        if socket == 'Custom Properties':
+                            has_driver = check_for_driver(self, socket,)
+                        else:
+                            for i in range(len(self.inputs[socket].links)):
+                                has_driver = check_for_driver(self, socket, 0, i)
+                                if has_driver: break
+                    if has_driver:
+                        raise GraphError(f"Error: Socket \"{socket}\" is not animatable and cannot be driven.")
+            except Exception as e:
+                # This isn't really an error and the user should not see it.
+                from .__init__ import DOERROR
+                if DOERROR:
+                    raise e
     
     def setup_custom_props(self, ob, input):
         from .mantis_dataclasses import custom_prop_template
@@ -143,6 +153,7 @@ class xFormNode(MantisNode):
             ob.property_overridable_library_set(f"[\"{name}\"]", True)
             pass
 
+# TODO this should use the socket templates / prop_sockets system!
 class xFormArmature(xFormNode):
     '''A node representing an armature object'''
 
@@ -238,6 +249,8 @@ class xFormArmature(xFormNode):
             ob.data.edit_bones.remove(ob.data.edit_bones[0])
         # bContext.view_layer.objects.active = prevAct
 
+        ob.data.display_type = self.evaluate_input('Display Type')
+
         # This will OVERWRITE the root armature since bones have to trace back to this one.
         root_armature = ob.name
         parent_xForm_info = get_parent_xForm_info(self)

+ 28 - 16
xForm_nodes_ui.py

@@ -146,8 +146,11 @@ class xFormBoneNode(Node, xFormNode):
                 self.display_ik_settings = pb.is_in_ik_chain
             self.inputs['Name'].display_text = ""
             mantis_node_ready = mantis_node and mantis_node.prepared
+            self.display_vp_settings = False
+            self.display_def_settings = False
+            self.display_bb_settings = False
             if self.inputs['Custom Object'].is_linked and mantis_node_ready:
-                self.display_vp_settings = mantis_node.evaluate_input("Custom Object")
+                self.display_vp_settings = True
             if self.inputs['Deform'].is_linked and mantis_node_ready:
                 self.display_def_settings = mantis_node.evaluate_input("Deform")
             else:
@@ -163,21 +166,30 @@ class xFormBoneNode(Node, xFormNode):
             if self.inputs['Name'].is_linked and mantis_node_ready:
                 self.inputs['Name'].display_text = mantis_node.evaluate_input("Name")
 
-            for template in self.socket_templates:
-                name = template.name
-                category = template.category
-                if category == "IK":
-                    self.inputs[name].hide = not self.display_ik_settings
-                if category == "Display":
-                    if name in ['Custom Object', 'Bone Collection']: continue
-                    self.inputs[name].hide = not self.display_vp_settings
-                if category == "Deform":
-                    if name in ['Deform']: continue
-                    self.inputs[name].hide = not self.display_def_settings
-                if category == "bbone":
-                    if name in ['BBone Segments']: continue
-                    self.inputs[name].hide = not self.display_bb_settings
-
+        for template in self.socket_templates:
+            name = template.name
+            category = template.category
+            if category == "IK":
+                self.inputs[name].hide = not self.display_ik_settings
+            if category == "Display":
+                if name in ['Custom Object', 'Bone Collection']: continue
+                self.inputs[name].hide = not self.display_vp_settings
+                if name == 'Display Type': # This one is only meaningful when there is no custom shape.
+                    self.inputs[name].hide = self.display_vp_settings
+            if category == "Deform":
+                if name in ['Deform']: continue
+                self.inputs[name].hide = not self.display_def_settings
+            if category == "bbone":
+                if name in ['BBone Segments']: continue
+                self.inputs[name].hide = not self.display_bb_settings
+            # Now hide the sockets that aren't usable in this Blender
+            if template.min_bpy_version:
+                if bpy_version < template.min_bpy_version:
+                    if template.is_input:
+                        self.inputs[template.name].hide = True # Not usable in this Blender
+        # TEMPORARY HACK because this one is basically not implemented
+        self.inputs['BBone HQ Deformation'].hide = True
+        
 def object_displaty_update(self, parsed_tree, context):
     custom_prop_display_update(self)
     if context.space_data:

+ 26 - 0
xForm_socket_templates.py

@@ -15,6 +15,9 @@ xFormArmatureSockets=[
             blender_property='matrix_world' ),
     RelationshipInTemplate := SockTemplate(
         name="Relationship", is_input=True,  bl_idname='RelationshipSocket', ),
+    ArmatureDisplayType := SockTemplate(name='Display Type', category='Display',
+        default_value='OCTAHEDRAL', blender_property='display_type',
+        min_bpy_version=(4,5,0), bl_idname='EnumArmatureDisplayType',  is_input=True,),
     CustomPropsTemplate := SockTemplate(
         name="Custom Properties", is_input=True,  bl_idname='CustomPropSocket',
             use_multi_input=True, is_animatable=False, ),
@@ -127,6 +130,23 @@ bbone_template = SockTemplate( name="<BBone Template>",
 # When there is a driver, you usually want the Pose Bone to hold it
 # but when there isn't you probably want it on the Bone since it isn't animated
 
+
+# Version-dependent for Blender
+
+BoneDisplayType = SockTemplate(name='Display Type', category='Display',
+    default_value='ARMATURE_DEFINED', blender_property='display_type',
+    min_bpy_version=(4,5,0), bl_idname='EnumDisplayType',
+    prop_owner_group='bone', is_input=True,)
+# 5.0 needed for these
+UseTransformAtCustomShape = SockTemplate(name="Affect Gizmo", category='Display',
+    default_value=False, blender_property='use_transform_at_custom_shape', is_input=True,
+    min_bpy_version=(5,0,0), bl_idname='BooleanSocket', prop_owner_group='pose_bone',)
+UseTransformAroundCustomShape = SockTemplate(name="Use as Pivot", category='Display',
+    default_value=False, blender_property='use_transform_around_custom_shape', is_input=True,
+    min_bpy_version=(5,0,0), bl_idname='BooleanSocket', prop_owner_group='pose_bone',)
+
+
+
 # and bones! this one is a bit much...
 from math import pi
 xFormBoneSockets = [
@@ -178,6 +198,12 @@ xFormBoneSockets = [
         name='Custom Object Scale to Bone Length', category='Display',
         blender_property='use_custom_shape_bone_size',
         default_value=True, prop_owner_group='pose_bone', ),
+    UseTransformAtCustomShape, # requires Blender >= 5.0 to use
+    UseTransformAroundCustomShape, # requires Blender >= 5.0 to use
+    CustomObjectWireWidth := SockTemplate(name='Custom Object Wire Width',
+        category='Display', default_value=1.0, blender_property='custom_shape_wire_width',
+        bl_idname='FloatPositiveSocket', prop_owner_group='pose_bone', is_input=True,),
+    BoneDisplayType, # requires Blender >= 4.5.0 to use
     CustomObjectWireframeTemplate := replace(HideRenderTemplate,
             name='Custom Object Wireframe', category='Display',
             blender_property='show_wire', default_value=True,

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä