BlenderCN论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 814|回复: 3

[求助]半抄半写的实现了一个IK/FK切换工具,但是会闪退

[复制链接]
发表于 2017-9-10 12:42:39 | 显示全部楼层 |阅读模式
本帖最后由 hazukiaoi 于 2017-9-10 12:42 编辑

因为动画实现上的需求,所以模仿原生的Rigify插件里面的IK和FK切换的功能实现了一个类似功能的脚本。但是出现问题,一旦进行了IK/FK切换之后,再按Ctrl+Z进行Undo操作,脚本就会报错或者直接导致闪退。
因为新手上路,不是很懂Blender内部的一些机制,所以不明白为什么会出现这样的情况,特来求助。
在此贴上代码和出错步骤以及源文件:
  1. import bpy
  2. import mathutils

  3. #创建列表,用于判断选中的对象是否需要在3D_VIEW面板显示按钮
  4. showButtonBoneList = [\
  5. 'C.IK.L',\
  6. 'C.IK.R',\
  7. 'C.handIK.L',\
  8. 'C.handIK.R',\
  9. 'C.shinC.L',\
  10. 'C.shinC.R',\
  11. 'C.forearm.L',\
  12. 'C.forearm.R',\
  13. 'C.Legtag.L',\
  14. 'C.Legtag.R',\
  15. 'C.upper_armTag.L',\
  16. 'C.upper_armTag.R',\
  17. 'C.head',\
  18. 'C.head.Tag'\
  19. ]

  20. #<span id="pos_placeholder" style="width: 0px; height: 0px; visibility: hidden; margin: 0px; padding: 0px;"></span>IK骨骼与选择对象的字典,根据选择中的骨骼找到对应的IK骨骼,极向骨骼,IK段数等等
  21. #Key = selected bone name
  22. #Value =
  23. #[
  24. #name display on panel,     0
  25. #IK Bone name,              1
  26. #constraints name           2
  27. #IK count,                  3
  28. #Pole bone                  4
  29. #Pole bone connecter bone   5
  30. #IK target                  6
  31. #]
  32. ikBones = {\
  33. 'C.shinC.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
  34. 'C.IK.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
  35. 'C.Legtag.L':['L Foot IK:','C.shinC.L','IK',2,'C.Legtag.L','C.LegtagC.L','C.IK.L'],\
  36. \
  37. 'C.shinC.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
  38. 'C.IK.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
  39. 'C.Legtag.R':['R Foot IK:','C.shinC.R','IK',2,'C.Legtag.R','C.LegtagC.R','C.IK.R'],\
  40. \
  41. 'C.forearm.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
  42. 'C.handIK.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
  43. 'C.upper_armTag.L':['L Hand IK:','C.forearm.L','IK',2,'C.upper_armTag.L','C.upperarmTagC.L','C.handIK.L'],\
  44. \
  45. 'C.forearm.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
  46. 'C.handIK.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
  47. 'C.upper_armTag.R':['R Hand IK:','C.forearm.R','IK',2,'C.upper_armTag.R','C.upperarmTagC.R','C.handIK.R'],\
  48. \
  49. 'C.head':['Head LookAt','C.head','LookAt',1,'C.head.Tag','C.head.TagC',''],\
  50. 'C.head.Tag':['Head LookAt','C.head','LookAt',1,'C.head.Tag','C.head.TagC',''],\
  51. }

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

  53. #IK/FKFunction
  54. '''
  55. def set_ik(data_path):
  56.     set_ik_influence(data_path, 1.0)
  57.    
  58. def set_fk(data_path):
  59.     set_ik_influence(data_path, 0.0)
  60. '''

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

  66. #UI
  67. class UIPanel(bpy.types.Panel):
  68.     bl_label = "Actor Rig IK/FK Snap"
  69.     bl_space_type = "VIEW_3D"
  70.     bl_region_type = "UI"
  71.    
  72.     #Check Selected and show bottom
  73.     @classmethod
  74.     def poll(cls, context):
  75.         selectedBoneCount = -1
  76.         try:
  77.             selectedBoneCount = len(bpy.context.selected_pose_bones)
  78.         except:
  79.             selectedBoneCount = -1
  80.         if selectedBoneCount == 1:
  81.             return bpy.context.selected_pose_bones[0].name in showButtonBoneList
  82.    
  83.     def draw(self, context):
  84.         seletced = ikBones[bpy.context.selected_pose_bones[0].name]      
  85.         l = self.layout
  86.         l.label(seletced[0])
  87.         l.prop(amt.pose.bones[seletced[1]].constraints[seletced[2]],'influence',slider=True)
  88.         l.operator('my.iktofk')
  89.         l.operator('my.fktoik')


  90. class IKtoFKButton(bpy.types.Operator):
  91.     bl_idname = "my.iktofk"
  92.     bl_label = "IK -> FK"
  93.   
  94.     def execute(self, context):
  95.         #Set Selected

  96.         selected = ikBones[bpy.context.selected_pose_bones[0].name]
  97.         ik_bone = amt.pose.bones[selected[1]]
  98.         if(selected[1] != 'C.head'):   
  99.             ik_target = amt.pose.bones[selected[6]]      
  100.         ik_pole = amt.pose.bones[selected[4]]
  101.         ik_connecter = amt.pose.bones[selected[5]]
  102.         influence_data_path = ik_bone.constraints[selected[2]].influence
  103.         
  104.         #copy fk matrix
  105.         #set_fk(influence_data_path)
  106.         ik_bone.constraints[selected[2]].influence = 0
  107.         
  108.         #pose update
  109.         bpy.ops.object.mode_set(mode='OBJECT')
  110.         bpy.ops.object.mode_set(mode='POSE')
  111.         
  112.         if(selected[1] != 'C.head'):
  113.             #set ik target
  114.             ik_target.matrix = set_translation(ik_target.matrix, ik_bone.tail)
  115.         
  116.         #set pole target
  117.         ik_pole.matrix = set_translation(ik_pole.matrix, ik_connecter.tail)
  118.         
  119.         return {'FINISHED'}
  120.    
  121. class FKtoIKButton(bpy.types.Operator):
  122.     bl_idname = "my.fktoik"
  123.     bl_label = "FK -> IK"
  124.   
  125.     def execute(self, context):   
  126.         #Set Selected
  127.         selected = ikBones[bpy.context.selected_pose_bones[0].name]
  128.         ik_bone = amt.pose.bones[selected[1]]
  129.         influence_data_path = ik_bone.constraints[selected[2]].influence
  130.         num_bones = selected[3]

  131.         # copy ik matrix
  132.         ik_bone.constraints[selected[2]].influence = 1
  133.         
  134.         #pose update
  135.         bpy.ops.object.mode_set(mode='OBJECT')
  136.         bpy.ops.object.mode_set(mode='POSE')
  137.         
  138.         ik_bone_matrixes = []
  139.         it = ik_bone
  140.         for i in range(num_bones):
  141.             ik_bone_matrixes.append(it.matrix)
  142.             it = ik_bone.parent
  143.    
  144.         # set ik matrix to fk bone
  145.         ik_bone.constraints[selected[2]].influence = 0
  146.         it = ik_bone
  147.         for i in range(num_bones):
  148.             it.matrix = ik_bone_matrixes[i]
  149.             it = it.parent
  150.         
  151.         return {'FINISHED'}

  152. def register():
  153.     bpy.utils.register_module(__name__)
  154.    
  155. def unregister():
  156.     bpy.utils.unregister_module(__name__)
  157.    
  158. if __name__ == "__main__":
  159.     register()
  160. #bpy.context.active_bone.matrix.to_quaternion()
