WIP: Rigify - modifier keys on Rig Layers buttons #104998

Draft
Paolo Acampora wants to merge 6 commits from PaoloAcampora/rigify-ui-improvements:panel_modifier_keys into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
Showing only changes of commit 2060824af9 - Show all commits

View File

@ -6,7 +6,8 @@ import bpy
from typing import Tuple, Optional, Sequence, Any from typing import Tuple, Optional, Sequence, Any
from bpy.types import PropertyGroup, Action, UIList, UILayout, Context, Panel, Operator, Armature, PoseBone from bpy.types import (PropertyGroup, Action, UIList, UILayout, Context, Panel, Operator, Armature,
PoseBone, Bone, BoneCollection)
from bpy.props import (EnumProperty, IntProperty, BoolProperty, StringProperty, FloatProperty, from bpy.props import (EnumProperty, IntProperty, BoolProperty, StringProperty, FloatProperty,
PointerProperty, CollectionProperty) PointerProperty, CollectionProperty)
@ -190,15 +191,13 @@ def is_pose_bone_all_locked(pose_bone: PoseBone) -> bool:
return True return True
def should_skip_bone(bone, pose_bones): def should_skip_bone(bone: Bone):
"""Return True if the bone should not be used (hidden, locked, etc..)""" """Return True if the bone should not be displayed (hidden, VIS_*)"""
if bone.hide: if bone.hide:
return True return True
if bone.name.startswith('VIS_'): if bone.name.startswith('VIS_'):
# "VIS_*" bones are used for drawing lines, e.g. line connecting knee to IK pole # "VIS_*" bones are used for drawing lines, e.g. line connecting knee to IK pole
return True return True
if is_pose_bone_all_locked(pose_bones[bone.name]):
return True
return False return False
@ -249,7 +248,7 @@ class RIGIFY_OT_jump_to_action_slot(Operator):
# noinspection PyPep8Naming # noinspection PyPep8Naming
class RIGIFY_OT_display_select_group(bpy.types.Operator): class RIGIFY_OT_display_select_group(bpy.types.Operator):
"""Toggle bone layer visibility. Shift + click to toggle selection, Ctrl + click to remove from selection. """Toggle bone layer visibility. Shift + click to toggle selection, Ctrl + click to remove from selection.
Alt + click displays a menu""" Alt + click displays a panel"""
bl_idname = "object.rigify_display_select_bone_group" bl_idname = "object.rigify_display_select_bone_group"
bl_label = "Display or Select the bones that belong to a selection" bl_label = "Display or Select the bones that belong to a selection"
@ -285,7 +284,9 @@ class RIGIFY_OT_display_select_group(bpy.types.Operator):
if self.action == 'TOGGLE_SELECT': if self.action == 'TOGGLE_SELECT':
pose_bones = context.object.pose.bones pose_bones = context.object.pose.bones
for bone in coll.bones: for bone in coll.bones:
if should_skip_bone(bone, pose_bones): if should_skip_bone(bone):
continue
if is_pose_bone_all_locked(pose_bones[bone.name]):
continue continue
bone.select = not bone.select bone.select = not bone.select
elif self.action == 'UNSELECT': elif self.action == 'UNSELECT':
@ -341,6 +342,7 @@ class RIGIFY_OT_select_prefix_bones(bpy.types.Operator):
# ============================================= # =============================================
# UI Panel # UI Panel
# noinspection PyPep8Naming
class RIGIFY_PT_select_active_group_bones(bpy.types.Panel): class RIGIFY_PT_select_active_group_bones(bpy.types.Panel):
"""Display Panel""" """Display Panel"""
bl_idname = "object.rigify_active_group_select_bones" bl_idname = "object.rigify_active_group_select_bones"
@ -355,20 +357,22 @@ class RIGIFY_PT_select_active_group_bones(bpy.types.Panel):
return context.mode == 'POSE' return context.mode == 'POSE'
@staticmethod @staticmethod
def collect_bone_sides(collection, pose_bones): def collect_bone_sides(collection: BoneCollection):
left_bones = [] left_bones = []
mid_bones = [] mid_bones = []
right_bones = [] right_bones = []
prefix_bones = set() prefix_bones = set()
digits = ".0123456789" # used for stripping dot and number from bone names digits = ".0123456789" # used for stripping dot and number from bone names
armature = collection.id_data
for bone in collection.bones: for bone in collection.bones:
if should_skip_bone(bone, pose_bones): if should_skip_bone(bone):
continue continue
if bone.name[-1].isdigit(): if bone.name[-1].isdigit():
# Looking for bones like "*.L.015", "*.R.023", "*.001"
base_name = bone.name.rstrip(digits) base_name = bone.name.rstrip(digits)
if base_name in pose_bones: # e.g. "*.L", "*.L.015", "*.R.023" if base_name in armature.bones:
prefix_bones.add(base_name) prefix_bones.add(base_name)
continue continue
@ -385,13 +389,17 @@ class RIGIFY_PT_select_active_group_bones(bpy.types.Panel):
def draw(self, context): def draw(self, context):
collection = context.object.data.collections.active collection = context.object.data.collections.active
bone_lists, prefix_bones = self.collect_bone_sides(collection, context.object.pose.bones) bone_lists, prefix_bones = self.collect_bone_sides(collection)
# display Left and Right bones # display Left and Right bones
row = self.layout.row() row = self.layout.row()
columns = row.column(), row.column() columns = row.column(), row.column()
pose_bones = context.object.pose.bones
for col, bone_list in zip(columns, bone_lists[:2]): for col, bone_list in zip(columns, bone_lists[:2]):
for bone in bone_list: for bone in bone_list:
if is_pose_bone_all_locked(pose_bones[bone.name]):
continue
if bone.name in prefix_bones: if bone.name in prefix_bones:
col.operator(RIGIFY_OT_select_prefix_bones.bl_idname, text=bone.name, icon='TRIA_RIGHT').prefix = bone.name col.operator(RIGIFY_OT_select_prefix_bones.bl_idname, text=bone.name, icon='TRIA_RIGHT').prefix = bone.name
else: else:
@ -401,6 +409,8 @@ class RIGIFY_PT_select_active_group_bones(bpy.types.Panel):
# display Mid bones # display Mid bones
for bone in bone_lists[2]: for bone in bone_lists[2]:
if is_pose_bone_all_locked(pose_bones[bone.name]):
continue
if bone.name in prefix_bones: if bone.name in prefix_bones:
col.operator(RIGIFY_OT_select_prefix_bones.bl_idname, text=bone.name, icon='TRIA_RIGHT').prefix = bone.name col.operator(RIGIFY_OT_select_prefix_bones.bl_idname, text=bone.name, icon='TRIA_RIGHT').prefix = bone.name
else: else: