1 # SPDX-License-Identifier: GPL-2.0-or-later
6 from bpy
.props
import (
13 from mathutils
import Color
15 from .utils
.errors
import MetarigError
16 from .utils
.rig
import write_metarig
17 from .utils
.widgets
import write_widget
18 from .utils
.naming
import unique_name
19 from .utils
.rig
import upgradeMetarigTypes
, outdated_types
21 from .rigs
.utils
import get_limb_generated_names
23 from .utils
.animation
import get_keyed_frames_in_range
, bones_in_frame
, overwrite_prop_animation
24 from .utils
.animation
import RIGIFY_OT_get_frame_range
26 from .utils
.animation
import register
as animation_register
27 from .utils
.animation
import unregister
as animation_unregister
29 from . import base_rig
30 from . import rig_lists
31 from . import generate
32 from . import rot_mode
33 from . import feature_set_list
36 def build_type_list(context
, rigify_types
):
39 for r
in sorted(rig_lists
.rigs
):
40 if (context
.object.data
.active_feature_set
in ('all', rig_lists
.rigs
[r
]['feature_set'])
41 or len(feature_set_list
.get_enabled_modules_names()) == 0
43 a
= rigify_types
.add()
47 class DATA_PT_rigify(bpy
.types
.Panel
):
49 bl_space_type
= 'PROPERTIES'
50 bl_region_type
= 'WINDOW'
54 def poll(cls
, context
):
56 if not context
.object:
58 return obj
.type == 'ARMATURE' \
59 and obj
.data
.get("rig_id") is None
61 def draw(self
, context
):
66 WARNING
= "Warning: Some features may change after generation"
68 show_update_metarig
= False
69 show_not_updatable
= False
70 show_upgrade_face
= False
72 check_props
= ['IK_follow', 'root/parent', 'FK_limb_follow', 'IK_Stretch']
74 for posebone
in obj
.pose
.bones
:
77 # If we are in edit mode and the bone was just created,
78 # a pose bone won't exist yet.
80 if bone
.layers
[30] and (list(set(posebone
.keys()) & set(check_props
))):
84 for b
in obj
.pose
.bones
:
85 if b
.rigify_type
in outdated_types
.keys():
87 old_rig
= b
.rigify_type
88 if outdated_types
[b
.rigify_type
]:
89 show_update_metarig
= True
91 show_update_metarig
= False
92 show_not_updatable
= True
94 elif b
.rigify_type
== 'faces.super_face':
95 show_upgrade_face
= True
98 layout
.label(text
=WARNING
, icon
='ERROR')
100 enable_generate
= not (show_not_updatable
or show_update_metarig
)
102 if show_not_updatable
:
103 layout
.label(text
="WARNING: This metarig contains deprecated rigify rig-types and cannot be upgraded automatically.", icon
='ERROR')
104 layout
.label(text
="("+old_rig
+" on bone "+old_bone
+")")
105 elif show_update_metarig
:
106 layout
.label(text
="This metarig contains old rig-types that can be automatically upgraded to benefit of rigify's new features.", icon
='ERROR')
107 layout
.label(text
="("+old_rig
+" on bone "+old_bone
+")")
108 layout
.operator("pose.rigify_upgrade_types", text
="Upgrade Metarig")
109 elif show_upgrade_face
:
110 layout
.label(text
="This metarig uses the old face rig.", icon
='INFO')
111 layout
.operator("pose.rigify_upgrade_face")
116 col
= layout
.column(align
=True)
117 col
.active
= (not 'rig_id' in C
.object.data
)
121 text
= "Re-Generate Rig" if obj
.data
.rigify_target_rig
else "Generate Rig"
122 row
.operator("pose.rigify_generate", text
=text
, icon
='POSE_HLT')
123 row
.enabled
= enable_generate
126 class DATA_PT_rigify_advanced(bpy
.types
.Panel
):
127 bl_space_type
= 'PROPERTIES'
128 bl_region_type
= 'WINDOW'
130 bl_label
= "Advanced"
131 bl_parent_id
= 'DATA_PT_rigify'
132 bl_options
= {'DEFAULT_CLOSED'}
134 def draw(self
, context
):
136 layout
.use_property_split
= True
137 layout
.use_property_decorate
= False
139 armature_id_store
= context
.object.data
141 col
= layout
.column()
142 col
.row().prop(armature_id_store
, "rigify_target_rig", text
="Target Rig")
143 col
.row().prop(armature_id_store
, "rigify_rig_ui", text
="Rig UI Script")
145 col
.row().prop(armature_id_store
, "rigify_widgets_collection")
146 col
.row().prop(armature_id_store
, "rigify_force_widget_update")
147 col
.row().prop(armature_id_store
, "rigify_mirror_widgets")
149 col
.row().prop(armature_id_store
, "rigify_finalize_script", text
="Run Script")
152 class DATA_PT_rigify_samples(bpy
.types
.Panel
):
154 bl_space_type
= 'PROPERTIES'
155 bl_region_type
= 'WINDOW'
157 bl_parent_id
= "DATA_PT_rigify"
158 bl_options
= {'DEFAULT_CLOSED'}
161 def poll(cls
, context
):
165 return obj
.type == 'ARMATURE' \
166 and obj
.data
.get("rig_id") is None \
167 and obj
.mode
== 'EDIT'
169 def draw(self
, context
):
171 layout
.use_property_split
= True
172 layout
.use_property_decorate
= False
174 id_store
= context
.window_manager
177 build_type_list(context
, id_store
.rigify_types
)
179 if id_store
.rigify_active_type
> len(id_store
.rigify_types
):
180 id_store
.rigify_active_type
= 0
183 if len(feature_set_list
.get_enabled_modules_names()) > 0:
185 row
.prop(context
.object.data
, "active_feature_set")
187 row
.template_list("UI_UL_list", "rigify_types", id_store
, "rigify_types", id_store
, 'rigify_active_type')
189 props
= layout
.operator("armature.metarig_sample_add", text
="Add sample")
190 props
.metarig_type
= id_store
.rigify_types
[id_store
.rigify_active_type
].name
193 class DATA_PT_rigify_layer_names(bpy
.types
.Panel
):
194 bl_label
= "Layer Names"
195 bl_space_type
= 'PROPERTIES'
196 bl_region_type
= 'WINDOW'
198 bl_options
= {'DEFAULT_CLOSED'}
199 bl_parent_id
= "DATA_PT_rigify"
202 def poll(cls
, context
):
203 if not context
.object:
205 return context
.object.type == 'ARMATURE' and context
.active_object
.data
.get("rig_id") is None
207 def draw(self
, context
):
212 # Ensure that the layers exist
214 for i
in range(1 + len(arm
.rigify_layers
), 29):
215 arm
.rigify_layers
.add()
217 # Can't add while drawing, just use button
218 if len(arm
.rigify_layers
) < 29:
219 layout
.operator("pose.rigify_layer_init")
223 main_row
= layout
.row(align
=True).split(factor
=0.05)
224 col1
= main_row
.column()
225 col2
= main_row
.column()
228 if i
== 16 or i
== 29:
230 col1
.label(text
=str(i
+1) + '.')
232 for i
, rigify_layer
in enumerate(arm
.rigify_layers
):
233 # note: rigify_layer == arm.rigify_layers[i]
237 col
.label(text
="Top Row:")
239 col
.label(text
="Bottom Row:")
243 row
= col
.row(align
=True)
244 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
245 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
246 #row.prop(arm, "layers", index=i, text="Layer %d" % (i + 1), toggle=True, icon=icon)
247 row
.prop(rigify_layer
, "name", text
="")
248 row
.prop(rigify_layer
, "row", text
="UI Row")
249 icon
= 'RADIOBUT_ON' if rigify_layer
.selset
else 'RADIOBUT_OFF'
250 row
.prop(rigify_layer
, "selset", text
="", toggle
=True, icon
=icon
)
251 row
.prop(rigify_layer
, "group", text
="Bone Group")
253 row
= col
.row(align
=True)
255 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
256 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
257 # row.prop(arm, "layers", index=i, text="Layer %d" % (i + 1), toggle=True, icon=icon)
258 row1
= row
.split(align
=True).row(align
=True)
259 row1
.prop(rigify_layer
, "name", text
="")
260 row1
.prop(rigify_layer
, "row", text
="UI Row")
262 icon
= 'RADIOBUT_ON' if rigify_layer
.selset
else 'RADIOBUT_OFF'
263 row
.prop(rigify_layer
, "selset", text
="", toggle
=True, icon
=icon
)
264 row
.prop(rigify_layer
, "group", text
="Bone Group")
265 if rigify_layer
.group
== 0:
266 row
.label(text
='None')
268 row
.label(text
=arm
.rigify_colors
[rigify_layer
.group
-1].name
)
271 col
.label(text
="Reserved:")
272 # reserved_names = {28: 'Root', 29: 'DEF', 30: 'MCH', 31: 'ORG'}
273 reserved_names
= {29: 'DEF', 30: 'MCH', 31: 'ORG'}
274 # for i in range(28, 32):
275 for i
in range(29, 32):
276 row
= col
.row(align
=True)
277 icon
= 'RESTRICT_VIEW_OFF' if arm
.layers
[i
] else 'RESTRICT_VIEW_ON'
278 row
.prop(arm
, "layers", index
=i
, text
="", toggle
=True, icon
=icon
)
279 row
.label(text
=reserved_names
[i
])
282 class DATA_OT_rigify_add_bone_groups(bpy
.types
.Operator
):
283 bl_idname
= "armature.rigify_add_bone_groups"
284 bl_label
= "Rigify Add Standard Bone Groups"
287 def poll(cls
, context
):
288 return context
.object and context
.object.type == 'ARMATURE'
290 def execute(self
, context
):
293 if not hasattr(armature
, 'rigify_colors'):
296 groups
= ['Root', 'IK', 'Special', 'Tweak', 'FK', 'Extra']
299 if g
in armature
.rigify_colors
.keys():
302 armature
.rigify_colors
.add()
303 armature
.rigify_colors
[-1].name
= g
305 armature
.rigify_colors
[g
].select
= Color((0.3140000104904175, 0.7839999794960022, 1.0))
306 armature
.rigify_colors
[g
].active
= Color((0.5490000247955322, 1.0, 1.0))
307 armature
.rigify_colors
[g
].standard_colors_lock
= True
310 armature
.rigify_colors
[g
].normal
= Color((0.43529415130615234, 0.18431372940540314, 0.41568630933761597))
312 armature
.rigify_colors
[g
].normal
= Color((0.6039215922355652, 0.0, 0.0))
314 armature
.rigify_colors
[g
].normal
= Color((0.9568628072738647, 0.7882353663444519, 0.0470588281750679))
316 armature
.rigify_colors
[g
].normal
= Color((0.03921568766236305, 0.21176472306251526, 0.5803921818733215))
318 armature
.rigify_colors
[g
].normal
= Color((0.11764706671237946, 0.5686274766921997, 0.03529411926865578))
320 armature
.rigify_colors
[g
].normal
= Color((0.9686275124549866, 0.250980406999588, 0.0941176563501358))
325 class DATA_OT_rigify_use_standard_colors(bpy
.types
.Operator
):
326 bl_idname
= "armature.rigify_use_standard_colors"
327 bl_label
= "Rigify Get active/select colors from current theme"
330 def poll(cls
, context
):
331 return context
.object and context
.object.type == 'ARMATURE'
333 def execute(self
, context
):
336 if not hasattr(armature
, 'rigify_colors'):
339 current_theme
= bpy
.context
.preferences
.themes
.items()[0][0]
340 theme
= bpy
.context
.preferences
.themes
[current_theme
]
342 armature
.rigify_selection_colors
.select
= theme
.view_3d
.bone_pose
343 armature
.rigify_selection_colors
.active
= theme
.view_3d
.bone_pose_active
345 # for col in armature.rigify_colors:
346 # col.select = theme.view_3d.bone_pose
347 # col.active = theme.view_3d.bone_pose_active
352 class DATA_OT_rigify_apply_selection_colors(bpy
.types
.Operator
):
353 bl_idname
= "armature.rigify_apply_selection_colors"
354 bl_label
= "Rigify Apply user defined active/select colors"
357 def poll(cls
, context
):
358 return context
.object and context
.object.type == 'ARMATURE'
360 def execute(self
, context
):
363 if not hasattr(armature
, 'rigify_colors'):
366 #current_theme = bpy.context.preferences.themes.items()[0][0]
367 #theme = bpy.context.preferences.themes[current_theme]
369 for col
in armature
.rigify_colors
:
370 col
.select
= armature
.rigify_selection_colors
.select
371 col
.active
= armature
.rigify_selection_colors
.active
376 class DATA_OT_rigify_bone_group_add(bpy
.types
.Operator
):
377 bl_idname
= "armature.rigify_bone_group_add"
378 bl_label
= "Rigify Add Bone Group color set"
381 def poll(cls
, context
):
382 return context
.object and context
.object.type == 'ARMATURE'
384 def execute(self
, context
):
388 if hasattr(armature
, 'rigify_colors'):
389 armature
.rigify_colors
.add()
390 armature
.rigify_colors
[-1].name
= unique_name(armature
.rigify_colors
, 'Group')
392 current_theme
= bpy
.context
.preferences
.themes
.items()[0][0]
393 theme
= bpy
.context
.preferences
.themes
[current_theme
]
395 armature
.rigify_colors
[-1].normal
= theme
.view_3d
.wire
396 armature
.rigify_colors
[-1].normal
.hsv
= theme
.view_3d
.wire
.hsv
397 armature
.rigify_colors
[-1].select
= theme
.view_3d
.bone_pose
398 armature
.rigify_colors
[-1].select
.hsv
= theme
.view_3d
.bone_pose
.hsv
399 armature
.rigify_colors
[-1].active
= theme
.view_3d
.bone_pose_active
400 armature
.rigify_colors
[-1].active
.hsv
= theme
.view_3d
.bone_pose_active
.hsv
405 class DATA_OT_rigify_bone_group_add_theme(bpy
.types
.Operator
):
406 bl_idname
= "armature.rigify_bone_group_add_theme"
407 bl_label
= "Rigify Add Bone Group color set from Theme"
408 bl_options
= {"REGISTER", "UNDO"}
410 theme
: EnumProperty(items
=(
411 ('THEME01', 'THEME01', ''),
412 ('THEME02', 'THEME02', ''),
413 ('THEME03', 'THEME03', ''),
414 ('THEME04', 'THEME04', ''),
415 ('THEME05', 'THEME05', ''),
416 ('THEME06', 'THEME06', ''),
417 ('THEME07', 'THEME07', ''),
418 ('THEME08', 'THEME08', ''),
419 ('THEME09', 'THEME09', ''),
420 ('THEME10', 'THEME10', ''),
421 ('THEME11', 'THEME11', ''),
422 ('THEME12', 'THEME12', ''),
423 ('THEME13', 'THEME13', ''),
424 ('THEME14', 'THEME14', ''),
425 ('THEME15', 'THEME15', ''),
426 ('THEME16', 'THEME16', ''),
427 ('THEME17', 'THEME17', ''),
428 ('THEME18', 'THEME18', ''),
429 ('THEME19', 'THEME19', ''),
430 ('THEME20', 'THEME20', '')
435 def poll(cls
, context
):
436 return context
.object and context
.object.type == 'ARMATURE'
438 def execute(self
, context
):
442 if hasattr(armature
, 'rigify_colors'):
444 if self
.theme
in armature
.rigify_colors
.keys():
446 armature
.rigify_colors
.add()
447 armature
.rigify_colors
[-1].name
= self
.theme
449 id = int(self
.theme
[-2:]) - 1
451 theme_color_set
= bpy
.context
.preferences
.themes
[0].bone_color_sets
[id]
453 armature
.rigify_colors
[-1].normal
= theme_color_set
.normal
454 armature
.rigify_colors
[-1].select
= theme_color_set
.select
455 armature
.rigify_colors
[-1].active
= theme_color_set
.active
460 class DATA_OT_rigify_bone_group_remove(bpy
.types
.Operator
):
461 bl_idname
= "armature.rigify_bone_group_remove"
462 bl_label
= "Rigify Remove Bone Group color set"
467 def poll(cls
, context
):
468 return context
.object and context
.object.type == 'ARMATURE'
470 def execute(self
, context
):
472 obj
.data
.rigify_colors
.remove(self
.idx
)
474 # set layers references to 0
475 for l
in obj
.data
.rigify_layers
:
476 if l
.group
== self
.idx
+ 1:
478 elif l
.group
> self
.idx
+ 1:
484 class DATA_OT_rigify_bone_group_remove_all(bpy
.types
.Operator
):
485 bl_idname
= "armature.rigify_bone_group_remove_all"
486 bl_label
= "Rigify Remove All Bone Groups"
489 def poll(cls
, context
):
490 return context
.object and context
.object.type == 'ARMATURE'
492 def execute(self
, context
):
495 for i
, col
in enumerate(obj
.data
.rigify_colors
):
496 obj
.data
.rigify_colors
.remove(0)
497 # set layers references to 0
498 for l
in obj
.data
.rigify_layers
:
505 class DATA_UL_rigify_bone_groups(bpy
.types
.UIList
):
506 def draw_item(self
, context
, layout
, data
, item
, icon
, active_data
, active_propname
, index
):
507 row
= layout
.row(align
=True)
508 row
= row
.split(factor
=0.1)
509 row
.label(text
=str(index
+1))
510 row
= row
.split(factor
=0.7)
511 row
.prop(item
, "name", text
='', emboss
=False)
512 row
= row
.row(align
=True)
513 icon
= 'LOCKED' if item
.standard_colors_lock
else 'UNLOCKED'
514 #row.prop(item, "standard_colors_lock", text='', icon=icon)
515 row
.prop(item
, "normal", text
='')
516 row2
= row
.row(align
=True)
517 row2
.prop(item
, "select", text
='')
518 row2
.prop(item
, "active", text
='')
519 #row2.enabled = not item.standard_colors_lock
520 row2
.enabled
= not bpy
.context
.object.data
.rigify_colors_lock
523 class DATA_MT_rigify_bone_groups_context_menu(bpy
.types
.Menu
):
524 bl_label
= 'Rigify Bone Groups Specials'
526 def draw(self
, context
):
529 layout
.operator('armature.rigify_bone_group_remove_all')
532 class DATA_PT_rigify_bone_groups(bpy
.types
.Panel
):
533 bl_label
= "Bone Groups"
534 bl_space_type
= 'PROPERTIES'
535 bl_region_type
= 'WINDOW'
537 bl_options
= {'DEFAULT_CLOSED'}
538 bl_parent_id
= "DATA_PT_rigify"
541 def poll(cls
, context
):
542 if not context
.object:
544 return context
.object.type == 'ARMATURE' and context
.active_object
.data
.get("rig_id") is None
546 def draw(self
, context
):
549 color_sets
= obj
.data
.rigify_colors
550 idx
= obj
.data
.rigify_colors_index
554 row
.operator("armature.rigify_use_standard_colors", icon
='FILE_REFRESH', text
='')
555 row
= row
.row(align
=True)
556 row
.prop(armature
.rigify_selection_colors
, 'select', text
='')
557 row
.prop(armature
.rigify_selection_colors
, 'active', text
='')
558 row
= layout
.row(align
=True)
559 icon
= 'LOCKED' if armature
.rigify_colors_lock
else 'UNLOCKED'
560 row
.prop(armature
, 'rigify_colors_lock', text
= 'Unified select/active colors', icon
=icon
)
561 row
.operator("armature.rigify_apply_selection_colors", icon
='FILE_REFRESH', text
='Apply')
563 row
.template_list("DATA_UL_rigify_bone_groups", "", obj
.data
, "rigify_colors", obj
.data
, "rigify_colors_index")
565 col
= row
.column(align
=True)
566 col
.operator("armature.rigify_bone_group_add", icon
='ZOOM_IN', text
="")
567 col
.operator("armature.rigify_bone_group_remove", icon
='ZOOM_OUT', text
="").idx
= obj
.data
.rigify_colors_index
568 col
.menu("DATA_MT_rigify_bone_groups_context_menu", icon
='DOWNARROW_HLT', text
="")
570 row
.prop(armature
, 'rigify_theme_to_add', text
= 'Theme')
571 op
= row
.operator("armature.rigify_bone_group_add_theme", text
="Add From Theme")
572 op
.theme
= armature
.rigify_theme_to_add
574 row
.operator("armature.rigify_add_bone_groups", text
="Add Standard")
577 class BONE_PT_rigify_buttons(bpy
.types
.Panel
):
578 bl_label
= "Rigify Type"
579 bl_space_type
= 'PROPERTIES'
580 bl_region_type
= 'WINDOW'
582 #bl_options = {'DEFAULT_OPEN'}
585 def poll(cls
, context
):
586 if not context
.object:
588 return context
.object.type == 'ARMATURE' and context
.active_pose_bone\
589 and context
.active_object
.data
.get("rig_id") is None
591 def draw(self
, context
):
593 id_store
= C
.window_manager
594 bone
= context
.active_pose_bone
595 rig_name
= str(context
.active_pose_bone
.rigify_type
).replace(" ", "")
600 build_type_list(context
, id_store
.rigify_types
)
603 if len(feature_set_list
.get_enabled_modules_names()) > 0:
605 row
.prop(context
.object.data
, "active_feature_set")
607 row
.prop_search(bone
, "rigify_type", id_store
, "rigify_types", text
="Rig type")
609 # Rig type parameters / Rig type non-exist alert
612 rig
= rig_lists
.rigs
[rig_name
]['module']
613 except (ImportError, AttributeError, KeyError):
616 box
.label(text
="ERROR: type \"%s\" does not exist!" % rig_name
, icon
='ERROR')
618 if hasattr(rig
.Rig
, 'parameters_ui'):
622 param_cb
= rig
.parameters_ui
624 # Ignore the known empty base method
625 if getattr(param_cb
, '__func__', None) == base_rig
.BaseRig
.parameters_ui
.__func
__:
627 except AttributeError:
631 col
= layout
.column()
632 col
.label(text
="No options")
634 col
= layout
.column()
635 col
.label(text
="Options:")
637 param_cb(box
, bone
.rigify_parameters
)
640 class VIEW3D_PT_tools_rigify_dev(bpy
.types
.Panel
):
641 bl_label
= "Rigify Dev Tools"
642 bl_space_type
= 'VIEW_3D'
643 bl_region_type
= 'UI'
644 bl_category
= "Rigify"
647 def poll(cls
, context
):
648 return context
.mode
in ['EDIT_ARMATURE', 'EDIT_MESH']
651 def poll(cls
, context
):
652 return context
.mode
in ['EDIT_ARMATURE', 'EDIT_MESH']
654 def draw(self
, context
):
655 obj
= context
.active_object
657 if context
.mode
== 'EDIT_ARMATURE':
658 r
= self
.layout
.row()
659 r
.operator("armature.rigify_encode_metarig", text
="Encode Metarig to Python")
660 r
= self
.layout
.row()
661 r
.operator("armature.rigify_encode_metarig_sample", text
="Encode Sample to Python")
663 if context
.mode
== 'EDIT_MESH':
664 r
= self
.layout
.row()
665 r
.operator("mesh.rigify_encode_mesh_widget", text
="Encode Mesh Widget to Python")
668 class VIEW3D_PT_rigify_animation_tools(bpy
.types
.Panel
):
669 bl_label
= "Rigify Animation Tools"
670 bl_context
= "posemode"
671 bl_space_type
= 'VIEW_3D'
672 bl_region_type
= 'UI'
673 bl_category
= "Rigify"
676 def poll(cls
, context
):
677 obj
= context
.active_object
678 if obj
and obj
.type == 'ARMATURE':
679 rig_id
= obj
.data
.get("rig_id")
680 if rig_id
is not None:
681 has_arm
= hasattr(bpy
.types
, 'POSE_OT_rigify_arm_ik2fk_' + rig_id
)
682 has_leg
= hasattr(bpy
.types
, 'POSE_OT_rigify_leg_ik2fk_' + rig_id
)
683 return has_arm
or has_leg
687 def draw(self
, context
):
688 obj
= context
.active_object
689 id_store
= context
.window_manager
691 row
= self
.layout
.row()
693 if id_store
.rigify_transfer_only_selected
:
694 icon
= 'OUTLINER_DATA_ARMATURE'
696 icon
= 'ARMATURE_DATA'
698 row
.prop(id_store
, 'rigify_transfer_only_selected', toggle
=True, icon
=icon
)
700 row
= self
.layout
.row(align
=True)
701 row
.operator("rigify.ik2fk", text
='IK2FK Pose', icon
='SNAP_ON')
702 row
.operator("rigify.fk2ik", text
='FK2IK Pose', icon
='SNAP_ON')
704 row
= self
.layout
.row(align
=True)
705 row
.operator("rigify.transfer_fk_to_ik", text
='IK2FK Action', icon
='ACTION_TWEAK')
706 row
.operator("rigify.transfer_ik_to_fk", text
='FK2IK Action', icon
='ACTION_TWEAK')
708 row
= self
.layout
.row(align
=True)
709 row
.operator("rigify.clear_animation", text
="Clear IK Action", icon
='CANCEL').anim_type
= "IK"
710 row
.operator("rigify.clear_animation", text
="Clear FK Action", icon
='CANCEL').anim_type
= "FK"
712 row
= self
.layout
.row(align
=True)
713 op
= row
.operator("rigify.rotation_pole", icon
='FORCE_HARMONIC', text
='Switch to pole')
717 op
= row
.operator("rigify.rotation_pole", icon
='FORCE_MAGNETIC', text
='Switch to rotation')
721 RIGIFY_OT_get_frame_range
.draw_range_ui(context
, self
.layout
)
724 def rigify_report_exception(operator
, exception
):
728 # find the non-utils module name where the error happened
729 # hint, this is the metarig type!
730 exceptionType
, exceptionValue
, exceptionTraceback
= sys
.exc_info()
731 fns
= [ item
.filename
for item
in traceback
.extract_tb(exceptionTraceback
) ]
732 fns_rig
= [ fn
for fn
in fns
if os
.path
.basename(os
.path
.dirname(fn
)) != 'utils' ]
734 fn
= os
.path
.basename(fn
)
735 fn
= os
.path
.splitext(fn
)[0]
737 if fn
.startswith("__"):
738 message
.append("Incorrect armature...")
740 message
.append("Incorrect armature for type '%s'" % fn
)
741 message
.append(exception
.message
)
743 message
.reverse() # XXX - stupid! menu's are upside down!
745 operator
.report({'ERROR'}, '\n'.join(message
))
748 class LayerInit(bpy
.types
.Operator
):
749 """Initialize armature rigify layers"""
751 bl_idname
= "pose.rigify_layer_init"
752 bl_label
= "Add Rigify Layers"
753 bl_options
= {'UNDO', 'INTERNAL'}
755 def execute(self
, context
):
758 for i
in range(1 + len(arm
.rigify_layers
), 30):
759 arm
.rigify_layers
.add()
760 arm
.rigify_layers
[28].name
= 'Root'
761 arm
.rigify_layers
[28].row
= 14
766 if not (obj
and obj
.data
and obj
.type == 'ARMATURE'):
768 if 'rig_id' in obj
.data
:
770 for b
in obj
.pose
.bones
:
771 if b
.rigify_type
!= "":
775 class Generate(bpy
.types
.Operator
):
776 """Generates a rig from the active metarig armature"""
778 bl_idname
= "pose.rigify_generate"
779 bl_label
= "Rigify Generate Rig"
780 bl_options
= {'UNDO'}
781 bl_description
= 'Generates a rig from the active metarig armature'
784 def poll(cls
, context
):
785 return is_metarig(context
.object)
787 def execute(self
, context
):
788 metarig
= context
.object
790 generate
.generate_rig(context
, metarig
)
791 except MetarigError
as rig_exception
:
793 traceback
.print_exc()
795 rigify_report_exception(self
, rig_exception
)
796 except Exception as rig_exception
:
798 traceback
.print_exc()
800 self
.report({'ERROR'}, 'Generation has thrown an exception: ' + str(rig_exception
))
802 self
.report({'INFO'}, 'Successfully generated: "' + metarig
.data
.rigify_target_rig
.name
+ '"')
804 bpy
.ops
.object.mode_set(mode
='OBJECT')
809 class UpgradeMetarigTypes(bpy
.types
.Operator
):
810 """Upgrades metarig bones rigify_types"""
812 bl_idname
= "pose.rigify_upgrade_types"
813 bl_label
= "Rigify Upgrade Metarig Types"
814 bl_description
= 'Upgrades the rigify types on the active metarig armature'
815 bl_options
= {'UNDO'}
817 def execute(self
, context
):
818 for obj
in bpy
.data
.objects
:
819 if type(obj
.data
) == bpy
.types
.Armature
:
820 upgradeMetarigTypes(obj
)
822 class Sample(bpy
.types
.Operator
):
823 """Create a sample metarig to be modified before generating the final rig"""
825 bl_idname
= "armature.metarig_sample_add"
826 bl_label
= "Add Metarig Sample"
827 bl_options
= {'UNDO'}
829 metarig_type
: StringProperty(
831 description
="Name of the rig type to generate a sample of",
833 options
={'SKIP_SAVE'}
837 def poll(cls
, context
):
838 return context
.mode
== 'EDIT_ARMATURE'
840 def draw(self
, context
):
842 layout
.use_property_split
= True
843 layout
.use_property_decorate
= False
844 col
= layout
.column()
845 build_type_list(context
, context
.window_manager
.rigify_types
)
846 col
.prop(context
.object.data
, "active_feature_set")
847 col
.prop_search(self
, "metarig_type", context
.window_manager
, "rigify_types")
849 def invoke(self
, context
, event
):
850 if self
.metarig_type
== "":
851 return context
.window_manager
.invoke_props_dialog(self
)
852 return self
.execute(context
)
854 def execute(self
, context
):
855 if self
.metarig_type
== "":
856 self
.report({'ERROR'}, "You must select a rig type to create a sample of.")
859 rig
= rig_lists
.rigs
[self
.metarig_type
]["module"]
860 create_sample
= rig
.create_sample
861 except (ImportError, AttributeError, KeyError):
862 raise Exception("rig type '" + self
.metarig_type
+ "' has no sample.")
864 create_sample(context
.active_object
)
866 bpy
.ops
.object.mode_set(mode
='EDIT')
871 class EncodeMetarig(bpy
.types
.Operator
):
872 """Creates Python code that will generate the selected metarig"""
873 bl_idname
= "armature.rigify_encode_metarig"
874 bl_label
= "Rigify Encode Metarig"
875 bl_options
= {'UNDO'}
878 def poll(self
, context
):
879 return context
.mode
== 'EDIT_ARMATURE' and is_metarig(context
.object)
881 def execute(self
, context
):
884 if name
in bpy
.data
.texts
:
885 text_block
= bpy
.data
.texts
[name
]
888 text_block
= bpy
.data
.texts
.new(name
)
890 text
= write_metarig(context
.active_object
, layers
=True, func_name
="create", groups
=True, widgets
=True)
891 text_block
.write(text
)
892 bpy
.ops
.object.mode_set(mode
='EDIT')
893 self
.report({'INFO'}, f
"Metarig written to text datablock: {text_block.name}")
897 class EncodeMetarigSample(bpy
.types
.Operator
):
898 """Creates Python code that will generate the selected metarig as a sample"""
899 bl_idname
= "armature.rigify_encode_metarig_sample"
900 bl_label
= "Rigify Encode Metarig Sample"
901 bl_options
= {'UNDO'}
904 def poll(self
, context
):
905 return context
.mode
== 'EDIT_ARMATURE' and is_metarig(context
.object)
907 def execute(self
, context
):
908 name
= "metarig_sample.py"
910 if name
in bpy
.data
.texts
:
911 text_block
= bpy
.data
.texts
[name
]
914 text_block
= bpy
.data
.texts
.new(name
)
916 text
= write_metarig(context
.active_object
, layers
=False, func_name
="create_sample")
917 text_block
.write(text
)
918 bpy
.ops
.object.mode_set(mode
='EDIT')
920 self
.report({'INFO'}, f
"Metarig Sample written to text datablock: {text_block.name}")
924 class VIEW3D_MT_rigify(bpy
.types
.Menu
):
926 bl_idname
= "VIEW3D_MT_rigify"
928 def draw(self
, context
):
932 text
= "Re-Generate Rig" if obj
.data
.rigify_target_rig
else "Generate Rig"
933 layout
.operator(Generate
.bl_idname
, text
=text
)
935 if context
.mode
== 'EDIT_ARMATURE':
937 layout
.operator(Sample
.bl_idname
)
939 layout
.operator(EncodeMetarig
.bl_idname
, text
="Encode Metarig")
940 layout
.operator(EncodeMetarigSample
.bl_idname
, text
="Encode Metarig Sample")
943 def draw_rigify_menu(self
, context
):
944 if is_metarig(context
.object):
945 self
.layout
.menu(VIEW3D_MT_rigify
.bl_idname
)
947 class EncodeWidget(bpy
.types
.Operator
):
948 """ Creates Python code that will generate the selected metarig.
950 bl_idname
= "mesh.rigify_encode_mesh_widget"
951 bl_label
= "Rigify Encode Widget"
952 bl_options
= {'UNDO'}
955 def poll(self
, context
):
956 return context
.mode
== 'EDIT_MESH'
958 def execute(self
, context
):
961 if name
in bpy
.data
.texts
:
962 text_block
= bpy
.data
.texts
[name
]
965 text_block
= bpy
.data
.texts
.new(name
)
967 text
= write_widget(context
.active_object
)
968 text_block
.write(text
)
969 bpy
.ops
.object.mode_set(mode
='EDIT')
973 def draw_mesh_edit_menu(self
, context
):
974 self
.layout
.operator(EncodeWidget
.bl_idname
)
975 self
.layout
.separator()
978 def FktoIk(rig
, window
='ALL'):
980 scn
= bpy
.context
.scene
981 id_store
= bpy
.context
.window_manager
983 rig_id
= rig
.data
['rig_id']
984 leg_ik2fk
= eval('bpy.ops.pose.rigify_leg_ik2fk_' + rig_id
)
985 arm_ik2fk
= eval('bpy.ops.pose.rigify_arm_ik2fk_' + rig_id
)
986 limb_generated_names
= get_limb_generated_names(rig
)
989 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
990 elif window
== 'CURRENT':
991 frames
= [scn
.frame_current
]
993 frames
= [scn
.frame_current
]
995 if not id_store
.rigify_transfer_only_selected
:
996 pbones
= rig
.pose
.bones
997 bpy
.ops
.pose
.select_all(action
='DESELECT')
999 pbones
= bpy
.context
.selected_pose_bones
1000 bpy
.ops
.pose
.select_all(action
='DESELECT')
1003 for group
in limb_generated_names
:
1004 if b
.name
in limb_generated_names
[group
].values() or b
.name
in limb_generated_names
[group
]['controls']\
1005 or b
.name
in limb_generated_names
[group
]['ik_ctrl']:
1006 names
= limb_generated_names
[group
]
1007 if names
['limb_type'] == 'arm':
1009 controls
= names
['controls']
1010 ik_ctrl
= names
['ik_ctrl']
1011 fk_ctrl
= names
['fk_ctrl']
1012 parent
= names
['parent']
1013 pole
= names
['pole']
1014 rig
.pose
.bones
[controls
[0]].bone
.select
= True
1015 rig
.pose
.bones
[controls
[4]].bone
.select
= True
1016 rig
.pose
.bones
[pole
].bone
.select
= True
1017 rig
.pose
.bones
[parent
].bone
.select
= True
1018 kwargs
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1019 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1], 'hand_ik': controls
[4],
1020 'pole': pole
, 'main_parent': parent
}
1021 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1022 controls
[4], pole
, parent
)
1025 controls
= names
['controls']
1026 ik_ctrl
= names
['ik_ctrl']
1027 fk_ctrl
= names
['fk_ctrl']
1028 parent
= names
['parent']
1029 pole
= names
['pole']
1030 rig
.pose
.bones
[controls
[0]].bone
.select
= True
1031 rig
.pose
.bones
[controls
[6]].bone
.select
= True
1032 rig
.pose
.bones
[controls
[5]].bone
.select
= True
1033 rig
.pose
.bones
[pole
].bone
.select
= True
1034 rig
.pose
.bones
[parent
].bone
.select
= True
1035 kwargs
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1036 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1037 'foot_ik': controls
[6], 'pole': pole
, 'footroll': controls
[5], 'mfoot_ik': ik_ctrl
[2],
1038 'main_parent': parent
}
1039 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1040 controls
[6], controls
[5], pole
, parent
)
1043 if not bones_in_frame(f
, rig
, *args
):
1047 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1048 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1050 bpy
.ops
.pose
.select_all(action
='DESELECT')
1051 limb_generated_names
.pop(group
)
1055 def IktoFk(rig
, window
='ALL'):
1057 scn
= bpy
.context
.scene
1058 id_store
= bpy
.context
.window_manager
1060 rig_id
= rig
.data
['rig_id']
1061 leg_fk2ik
= eval('bpy.ops.pose.rigify_leg_fk2ik_' + rig_id
)
1062 arm_fk2ik
= eval('bpy.ops.pose.rigify_arm_fk2ik_' + rig_id
)
1063 limb_generated_names
= get_limb_generated_names(rig
)
1066 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
1067 elif window
== 'CURRENT':
1068 frames
= [scn
.frame_current
]
1070 frames
= [scn
.frame_current
]
1072 if not id_store
.rigify_transfer_only_selected
:
1073 bpy
.ops
.pose
.select_all(action
='DESELECT')
1074 pbones
= rig
.pose
.bones
1076 pbones
= bpy
.context
.selected_pose_bones
1077 bpy
.ops
.pose
.select_all(action
='DESELECT')
1080 for group
in limb_generated_names
:
1081 if b
.name
in limb_generated_names
[group
].values() or b
.name
in limb_generated_names
[group
]['controls']\
1082 or b
.name
in limb_generated_names
[group
]['ik_ctrl']:
1083 names
= limb_generated_names
[group
]
1084 if names
['limb_type'] == 'arm':
1086 controls
= names
['controls']
1087 ik_ctrl
= names
['ik_ctrl']
1088 fk_ctrl
= names
['fk_ctrl']
1089 parent
= names
['parent']
1090 pole
= names
['pole']
1091 rig
.pose
.bones
[controls
[1]].bone
.select
= True
1092 rig
.pose
.bones
[controls
[2]].bone
.select
= True
1093 rig
.pose
.bones
[controls
[3]].bone
.select
= True
1094 kwargs
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1095 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1],
1096 'hand_ik': controls
[4]}
1097 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1098 controls
[4], pole
, parent
)
1101 controls
= names
['controls']
1102 ik_ctrl
= names
['ik_ctrl']
1103 fk_ctrl
= names
['fk_ctrl']
1104 parent
= names
['parent']
1105 pole
= names
['pole']
1106 rig
.pose
.bones
[controls
[1]].bone
.select
= True
1107 rig
.pose
.bones
[controls
[2]].bone
.select
= True
1108 rig
.pose
.bones
[controls
[3]].bone
.select
= True
1109 kwargs
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1110 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1111 'foot_ik': ik_ctrl
[2], 'mfoot_ik': ik_ctrl
[2]}
1112 args
= (controls
[0], controls
[1], controls
[2], controls
[3],
1113 controls
[6], controls
[5], pole
, parent
)
1116 if not bones_in_frame(f
, rig
, *args
):
1120 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1121 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1123 bpy
.ops
.pose
.select_all(action
='DESELECT')
1124 limb_generated_names
.pop(group
)
1128 def clearAnimation(act
, anim_type
, names
):
1132 if names
[group
]['limb_type'] == 'arm':
1133 if anim_type
== 'IK':
1134 bones
.extend([names
[group
]['controls'][0], names
[group
]['controls'][4]])
1135 elif anim_type
== 'FK':
1136 bones
.extend([names
[group
]['controls'][1], names
[group
]['controls'][2], names
[group
]['controls'][3]])
1138 if anim_type
== 'IK':
1139 bones
.extend([names
[group
]['controls'][0], names
[group
]['controls'][6], names
[group
]['controls'][5],
1140 names
[group
]['controls'][4]])
1141 elif anim_type
== 'FK':
1142 bones
.extend([names
[group
]['controls'][1], names
[group
]['controls'][2], names
[group
]['controls'][3],
1143 names
[group
]['controls'][4]])
1145 for fcu
in act
.fcurves
:
1146 words
= fcu
.data_path
.split('"')
1147 if (words
[0] == "pose.bones[" and
1155 act
.fcurves
.remove(fcu
)
1157 # Put cleared bones back to rest pose
1158 bpy
.ops
.pose
.loc_clear()
1159 bpy
.ops
.pose
.rot_clear()
1160 bpy
.ops
.pose
.scale_clear()
1165 def rotPoleToggle(rig
, window
='ALL', value
=False, toggle
=False, bake
=False):
1167 scn
= bpy
.context
.scene
1168 id_store
= bpy
.context
.window_manager
1170 rig_id
= rig
.data
['rig_id']
1171 leg_fk2ik
= eval('bpy.ops.pose.rigify_leg_fk2ik_' + rig_id
)
1172 arm_fk2ik
= eval('bpy.ops.pose.rigify_arm_fk2ik_' + rig_id
)
1173 leg_ik2fk
= eval('bpy.ops.pose.rigify_leg_ik2fk_' + rig_id
)
1174 arm_ik2fk
= eval('bpy.ops.pose.rigify_arm_ik2fk_' + rig_id
)
1175 limb_generated_names
= get_limb_generated_names(rig
)
1178 frames
= get_keyed_frames_in_range(bpy
.context
, rig
)
1179 elif window
== 'CURRENT':
1180 frames
= [scn
.frame_current
]
1182 frames
= [scn
.frame_current
]
1184 if not id_store
.rigify_transfer_only_selected
:
1185 bpy
.ops
.pose
.select_all(action
='DESELECT')
1186 pbones
= rig
.pose
.bones
1188 pbones
= bpy
.context
.selected_pose_bones
1189 bpy
.ops
.pose
.select_all(action
='DESELECT')
1192 for group
in limb_generated_names
:
1193 names
= limb_generated_names
[group
]
1196 new_pole_vector_value
= not rig
.pose
.bones
[names
['parent']]['pole_vector']
1198 new_pole_vector_value
= value
1200 if b
.name
in names
.values() or b
.name
in names
['controls'] or b
.name
in names
['ik_ctrl']:
1201 if names
['limb_type'] == 'arm':
1204 controls
= names
['controls']
1205 ik_ctrl
= names
['ik_ctrl']
1206 fk_ctrl
= names
['fk_ctrl']
1207 parent
= names
['parent']
1208 pole
= names
['pole']
1209 rig
.pose
.bones
[controls
[0]].bone
.select
= not new_pole_vector_value
1210 rig
.pose
.bones
[controls
[4]].bone
.select
= not new_pole_vector_value
1211 rig
.pose
.bones
[parent
].bone
.select
= not new_pole_vector_value
1212 rig
.pose
.bones
[pole
].bone
.select
= new_pole_vector_value
1214 kwargs1
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1215 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1],
1216 'hand_ik': controls
[4]}
1217 kwargs2
= {'uarm_fk': controls
[1], 'farm_fk': controls
[2], 'hand_fk': controls
[3],
1218 'uarm_ik': controls
[0], 'farm_ik': ik_ctrl
[1], 'hand_ik': controls
[4],
1219 'pole': pole
, 'main_parent': parent
}
1220 args
= (controls
[0], controls
[4], pole
, parent
)
1224 controls
= names
['controls']
1225 ik_ctrl
= names
['ik_ctrl']
1226 fk_ctrl
= names
['fk_ctrl']
1227 parent
= names
['parent']
1228 pole
= names
['pole']
1229 rig
.pose
.bones
[controls
[0]].bone
.select
= not new_pole_vector_value
1230 rig
.pose
.bones
[controls
[6]].bone
.select
= not new_pole_vector_value
1231 rig
.pose
.bones
[controls
[5]].bone
.select
= not new_pole_vector_value
1232 rig
.pose
.bones
[parent
].bone
.select
= not new_pole_vector_value
1233 rig
.pose
.bones
[pole
].bone
.select
= new_pole_vector_value
1235 kwargs1
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1236 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1237 'foot_ik': ik_ctrl
[2], 'mfoot_ik': ik_ctrl
[2]}
1238 kwargs2
= {'thigh_fk': controls
[1], 'shin_fk': controls
[2], 'foot_fk': controls
[3],
1239 'mfoot_fk': controls
[7], 'thigh_ik': controls
[0], 'shin_ik': ik_ctrl
[1],
1240 'foot_ik': controls
[6], 'pole': pole
, 'footroll': controls
[5], 'mfoot_ik': ik_ctrl
[2],
1241 'main_parent': parent
}
1242 args
= (controls
[0], controls
[6], controls
[5], pole
, parent
)
1245 if bake
and not bones_in_frame(f
, rig
, *args
):
1249 rig
.pose
.bones
[names
['parent']]['pole_vector'] = new_pole_vector_value
1252 bpy
.ops
.anim
.keyframe_insert_menu(type='BUILTIN_KSI_VisualLocRot')
1253 bpy
.ops
.anim
.keyframe_insert_menu(type='Scaling')
1254 overwrite_prop_animation(rig
, rig
.pose
.bones
[parent
], 'pole_vector', new_pole_vector_value
, [f
])
1256 bpy
.ops
.pose
.select_all(action
='DESELECT')
1257 limb_generated_names
.pop(group
)
1262 class OBJECT_OT_IK2FK(bpy
.types
.Operator
):
1263 """ Snaps IK limb on FK limb at current frame"""
1264 bl_idname
= "rigify.ik2fk"
1266 bl_description
= "Snaps IK limb on FK"
1267 bl_options
= {'INTERNAL'}
1269 def execute(self
,context
):
1270 rig
= context
.object
1271 id_store
= context
.window_manager
1273 FktoIk(rig
, window
='CURRENT')
1278 class OBJECT_OT_FK2IK(bpy
.types
.Operator
):
1279 """ Snaps FK limb on IK limb at current frame"""
1280 bl_idname
= "rigify.fk2ik"
1282 bl_description
= "Snaps FK limb on IK"
1283 bl_options
= {'INTERNAL'}
1285 def execute(self
,context
):
1286 rig
= context
.object
1288 IktoFk(rig
, window
='CURRENT')
1293 class OBJECT_OT_TransferFKtoIK(bpy
.types
.Operator
):
1294 """Transfers FK animation to IK"""
1295 bl_idname
= "rigify.transfer_fk_to_ik"
1296 bl_label
= "Transfer FK anim to IK"
1297 bl_description
= "Transfer FK animation to IK bones"
1298 bl_options
= {'INTERNAL'}
1300 def execute(self
, context
):
1301 rig
= context
.object
1302 id_store
= context
.window_manager
1309 class OBJECT_OT_TransferIKtoFK(bpy
.types
.Operator
):
1310 """Transfers FK animation to IK"""
1311 bl_idname
= "rigify.transfer_ik_to_fk"
1312 bl_label
= "Transfer IK anim to FK"
1313 bl_description
= "Transfer IK animation to FK bones"
1314 bl_options
= {'INTERNAL'}
1316 def execute(self
, context
):
1317 rig
= context
.object
1324 class OBJECT_OT_ClearAnimation(bpy
.types
.Operator
):
1325 bl_idname
= "rigify.clear_animation"
1326 bl_label
= "Clear Animation"
1327 bl_description
= "Clear Animation For FK or IK Bones"
1328 bl_options
= {'INTERNAL'}
1330 anim_type
: StringProperty()
1332 def execute(self
, context
):
1333 rig
= context
.object
1335 if not rig
.animation_data
:
1337 act
= rig
.animation_data
.action
1341 clearAnimation(act
, self
.anim_type
, names
=get_limb_generated_names(rig
))
1345 class OBJECT_OT_Rot2Pole(bpy
.types
.Operator
):
1346 bl_idname
= "rigify.rotation_pole"
1347 bl_label
= "Rotation - Pole toggle"
1348 bl_description
= "Toggles IK chain between rotation and pole target"
1349 bl_options
= {'INTERNAL'}
1351 bone_name
: StringProperty(default
='')
1352 window
: StringProperty(default
='ALL')
1353 toggle
: BoolProperty(default
=True)
1354 value
: BoolProperty(default
=True)
1355 bake
: BoolProperty(default
=True)
1357 def execute(self
, context
):
1358 rig
= context
.object
1361 bpy
.ops
.pose
.select_all(action
='DESELECT')
1362 rig
.pose
.bones
[self
.bone_name
].bone
.select
= True
1364 rotPoleToggle(rig
, window
=self
.window
, toggle
=self
.toggle
, value
=self
.value
, bake
=self
.bake
)
1372 DATA_OT_rigify_add_bone_groups
,
1373 DATA_OT_rigify_use_standard_colors
,
1374 DATA_OT_rigify_apply_selection_colors
,
1375 DATA_OT_rigify_bone_group_add
,
1376 DATA_OT_rigify_bone_group_add_theme
,
1377 DATA_OT_rigify_bone_group_remove
,
1378 DATA_OT_rigify_bone_group_remove_all
,
1379 DATA_UL_rigify_bone_groups
,
1380 DATA_MT_rigify_bone_groups_context_menu
,
1382 DATA_PT_rigify_advanced
,
1383 DATA_PT_rigify_bone_groups
,
1384 DATA_PT_rigify_layer_names
,
1385 DATA_PT_rigify_samples
,
1386 BONE_PT_rigify_buttons
,
1387 VIEW3D_PT_rigify_animation_tools
,
1388 VIEW3D_PT_tools_rigify_dev
,
1391 UpgradeMetarigTypes
,
1395 EncodeMetarigSample
,
1399 OBJECT_OT_TransferFKtoIK
,
1400 OBJECT_OT_TransferIKtoFK
,
1401 OBJECT_OT_ClearAnimation
,
1407 from bpy
.utils
import register_class
1409 animation_register()
1415 bpy
.types
.VIEW3D_MT_editor_menus
.append(draw_rigify_menu
)
1416 bpy
.types
.VIEW3D_MT_edit_mesh
.prepend(draw_mesh_edit_menu
)
1423 from bpy
.utils
import unregister_class
1426 rot_mode
.unregister()
1430 unregister_class(cls
)
1432 bpy
.types
.VIEW3D_MT_editor_menus
.remove(draw_rigify_menu
)
1433 bpy
.types
.VIEW3D_MT_edit_mesh
.remove(draw_mesh_edit_menu
)
1435 animation_unregister()