I Want to write a script to set pose IK <=> FK, But error

Hi,
I write a script to set pose IK <=> FK,the code is work.
But when i used code and undo, is error.

my code source from:
http://dskjal.com/blender/ik-fk-snap.html

And error reproduce:
1.Run the code
2.Move foot IK target


3.Click button


4.undo and error

And code:


import bpy
import mathutils


#When Selected bone in list,show VIEW_3D panel
showButtonBoneList = [\
'C.IK.L',\
'C.IK.R',\
'C.handIK.L',\
'C.handIK.R',\
'C.shinC.L',\
'C.shinC.R',\
'C.forearm.L',\
'C.forearm.R',\
'C.Legtag.L',\
'C.Legtag.R',\
'C.upper_armTag.L',\
'C.upper_armTag.R',\
'C.head',\
'C.head.Tag'\
]


#ikBones is a dict for selected bones IK relation
#Key = selected bone name
#Value = 
#[
#name display on panel,     0
#IK Bone name,              1
#constraints name           2
#IK count,                  3
#Pole bone                  4
#Pole bone connecter bone   5
#IK target                  6
#]
ikBones = {\
'C.shinC.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
'C.IK.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
'C.Legtag.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
\
'C.shinC.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
'C.IK.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
'C.Legtag.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
\
'C.forearm.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
'C.handIK.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
'C.upper_armTag.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
\
'C.forearm.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
'C.handIK.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
'C.upper_armTag.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
\
'C.head':['Head LookAt','C.head','LookAt',1,'C.head.Tag','C.head.TagC',''],\
'C.head.Tag':['Head LookAt','C.head','LookAt',1,'C.head.Tag','C.head.TagC',''],\
}


amt = bpy.data.objects["ActorMetarig"]


#IK/FKFunction
'''
def set_ik(data_path):
    set_ik_influence(data_path, 1.0)
    
def set_fk(data_path):
    set_ik_influence(data_path, 0.0)
'''


def set_translation(matrix, loc):
    trs = matrix.decompose()
    rot = trs[1].to_matrix().to_4x4()
    scale = mathutils.Matrix.Scale(1, 4, trs[2])
    return mathutils.Matrix.Translation(loc) * (rot * scale)


#UI
class UIPanel(bpy.types.Panel):
    bl_label = "Actor Rig IK/FK Snap"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    #Check Selected and show bottom
    @classmethod
    def poll(cls, context):
        selectedBoneCount = -1
        try:
            selectedBoneCount = len(bpy.context.selected_pose_bones)
        except:
            selectedBoneCount = -1
        if selectedBoneCount == 1:
            return bpy.context.selected_pose_bones[0].name in showButtonBoneList
    
    def draw(self, context):
        seletced = ikBones[bpy.context.selected_pose_bones[0].name]       
        l = self.layout
        l.label(seletced[0])
        l.prop(amt.pose.bones[seletced[1]].constraints[seletced[2]],'influence',slider=True)
        l.operator('my.iktofk')
        l.operator('my.fktoik')




class IKtoFKButton(bpy.types.Operator):
    bl_idname = "my.iktofk"
    bl_label = "IK -&gt; FK"
  
    def execute(self, context):
        #Set Selected


        selected = ikBones[bpy.context.selected_pose_bones[0].name]
        ik_bone = amt.pose.bones[selected[1]]
        if(selected[1] != 'C.head'):   
            ik_target = amt.pose.bones[selected[6]]      
        ik_pole = amt.pose.bones[selected[4]]
        ik_connecter = amt.pose.bones[selected[5]]
        influence_data_path = ik_bone.constraints[selected[2]].influence
        
        #copy fk matrix
        #set_fk(influence_data_path)
        ik_bone.constraints[selected[2]].influence = 0
        
        #pose update
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
        
        if(selected[1] != 'C.head'):
            #set ik target
            ik_target.matrix = set_translation(ik_target.matrix, ik_bone.tail)
        
        #set pole target
        ik_pole.matrix = set_translation(ik_pole.matrix, ik_connecter.tail)
        
        return {'FINISHED'}
    
class FKtoIKButton(bpy.types.Operator):
    bl_idname = "my.fktoik"
    bl_label = "FK -&gt; IK"
  
    def execute(self, context):   
        #Set Selected
        selected = ikBones[bpy.context.selected_pose_bones[0].name]
        ik_bone = amt.pose.bones[selected[1]]
        influence_data_path = ik_bone.constraints[selected[2]].influence
        num_bones = selected[3]


        # copy ik matrix
        ik_bone.constraints[selected[2]].influence = 1
        
        #pose update
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
        
        ik_bone_matrixes = []
        it = ik_bone
        for i in range(num_bones):
            ik_bone_matrixes.append(it.matrix)
            it = ik_bone.parent
    
        # set ik matrix to fk bone
        ik_bone.constraints[selected[2]].influence = 0
        it = ik_bone
        for i in range(num_bones):
            it.matrix = ik_bone_matrixes[i]
            it = it.parent
        
        return {'FINISHED'}


def register():
    bpy.utils.register_module(__name__)
    
def unregister():
    bpy.utils.unregister_module(__name__)
    
if __name__ == "__main__":
    register()
#bpy.context.active_bone.matrix.to_quaternion()

and file:
ErrorFile.zip (312 KB)

The undo crash bug of the site is fixed. Because of global Blender objects like ‘amt = bpy.data.objects[“ActorMetarig”]’, the crash is caused. Undo disables global Blender objects. You avoid this problem like this.

armature_name = ‘ActorMetarig’

#paste this code where use amt except for global
amt = bpy.data.objects[armature_name]