Skip to content

Commit

Permalink
Deform Only Update
Browse files Browse the repository at this point in the history
Reworked how the "deform only" option calculates new parents for bones with non-deform parents.
  • Loading branch information
Sandman13sq committed Oct 26, 2022
1 parent 47cdc2a commit f988d64
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 31 deletions.
Binary file modified DmrBlender_VBM.zip
Binary file not shown.
12 changes: 8 additions & 4 deletions DmrBlender_VBM/vbm_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,13 +434,17 @@ def GetAttribLayers(layers, targets, is_color=False):
vgroups = workingobj.vertex_groups
weightdefaults = (1,1,1,1) if len(vgroups) == 0 else (0,0,0,0)

# Map Vertex Groups to Armature Indices
validvgroups = tuple(vg.index for vg in vgroups)
vgremap = {vg.index: vg.index for vg in vgroups}
vgroupremap = {vg.index: vg.index for vg in vgroups}

if armature:
bonenames = tuple([b.name for b in armature.data.bones if ((deformonly and b.use_deform) or not deformonly)])
bonenames = settings.get('bonenames', None)
if not bonenames:
bonenames = tuple([b.name for b in armature.data.bones if ((deformonly and b.use_deform) or not deformonly)])

validvgroups = tuple([vg.index for vg in vgroups if vg.name in bonenames])
vgremap = {vg.index: (bonenames.index(vg.name) if vg.name in bonenames else -1) for vg in vgroups}
vgroupremap = {vg.index: (bonenames.index(vg.name) if vg.name in bonenames else -1) for vg in vgroups}

weightsortkey = lambda x: x.weight

Expand All @@ -460,7 +464,7 @@ def VEntry(v):
validvges.sort(key=weightsortkey, reverse=True)
validvges = validvges[:4]

boneindices = tuple(vgremap[vge.group] for vge in validvges)
boneindices = tuple(vgroupremap[vge.group] for vge in validvges)
weights = tuple(vge.weight for vge in validvges)
wlength = sum(weights)

Expand Down
50 changes: 46 additions & 4 deletions DmrBlender_VBM/vbm_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,20 +941,63 @@ def ComposeBoneData(armature):

bones = workingarmature.bones[:]
if settings.get('deformonly', False):
context.scene.collection.objects.link(workingobj)
context.view_layer.objects.active = workingobj
bpy.ops.object.select_all(action='DESELECT')
workingobj.select_set(True)

# Relink armature (Rigify)
bpy.ops.object.mode_set(mode='EDIT')

ebones = workingobj.data.edit_bones
deformebones = [b for b in ebones if b.use_deform]
nondeformebones = [b for b in ebones if not b.use_deform]

def FindFirstDeform(b, usedbones=[]):
if not b.parent:
return None

usedbones.append(b)
basename = b.name[b.name.find("-")+1:]

nextdeforms = [x for x in deformebones
if (x not in usedbones and x.name[-len(basename):] == basename)]
if nextdeforms:
return nextdeforms[0]
return FindFirstDeform(b.parent)

for b in deformebones:
if not b.parent:
continue

if b.parent not in deformebones:
b.parent = FindFirstDeform(b.parent, [b])

bpy.ops.armature.layers_show_all()
bpy.ops.armature.reveal()
for eb in workingobj.data.edit_bones:
eb.select = not eb.use_deform
bpy.ops.armature.delete()

bpy.ops.object.mode_set(mode='OBJECT')

bones = [b for b in workingarmature.bones if b.use_deform]

bonemat = {b: (settingsmatrix @ b.matrix_local.copy()) for b in bones}

# Write Data
out_bone = b''

out_bone += Pack('I', len(bones)) # Bone count
out_bone += b''.join( [PackString(b.name) for b in bones] ) # Bone names
out_bone += b''.join( [Pack('I', bones.index(BoneDeformParent(b)) if BoneDeformParent(b) else 0) for b in bones] ) # Bone parent index
out_bone += b''.join( [Pack('I', bones.index(b.parent) if b.parent else 0) for b in bones] ) # Bone parent index
out_bone += b''.join( [PackMatrix('f',
(bonemat[BoneDeformParent(b)].inverted() @ bonemat[b]) # local matrices
if BoneDeformParent(b) else bonemat[b]) for b in bones] )
(bonemat[b.parent].inverted() @ bonemat[b]) # local matrices
if b.parent else bonemat[b]) for b in bones] )
out_bone += b''.join( [PackMatrix('f', bonemat[b].inverted()) for b in bones] ) # inverse matrices

