diff --git a/DmrBlender_VBM.zip b/DmrBlender_VBM.zip index be2380e..0301d91 100644 Binary files a/DmrBlender_VBM.zip and b/DmrBlender_VBM.zip differ diff --git a/DmrBlender_VBM/vbm_func.py b/DmrBlender_VBM/vbm_func.py index 56ca59f..fbea527 100644 --- a/DmrBlender_VBM/vbm_func.py +++ b/DmrBlender_VBM/vbm_func.py @@ -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 @@ -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) diff --git a/DmrBlender_VBM/vbm_op.py b/DmrBlender_VBM/vbm_op.py index c3dcd02..6ec25de 100644 --- a/DmrBlender_VBM/vbm_op.py +++ b/DmrBlender_VBM/vbm_op.py @@ -941,7 +941,48 @@ 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 @@ -949,12 +990,14 @@ def ComposeBoneData(armature): 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) @@ -966,7 +1009,6 @@ def ComposeBoneData(armature): out_bone = ComposeBoneData(armature) # Compose Vertex Buffer Data ================================================ - def GetVBGroupSorted(objlist): vbgroups = {} vbkeys = [] diff --git a/DmrBlender_VBM/vbm_op_action.py b/DmrBlender_VBM/vbm_op_action.py index 4eaa9cd..7f0c921 100644 --- a/DmrBlender_VBM/vbm_op_action.py +++ b/DmrBlender_VBM/vbm_op_action.py @@ -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 ---------------------------------------------------------------- @@ -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