From 6ef67149cd41b4ee3fb889553885a0b7210dcd2c Mon Sep 17 00:00:00 2001 From: dmeerev Date: Sat, 10 Jan 2026 21:58:23 +0300 Subject: [PATCH 1/2] fixed for b4x, added loc limits to control bones --- handrig.py | 114 ++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/handrig.py b/handrig.py index df731b5..c5cbd43 100644 --- a/handrig.py +++ b/handrig.py @@ -1,5 +1,5 @@ """INSTRUCTIONS -Run "autogrip.py" in Blender's text editor or install it as an add-on through the preferences menu. +Run "handrig.py" in Blender's text editor or install it as an add-on through the preferences menu. Once that's done, check object mode, and all the buttons you need are in a tab in the N-panel called "AutoGrip." @@ -38,12 +38,17 @@ If you're sick of it and you want your old armature back, "Reset Hand R" and "Reset Hand L" clean up after themselves pretty well, deleting everything this script did and leaving the original rig untouched. + +CONTRIBUTION INFO +Dmeerev: + - Modified to work with blender 4.X + - Controller bones now has location limits to calm control transforms """ bl_info = { "name": "AutoGrip", - "blender": (3, 3, 0), + "blender": (4, 0, 0), "category": "Object", "description": "Automatically poses hands to grab props." } @@ -375,57 +380,30 @@ def constrain_IK(self): aim = obj.pose.bones[namestring] addIK(joint, aim) - def clean_layers(self): - - # Moves all the project bones and the control bone to designated layers. - # You'd expect this to take an input, but I defined that out in - # set_armature_layers instead. May rearrange that for some clarity - - for joint in self.projectors: - i = 0 - joint.bone.layers[self.project_layer] = True - # Doing this in a weird order bc it won't let me set all layers to false - while (i < 32): - if self.project_layer != i: - joint.bone.layers[i] = False - i = i+1 - i = 0 - self.control_bone.bone.layers[self.control_layer] = True - while (i<32): - if self.control_layer != i: - self.control_bone.bone.layers[i] = False - i = i+1 - + def clean_layers(arm): + # Get rid of old blender layers system + pass + def set_armature_layers(self): - - rig_choice = bpy.props.EnumProperty( - name="Rig selection", - description="Select an option", - - items = [ - ('MHX', "MHX", "MakeHuman Exchange"), - ('RFY', "Rigify", "Modular armature from the Rigify add-on"), - ('ARP', "AutoRig Pro", "Auto rig pro"), - ] - ) + arm = bpy.context.object.data - rig_choice = obj.global_rig_choice - - if rig_choice == 'MHX': - if self.control_bone.name[-1] == 'R': - print("setting layer for RIGHT finger") - self.control_layer = 22 - elif self.control_bone.name[-1] == 'L': - print("setting layer for LEFT finger") - self.control_layer = 6 - self.project_layer = 24 - elif rig_choice == 'RFY': - self.control_layer = 6 - self.project_layer = 23 - elif rig_choice == 'ARP': - self.control_layer = 16 - self.project_layer = 16 - self.clean_layers() + if self.control_bone is not None: + collection_name = f"Layer {self.control_layer + 1}" + if collection_name not in arm.collections: + arm.collections.new(collection_name) + try: + arm.collections[collection_name].assign(self.control_bone.bone) + except RuntimeError: + pass + + for projector in self.projectors: + collection_name = f"Layer {self.project_layer + 1}" + if collection_name not in arm.collections: + arm.collections.new(collection_name) + try: + arm.collections[collection_name].assign(projector.bone) + except RuntimeError: + pass def reconstruct(self): # When the finger already has a bonechain, finds projectors and control bone @@ -631,9 +609,9 @@ def assemble_hand(handbone): def control_drivers(finger): - # Puts rotation limits on control bone, then hooks up the influence of all those IK constraints + # Puts rotation and location limits on control bone, then hooks up the influence of all those IK constraints # to depend on control bone rotation. Maybe the rotation limit part should be somewhere else - + finger.control_bone.rotation_mode = "XYZ" print("\nApplying rotation limits to " + finger.name + " control bone") @@ -645,10 +623,29 @@ def control_drivers(finger): rotationlock.use_limit_y = True rotationlock.use_limit_z = True + print("Applying location limits to " + finger.name + " control bone") + locationlock = finger.control_bone.constraints.new("LIMIT_LOCATION") + locationlock.owner_space = "LOCAL" + locationlock.name = prefix + "Location Limit" + locationlock.use_min_x = True + locationlock.use_min_y = True + locationlock.use_min_z = True + locationlock.use_max_x = True + locationlock.use_max_y = True + locationlock.use_max_z = True + locationlock.min_x = 0 + locationlock.min_y = 0 + locationlock.min_z = 0 + locationlock.max_x = 0 + locationlock.max_y = 0 + locationlock.max_z = 0 + print("Applying angle drivers") for joint in finger.phalanges: - #print('driver for bone ' + joint.name) - driver = obj.driver_add('pose.bones["' + joint.name + '"].constraints["' + prefix + 'IK"].influence').driver + fcurve = obj.driver_add('pose.bones["' + joint.name + '"].constraints["' + prefix + 'IK"].influence') + driver = fcurve.driver + fcurve.mute = False + v = driver.variables.new() v.name = 'gripcontrol' @@ -659,10 +656,11 @@ def control_drivers(finger): print("Applying scale drivers") for p in finger.projectors: - #print(p.name) stringholder = p.name - scaledriver = obj.driver_add('pose.bones["' + stringholder + '"].constraints["' + prefix - + 'shrinkwrap"].distance').driver + fcurve = obj.driver_add('pose.bones["' + stringholder + '"].constraints["' + prefix + 'shrinkwrap"].distance') + scaledriver = fcurve.driver + fcurve.mute = False + v = scaledriver.variables.new() v.name = 'gripscale' From dc727a2ccc6d76a6b28e6a4eb503bdeb75b81832 Mon Sep 17 00:00:00 2001 From: Dmeerev Date: Sat, 10 Jan 2026 19:05:16 +0000 Subject: [PATCH 2/2] Update __init__.py to b4x --- __init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 11a280a..60e431d 100644 --- a/__init__.py +++ b/__init__.py @@ -6,8 +6,8 @@ bl_info = { "name": "Autogrip", "author": "Jetpack Crow", - "version": (1, 21), - "blender": (3, 4, 1), + "version": (2, 2), + "blender": (4, 0, 0), "location": "View3D > Extended Tools > AutoGrip", "description": "Automatically poses hand rigs", "category": '3D View'}