|
本帖最后由 hazukiaoi 于 2017-9-10 12:42 编辑
因为动画实现上的需求,所以模仿原生的Rigify插件里面的IK和FK切换的功能实现了一个类似功能的脚本。但是出现问题,一旦进行了IK/FK切换之后,再按Ctrl+Z进行Undo操作,脚本就会报错或者直接导致闪退。
因为新手上路,不是很懂Blender内部的一些机制,所以不明白为什么会出现这样的情况,特来求助。
在此贴上代码和出错步骤以及源文件:
- import bpy
- import mathutils
- #创建列表,用于判断选中的对象是否需要在3D_VIEW面板显示按钮
- 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'\
- ]
- #<span id="pos_placeholder" style="width: 0px; height: 0px; visibility: hidden; margin: 0px; padding: 0px;"></span>IK骨骼与选择对象的字典,根据选择中的骨骼找到对应的IK骨骼,极向骨骼,IK段数等等
- #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 -> 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 -> 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()
复制代码 错误重现:
1、启动脚本
2、移动脚部IK目标
移动脚部IK
3、执行FK->IK脚本操作
执行按钮操作
4、变换已经被应用,已经切换成FK
变换被应用
5、此时按下Ctrl+Z进行Undo,然后代码失效了,此时选中的对象和最开始无异。
失效
6、清除位移操作,代码报红
红
7、完成错误重现。
在此附上出错文件以及我模仿的源文件和原帖地址:
ErrorFile.zip
(312.17 KB, 下载次数: 955)
|
|