From 2be6ea94dfb5a8dcf79676f91f4032d67fa7efe2 Mon Sep 17 00:00:00 2001 From: Alan O'Cull Date: Wed, 7 Feb 2024 13:20:07 -0500 Subject: [PATCH] Set up rigging file --- characters/infantry/post_rig.py | 167 ++++++++++++++++++++++++++++ characters/infantry/rigging-1.blend | 3 + 2 files changed, 170 insertions(+) create mode 100644 characters/infantry/post_rig.py create mode 100644 characters/infantry/rigging-1.blend diff --git a/characters/infantry/post_rig.py b/characters/infantry/post_rig.py new file mode 100644 index 0000000..6b54fdb --- /dev/null +++ b/characters/infantry/post_rig.py @@ -0,0 +1,167 @@ +import bpy +from bpy.types import Constraint, PoseBone + +rig = bpy.data.objects["skeleton_insurrectionist"] + +## FIX PARENTS +def reparent(b: str, newParent: str = 'DEF-spine'): + rig.data.edit_bones[b].parent = rig.data.edit_bones[newParent] +def fix(b: str): + p = rig.data.edit_bones[b].parent.name.replace('ORG','DEF') + reparent(b, p) + +# Switch to EDIT mode to modify bone hiearchy to be proper for Unreal +bpy.ops.object.mode_set(mode='EDIT') + +# List of bones that need to be reparented to their deforming counterparts +fixList = [ + # Hands + 'DEF-thumb01.L', + 'DEF-index01.L', + 'DEF-middle01.L', + 'DEF-ring01.L', + 'DEF-pinky01.L', + + # Arms + 'shoulder.L', + 'breast.L', + + # Legs + 'DEF-thigh.L', +] +# Iterate through and fix each bone +for item in fixList: + fix(item) + if item.endswith('.L'): # If it's left-sided, fix right-side counterparts too + fix(item.replace('.L','.R')) + +# Pelvis parents work a little differently +reparent('DEF-pelvis.L', 'DEF-spine') +reparent('DEF-pelvis.R', 'DEF-spine') +# Deform parents on palms are actually parented to originals, so skip that layer +reparent('DEF-palm.01.L', 'DEF-hand.L') +reparent('DEF-palm.02.L', 'DEF-hand.L') +reparent('DEF-palm.03.L', 'DEF-hand.L') +reparent('DEF-palm.04.L', 'DEF-hand.L') +reparent('DEF-palm.01.R', 'DEF-hand.R') +reparent('DEF-palm.02.R', 'DEF-hand.R') +reparent('DEF-palm.03.R', 'DEF-hand.R') +reparent('DEF-palm.04.R', 'DEF-hand.R') + +# Force axe to be exported by setting it as a deform bone +rig.data.edit_bones['axe'].use_deform = True + +# Switch into POSE mode to set up animation constraints +bpy.ops.object.mode_set(mode='POSE') + +## Declare Functions for animation constraints +def arrcopy(copyTo, copyFrom): + for i in range(min(len(copyTo), len(copyFrom))): + copyTo[i] = copyFrom[i] +def drv_blend_1D(shape_target: str, key_target: str, bone_name: str, max_x: float, prop: str = 'LOC_Y', formula: str = ''): + block = bpy.data.shape_keys[shape_target].key_blocks[key_target] + bmin = block.slider_min + bmax = block.slider_max + + block.driver_remove('value') + fcurve = block.driver_add('value') + d = fcurve.driver + d.type = 'SCRIPTED' + + if formula == '': + d.expression = str(bmax / max_x) + '*x' + else: + d.expression = formula + + v = d.variables.new() + v.name = 'x' + v.type = 'TRANSFORMS' + t = v.targets[0] + t.id = rig + t.bone_target = bone_name + t.transform_type = prop + t.transform_space = 'LOCAL_SPACE' +def drv_constraint_1D(c: Constraint, bone_name: str, max_x: float, prop: str = 'LOC_Y', formula: str = ''): + bmin = 0.0 + bmax = 1.0 + + c.driver_remove('influence') + fcurve = c.driver_add('influence') + d = fcurve.driver + d.type = 'SCRIPTED' + + if formula == '': + d.expression = str(bmax / max_x) + '*x' + else: + d.expression = formula + + v = d.variables.new() + v.name = 'x' + v.type = 'TRANSFORMS' + t = v.targets[0] + t.id = rig + t.bone_target = bone_name + t.transform_type = prop + t.transform_space = 'LOCAL_SPACE' +def constrain_slider(b: PoseBone, minimum: float = 0, maximum: float = 0.06): + c = b.constraints.new('LIMIT_LOCATION') + c.use_min_y = True + c.use_max_y = True + c.min_y = minimum + c.max_y = maximum + c.use_transform_limit = True + c.owner_space = 'LOCAL' + +# Fix widget scalings +for b in rig.pose.bones: + if b.name.startswith("menu_"): + b.use_custom_shape_bone_size = False + b.custom_shape_translation = (0.0, 0.03, 0.0) + b.custom_shape_scale_xyz = (0.06, 0.06, 0.0) + arrcopy(b.lock_scale, [False, True, False]) + elif b.name.startswith("slider1d"): + b.use_custom_shape_bone_size = False + b.custom_shape_scale_xyz = (0.02, 0.003, 0.005) + + arrcopy(b.lock_location, [True, False, True]) + arrcopy(b.lock_rotation, [True, True, True]) + arrcopy(b.lock_scale, [True, True, True]) + b.lock_rotation_w = True + elif b.name == "axe_gripadjust": + b.custom_shape_scale_xyz = (1.0, 0.8, 0.1) + +# Constrain menu sliders so they are limited to proper bounds +constrain_slider(rig.pose.bones.get('slider1d_axe_gripadjust')) +constrain_slider(rig.pose.bones.get('slider1d_axe_lefthand_grip')) +constrain_slider(rig.pose.bones.get('slider1d_axe_smear'), -0.03, 0.03) + +# Arm and Hand switch for Axe Base +# https://blender.stackexchange.com/questions/46928/set-bone-constraints-via-python-api#46986 +axe_base = rig.pose.bones.get("axe_base") +axe_constraint: Constraint = None +if axe_base is not None: + axe_constraint = axe_base.constraints.new('COPY_TRANSFORMS') + axe_constraint.target = rig + axe_constraint.subtarget = 'DEF-hand.R' # note subtarget uses name not object + axe_constraint.target_space = 'POSE' + axe_constraint.owner_space = 'POSE' + axe_constraint.influence = 0.0 + +# Left-Hand grip switch for Axe +left_hand = rig.pose.bones.get("hand_ik.L") +lh_constraint: Constraint = None +if axe_base is not None: + lh_constraint = left_hand.constraints.new('COPY_TRANSFORMS') + lh_constraint.target = rig + lh_constraint.subtarget = 'axe_grip_lefthand' # note subtarget uses name not object + lh_constraint.target_space = 'POSE' + lh_constraint.owner_space = 'POSE' + lh_constraint.influence = 0.0 + +## Set up driver constraint for the switches +drv_constraint_1D(axe_constraint, 'slider1d_axe_gripadjust', 0.06) +drv_constraint_1D(lh_constraint, 'slider1d_axe_lefthand_grip', 0.06) + +## Set up smear effect drivers for axe +drv_blend_1D('Key', 'smear_down', 'slider1d_axe_smear', 0.03) +drv_blend_1D('Key', 'smear_up', 'slider1d_axe_smear', -0.03) diff --git a/characters/infantry/rigging-1.blend b/characters/infantry/rigging-1.blend new file mode 100644 index 0000000..1bafa6e --- /dev/null +++ b/characters/infantry/rigging-1.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5742256274001af613917b774339e7a5ff71ee5546480d1a6eec9489d9f87d0f +size 1479232