import bpy
import bmesh
import math as m
import fnmatch
character = "MyCharacter"
rig = f"{character}_Armature"
origin = (0,0,0)
emplist = bpy.data.collections['EmptyCollection'].all_objects
def findEmpty(e):
for em in emplist:
if em.name == e:
return em.location
def SelectReturn(b):
for bone in Armature.data.edit_bones:
if fnmatch.fnmatchcase(bone.name, b):
return bone
def SelectListReturn(*args):
blist = []
for bone in Armature.data.edit_bones:
for a in args:
if fnmatch.fnmatchcase(bone.name, a):
blist.append(bone)
return blist
def SelectSymmetrize():
for bone in Armature.data.edit_bones:
if fnmatch.fnmatchcase(bone.name, '*l'):
bone.select = True
bone.select_head = True
bone.select_tail = True
bpy.ops.armature.symmetrize()
def AddConstraint(con, activeBone, subtar, polsubtar=None, limitcon=None, PHY_tar=None, COLL_tar=None):
if limitcon != None:
if limitcon == 'LOC':
pbone = bpy.context.object.pose.bones[activeBone]
constraint = pbone.constraints.new(con)
elif limitcon == 'ROT':
pbone = bpy.context.object.pose.bones[activeBone]
constraint = pbone.constraints.new(con)
else:
pbone = bpy.context.object.pose.bones[activeBone]
if COLL_tar != None:
target = bpy.data.objects[COLL_tar]
subtarget = bpy.data.objects[COLL_tar].vertex_groups[subtar]
elif PHY_tar != None:
target = bpy.data.objects[PHY_tar]
subtarget = bpy.data.objects[PHY_tar].vertex_groups[subtar]
else:
target = bpy.context.scene.objects.get(rig)
subtarget = bpy.context.scene.objects.get(rig).pose.bones.get(subtar)
constraint = pbone.constraints.new(con)
constraint.target = target
constraint.subtarget = subtarget.name
if polsubtar != None:
poletarget = bpy.context.scene.objects.get(rig)
polesubtarget = bpy.context.scene.objects.get(rig).pose.bones.get(polsubtar)
constraint.pole_target = poletarget
constraint.pole_subtarget = polsubtar
return constraint
def SymmetrizeConstraints():
copyFrom = "l"
pBones = [ b for b in bpy.context.object.pose.bones if b.name[-2:] == "_%s" % copyFrom ]
for b in pBones:
for c in b.constraints:
otherSide = "r" if copyFrom == "l" else "l"
otherBone = bpy.context.object.pose.bones[
b.name.replace( "_%s" % copyFrom, "_%s" % otherSide )
]
nc = otherBone.constraints.new( c.type )
for prop in dir( c ):
try:
constrProp = getattr( c, prop )
if type( constrProp ) == type(str()) and constrProp[-2:] in ["_l", "_r"]:
oppositeVal = constrProp.replace("_l", "_r") if constrProp[-2:] == "_l" else constrProp.replace("_r", "_l")
setattr( nc, prop, oppositeVal )
elif 'max_' in prop and 'LIMIT_LOCATION' not in c.type:
setattr( nc, prop, getattr( c, prop.replace( 'max', 'min' ) ) * -1 )
elif 'min_' in prop and 'LIMIT_LOCATION' not in c.type:
setattr( nc, prop, getattr( c, prop.replace( 'min', 'max' ) ) * -1 )
elif prop == 'influence':
setattr( nc, prop, abs( constrProp) )
elif prop == 'distance':
setattr( nc, prop, constrProp )
elif prop == 'rest_length':
setattr( nc, prop, constrProp )
elif prop == 'head_tail':
setattr( nc, prop, constrProp )
elif prop == 'chain_count':
setattr( nc, prop, constrProp )
elif prop == 'iterations':
setattr( nc, prop, constrProp )
elif prop == 'weight':
setattr( nc, prop, constrProp )
elif type( constrProp ) in [ type( float() ), type( int() ) ] and prop != 'pole_angle' and c.type != 'LIMIT_LOCATION':
setattr( nc, prop, constrProp * -1 )
elif prop == 'pole_angle':
if constrProp==m.radians(180):
setattr( nc, prop, m.radians(0))
elif constrProp==m.radians(0):
setattr( nc, prop, m.radians(180))
else:
setattr( nc, prop, constrProp )
except:
pass
def constraintFix(bone, const, prop, value):
code = f"bpy.context.object.pose.bones['{bone}'].constraints['{const}'].{prop} = {value}"
exec(code)
def AddDriver(bone, drivenChannel, tarBone, tarChannel, space, exp, custVar=[], varCount=1,\
package=None, channelIndex=-1, vtype='TRANSFORMS', dtype='SCRIPTED'):
if package!=None:
con = bpy.data.objects[rig]
driv = con.driver_add(package)
driv.driver.type = dtype
driv.driver.expression = exp
else:
driv = bpy.data.objects[rig].pose.bones[bone].driver_add(drivenChannel, channelIndex)
driv.driver.type = dtype
driv.driver.expression = exp
if varCount>1:
for v in range(varCount):
var = driv.driver.variables.new()
var.name = 'var'+str(v)
var.type = vtype
var.targets[0].id = bpy.data.objects[rig]
var.targets[0].bone_target = tarBone[v]
var.targets[0].transform_type = tarChannel[v]
var.targets[0].transform_space = space[v]
elif varCount==1:
var = driv.driver.variables.new()
var.name = 'var0'
var.type = vtype
var.targets[0].id = bpy.data.objects[rig]
var.targets[0].bone_target = tarBone
var.targets[0].transform_type = tarChannel
var.targets[0].transform_space = space
else:
pass
if custVar != []:
if len(custVar)==5:
var = driv.driver.variables.new()
var.name = 'var'+str(len(driv.driver.variables)-1)
var.type = custVar[0]
var.targets[0].id = bpy.data.objects[rig]
var.targets[0].bone_target = custVar[1]
var.targets[0].transform_space = custVar[2]
var.targets[1].id = bpy.data.objects[rig]
var.targets[1].bone_target = custVar[3]
var.targets[1].transform_space = custVar[4]
elif len(custVar)==3:
var = driv.driver.variables.new()
var.name = 'var'+str(len(driv.driver.variables)-1)
var.type = custVar[0]
var.targets[0].id = bpy.data.objects[rig]
var.targets[0].bone_target = custVar[1]
var.targets[1].id = bpy.data.objects[rig]
var.targets[1].bone_target = custVar[2]
else:
pass
return driv
def AddPropertyDriver(bone, drivenChannel, tarId, tarDataPath, exp,\
varCount=1, package=None, channelIndex=-1, vtype='SINGLE_PROP', dtype='SCRIPTED'):
if package!=None:
con = bpy.data.objects[rig]
driv = con.driver_add(package)
driv.driver.type = dtype
driv.driver.expression = exp
else:
driv = bpy.data.objects[rig].pose.bones[bone].driver_add(drivenChannel, channelIndex)
driv.driver.type = dtype
driv.driver.expression = exp
if varCount>1:
for v in range(varCount):
var = driv.driver.variables.new()
var.name = 'var'+str(v)
var.type = vtype
var.targets[v].id = bpy.data.objects[tarId[v]]
var.targets[v].data_path = tarDataPath[v]
else:
var = driv.driver.variables.new()
var.name = 'var'
var.type = vtype
var.targets[0].id = bpy.data.objects[tarId]
var.targets[0].data_path = tarDataPath
return driv
def Add_PHY_PropertyDriver(mesh, mod, prop, tarId, tarDataPath, vtype='SINGLE_PROP', dtype='AVERAGE'):
package = f'modifiers["{mod}"].settings.{prop}'
con = bpy.data.objects[mesh]
driv = con.driver_add(package)
driv.driver.type = dtype
var = driv.driver.variables.new()
var.name = 'var'
var.type = vtype
var.targets[0].id = bpy.data.objects[tarId]
var.targets[0].data_path = tarDataPath
return driv
def add_Physics(parbone, PHYgroup):
bpy.context.scene.cursor.location = (0,0,0)
parentBoneLOC = bpy.data.objects[rig].matrix_world @ \
bpy.data.objects[rig].pose.bones[parbone].matrix.to_translation()
bpy.ops.mesh.primitive_cube_add(enter_editmode=True)
PHy_mesh = 'PHY_mesh_'+ parbone
bpy.context.active_object.name = PHy_mesh
mesh = bmesh.from_edit_mesh(bpy.context.object.data)
if mesh.select_mode != 'VERT':
bpy.ops.mesh.select_mode(type='VERT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.merge(type='CENTER')
bonelist = []
mesh.verts.ensure_lookup_table()
for bone in bpy.data.objects[rig].pose.bones:
if PHYgroup in bone.name:
bonelist.append(bone.name)
fm = bpy.data.objects[rig].matrix_world @ bpy.data.objects[rig].pose.bones[bonelist[0]].matrix
fm = fm.to_translation()
mesh.verts.ensure_lookup_table()
mesh.verts[0].co = fm
bpy.ops.object.vertex_group_add()
bpy.context.object.vertex_groups.active.name = 'Vgrp_' + bonelist[0]
bpy.ops.object.vertex_group_assign()
if len(bonelist) > 1:
for i in range(1, len(bonelist)):
mesh.verts.ensure_lookup_table()
mesh.verts[i-1].select_set(True)
bpy.ops.mesh.duplicate_move(MESH_OT_duplicate={"mode":1},\
TRANSFORM_OT_translate={"value":(0, 0, 0), "orient_axis_ortho":'X',\
"orient_type":'GLOBAL', "orient_matrix":((0, 0, 0), (0, 0, 0), (0, 0, 0)),\
"orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False),\
"mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH',\
"proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False,\
"snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False,\
"snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False,\
"remove_on_cancel":False, "view2d_edge_pan":False, "release_confirm":False, "use_accurate":False,\
"use_automerge_and_split":False})
for v in mesh.verts:
v.select_set(False)
mesh.verts.ensure_lookup_table()
mesh.verts[i].select_set(True)
bpy.ops.object.vertex_group_remove_from()
bpy.ops.object.vertex_group_add()
bpy.context.object.vertex_groups.active.name = 'Vgrp_' + bonelist[i]
bpy.ops.object.vertex_group_assign()
fm = bpy.data.objects[rig].matrix_world\
@ bpy.data.objects[rig].pose.bones[bonelist[i]].matrix
fm = fm.to_translation()
mesh.verts.ensure_lookup_table()
mesh.verts[i].co = fm
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.scene.cursor.location = parentBoneLOC
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[PHy_mesh].select_set(True)
bpy.ops.object.modifier_add(type='SOFT_BODY')
bpy.data.objects[PHy_mesh].modifiers["Softbody"].settings.friction = 13
bpy.data.objects[PHy_mesh].modifiers["Softbody"].settings.mass = .2
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[rig].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects[rig]
bpy.ops.object.mode_set(mode='POSE')
for bone in bonelist:
if fnmatch.fnmatchcase(bone, '*MAIN_l'):
for bon in bonelist:
if fnmatch.fnmatchcase(bon, '*AIM_l'):
boneVarDamp = AddConstraint('DAMPED_TRACK', bone, bon)
boneVarDamp.name = 'PHY_DAMP_' + bone
boneVarDamp.head_tail = 0
boneVarDamp.track_axis = 'TRACK_Y'
boneVarDamp.influence = 1
if fnmatch.fnmatchcase(bone, '*MAIN_r'):
for bon in bonelist:
if fnmatch.fnmatchcase(bon, '*AIM_r'):
boneVarDamp = AddConstraint('DAMPED_TRACK', bone, bon)
boneVarDamp.name = 'PHY_DAMP_' + bone
boneVarDamp.head_tail = 0
boneVarDamp.track_axis = 'TRACK_Y'
boneVarDamp.influence = 1
boneVarloc = AddConstraint('COPY_LOCATION', bone, 'Vgrp_' + bone, PHY_tar= PHy_mesh)
boneVarloc.name = 'PHY_LOC_' + bone
boneVarloc.use_x = True
boneVarloc.use_y = True
boneVarloc.use_z = True
boneVarloc.use_offset = False
boneVarloc.target_space = 'WORLD'
boneVarloc.owner_space = 'WORLD'
if 'MAIN_' in bone:
boneVarloc.influence = .7
else:
boneVarloc.influence = 1
boneVarLim = AddConstraint('LIMIT_LOCATION', bone, '', limitcon='LOC')
boneVarLim.name = 'PHY_LIM_' + bone
if 'AIM_' in bone:
param = {'min':[-.05,-.05,-.05], 'max':[.05,.05,.05]}
else:
param = {'min':[-.03,-.03,-.03], 'max':[.03,.03,.03]}
x, y, z = 0,1,2
for end in ['min','max']:
for ax in ['x','y','z']:
code = f"boneVarLim.use_{end}_{ax} = True\nboneVarLim.{end}_{ax} = {param.get(end)[eval(ax)]}"
exec(code)
boneVarLim.owner_space = 'LOCAL'
boneVarLim.influence = 1
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[rig].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects[rig]
bpy.ops.object.mode_set(mode='POSE')
bpy.context.object.pose.bones[parbone].bone.select = True
bpy.context.object.data.bones.active = bpy.context.object.pose.bones[parbone].bone
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[PHy_mesh].select_set(True)
bpy.data.objects[rig].select_set(True)
bpy.ops.object.parent_set(type='BONE', keep_transform=True)
bpy.context.scene.cursor.location = 0,0,0
bpy.ops.object.armature_add( enter_editmode=False )
bpy.data.objects['Armature'].name = rig
Armature = bpy.data.objects[rig]
ArmatureOps = bpy.ops.object
ArmEdit = Armature.data.edit_bones
ArmBones = Armature.data.bones
ArmPose = Armature.pose.bones
ArmContx = bpy.context.object
Armature.select_set(True)
ArmatureOps.mode_set(mode='EDIT', toggle=False)
bpy.data.armatures[bpy.context.object.data.name].display_type = 'STICK'
ArmEdit.remove(ArmEdit[0])
root = ArmContx.data.edit_bones.new('root')
root.head = origin
root.tail = (0,1,0)
gravity_ROOT = ArmContx.data.edit_bones.new('gravity_ROOT')
gravity_ROOT.head = origin
gravity_ROOT.tail = findEmpty('gravity_ROOT_tail')
gravity_ROOT.roll = m.radians(0)
gravity_AIM = ArmContx.data.edit_bones.new('gravity_AIM')
gravity_AIM.head = findEmpty('gravity_AIM_head')
gravity_AIM.tail = findEmpty('gravity_AIM_tail')
gravity_AIM.roll = m.radians(0)
Armature.data.edit_bones['gravity_AIM'].parent = Armature.data.edit_bones['gravity_ROOT']
Armature.data.edit_bones['gravity_AIM'].use_connect = False
PROPERTIES = ArmContx.data.edit_bones.new('PROPERTIES')
PROPERTIES.head = findEmpty('PROPERTIES_head')
PROPERTIES.tail = findEmpty('PROPERTIES_tail')
PROPERTIES.roll = m.radians(89)
Armature.data.edit_bones['PROPERTIES'].parent = Armature.data.edit_bones['root']
Armature.data.edit_bones['PROPERTIES'].use_connect = False
pelvis = ArmContx.data.edit_bones.new('pelvis')
pelvis.head = findEmpty('pelvis_head')
pelvis.tail = findEmpty('spine_01_head')
pelvis.roll = m.radians(89)
Armature.data.edit_bones['pelvis'].parent = Armature.data.edit_bones['root']
Armature.data.edit_bones['pelvis'].use_connect = False
spine_01 = ArmContx.data.edit_bones.new('spine_01')
if True:
PHY_07_bellyShake_MAIN_l = ArmContx.data.edit_bones.new('PHY_07_bellyShake_MAIN_l')
PHY_07_bellyShake_MAIN_l.head = findEmpty('PHY_07_bellyShake_MAIN_l_head')
PHY_07_bellyShake_MAIN_l.tail = findEmpty('PHY_07_bellyShake_MAIN_l_tail')
PHY_07_bellyShake_MAIN_l.roll = m.radians(60)
Armature.data.edit_bones['PHY_07_bellyShake_MAIN_l'].parent = Armature.data.edit_bones['spine_02_PhyINTR_l']
Armature.data.edit_bones['PHY_07_bellyShake_MAIN_l'].use_connect = False
PHY_07_bellyShake_topOuter_l = ArmContx.data.edit_bones.new('PHY_07_bellyShake_topOuter_l')
PHY_07_bellyShake_topOuter_l.head = findEmpty('PHY_07_bellyShake_topOuter_l_head')
PHY_07_bellyShake_topOuter_l.tail = findEmpty('PHY_07_bellyShake_topOuter_l_tail')
PHY_07_bellyShake_topOuter_l.roll = m.radians(60)
Armature.data.edit_bones['PHY_07_bellyShake_topOuter_l'].parent = Armature.data.edit_bones['PHY_07_bellyShake_MAIN_l']
Armature.data.edit_bones['PHY_07_bellyShake_topOuter_l'].use_connect = False
PHY_07_bellyShake_bottomOuter_l = ArmContx.data.edit_bones.new('PHY_07_bellyShake_bottomOuter_l')
PHY_07_bellyShake_bottomOuter_l.head = findEmpty('PHY_07_bellyShake_bottomOuter_l_head')
PHY_07_bellyShake_bottomOuter_l.tail = findEmpty('PHY_07_bellyShake_bottomOuter_l_tail')
PHY_07_bellyShake_bottomOuter_l.roll = m.radians(60)
Armature.data.edit_bones['PHY_07_bellyShake_bottomOuter_l'].parent = Armature.data.edit_bones['PHY_07_bellyShake_MAIN_l']
Armature.data.edit_bones['PHY_07_bellyShake_bottomOuter_l'].use_connect = False
PHY_07_bellyShake_bottomInner_l = ArmContx.data.edit_bones.new('PHY_07_bellyShake_bottomInner_l')
PHY_07_bellyShake_bottomInner_l.head = findEmpty('PHY_07_bellyShake_bottomInner_l_head')
PHY_07_bellyShake_bottomInner_l.tail = findEmpty('PHY_07_bellyShake_bottomInner_l_tail')
PHY_07_bellyShake_bottomInner_l.roll = m.radians(60)
Armature.data.edit_bones['PHY_07_bellyShake_bottomInner_l'].parent = Armature.data.edit_bones['PHY_07_bellyShake_MAIN_l']
Armature.data.edit_bones['PHY_07_bellyShake_bottomInner_l'].use_connect = False
"""
more code in this section.
- All creating the bones of the rig
- setting the parent child relationship.
- Set non-deforming bones to false
- Set non-use inherit rotation to false
- Set non-use inherit scale to false
- changing rotation mode to either euler or quanternion
- adding controllers
Skipping a few sections to constraints.
example adding constraints
"""
SelectSymmetrize()
calf_IKCONST_l = AddConstraint('IK', 'calf_l', 'ikHandleLeg_l', polsubtar='poleVectorLeg_l')
calf_IKCONST_l.name = 'calf_IKCONST_l'
calf_IKCONST_l.pole_angle = m.radians(0)
calf_IKCONST_l.chain_count = 2
calf_IKCONST_l.use_tail = True
calf_IKCONST_l.use_stretch = True
calf_IKCONST_l.influence = 1
autoPoleNormLeg_0_DAMPTRK_l = AddConstraint('DAMPED_TRACK', 'autoPoleNormLeg_0_l', 'autoPoleNormLeg_2_l')
autoPoleNormLeg_0_DAMPTRK_l.name = 'autoPoleNormLeg_0_DAMPTRK_l'
autoPoleNormLeg_0_DAMPTRK_l.head_tail = 0
autoPoleNormLeg_0_DAMPTRK_l.track_axis = 'TRACK_Y'
autoPoleNormLeg_0_DAMPTRK_l.influence = 1
if True:
autoPoleNormLeg_1_COPLOC_01_l = AddConstraint('COPY_LOCATION', 'autoPoleNormLeg_1_l', 'autoPoleNormLeg_0_l')
autoPoleNormLeg_1_COPLOC_01_l.name = 'autoPoleNormLeg_1_COPLOC_01_l'
autoPoleNormLeg_1_COPLOC_01_l.head_tail = 0
autoPoleNormLeg_1_COPLOC_01_l.use_x = True
autoPoleNormLeg_1_COPLOC_01_l.use_y = True
autoPoleNormLeg_1_COPLOC_01_l.use_z = True
autoPoleNormLeg_1_COPLOC_01_l.target_space = 'WORLD'
autoPoleNormLeg_1_COPLOC_01_l.owner_space = 'WORLD'
autoPoleNormLeg_1_COPLOC_01_l.influence = 1
autoPoleNormLeg_1_COPLOC_02_l = AddConstraint('COPY_LOCATION', 'autoPoleNormLeg_1_l', 'autoPoleNormLeg_2_l')
autoPoleNormLeg_1_COPLOC_02_l.name = 'autoPoleNormLeg_1_COPLOC_02_l'
autoPoleNormLeg_1_COPLOC_02_l.head_tail = 0
autoPoleNormLeg_1_COPLOC_02_l.use_x = True
autoPoleNormLeg_1_COPLOC_02_l.use_y = True
autoPoleNormLeg_1_COPLOC_02_l.use_z = True
autoPoleNormLeg_1_COPLOC_02_l.target_space = 'WORLD'
autoPoleNormLeg_1_COPLOC_02_l.owner_space = 'WORLD'
autoPoleNormLeg_1_COPLOC_02_l.influence = 0.5
autoPoleNormLeg_1_COPROT_l = AddConstraint('COPY_ROTATION', 'autoPoleNormLeg_1_l', 'autoPoleNormLeg_2_l')
autoPoleNormLeg_1_COPROT_l.name = 'autoPoleNormLeg_1_COPROT_l'
autoPoleNormLeg_1_COPROT_l.use_x = True
autoPoleNormLeg_1_COPROT_l.use_y = True
autoPoleNormLeg_1_COPROT_l.use_z = True
autoPoleNormLeg_1_COPROT_l.target_space = 'WORLD'
autoPoleNormLeg_1_COPROT_l.owner_space = 'WORLD'
autoPoleNormLeg_1_COPROT_l.influence = 1
"""
more code in this section.
all more if this, adding contraints to bone
ie. IK, copy rotation, copy location, stretchto, damptrack, etc..
examples adding drivers
"""
innerThighAdj_LocX_L = AddDriver("innerThighAdj_l", 'location', ['thigh_l', 'thigh_l'], ['ROT_X', 'ROT_Z'],\
['LOCAL_SPACE', 'LOCAL_SPACE'], 'abs(var0*.3) if var0>0 else (var1*.35)', varCount=2, channelIndex=0)
innerThighAdj_LocY_L = AddDriver("innerThighAdj_l", 'location', 'thigh_l', 'ROT_Z', 'LOCAL_SPACE', 'abs(var0*.45) if var0<0 else (var0*.45)', channelIndex=1)
innerThighAdj_LocZ_L = AddDriver("innerThighAdj_l", 'location', 'thigh_l', 'ROT_Z', 'LOCAL_SPACE', 'var0*.4 if var0<0 else -(var0*.3)', channelIndex=2)
innerThighAdj_LocX_R = AddDriver("innerThighAdj_r", 'location', ['thigh_r', 'thigh_r'], ['ROT_X', 'ROT_Z'],\
['LOCAL_SPACE', 'LOCAL_SPACE'], '-abs(var0*.3) if var0>0 else -(var1*.35)', varCount=2, channelIndex=0)
innerThighAdj_LocY_R = AddDriver("innerThighAdj_r", 'location', 'thigh_r', 'ROT_Z', 'LOCAL_SPACE', 'abs(var0*-.45) if var0>0 else -(var0*.45)', channelIndex=1)
innerThighAdj_LocZ_R = AddDriver("innerThighAdj_r", 'location', 'thigh_r', 'ROT_Z', 'LOCAL_SPACE', 'var0*-.4 if var0>0 else (var0*.3)', channelIndex=2)
thigh_ScaleY_L = AddDriver('thigh_l', 'scale', 'thigh_l', 'ROT_Z', 'LOCAL_SPACE', 'max(1-abs(var0 *.03), .98)', channelIndex=1)
thigh_ScaleY_R = AddDriver('thigh_r', 'scale', 'thigh_r', 'ROT_Z', 'LOCAL_SPACE', 'max(1-abs(var0 *.03), .98)', channelIndex=1)
thigh_ScaleY_L = AddDriver('thigh_l', 'scale', 'thigh_l', 'ROT_Z', 'LOCAL_SPACE', 'max(1-abs(var0 *.03), .98)', channelIndex=1)
thigh_ScaleY_R = AddDriver('thigh_r', 'scale', 'thigh_r', 'ROT_Z', 'LOCAL_SPACE', 'max(1-abs(var0 *-.03), .98)', channelIndex=1)
sideMoveHip_ScaleX_l = AddPropertyDriver('sideMoveHip_l', 'scale', 'PROPERTIES_SPHERE', '["Hip_Width"]', '(var*3) + 1.0', channelIndex=0)
sideMoveHip_ScaleX_r = AddPropertyDriver('sideMoveHip_r', 'scale', 'PROPERTIES_SPHERE', '["Hip_Width"]', '(var*3) + 1.0', channelIndex=0)
sideMoveHip_ScaleZ_l = AddPropertyDriver('sideMoveHip_l', 'scale', 'PROPERTIES_SPHERE', '["Hip_Width"]', '(var*3) + 1.0', channelIndex=2)
sideMoveHip_ScaleZ_r = AddPropertyDriver('sideMoveHip_r', 'scale', 'PROPERTIES_SPHERE', '["Hip_Width"]', '(var*3) + 1.0', channelIndex=2)
pelvis_LIMLOC_DRIV_package = 'pose.bones["pelvis"].constraints["pelvis_LIMLOC"].influence'
pelvis_LIMLOC_DRIV = AddPropertyDriver('pelvis', '', ['PROPERTIES_SPHERE', 'PROPERTIES_SPHERE'], ['["Hip_Width"]', '["Thigh_Size"]'],\
'-4.0 if var0>.05 or var1>.1 else -5', varCount=2, package=pelvis_LIMLOC_DRIV_package)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects['body1'].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['body1']
bpy.ops.object.mode_set(mode='WEIGHT_PAINT')
for grp in bpy.context.object.vertex_groups:
if grp.name[-2:] == '_r':
other_side = bpy.context.object.vertex_groups[grp.name].index
bpy.context.object.vertex_groups.active_index = other_side
bpy.ops.object.vertex_group_remove(all=False, all_unlocked=False)
for grp in bpy.context.object.vertex_groups:
if grp.name[-2:] == '_l':
act = bpy.context.object.vertex_groups[grp.name].index
bpy.context.object.vertex_groups.active_index = act
bpy.ops.object.vertex_group_copy()
bpy.ops.object.vertex_group_mirror(use_topology=False)
if 'PHY_' in grp.name:
for i in range(1,12,2):
if grp.name[4:6] == f'0{i}':
new_name = f'PHY_0{i+1}' + grp.name[6:-2] + '_r'
elif grp.name[4:6] == f'{i}':
new_name = f'PHY_{i+1}' + grp.name[6:-2] + '_r'
else:
new_name = grp.name[:-2]+'_r'
bpy.context.object.vertex_groups[grp.name+'_copy'].name = new_name
else:
pass
con_list = ['spine_02', 'pelvis', 'ikHandleArm_r', 'ikHandleArm_l', 'poleVectorLeg_r', 'poleVectorLeg_l',\
'neck_02', 'spine_04', 'foot_CON_l', 'footRoll_CON_l', 'foot_CON_r', 'footRoll_CON_r',\
'poleVectorArm_l', 'poleVectorArm_r', 'hand_l', 'hand_r']
hidden_bones = {}
for bone in bpy.context.object.pose.bones:
if bone.name not in con_list:
drive = bpy.data.objects[rig].pose.bones[bone.name].bone.driver_add('hide')
drive.driver.type = 'SCRIPTED'
drive.driver.expression = 'var'
var = drive.driver.variables.new()
var.name = 'var'
var.type = 'SINGLE_PROP'
var.targets[0].id = bpy.data.objects['PROPERTIES_SPHERE']
var.targets[0].data_path = '["_INTERNAL_VISIBILITY"]'
hidden_bones[f"hide_{bone.name}"] = drive
add_Physics('spine_02_PhyINTR_l', 'PHY_07')
add_Physics('spine_02_PhyINTR_r', 'PHY_08')
PHY_mesh_spine_02_PhyINTR_FRICTION_DRIV_l = Add_PHY_PropertyDriver("PHY_mesh_spine_02_PhyINTR_l", 'Softbody',\
'friction', 'PROPERTIES_SPHERE', '["phyFRICTION_stomach"]')
PHY_mesh_spine_02_PhyINTR_FRICTION_DRIV_r = Add_PHY_PropertyDriver("PHY_mesh_spine_02_PhyINTR_r", 'Softbody',\
'friction', 'PROPERTIES_SPHERE', '["phyFRICTION_stomach"]')
PHY_mesh_spine_02_PhyINTR_MASS_DRIV_l = Add_PHY_PropertyDriver("PHY_mesh_spine_02_PhyINTR_l", 'Softbody',\
'mass', 'PROPERTIES_SPHERE', '["phyMASS_stomach"]')
PHY_mesh_spine_02_PhyINTR_MASS_DRIV_r = Add_PHY_PropertyDriver("PHY_mesh_spine_02_PhyINTR_r", 'Softbody',\
'mass', 'PROPERTIES_SPHERE', '["phyMASS_stomach"]')
bpy.ops.object.posemode_toggle()
restlist = ['thigh_l', 'thigh_r', 'calf_l', 'calf_r']
for bone in bpy.context.object.pose.bones:
bone.bone.select = False
for res in restlist:
bpy.context.object.pose.bones[res].bone.select = True
bpy.ops.pose.armature_apply(selected=True)
for bone in bpy.data.objects[rig].pose.bones:
for const in bone.constraints:
if const.type == 'STRETCH_TO':
bpy.context.object.data.bones.active = bone.bone
bpy.ops.constraint.stretchto_reset(constraint=const.name, owner='BONE')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
meshlist = bpy.data.collections[character].all_objects
for mes in meshlist:
mes.modifiers['Armature'].object = bpy.data.objects[rig]
for o in bpy.data.objects:
if 'Auto_Eye' in o.name or 'PROPERTIES_SPHERE' in o.name:
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[rig].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects[rig]
bpy.ops.object.mode_set(mode='POSE')
bpy.context.object.pose.bones['head'].bone.select = True
bpy.context.object.data.bones.active = bpy.context.object.pose.bones['head'].bone
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[o.name].select_set(True)
bpy.data.objects[rig].select_set(True)
bpy.ops.object.parent_set(type='BONE', keep_transform=True)
bpy.data.objects['PROPERTIES_SPHERE'].select_set(False)