settings['bonenames'] = [b.name for b in bones]

# Delete Temporary
bpy.data.objects.remove(workingobj)
bpy.data.armatures.remove(workingarmature)
Expand All @@ -966,7 +1009,6 @@ def ComposeBoneData(armature):
out_bone = ComposeBoneData(armature)

# Compose Vertex Buffer Data ================================================

def GetVBGroupSorted(objlist):
vbgroups = {}
vbkeys = []
Expand Down
85 changes: 62 additions & 23 deletions DmrBlender_VBM/vbm_op_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,29 +219,6 @@ def GetTRKData(context, sourceobj, sourceaction, settings):
sc.frame_set(sc.frame_current)
vl.update()

bones = {b.name: b for b in workingobj.data.bones}

# Make dict of selected bones
if selected_bones_only:
bones = {b.name: b for b in bones.values() if b.select}

boneparents = {b: BoneFindParent(b, selected_bones_only, deform_only) for b in bones.values()}
pbones = [workingobj.pose.bones[b.name] for b in bones.values()]

# Make dict of deform bones
if deform_only:
pbones = {x.name: x for x in pbones if bones[x.name].use_deform}
pboneparents = {pbones[b.name]: pbones[boneparents[b].name] if boneparents[b] else None for b in bones.values() if b.use_deform}
# Make dict of all bones
else:
pbones = {x.name: x for x in pbones}
pboneparents = {pbones[b.name]: pbones[boneparents[b].name] if boneparents[b] else None for b in bones.values()}

bonecurves = {pbones[x]: [ [(),(),()], [(),(),(),()], [(),(),()] ] for x in pbones}
pboneslist = [x for x in pbones.values()]
pbonesnames = [x.name for x in pboneslist]
bonenames = [x for x in pbones.keys()]

workingobj.data.pose_position = 'POSE'

# Baking ----------------------------------------------------------------
Expand Down Expand Up @@ -283,7 +260,69 @@ def GetTRKData(context, sourceobj, sourceaction, settings):
x.name += '__temp'
action = dataactions[-1]
action.name = lastaction.name + '__temp'

# Relink armature (Rigify)
bpy.ops.object.select_all(action='DESELECT')
workingobj.select_set(True)

bpy.ops.object.mode_set(mode='EDIT')

ebones = workingobj.data.edit_bones
deformebones = [b for b in ebones if b.use_deform]
nondeformebones = [b for b in ebones if not b.use_deform]

def FindFirstDeform(b, usedbones=[]):
if not b.parent:
return None

usedbones.append(b)
basename = b.name[b.name.find("-")+1:]

nextdeforms = [x for x in deformebones
if (x not in usedbones and x.name[-len(basename):] == basename)]
if nextdeforms:
return nextdeforms[0]
return FindFirstDeform(b.parent)

for b in deformebones:
if not b.parent:
continue

if b.parent not in deformebones:
b.parent = FindFirstDeform(b.parent, [b])

bpy.ops.armature.layers_show_all()
bpy.ops.armature.reveal()
for eb in workingobj.data.edit_bones:
eb.select = not eb.use_deform
bpy.ops.armature.delete()

bpy.ops.object.mode_set(mode='OBJECT')

bones = {b.name: b for b in workingobj.data.bones}

# Make dict of selected bones
if selected_bones_only:
bones = {b.name: b for b in bones.values() if b.select}

boneparents = {b: b.parent for b in bones.values()}
pbones = [workingobj.pose.bones[b.name] for b in bones.values()]

# Make dict of deform bones
if deform_only:
pbones = {x.name: x for x in pbones if bones[x.name].use_deform}
pboneparents = {pbones[b.name]: pbones[boneparents[b].name] if boneparents[b] else None for b in bones.values() if b.use_deform}
# Make dict of all bones
else:
pbones = {x.name: x for x in pbones}
pboneparents = {pbones[b.name]: pbones[boneparents[b].name] if boneparents[b] else None for b in bones.values()}

bonecurves = {pbones[x]: [ [(),(),()], [(),(),(),()], [(),(),()] ] for x in pbones}
pboneslist = [x for x in pbones.values()]
pbonesnames = [x.name for x in pboneslist]
bonenames = [x for x in pbones.keys()]

# Action Details
workingobj.animation_data.action = action

fcurves = action.fcurves
Expand Down

0 comments on commit f988d64

Please sign in to comment.