1 # SPDX-License-Identifier: GPL-2.0-or-later
4 from bpy
.props
import (
11 from mathutils
import Color
13 from .utils
.errors
import MetarigError
14 from .utils
.rig
import write_metarig
15 from .utils
.widgets
import write_widget
16 from .utils
.naming
import unique_name
17 from .utils
.rig
import upgradeMetarigTypes
, outdated_types
19 from .rigs
.utils
import get_limb_generated_names
21 from .utils
.animation
import get_keyed_frames_in_range
, bones_in_frame
, overwrite_prop_animation
22 from .utils
.animation
import RIGIFY_OT_get_frame_range
24 from .utils
.animation
import register
as animation_register
25 from .utils
.animation
import unregister
as animation_unregister
27 from . import base_rig
28 from . import rig_lists
29 from . import generate
30 from . import rot_mode
31 from . import feature_set_list
34 def build_type_list(context
, rigify_types
):
37 for r
in sorted(rig_lists
.rigs
):
38 if (context
.object.data
.active_feature_set
in ('all', rig_lists
.rigs
[r
]['feature_set'])
39 or len(feature_set_list
.get_enabled_modules_names()) == 0
41 a
= rigify_types
.add()
45 class DATA_PT_rigify(bpy
.types
.Panel
):
47 bl_space_type
= 'PROPERTIES'
48 bl_region_type
= 'WINDOW'
52 def poll(cls
, context
):
54 if not context
.object:
56 return obj
.type == 'ARMATURE' \
57 and obj
.data
.get("rig_id") is None
59 def draw(self
, context
):
64 WARNING
= "Warning: Some features may change after generation"
66 show_update_metarig
= False
67 show_not_updatable
= False
68 show_upgrade_face
= False
70 check_props
= ['IK_follow', 'root/parent', 'FK_limb_follow', 'IK_Stretch']
72 for posebone
in obj
.pose
.bones
:
75 # If we are in edit mode and the bone was just created,
76 # a pose bone won't exist yet.
78 if bone
.layers
[30] and (list(set(posebone
.keys()) & set(check_props
))):
82 for b
in obj
.pose
.bones
:
83 if b
.rigify_type
in outdated_types
.keys():
85 old_rig
= b
.rigify_type
86 if outdated_types
[b
.rigify_type
]:
87 show_update_metarig
= True
89 show_update_metarig
= False
90 show_not_updatable
= True
92 elif b
.rigify_type
== 'faces.super_face':
93 show_upgrade_face
= True
96 layout
.label(text
=WARNING
, icon
='ERROR')
98 enable_generate
= not (show_not_updatable
or show_update_metarig
)
100 if show_not_updatable
:
101 layout
.label(text
="WARNING: This metarig contains deprecated rigify rig-types and cannot be upgraded automatically.", icon
='ERROR')
102 layout
.label(text
="("+old_rig
+" on bone "+old_bone
+")")
103 elif show_update_metarig
:
104 layout
.label(text
="This metarig contains old rig-types that can be automatically upgraded to benefit of rigify's new features.", icon
='ERROR')
105 layout
.label(text
="("+old_rig
+" on bone "+old_bone
+")")
106 layout
.operator("pose.rigify_upgrade_types", text
="Upgrade Metarig")
107 elif show_upgrade_face
:
108 layout
.label(text
="This metarig uses the old face rig.", icon
='INFO')
109 layout
.operator("pose.rigify_upgrade_face")
114 col
= layout
.column(align
=True)
115 col
.active
= (not 'rig_id' in C
.object.data
)
119 text
= "Re-Generate Rig" if obj
.data
.rigify_target_rig
else "Generate Rig"
120 row
.operator("pose.rigify_generate", text
=text
, icon
='POSE_HLT')
121 row
.enabled
= enable_generate
124 class DATA_PT_rigify_advanced(bpy
.types
.Panel
):
125 bl_space_type
= 'PROPERTIES'
126 bl_region_type
= 'WINDOW'
128 bl_label
= "Advanced"
129 bl_parent_id
= 'DATA_PT_rigify'
130 bl_options
= {'DEFAULT_CLOSED'}
132 def draw(self
, context
):
134 layout
.use_property_split
= True
135 layout
.use_property_decorate
= False
137 armature_id_store
= context
.object.data
139 col
= layout
.column()
140 col
.row().prop(armature_id_store
, "rigify_target_rig", text
="Target Rig")
141 col
.row().prop(armature_id_store
, "rigify_rig_ui", text
="Rig UI Script")
143 col
.row().prop(armature_id_store
, "rigify_widgets_collection")
144 col
.row().prop(armature_id_store
, "rigify_force_widget_update")
145 col
.row().prop(armature_id_store
, "rigify_mirror_widgets")
147 col
.row().prop(armature_id_store
, "rigify_finalize_script", text
="Run Script")
150 class DATA_PT_rigify_samples(bpy
.types
.Panel
):
152 bl_space_type
= 'PROPERTIES'
153 bl_region_type
= 'WINDOW'
155 bl_parent_id
= "DATA_PT_rigify"
156 bl_options
= {'DEFAULT_CLOSED'}
159 def poll(cls
, context
):
163 return obj
.type == 'ARMATURE' \
164 and obj
.data
.get("rig_id") is None \
165 and obj
.mode
== 'EDIT'
167 def draw(self
, context
):
169 layout
.use_property_split
= True
170 layout
.use_property_decorate
= False
172 id_store
= context
.window_manager
175 build_type_list(context
, id_store
.rigify_types
)
177 if id_store
.rigify_active_type
> len(id_store
.rigify_types
):
178 id_store
.rigify_active_type
= 0
181 if len(feature_set_list
.get_enabled_modules_names()) > 0:
183 row
.prop(context
.object.data
, "active_feature_set")
185 row
.template_list("UI_UL_list", "rigify_types", id_store
, "rigify_types", id_store
, 'rigify_active_type')
187 props
= layout
.operator("armature.metarig_sample_add", text
="Add sample")
188 props
.metarig_type
= id_store
.rigify_types
[id_store
.rigify_active_type
].name
191 class DATA_PT_rigify_layer_names(bpy
.types
.Panel
):
192 bl_label
= "Layer Names"
193 bl_space_type
= 'PROPERTIES'
194 bl_region_type
= 'WINDOW'
196 bl_options
= {'DEFAULT_CLOSED'}
197 bl_parent_id
= "DATA_PT_rigify"
200 def poll(cls
, context
):
201 if not context
.object:
203 return context
.object.type == 'ARMATURE' and context
.active_object
.data
.get("rig_id") is None
205 def draw(self
, context
):
210 # Ensure that the layers exist
212 for i
in range(1 + len(arm
.rigify_layers
), 29):
213 arm
.rigify_layers
.add()
215 # Can't add while drawing, just use button
216 if len(arm
.rigify_layers
) < 29:
217 layout
.operator("pose.rigify_layer_init")
221 main_row
= layout
.row(align
=True).split(factor
=0.05)
222 col1
= main_row
.column()
223 col2
= main_row
.column()
226 if i
== 16 or i
== 29:
228 col1
.label(text
=str(i
))
230 for i
, rigify_layer
in enumerate(arm
.rigify_layers
):
231 # note: rigify_layer == arm.rigify_layers[i]
235 col
.label(text
="Top Row:")
237 col
.label(text
="Bottom Row:")
241 row
= col
.row(align
=True)
242 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
243 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
244 #row.prop(arm, "layers", index=i, text="Layer %d" % (i + 1), toggle=True, icon=icon)
245 row
.prop(rigify_layer
, "name", text
="")
246 row
.prop(rigify_layer
, "row", text
="UI Row")
247 icon
= 'RADIOBUT_ON' if rigify_layer
.selset
else 'RADIOBUT_OFF'
248 row
.prop(rigify_layer
, "selset", text
="", toggle
=True, icon
=icon
)
249 row
.prop(rigify_layer
, "group", text
="Bone Group")
251 row
= col
.row(align
=True)
253 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
254 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
255 # row.prop(arm, "layers", index=i, text="Layer %d" % (i + 1), toggle=True, icon=icon)
256 row1
= row
.split(align
=True).row(align
=True)
257 row1
.prop(rigify_layer
, "name", text
="")
258 row1
.prop(rigify_layer
, "row", text
="UI Row")
260 icon
= 'RADIOBUT_ON' if rigify_layer
.selset
else 'RADIOBUT_OFF'
261 row
.prop(rigify_layer
, "selset", text
="", toggle
=True, icon
=icon
)
262 row
.prop(rigify_layer
, "group", text
="Bone Group")
263 if rigify_layer
.group
== 0:
264 row
.label(text
='None')
266 row
.label(text
=arm
.rigify_colors
[rigify_layer
.group
-1].name
)
269 col
.label(text
="Reserved:")
270 # reserved_names = {28: 'Root', 29: 'DEF', 30: 'MCH', 31: 'ORG'}
271 reserved_names
= {29: 'DEF', 30: 'MCH', 31: 'ORG'}
272 # for i in range(28, 32):
273 for i
in range(29, 32):
274 row
= col
.row(align
=True)
275 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
276 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
277 row
.label(text
=reserved_names
[i
])
280 class DATA_OT_rigify_add_bone_groups(bpy
.types
.Operator
):
281 bl_idname
= "armature.rigify_add_bone_groups"
282 bl_label
= "Rigify Add Standard Bone Groups"
285 def poll(cls
, context
):
286 return context
.object and context
.object.type == 'ARMATURE'
288 def execute(self
, context
):
291 if not hasattr(armature
, 'rigify_colors'):
294 groups
= ['Root', 'IK', 'Special', 'Tweak', 'FK', 'Extra']
297 if g
in armature
.rigify_colors
.keys():
300 armature
.rigify_colors
.add()
301 armature
.rigify_colors
[-1].name
= g
303 armature
.rigify_colors
[g
].select
= Color((0.3140000104904175, 0.7839999794960022, 1.0))
304 armature
.rigify_colors
[g
].active
= Color((0.5490000247955322, 1.0, 1.0))
305 armature
.rigify_colors
[g
].standard_colors_lock
= True
308 armature
.rigify_colors
[g
].normal
= Color((0.43529415130615234, 0.18431372940540314, 0.41568630933761597))
310 armature
.rigify_colors
[g
].normal
= Color((0.6039215922355652, 0.0, 0.0))
312 armature
.rigify_colors
[g
].normal
= Color((0.9568628072738647, 0.7882353663444519, 0.0470588281750679))
314 armature
.rigify_colors
[g
].normal
= Color((0.03921568766236305, 0.21176472306251526, 0.5803921818733215))
316 armature
.rigify_colors
[g
].normal
= Color((0.11764706671237946, 0.5686274766921997, 0.03529411926865578))
318 armature
.rigify_colors
[g
].normal
= Color((0.9686275124549866, 0.250980406999588, 0.0941176563501358))
323 class DATA_OT_rigify_use_standard_colors(bpy
.types
.Operator
):
324 bl_idname
= "armature.rigify_use_standard_colors"
325 bl_label
= "Rigify Get active/select colors from current theme"
328 def poll(cls
, context
):
329 return context
.object and context
.object.type == 'ARMATURE'
331 def execute(self
, context
):
334 if not hasattr(armature
, 'rigify_colors'):
337 current_theme
= bpy
.context
.preferences
.themes
.items()[0][0]
338 theme
= bpy
.context
.preferences
.themes
[current_theme
]
340 armature
.rigify_selection_colors
.select
= theme
.view_3d
.bone_pose
341 armature
.rigify_selection_colors
.active
= theme
.view_3d
.bone_pose_active
343 # for col in armature.rigify_colors:
344 # col.select = theme.view_3d.bone_pose
345 # col.active = theme.view_3d.bone_pose_active
350 class DATA_OT_rigify_apply_selection_colors(bpy
.types
.Operator
):
351 bl_idname
= "armature.rigify_apply_selection_colors"
352 bl_label
= "Rigify Apply user defined active/select colors"
355 def poll(cls
, context
):
356 return context
.object and context
.object.type == 'ARMATURE'
358 def execute(self
, context
):
361 if not hasattr(armature
, 'rigify_colors'):
364 #current_theme = bpy.context.preferences.themes.items()[0][0]
365 #theme = bpy.context.preferences.themes[current_theme]
367 for col
in armature
.rigify_colors
:
368 col
.select
= armature
.rigify_selection_colors
.select
369 col
.active
= armature
.rigify_selection_colors
.active
374 class DATA_OT_rigify_bone_group_add(bpy
.types
.Operator
):
375 bl_idname
= "armature.rigify_bone_group_add"
376 bl_label
= "Rigify Add Bone Group color set"
379 def poll(cls
, context
):
380 return context
.object and context
.object.type == 'ARMATURE'
382 def execute(self
, context
):
386 if hasattr(armature
, 'rigify_colors'):
387 armature
.rigify_colors
.add()
388 armature
.rigify_colors
[-1].name
= unique_name(armature
.rigify_colors
, 'Group')
390 current_theme
= bpy
.context
.preferences
.themes
.items()[0][0]
391 theme
= bpy
.context
.preferences
.themes
[current_theme
]
393 armature
.rigify_colors
[-1].normal
= theme
.view_3d
.wire
394 armature
.rigify_colors
[-1].normal
.hsv
= theme
.view_3d
.wire
.hsv
395 armature
.rigify_colors
[-1].select
= theme
.view_3d
.bone_pose
396 armature
.rigify_colors
[-1].select
.hsv
= theme
.view_3d
.bone_pose
.hsv
397 armature
.rigify_colors
[-1].active
= theme
.view_3d
.bone_pose_active
398 armature
.rigify_colors
[-1].active
.hsv
= theme
.view_3d
.bone_pose_active
.hsv
403 class DATA_OT_rigify_bone_group_add_theme(bpy
.types
.Operator
):
404 bl_idname
= "armature.rigify_bone_group_add_theme"
405 bl_label
= "Rigify Add Bone Group color set from Theme"
406 bl_options
= {"REGISTER", "UNDO"}
408 theme
: EnumProperty(items
=(
409 ('THEME01', 'THEME01', ''),
410 ('THEME02', 'THEME02', ''),
411 ('THEME03', 'THEME03', ''),
412 ('THEME04', 'THEME04', ''),
413 ('THEME05', 'THEME05', ''),
414 ('THEME06', 'THEME06', ''),
415 ('THEME07', 'THEME07', ''),
416 ('THEME08', 'THEME08', ''),
417 ('THEME09', 'THEME09', ''),
418 ('THEME10', 'THEME10', ''),
419 ('THEME11', 'THEME11', ''),
420 ('THEME12', 'THEME12', ''),
421 ('THEME13', 'THEME13', ''),
422 ('THEME14', 'THEME14', ''),
423 ('THEME15', 'THEME15', ''),
424 ('THEME16', 'THEME16', ''),
425 ('THEME17', 'THEME17', ''),
426 ('THEME18', 'THEME18', ''),
427 ('THEME19', 'THEME19', ''),
428 ('THEME20', 'THEME20', '')
433 def poll(cls
, context
):
434 return context
.object and context
.object.type == 'ARMATURE'
436 def execute(self
, context
):
440 if hasattr(armature
, 'rigify_colors'):
442 if self
.theme
in armature
.rigify_colors
.keys():
444 armature
.rigify_colors
.add()
445 armature
.rigify_colors
[-1].name
= self
.theme
447 id = int(self
.theme
[-2:]) - 1
449 theme_color_set
= bpy
.context
.preferences
.themes
[0].bone_color_sets
[id]
451 armature
.rigify_colors
[-1].normal
= theme_color_set
.normal
452 armature
.rigify_colors
[-1].select
= theme_color_set
.select
453 armature
.rigify_colors
[-1].active
= theme_color_set
.active
458 class DATA_OT_rigify_bone_group_remove(bpy
.types
.Operator
):
459 bl_idname
= "armature.rigify_bone_group_remove"
460 bl_label
= "Rigify Remove Bone Group color set"
465 def poll(cls
, context
):
466 return context
.object and context
.object.type == 'ARMATURE'
468 def execute(self
, context
):
470 obj
.data
.rigify_colors
.remove(self
.idx
)
472 # set layers references to 0
473 for l
in obj
.data
.rigify_layers
:
474 if l
.group
== self
.idx
+ 1:
476 elif l
.group
> self
.idx
+ 1:
482 class DATA_OT_rigify_bone_group_remove_all(bpy
.types
.Operator
):
483 bl_idname
= "armature.rigify_bone_group_remove_all"
484 bl_label
= "Rigify Remove All Bone Groups"
487 def poll(cls
, context
):
488 return context
.object and context
.object.type == 'ARMATURE'
490 def execute(self
, context
):
493 for i
, col
in enumerate(obj
.data
.rigify_colors
):
494 obj
.data
.rigify_colors
.remove(0)
495 # set layers references to 0
496 for l
in obj
.data
.rigify_layers
:
503 class DATA_UL_rigify_bone_groups(bpy
.types
.UIList
):
504 def draw_item(self
, context
, layout
, data
, item
, icon
, active_data
, active_propname
, index
):
505 row
= layout
.row(align
=True)
506 row
= row
.split(factor
=0.1)
507 row
.label(text
=str(index
+1))
508 row
= row
.split(factor
=0.7)
509 row
.prop(item
, "name", text
='', emboss
=False)
510 row
= row
.row(align
=True)
511 icon
= 'LOCKED' if item
.standard_colors_lock
else 'UNLOCKED'
512 #row.prop(item, "standard_colors_lock", text='', icon=icon)
513 row
.prop(item
, "normal", text
='')
514 row2
= row
.row(align
=True)
515 row2
.prop(item
, "select", text
='')
516 row2
.prop(item
, "active", text
='')
517 #row2.enabled = not item.standard_colors_lock
518 row2
.enabled
= not bpy
.context
.object.data
.rigify_colors_lock
521 class DATA_MT_rigify_bone_groups_context_menu(bpy
.types
.Menu
):
522 bl_label
= 'Rigify Bone Groups Specials'
524 def draw(self
, context
):
527 layout
.operator('armature.rigify_bone_group_remove_all')
530 class DATA_PT_rigify_bone_groups(bpy
.types
.Panel
):
531 bl_label
= "Bone Groups"
532 bl_space_type
= 'PROPERTIES'
533 bl_region_type
= 'WINDOW'
535 bl_options
= {'DEFAULT_CLOSED'}
536 bl_parent_id
= "DATA_PT_rigify"
539 def poll(cls
, context
):
540 if not context
.object:
542 return context
.object.type == 'ARMATURE' and context
.active_object
.data
.get("rig_id") is None
544 def draw(self
, context
):
547 color_sets
= obj
.data
.rigify_colors
548 idx
= obj
.data
.rigify_colors_index
552 row
.operator("armature.rigify_use_standard_colors", icon
='FILE_REFRESH', text
='')
553 row
= row
.row(align
=True)
554 row
.prop(armature
.rigify_selection_colors
, 'select', text
='')
555 row
.prop(armature
.rigify_selection_colors
, 'active', text
='')
556 row
= layout
.row(align
=True)
557 icon
= 'LOCKED' if armature
.rigify_colors_lock
else 'UNLOCKED'
558 row
.prop(armature
, 'rigify_colors_lock', text
= 'Unified select/active colors', icon
=icon
)
559 row
.operator("armature.rigify_apply_selection_colors", icon
='FILE_REFRESH', text
='Apply')
561 row
.template_list("DATA_UL_rigify_bone_groups", "", obj
.data
, "rigify_colors", obj
.data
, "rigify_colors_index")
563 col
= row
.column(align
=True)
564 col
.operator("armature.rigify_bone_group_add", icon
='ADD', text
="")
565 col
.operator("armature.rigify_bone_group_remove", icon
='REMOVE', text
="").idx
= obj
.data
.rigify_colors_index
566 col
.menu("DATA_MT_rigify_bone_groups_context_menu", icon
='DOWNARROW_HLT', text
="")
568 row
.prop(armature
, 'rigify_theme_to_add', text
= 'Theme')
569 op
= row
.operator("armature.rigify_bone_group_add_theme", text
="Add From Theme")
570 op
.theme
= armature
.rigify_theme_to_add
572 row
.operator("armature.rigify_add_bone_groups", text
="Add Standard")
575 class BONE_PT_rigify_buttons(bpy
.types
.Panel
):
576 bl_label
= "Rigify Type"
577 bl_space_type
= 'PROPERTIES'
578 bl_region_type
= 'WINDOW'
580 #bl_options = {'DEFAULT_OPEN'}
583 def poll(cls
, context
):
584 if not context
.object:
586 return context
.object.type == 'ARMATURE' and context
.active_pose_bone\
587 and context
.active_object
.data
.get("rig_id") is None
589 def draw(self
, context
):
591 id_store
= C
.window_manager
592 bone
= context
.active_pose_bone
593 rig_name
= str(context
.active_pose_bone
.rigify_type
).replace(" ", "")
598 build_type_list(context
, id_store
.rigify_types
)
601 if len(feature_set_list
.get_enabled_modules_names()) > 0:
603 row
.prop(context
.object.data
, "active_feature_set")
605 row
.prop_search(bone
, "rigify_type", id_store
, "rigify_types", text
="Rig type")
607 # Rig type parameters / Rig type non-exist alert
610 rig
= rig_lists
.rigs
[rig_name
]['module']
611 except (ImportError, AttributeError, KeyError):
614 box
.label(text
="ERROR: type \"%s\" does not exist!" % rig_name
, icon
='ERROR')
616 if hasattr(rig
.Rig
, 'parameters_ui'):
620 param_cb
= rig
.parameters_ui
622 # Ignore the known empty base method
623 if getattr(param_cb
, '__func__', None) == base_rig
.BaseRig
.parameters_ui
.__func
__:
625 except AttributeError:
629 col
= layout
.column()
630 col
.label(text
="No options")
632 col
= layout
.column()
633 col
.label(text
="Options:")
635 param_cb(box
, bone
.rigify_parameters
)
638 class VIEW3D_PT_tools_rigify_dev(bpy
.types
.Panel
):
639 bl_label
= "Rigify Dev Tools"
640 bl_space_type
= 'VIEW_3D'
641 bl_region_type
= 'UI'
642 bl_category
= "Rigify"
645 def poll(cls
, context
):
646 return context
.mode
in ['EDIT_ARMATURE', 'EDIT_MESH']
649 def poll(cls
, context
):
650 return context
.mode
in ['EDIT_ARMATURE', 'EDIT_MESH']
652 def draw(self
, context
):
653 obj
= context
.active_object
655 if context
.mode
== 'EDIT_ARMATURE':
656 r
= self
.layout
.row()
657 r
.operator("armature.rigify_encode_metarig", text
="Encode Metarig to Python")
658 r
= self
.layout
.row()
659 r
.operator("armature.rigify_encode_metarig_sample", text
="Encode Sample to Python")
661 if context
.mode
== 'EDIT_MESH':
662 r
= self
.layout
.row()
663 r
.operator("mesh.rigify_encode_mesh_widget", text
="Encode Mesh Widget to Python")
666 class VIEW3D_PT_rigify_animation_tools(bpy
.types
.Panel
):
667 bl_label
= "Rigify Animation Tools"
668 bl_context
= "posemode"
669 bl_space_type
= 'VIEW_3D'
670 bl_region_type
= 'UI'
671 bl_category
= "Rigify"
674 def poll(cls
, context
):
675 obj
= context
.active_object
676 if obj
and obj
.type == 'ARMATURE':
677 rig_id
= obj
.data
.get("rig_id")
678 if rig_id
is not None:
679 has_arm
= hasattr(bpy
.types
, 'POSE_OT_rigify_arm_ik2fk_' + rig_id
)
680 has_leg
= hasattr(bpy
.types
, 'POSE_OT_rigify_leg_ik2fk_' + rig_id
)
681 return has_arm
or has_leg
685 def draw(self
, context
):
686 obj
= context
.active_object
687 id_store
= context
.window_manager
689 row
= self
.layout
.row()
691 if id_store
.rigify_transfer_only_selected
:
692 icon
= 'OUTLINER_DATA_ARMATURE'
694 icon
= 'ARMATURE_DATA'
696 row
.prop(id_store
, 'rigify_transfer_only_selected', toggle
=True, icon
=icon
)
698 row
= self
.layout
.row(align
=True)
699 row
.operator("rigify.ik2fk", text
='IK2FK Pose', icon
='SNAP_ON')
700 row
.operator("rigify.fk2ik", text
='FK2IK Pose', icon
='SNAP_ON')
702 row
= self
.layout
.row(align
=True)
703 row
.operator("rigify.transfer_fk_to_ik", text
='IK2FK Action', icon
='ACTION_TWEAK')
704 row
.operator("rigify.transfer_ik_to_fk", text
='FK2IK Action', icon
='ACTION_TWEAK')
706 row
= self
.layout
.row(align
=True)
707 row
.operator("rigify.clear_animation", text
="Clear IK Action", icon
='CANCEL').anim_type
= "IK"
708 row
.operator("rigify.clear_animation", text
="Clear FK Action", icon
='CANCEL').anim_type
= "FK"
710 row
= self
.layout
.row(align
=True)
711 op
= row
.operator("rigify.rotation_pole", icon
='FORCE_HARMONIC', text
='Switch to pole')
715 op
= row
.operator("rigify.rotation_pole", icon
='FORCE_MAGNETIC', text
='Switch to rotation')
719 RIGIFY_OT_get_frame_range
.draw_range_ui(context
, self
.layout
)
722 def rigify_report_exception(operator
, exception
):
726 # find the non-utils module name where the error happened
727 # hint, this is the metarig type!
728 exceptionType
, exceptionValue
, exceptionTraceback
= sys
.exc_info()
729 fns
= [ item
.filename
for item
in traceback
.extract_tb(exceptionTraceback
) ]
730 fns_rig
= [ fn
for fn
in fns
if os
.path
.basename(os
.path
.dirname(fn
)) != 'utils' ]
732 fn
= os
.path
.basename(fn
)
733 fn
= os
.path
.splitext(fn
)[0]
735 if fn
.startswith("__"):
736 message
.append("Incorrect armature...")
738 message
.append("Incorrect armature for type '%s'" % fn
)
739 message
.append(exception
.message
)
741 message
.reverse() # XXX - stupid! menu's are upside down!
743 operator
.report({'ERROR'}, '\n'.join(message
))
746 class LayerInit(bpy
.types
.Operator
):
747 """Initialize armature rigify layers"""
749 bl_idname
= "pose.rigify_layer_init"
750 bl_label
= "Add Rigify Layers"
751 bl_options
= {'UNDO', 'INTERNAL'}
753 def execute(self
, context
):
756 for i
in range(1 + len(arm
.rigify_layers
), 30):
757 arm
.rigify_layers
.add()
758 arm
.rigify_layers
[28].name
= 'Root'
759 arm
.rigify_layers
[28].row
= 14
764 if not (obj
and obj
.data
and obj
.type == 'ARMATURE'):
766 if 'rig_id' in obj
.data
:
768 for b
in obj
.pose
.bones
:
769 if b
.rigify_type
!= "":
773 class Generate(bpy
.types
.Operator
):
774 """Generates a rig from the active metarig armature"""
776 bl_idname
= "pose.rigify_generate"
777 bl_label
= "Rigify Generate Rig"
778 bl_options
= {'UNDO'}
779 bl_description
= 'Generates a rig from the active metarig armature'
782 def poll(cls
, context
):
783 return is_metarig(context
.object)
785 def execute(self
, context
):
786 metarig
= context
.object
788 generate
.generate_rig(context
, metarig
)
789 except MetarigError
as rig_exception
:
791 traceback
.print_exc()
793 rigify_report_exception(self
, rig_exception
)
794 except Exception as rig_exception
:
796 traceback
.print_exc()
798 self
.report({'ERROR'}, 'Generation has thrown an exception: ' + str(rig_exception
))
800 self
.report({'INFO'}, 'Successfully generated: "' + metarig
.data
.rigify_target_rig
.name
+ '"')
802 bpy
.ops
.object.mode_set(mode
='OBJECT')
807 class UpgradeMetarigTypes(bpy
.types
.Operator
):
808 """Upgrades metarig bones rigify_types"""
810 bl_idname
= "pose.rigify_upgrade_types"
811 bl_label
= "Rigify Upgrade Metarig Types"
812 bl_description
= 'Upgrades the rigify types on the active metarig armature'
813 bl_options
= {'UNDO'}
815 def execute(self
, context
):
816 for obj
in bpy
.data
.objects
:
817 if type(obj
.data
) == bpy
.types
.Armature
:
818 upgradeMetarigTypes(obj
)
820 class Sample(bpy
.types
.Operator
):
821 """Create a sample metarig to be modified before generating the final rig"""
823 bl_idname
= "armature.metarig_sample_add"
824 bl_label
= "Add Metarig Sample"
825 bl_options
= {'UNDO'}
827 metarig_type
: StringProperty(
829 description
="Name of the rig type to generate a sample of",
831 options
={'SKIP_SAVE'}
835 def poll(cls
, context
):
836 return context
.mode
== 'EDIT_ARMATURE'
838 def draw(self
, context
):
840 layout
.use_property_split
= True
841 layout
.use_property_decorate
= False
842 col
= layout
.column()
843 build_type_list(context
, context
.window_manager
.rigify_types
)
844 col
.prop(context
.object.data
, "active_feature_set")
845 col
.prop_search(self
, "metarig_type", context
.window_manager
, "rigify_types")
847 def invoke(self
, context
, event
):
848 if self
.metarig_type
== "":
849 return context
.window_manager
.invoke_props_dialog(self
)
850 return self
.execute(context
)
852 def execute(self
, context
):
853 if self
.metarig_type
== "":
854 self
.report({'ERROR'}, "You must select a rig type to create a sample of.")
857 rig
= rig_lists
.rigs
[self
.metarig_type
]["module"]
858 create_sample
= rig
.create_sample
859 except (ImportError, AttributeError, KeyError):
860 raise Exception("rig type '" + self
.metarig_type
+ "' has no sample.")
862 create_sample(context
.active_object
)
864 bpy
.ops
.object.mode_set(mode
='EDIT')
869 class EncodeMetarig(bpy
.types
.Operator
):
870 """Creates Python code that will generate the selected metarig"""
871 bl_idname
= "armature.rigify_encode_metarig"
872 bl_label
= "Rigify Encode Metarig"
873 bl_options
= {'UNDO'}
876 def poll(self
, context
):
877 return context
.mode
== 'EDIT_ARMATURE' and is_metarig(context
.object)
879 def execute(self
, context
):
882 if name
in bpy
.data
.texts
:
883 text_block
= bpy
.data
.texts
[name
]
886 text_block
= bpy
.data
.texts
.new(name
)
888 text
= write_metarig(context
.active_object
, layers
=True, func_name
="create", groups
=True, widgets
=True)
889 text_block
.write(text
)
890 bpy
.ops
.object.mode_set(mode
='EDIT')
891 self
.report({'INFO'}, f
"Metarig written to text datablock: {text_block.name}")
895 class EncodeMetarigSample(bpy
.types
.Operator
):
896 """Creates Python code that will generate the selected metarig as a sample"""
897 bl_idname
= "armature.rigify_encode_metarig_sample"
898 bl_label
= "Rigify Encode Metarig Sample"
899 bl_options
= {'UNDO'}
902 def poll(self
, context
):
903 return context
.mode
== 'EDIT_ARMATURE' and is_metarig(context
.object)
905 def execute(self
, context
):
906 name
= "metarig_sample.py"
908 if name
in bpy
.data
.texts
:
909 text_block
= bpy
.data
.texts
[name
]
912 text_block
= bpy
.data
.texts
.new(name
)
914 text
= write_metarig(context
.active_object
, layers
=False, func_name
="create_sample")
915 text_block
.write(text
)
916 bpy
.ops
.object.mode_set(mode
='EDIT')
918 self
.report({'INFO'}, f
"Metarig Sample written to text datablock: {text_block.name}")
922 class VIEW3D_MT_rigify(bpy
.types
.Menu
):
924 bl_idname
= "VIEW3D_MT_rigify"
926 def draw(self
, context
):
930 text
= "Re-Generate Rig" if obj
.data
.rigify_target_rig
else "Generate Rig"
931 layout
.operator(Generate
.bl_idname
, text
=text
)
933 if context
.mode
== 'EDIT_ARMATURE':
935 layout
.operator(Sample
.bl_idname
)
937 layout
.operator(EncodeMetarig
.bl_idname
, text
="Encode Metarig")
938 layout
.operator(EncodeMetarigSample
.bl_idname
, text
="Encode Metarig Sample")
941 def draw_rigify_menu(self
, context
):
942 if is_metarig(context
.object):
943 self
.layout
.menu(VIEW3D_MT_rigify
.bl_idname
)
945 class EncodeWidget(bpy
.types
.Operator
):
946 """ Creates Python code that will generate the selected metarig.
948 bl_idname
= "mesh.rigify_encode_mesh_widget"
949 bl_label
= "Rigify Encode Widget"
950 bl_options
= {'UNDO'}
953 def poll(self
, context
):
954 return context
.mode
== 'EDIT_MESH'
956 def execute(self
, context
):
959 if name
in bpy
.data
.texts
:
960 text_block
= bpy
.data
.texts
[name
]
963 text_block
= bpy
.data
.texts
.new(name
)
965 text
= write_widget(context
.active_object
)
966 text_block
.write(text
)
967 bpy
.ops
.object.mode_set(mode
='EDIT')
971 def draw_mesh_edit_menu(self
, context
):
972 self
.layout
.operator(EncodeWidget
.bl_idname
)
973 self
.layout
.separator()
976 def FktoIk(rig
, window
='ALL'):
978 scn
= bpy
.context
.scene
979 id_store
= bpy
.context
.window_manager
981 rig_id
= rig
.data
['rig_id']
982 leg_ik2fk
= eval('bpy.ops.pose.rigify_leg_ik2fk_' + rig_id
)
983 arm_ik2fk
= eval('bpy.ops.pose.rigify_arm_ik2fk_' + rig_id
)
984 limb_generated_names
= get_limb_generated_names(rig
)
987 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
988 elif window
== 'CURRENT':
989 frames
= [scn
.frame_current
]
991 frames
= [scn
.frame_current
]
993 if not id_store
.rigify_transfer_only_selected
:
994 pbones
= rig
.pose
.bones
995 bpy
.ops
.pose
.select_all(action
='DESELECT')
997 pbones
= bpy
.context
.selected_pose_bones
998 bpy
.ops
.pose
.select_all(action
='DESELECT')
1001 for group
in limb_generated_names
:
1002 if b
.name
in limb_generated_names
[group
].values() or b
.name
in limb_generated_names
[group
]['controls']\
1003 or b
.name
in limb_generated_names
[group
]['ik_ctrl']:
1004 names
= limb_generated_names
[group
]
1005 if names
['limb_type'] == 'arm':
1007 controls
= names
['controls']
1008 ik_ctrl
= names
['ik_ctrl']
1009 fk_ctrl
= names
['fk_ctrl']
1010 parent
= names
['parent']
1011 pole
= names
['pole']
1012 rig
.pose
.bones
[controls
[0]].bone
.select
= True
1013 rig
.pose
.bones
[controls
[4]].bone
.select
= True
1014 rig
.pose
.bones
[pole
].bone
.select
= True
1015 rig
.pose
.bones
[parent
].bone
.select
= True
1016 kwargs
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1017 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1], 'hand_ik': controls
[4],
1018 'pole': pole
, 'main_parent': parent
}
1019 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1020 controls
[4], pole
, parent
)
1023 controls
= names
['controls']
1024 ik_ctrl
= names
['ik_ctrl']
1025 fk_ctrl
= names
['fk_ctrl']
1026 parent
= names
['parent']
1027 pole
= names
['pole']
1028 rig
.pose
.bones
[controls
[0]].bone
.select
= True
1029 rig
.pose
.bones
[controls
[6]].bone
.select
= True
1030 rig
.pose
.bones
[controls
[5]].bone
.select
= True
1031 rig
.pose
.bones
[pole
].bone
.select
= True
1032 rig
.pose
.bones
[parent
].bone
.select
= True
1033 kwargs
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1034 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1035 'foot_ik': controls
[6], 'pole': pole
, 'footroll': controls
[5], 'mfoot_ik': ik_ctrl
[2],
1036 'main_parent': parent
}
1037 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1038 controls
[6], controls
[5], pole
, parent
)
1041 if not bones_in_frame(f
, rig
, *args
):
1045 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1046 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1048 bpy
.ops
.pose
.select_all(action
='DESELECT')
1049 limb_generated_names
.pop(group
)
1053 def IktoFk(rig
, window
='ALL'):
1055 scn
= bpy
.context
.scene
1056 id_store
= bpy
.context
.window_manager
1058 rig_id
= rig
.data
['rig_id']
1059 leg_fk2ik
= eval('bpy.ops.pose.rigify_leg_fk2ik_' + rig_id
)
1060 arm_fk2ik
= eval('bpy.ops.pose.rigify_arm_fk2ik_' + rig_id
)
1061 limb_generated_names
= get_limb_generated_names(rig
)
1064 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
1065 elif window
== 'CURRENT':
1066 frames
= [scn
.frame_current
]
1068 frames
= [scn
.frame_current
]
1070 if not id_store
.rigify_transfer_only_selected
:
1071 bpy
.ops
.pose
.select_all(action
='DESELECT')
1072 pbones
= rig
.pose
.bones
1074 pbones
= bpy
.context
.selected_pose_bones
1075 bpy
.ops
.pose
.select_all(action
='DESELECT')
1078 for group
in limb_generated_names
:
1079 if b
.name
in limb_generated_names
[group
].values() or b
.name
in limb_generated_names
[group
]['controls']\
1080 or b
.name
in limb_generated_names
[group
]['ik_ctrl']:
1081 names
= limb_generated_names
[group
]
1082 if names
['limb_type'] == 'arm':
1084 controls
= names
['controls']
1085 ik_ctrl
= names
['ik_ctrl']
1086 fk_ctrl
= names
['fk_ctrl']
1087 parent
= names
['parent']
1088 pole
= names
['pole']
1089 rig
.pose
.bones
[controls
[1]].bone
.select
= True
1090 rig
.pose
.bones
[controls
[2]].bone
.select
= True
1091 rig
.pose
.bones
[controls
[3]].bone
.select
= True
1092 kwargs
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1093 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1],
1094 'hand_ik': controls
[4]}
1095 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1096 controls
[4], pole
, parent
)
1099 controls
= names
['controls']
1100 ik_ctrl
= names
['ik_ctrl']
1101 fk_ctrl
= names
['fk_ctrl']
1102 parent
= names
['parent']
1103 pole
= names
['pole']
1104 rig
.pose
.bones
[controls
[1]].bone
.select
= True
1105 rig
.pose
.bones
[controls
[2]].bone
.select
= True
1106 rig
.pose
.bones
[controls
[3]].bone
.select
= True
1107 kwargs
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1108 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1109 'foot_ik': ik_ctrl
[2], 'mfoot_ik': ik_ctrl
[2]}
1110 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1111 controls
[6], controls
[5], pole
, parent
)
1114 if not bones_in_frame(f
, rig
, *args
):
1118 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1119 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1121 bpy
.ops
.pose
.select_all(action
='DESELECT')
1122 limb_generated_names
.pop(group
)
1126 def clearAnimation(act
, anim_type
, names
):
1130 if names
[group
]['limb_type'] == 'arm':
1131 if anim_type
== 'IK':
1132 bones
.extend([names
[group
]['controls'][0], names
[group
]['controls'][4]])
1133 elif anim_type
== 'FK':
1134 bones
.extend([names
[group
]['controls'][1], names
[group
]['controls'][2], names
[group
]['controls'][3]])
1136 if anim_type
== 'IK':
1137 bones
.extend([names
[group
]['controls'][0], names
[group
]['controls'][6], names
[group
]['controls'][5],
1138 names
[group
]['controls'][4]])
1139 elif anim_type
== 'FK':
1140 bones
.extend([names
[group
]['controls'][1], names
[group
]['controls'][2], names
[group
]['controls'][3],
1141 names
[group
]['controls'][4]])
1143 for fcu
in act
.fcurves
:
1144 words
= fcu
.data_path
.split('"')
1145 if (words
[0] == "pose.bones[" and
1153 act
.fcurves
.remove(fcu
)
1155 # Put cleared bones back to rest pose
1156 bpy
.ops
.pose
.loc_clear()
1157 bpy
.ops
.pose
.rot_clear()
1158 bpy
.ops
.pose
.scale_clear()
1163 def rotPoleToggle(rig
, window
='ALL', value
=False, toggle
=False, bake
=False):
1165 scn
= bpy
.context
.scene
1166 id_store
= bpy
.context
.window_manager
1168 rig_id
= rig
.data
['rig_id']
1169 leg_fk2ik
= eval('bpy.ops.pose.rigify_leg_fk2ik_' + rig_id
)
1170 arm_fk2ik
= eval('bpy.ops.pose.rigify_arm_fk2ik_' + rig_id
)
1171 leg_ik2fk
= eval('bpy.ops.pose.rigify_leg_ik2fk_' + rig_id
)
1172 arm_ik2fk
= eval('bpy.ops.pose.rigify_arm_ik2fk_' + rig_id
)
1173 limb_generated_names
= get_limb_generated_names(rig
)
1176 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
1177 elif window
== 'CURRENT':
1178 frames
= [scn
.frame_current
]
1180 frames
= [scn
.frame_current
]
1182 if not id_store
.rigify_transfer_only_selected
:
1183 bpy
.ops
.pose
.select_all(action
='DESELECT')
1184 pbones
= rig
.pose
.bones
1186 pbones
= bpy
.context
.selected_pose_bones
1187 bpy
.ops
.pose
.select_all(action
='DESELECT')
1190 for group
in limb_generated_names
:
1191 names
= limb_generated_names
[group
]
1194 new_pole_vector_value
= not rig
.pose
.bones
[names
['parent']]['pole_vector']
1196 new_pole_vector_value
= value
1198 if b
.name
in names
.values() or b
.name
in names
['controls'] or b
.name
in names
['ik_ctrl']:
1199 if names
['limb_type'] == 'arm':
1202 controls
= names
['controls']
1203 ik_ctrl
= names
['ik_ctrl']
1204 fk_ctrl
= names
['fk_ctrl']
1205 parent
= names
['parent']
1206 pole
= names
['pole']
1207 rig
.pose
.bones
[controls
[0]].bone
.select
= not new_pole_vector_value
1208 rig
.pose
.bones
[controls
[4]].bone
.select
= not new_pole_vector_value
1209 rig
.pose
.bones
[parent
].bone
.select
= not new_pole_vector_value
1210 rig
.pose
.bones
[pole
].bone
.select
= new_pole_vector_value
1212 kwargs1
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1213 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1],
1214 'hand_ik': controls
[4]}
1215 kwargs2
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1216 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1], 'hand_ik': controls
[4],
1217 'pole': pole
, 'main_parent': parent
}
1218 args
= (controls
[0], controls
[4], pole
, parent
)
1222 controls
= names
['controls']
1223 ik_ctrl
= names
['ik_ctrl']
1224 fk_ctrl
= names
['fk_ctrl']
1225 parent
= names
['parent']
1226 pole
= names
['pole']
1227 rig
.pose
.bones
[controls
[0]].bone
.select
= not new_pole_vector_value
1228 rig
.pose
.bones
[controls
[6]].bone
.select
= not new_pole_vector_value
1229 rig
.pose
.bones
[controls
[5]].bone
.select
= not new_pole_vector_value
1230 rig
.pose
.bones
[parent
].bone
.select
= not new_pole_vector_value
1231 rig
.pose
.bones
[pole
].bone
.select
= new_pole_vector_value
1233 kwargs1
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1234 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1235 'foot_ik': ik_ctrl
[2], 'mfoot_ik': ik_ctrl
[2]}
1236 kwargs2
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1237 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1238 'foot_ik': controls
[6], 'pole': pole
, 'footroll': controls
[5], 'mfoot_ik': ik_ctrl
[2],
1239 'main_parent': parent
}
1240 args
= (controls
[0], controls
[6], controls
[5], pole
, parent
)
1243 if bake
and not bones_in_frame(f
, rig
, *args
):
1247 rig
.pose
.bones
[names
['parent']]['pole_vector'] = new_pole_vector_value
1250 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1251 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1252 overwrite_prop_animation(rig
, rig
.pose
.bones
[parent
], 'pole_vector', new_pole_vector_value
, [f
])
1254 bpy
.ops
.pose
.select_all(action
='DESELECT')
1255 limb_generated_names
.pop(group
)
1260 class OBJECT_OT_IK2FK(bpy
.types
.Operator
):
1261 """ Snaps IK limb on FK limb at current frame"""
1262 bl_idname
= "rigify.ik2fk"
1264 bl_description
= "Snaps IK limb on FK"
1265 bl_options
= {'INTERNAL'}
1267 def execute(self
,context
):
1268 rig
= context
.object
1269 id_store
= context
.window_manager
1271 FktoIk(rig
, window
='CURRENT')
1276 class OBJECT_OT_FK2IK(bpy
.types
.Operator
):
1277 """ Snaps FK limb on IK limb at current frame"""
1278 bl_idname
= "rigify.fk2ik"
1280 bl_description
= "Snaps FK limb on IK"
1281 bl_options
= {'INTERNAL'}
1283 def execute(self
,context
):
1284 rig
= context
.object
1286 IktoFk(rig
, window
='CURRENT')
1291 class OBJECT_OT_TransferFKtoIK(bpy
.types
.Operator
):
1292 """Transfers FK animation to IK"""
1293 bl_idname
= "rigify.transfer_fk_to_ik"
1294 bl_label
= "Transfer FK anim to IK"
1295 bl_description
= "Transfer FK animation to IK bones"
1296 bl_options
= {'INTERNAL'}
1298 def execute(self
, context
):
1299 rig
= context
.object
1300 id_store
= context
.window_manager
1307 class OBJECT_OT_TransferIKtoFK(bpy
.types
.Operator
):
1308 """Transfers FK animation to IK"""
1309 bl_idname
= "rigify.transfer_ik_to_fk"
1310 bl_label
= "Transfer IK anim to FK"
1311 bl_description
= "Transfer IK animation to FK bones"
1312 bl_options
= {'INTERNAL'}
1314 def execute(self
, context
):
1315 rig
= context
.object
1322 class OBJECT_OT_ClearAnimation(bpy
.types
.Operator
):
1323 bl_idname
= "rigify.clear_animation"
1324 bl_label
= "Clear Animation"
1325 bl_description
= "Clear Animation For FK or IK Bones"
1326 bl_options
= {'INTERNAL'}
1328 anim_type
: StringProperty()
1330 def execute(self
, context
):
1331 rig
= context
.object
1333 if not rig
.animation_data
:
1335 act
= rig
.animation_data
.action
1339 clearAnimation(act
, self
.anim_type
, names
=get_limb_generated_names(rig
))
1343 class OBJECT_OT_Rot2Pole(bpy
.types
.Operator
):
1344 bl_idname
= "rigify.rotation_pole"
1345 bl_label
= "Rotation - Pole toggle"
1346 bl_description
= "Toggles IK chain between rotation and pole target"
1347 bl_options
= {'INTERNAL'}
1349 bone_name
: StringProperty(default
='')
1350 window
: StringProperty(default
='ALL')
1351 toggle
: BoolProperty(default
=True)
1352 value
: BoolProperty(default
=True)
1353 bake
: BoolProperty(default
=True)
1355 def execute(self
, context
):
1356 rig
= context
.object
1359 bpy
.ops
.pose
.select_all(action
='DESELECT')
1360 rig
.pose
.bones
[self
.bone_name
].bone
.select
= True
1362 rotPoleToggle(rig
, window
=self
.window
, toggle
=self
.toggle
, value
=self
.value
, bake
=self
.bake
)
1370 DATA_OT_rigify_add_bone_groups
,
1371 DATA_OT_rigify_use_standard_colors
,
1372 DATA_OT_rigify_apply_selection_colors
,
1373 DATA_OT_rigify_bone_group_add
,
1374 DATA_OT_rigify_bone_group_add_theme
,
1375 DATA_OT_rigify_bone_group_remove
,
1376 DATA_OT_rigify_bone_group_remove_all
,
1377 DATA_UL_rigify_bone_groups
,
1378 DATA_MT_rigify_bone_groups_context_menu
,
1380 DATA_PT_rigify_advanced
,
1381 DATA_PT_rigify_bone_groups
,
1382 DATA_PT_rigify_layer_names
,
1383 DATA_PT_rigify_samples
,
1384 BONE_PT_rigify_buttons
,
1385 VIEW3D_PT_rigify_animation_tools
,
1386 VIEW3D_PT_tools_rigify_dev
,
1389 UpgradeMetarigTypes
,
1393 EncodeMetarigSample
,
1397 OBJECT_OT_TransferFKtoIK
,
1398 OBJECT_OT_TransferIKtoFK
,
1399 OBJECT_OT_ClearAnimation
,
1405 from bpy
.utils
import register_class
1407 animation_register()
1413 bpy
.types
.VIEW3D_MT_editor_menus
.append(draw_rigify_menu
)
1414 bpy
.types
.VIEW3D_MT_edit_mesh
.prepend(draw_mesh_edit_menu
)
1421 from bpy
.utils
import unregister_class
1424 rot_mode
.unregister()
1428 unregister_class(cls
)
1430 bpy
.types
.VIEW3D_MT_editor_menus
.remove(draw_rigify_menu
)
1431 bpy
.types
.VIEW3D_MT_edit_mesh
.remove(draw_mesh_edit_menu
)
1433 animation_unregister()