复制代码
错误重现:
1、启动脚本
2、移动脚部IK目标

移动脚部IK

移动脚部IK

3、执行FK->IK脚本操作

执行按钮操作

执行按钮操作

4、变换已经被应用,已经切换成FK

变换被应用

变换被应用

5、此时按下Ctrl+Z进行Undo,然后代码失效了,此时选中的对象和最开始无异。

失效

失效

6、清除位移操作,代码报红

红


7、完成错误重现。

在此附上出错文件以及我模仿的源文件和原帖地址:
ErrorFile.zip (312.17 KB, 下载次数: 280)
发表于 2017-9-10 12:50:15 | 显示全部楼层
牛B。。。。程序向。。。。。。只能默默看着了
回复 支持 反对

使用道具 举报

发表于 2017-9-21 23:37:07 | 显示全部楼层
没细看,不知道是不是 draw中物体is None造成。

点评

你好,我有点疑问想咨询一下。现在知道了bpy_interface.c是最终地点,我想找到bpy_interface.c与blender.exe的接口在哪儿,那现在根据这个回推,bpy_interface.c与wm_init_exit.c的关系,最后如何去找到bpy_interfac  详情 回复 发表于 2018-10-16 09:25
回复 支持 反对

使用道具 举报

发表于 2018-10-16 09:25:11 | 显示全部楼层
nirenyang 发表于 2017-9-21 23:37
没细看,不知道是不是 draw中物体is None造成。

你好,我有点疑问想咨询一下。现在知道了bpy_interface.c是最终地点,我想找到bpy_interface.c与blender.exe的接口在哪儿,那现在根据这个回推,bpy_interface.c与wm_init_exit.c的关系,最后如何去找到bpy_interface.c与blender.exe的关系接口在哪儿呢??
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

Blender最新中文教学视频|Blender头条|小黑屋|手机版|Archiver|Blender中国 ( 蜀ICP备17002929号 )360网站安全检测平台

GMT+8, 2018-11-19 07:41 , Processed in 0.017165 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表