2025-12-01
This commit is contained in:
@@ -1573,7 +1573,8 @@ class PasteMatrix(bpy.types.Operator):
|
||||
if bone.id_data.name in objs_matrix:
|
||||
if bone.name in objs_matrix[bone.id_data.name]:
|
||||
matrix_copied = objs_matrix[bone.id_data.name][bone.name]
|
||||
|
||||
|
||||
matrix_copied = obj.matrix_world.inverted() @ matrix_copied
|
||||
#Store the matrices for each bone that will use it
|
||||
matrix_copied = reverse_childof_constraint(bone, matrix_copied, constrained)
|
||||
|
||||
@@ -1662,11 +1663,11 @@ class CopyRelativeMatrix(bpy.types.Operator):
|
||||
#create a dictionary for all the realtive distance of the bones and objects
|
||||
objs_matrix_dist = dict()
|
||||
|
||||
#get the source bofne or object
|
||||
#get the source bone or object
|
||||
if context.active_pose_bone:
|
||||
source_active = context.active_pose_bone
|
||||
source_rig_name = source_active.id_data.name
|
||||
source_matrix = source_active.matrix
|
||||
source_matrix = source_active.matrix
|
||||
else:
|
||||
source_active = context.active_object
|
||||
source_matrix = source_active.matrix_world
|
||||
@@ -1681,8 +1682,14 @@ class CopyRelativeMatrix(bpy.types.Operator):
|
||||
continue
|
||||
if bone_relative == source_active:
|
||||
continue
|
||||
matrix_dist = source_matrix.inverted() @ obj.matrix_world @ bone_relative.matrix# @ obj.matrix_world
|
||||
|
||||
#Adding the offset from the armature transform both for the active and relative
|
||||
rig_offset = obj.matrix_world
|
||||
if source_active.id_data.type == 'ARMATURE':
|
||||
rig_offset = source_active.id_data.matrix_world.inverted() @ rig_offset
|
||||
|
||||
matrix_dist = source_matrix.inverted() @ rig_offset @ bone_relative.matrix
|
||||
|
||||
#store each bone matrix distance in a dictionary
|
||||
if obj.name in objs_matrix_dist:
|
||||
objs_matrix_dist[obj.name].update({bone_relative.name : matrix_dist})
|
||||
@@ -1735,41 +1742,59 @@ def reverse_childof_constraint(source, matrix_source, constrained = set()):
|
||||
offsets_lerp = []
|
||||
offset_inv = Matrix.Identity(4)
|
||||
offset_inv_lerp = Matrix.Identity(4)
|
||||
|
||||
#If the source is a bone then get the Armature matrix to add to the calculation
|
||||
if type(source) == bpy.types.PoseBone:
|
||||
obj_offset = obj.matrix_world
|
||||
else:
|
||||
obj_offset = Matrix.Identity(4)
|
||||
|
||||
#iterate and store all the inverted offsets of all the child constraints
|
||||
for con in source.constraints:
|
||||
if con.mute or not con.influence:
|
||||
continue
|
||||
if hasattr(con, 'target') and con.target is None:
|
||||
continue
|
||||
if con.type != 'CHILD_OF':
|
||||
constrained.add(source)
|
||||
continue
|
||||
parent_matrix = con.target.matrix_world
|
||||
if con.subtarget != '':
|
||||
if con.subtarget == '':
|
||||
parent_matrix = obj_offset.inverted() @ con.target.matrix_world
|
||||
#remove obj.matrix_world when connected to an object
|
||||
offset = parent_matrix @ con.inverse_matrix - Matrix.Identity(4)
|
||||
#offset for the scale with influence already included
|
||||
offset_lerp = Matrix.Identity(4).lerp(parent_matrix @ con.inverse_matrix, con.influence)
|
||||
else:
|
||||
|
||||
parent_matrix = con.target.pose.bones[con.subtarget].matrix
|
||||
offsets.append(Matrix.Identity(4) + con.influence * (parent_matrix @ con.inverse_matrix - Matrix.Identity(4)))
|
||||
offsets_lerp.append(Matrix.Identity(4).lerp(parent_matrix @ con.inverse_matrix, con.influence))
|
||||
|
||||
if con.target != obj:
|
||||
parent_matrix = obj_offset.inverted() @ con.target.matrix_world @ parent_matrix
|
||||
|
||||
#Include armature object matrix
|
||||
offset = parent_matrix @ con.inverse_matrix - Matrix.Identity(4)
|
||||
offset_lerp = Matrix.Identity(4).lerp(parent_matrix @ con.inverse_matrix, con.influence)
|
||||
|
||||
#Adding the influence to the offset
|
||||
offset = Matrix.Identity(4) + con.influence * offset
|
||||
|
||||
offset_inv = offset_inv @ offset.inverted()
|
||||
offset_inv_lerp = offset_inv_lerp @ offset_lerp.inverted()
|
||||
|
||||
offsets.append(offset)
|
||||
|
||||
if not offsets:
|
||||
return matrix_source #@ obj.matrix_world.inverted()
|
||||
return matrix_source
|
||||
|
||||
#Multiply all the child constraint inverted offsets
|
||||
for offset, offsets_lerp in zip(offsets, offsets_lerp):
|
||||
#offset_inv = offset_inv @ parent_offset_inv
|
||||
offset_inv = offset_inv @ offset.inverted()
|
||||
offset_inv_lerp = offset_inv_lerp @ offsets_lerp.inverted()
|
||||
# add object space if it's a bone
|
||||
if source != obj:
|
||||
offset_inv = offset_inv #@ obj.matrix_world.inverted()
|
||||
|
||||
#final Matrix values
|
||||
matrix_basis = offset_inv @ matrix_source
|
||||
matrix_lerp = offset_inv_lerp @ matrix_source
|
||||
matrix_lerp = offset_inv_lerp @ matrix_source
|
||||
loc, rot, scale = matrix_basis.decompose()
|
||||
loc_lerp, rot_lerp, scale_lerp = matrix_lerp.decompose()
|
||||
|
||||
matrix_basis = Matrix.LocRotScale(loc, rot_lerp, scale_lerp)
|
||||
|
||||
return matrix_basis
|
||||
return matrix_basis
|
||||
|
||||
def reorder_bones_matrices(bones_matrices, constrained):
|
||||
#Reordering the bones, so that we apply first the matrix offset to the constrained bones
|
||||
@@ -1837,9 +1862,11 @@ class PasteRelativeMatrix(bpy.types.Operator):
|
||||
if 'source_rig_name' in globals():
|
||||
if source_rig_name in bpy.data.objects:
|
||||
source_rig = bpy.data.objects[source_rig_name]
|
||||
source_obj = source_rig
|
||||
source_bone = source_rig.pose.bones[source_active_name]
|
||||
#Get the current matrix of the source bone
|
||||
matrix_source = source_bone.matrix
|
||||
|
||||
elif 'source_active_name' in globals():
|
||||
if source_active_name in bpy.data.objects:
|
||||
source_obj = bpy.data.objects[source_active_name]
|
||||
@@ -1854,10 +1881,14 @@ class PasteRelativeMatrix(bpy.types.Operator):
|
||||
#if the source object was in object mode during copy and now it's pose mode then quit
|
||||
frame_range, inbetweens = get_frame_range(context, obj)
|
||||
fcu_inbetweens = dict()
|
||||
|
||||
|
||||
for frame in sorted(frame_range+inbetweens):
|
||||
scene.frame_set(int(frame))
|
||||
if obj.mode == 'POSE':
|
||||
for bone in context.selected_pose_bones:
|
||||
if bone.id_data != obj:
|
||||
continue
|
||||
#check that the selected bone is not the source bone
|
||||
if bone == source_bone:
|
||||
continue
|
||||
@@ -1868,14 +1899,18 @@ class PasteRelativeMatrix(bpy.types.Operator):
|
||||
if bone.name in objs_matrix_dist[bone.id_data.name]:
|
||||
bone_matrix_dist = objs_matrix_dist[bone.id_data.name][bone.name]
|
||||
|
||||
matrix_new = matrix_source @ bone_matrix_dist
|
||||
#Adding the offset from the armature transform both for the active and relative
|
||||
#If it's the same Armature it will cancel each other
|
||||
rig_offset = obj.matrix_world.inverted()
|
||||
if source_rig:
|
||||
rig_offset = rig_offset @ source_rig.matrix_world
|
||||
matrix_new = rig_offset @ matrix_source @ bone_matrix_dist
|
||||
|
||||
#Store the matrices for each bone that will use it
|
||||
matrix_new = reverse_childof_constraint(bone, matrix_new, constrained)
|
||||
|
||||
bones_matrices.update({bone : matrix_new})
|
||||
|
||||
matrix_copied = reverse_childof_constraint(bone, matrix_new, constrained)
|
||||
# if bone not in constrained:
|
||||
# matrix_copied = filter_matrix_properties(context, bone.matrix, matrix_copied)
|
||||
|
||||
|
||||
#Reordering the bones, so that we apply first the matrix offset to the constrained bones
|
||||
bones_matrices = reorder_bones_matrices(bones_matrices, constrained)
|
||||
|
||||
@@ -1896,16 +1931,16 @@ class PasteRelativeMatrix(bpy.types.Operator):
|
||||
else:
|
||||
obj_matrix_dist = matrix_dist
|
||||
|
||||
matrix_new = matrix_source @ obj_matrix_dist
|
||||
matrix_copied = reverse_childof_constraint(target, matrix_new)
|
||||
matrix_new = matrix_source @ obj_matrix_dist
|
||||
matrix_new = reverse_childof_constraint(target, matrix_new)
|
||||
if target not in constrained:
|
||||
matrix_copied = filter_matrix_properties(context, target.matrix_world, matrix_copied)
|
||||
target.matrix_world = matrix_copied
|
||||
matrix_new = filter_matrix_properties(context, target.matrix_world, matrix_new)
|
||||
target.matrix_world = matrix_new
|
||||
|
||||
if target in constrained:
|
||||
context.view_layer.update()
|
||||
matrix_copied = reverse_constraint_offset(target.matrix_world, matrix_copied)
|
||||
target.matrix_world = filter_matrix_properties(context, target.matrix_world, matrix_copied)
|
||||
matrix_new = reverse_constraint_offset(target.matrix_world, matrix_new)
|
||||
target.matrix_world = filter_matrix_properties(context, target.matrix_world, matrix_new)
|
||||
|
||||
paste_keyframes_get_inbetweens(scene, target, inbetweens, frame, frame_range, fcu_inbetweens)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user