Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xio_scene_gltf2/__init__.py2
-rw-r--r--rigify/operators/copy_mirror_parameters.py150
-rw-r--r--rigify/rigs/limbs/super_finger.py6
-rw-r--r--rigify/utils/layers.py6
-rw-r--r--rigify/utils/mechanism.py12
-rw-r--r--space_view3d_copy_attributes.py101
6 files changed, 269 insertions, 8 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index babf37fb..069596fa 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
- "version": (1, 7, 33),
+ "version": (1, 8, 2),
'blender': (3, 0, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
diff --git a/rigify/operators/copy_mirror_parameters.py b/rigify/operators/copy_mirror_parameters.py
index 95818ba8..a844f8da 100644
--- a/rigify/operators/copy_mirror_parameters.py
+++ b/rigify/operators/copy_mirror_parameters.py
@@ -22,6 +22,7 @@ import bpy
import importlib
from ..utils.naming import Side, get_name_base_and_sides, mirror_name
+from ..utils.misc import property_to_python
from ..utils.rig import get_rigify_type
from ..rig_lists import get_rig_class
@@ -109,11 +110,157 @@ def make_copy_parameter_button(layout, property_name, *, base_class, mirror_bone
props.class_name = base_class.__name__
+def recursive_mirror(value):
+ """Mirror strings(.L/.R) in any mixed structure of dictionaries/lists."""
+
+ if isinstance(value, dict):
+ return { key: recursive_mirror(val) for key, val in value.items() }
+
+ elif isinstance(value, list):
+ return [recursive_mirror(elem) for elem in value]
+
+ elif isinstance(value, str):
+ return mirror_name(value)
+
+ else:
+ return value
+
+
+def copy_rigify_params(from_bone: bpy.types.PoseBone, to_bone: bpy.types.PoseBone, *, match_type=False, x_mirror=False) -> bool:
+ rig_type = to_bone.rigify_type
+ if match_type and to_bone.rigify_type != from_bone.rigify_type:
+ return False
+ else:
+ rig_type = to_bone.rigify_type = get_rigify_type(from_bone)
+
+ from_params = from_bone.get('rigify_parameters')
+ if from_params and rig_type:
+ param_dict = property_to_python(from_params)
+ if x_mirror:
+ param_dict = recursive_mirror(param_dict)
+ to_bone['rigify_parameters'] = param_dict
+ else:
+ try:
+ del to_bone['rigify_parameters']
+ except KeyError:
+ pass
+ return True
+
+
+class POSE_OT_rigify_mirror_parameters(bpy.types.Operator):
+ """Mirror Rigify type and parameters of selected bones to the opposite side. Names should end in L/R"""
+
+ bl_idname = "pose.rigify_mirror_parameters"
+ bl_label = "Mirror Rigify Parameters"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ if not obj or obj.type != 'ARMATURE' or obj.mode != 'POSE':
+ return False
+ sel_bones = context.selected_pose_bones
+ if not sel_bones:
+ return False
+ for pb in sel_bones:
+ mirrored_name = mirror_name(pb.name)
+ if mirrored_name != pb.name and mirrored_name in obj.pose.bones:
+ return True
+ return False
+
+ def execute(self, context):
+ rig = context.object
+
+ num_mirrored = 0
+
+ # First make sure that all selected bones can be mirrored unambiguously.
+ for pb in context.selected_pose_bones:
+ flip_bone = rig.pose.bones.get(mirror_name(pb.name))
+ if not flip_bone:
+ # Bones without an opposite will just be ignored.
+ continue
+ if flip_bone != pb and flip_bone.bone.select:
+ self.report(
+ {'ERROR'}, f"Bone {pb.name} selected on both sides, mirroring would be ambiguous, aborting. Only select the left or right side, not both!")
+ return {'CANCELLED'}
+
+ # Then mirror the parameters.
+ for pb in context.selected_pose_bones:
+ flip_bone = rig.pose.bones.get(mirror_name(pb.name))
+ if flip_bone == pb or not flip_bone:
+ # Bones without an opposite will just be ignored.
+ continue
+
+ num_mirrored += copy_rigify_params(pb, flip_bone, match_type=False, x_mirror=True)
+
+ self.report({'INFO'}, f"Mirrored parameters of {num_mirrored} bones.")
+
+ return {'FINISHED'}
+
+
+class POSE_OT_rigify_copy_parameters(bpy.types.Operator):
+ """Copy Rigify type and parameters from active to selected bones"""
+
+ bl_idname = "pose.rigify_copy_parameters"
+ bl_label = "Copy Rigify Parameters to Selected"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ match_type: bpy.props.BoolProperty(
+ name = "Match Type",
+ description = "Only mirror rigify parameters to selected bones which have the same rigify type as the active bone",
+ default = False
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ if not obj or obj.type != 'ARMATURE' or obj.mode != 'POSE':
+ return False
+
+ active = context.active_pose_bone
+ if not active or not active.rigify_type:
+ return False
+
+ select = context.selected_pose_bones
+ if len(select) < 2 or active not in select:
+ return False
+
+ return True
+
+ def execute(self, context):
+ active_bone = context.active_pose_bone
+
+ num_copied = 0
+ for pb in context.selected_pose_bones:
+ if pb == active_bone:
+ continue
+ num_copied += copy_rigify_params(active_bone, pb, match_type=self.match_type)
+
+ self.report({'INFO'}, f"Copied {active_bone.rigify_type} parameters to {num_copied} bones.")
+
+ return {'FINISHED'}
+
+
+def draw_copy_mirror_ops(self, context):
+ layout = self.layout
+ if context.mode == 'POSE':
+ layout.separator()
+ op = layout.operator(POSE_OT_rigify_copy_parameters.bl_idname,
+ icon='DUPLICATE', text="Copy Only Parameters")
+ op.match_type = True
+ op = layout.operator(POSE_OT_rigify_copy_parameters.bl_idname,
+ icon='DUPLICATE', text="Copy Type & Parameters")
+ op.match_type = False
+ layout.operator(POSE_OT_rigify_mirror_parameters.bl_idname,
+ icon='MOD_MIRROR', text="Mirror Type & Parameters")
+
# =============================================
# Registration
classes = (
POSE_OT_rigify_copy_single_parameter,
+ POSE_OT_rigify_mirror_parameters,
+ POSE_OT_rigify_copy_parameters
)
@@ -122,8 +269,11 @@ def register():
for cls in classes:
register_class(cls)
+ bpy.types.VIEW3D_MT_rigify.append(draw_copy_mirror_ops)
def unregister():
from bpy.utils import unregister_class
for cls in classes:
unregister_class(cls)
+
+ bpy.types.VIEW3D_MT_rigify.remove(draw_copy_mirror_ops)
diff --git a/rigify/rigs/limbs/super_finger.py b/rigify/rigs/limbs/super_finger.py
index b50d54f9..a6e329bb 100644
--- a/rigify/rigs/limbs/super_finger.py
+++ b/rigify/rigs/limbs/super_finger.py
@@ -174,6 +174,8 @@ class Rig(SimpleChainRig):
bone.lock_rotation_w = True
bone.lock_scale = True, True, True
+ ControlLayersOption.EXTRA_IK.assign_rig(self, [self.bones.ctrl.ik])
+
@stage.configure_bones
def configure_ik_control_properties(self):
if self.make_ik:
@@ -379,6 +381,7 @@ class Rig(SimpleChainRig):
)
ControlLayersOption.TWEAK.add_parameters(params)
+ ControlLayersOption.EXTRA_IK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
@@ -393,6 +396,9 @@ class Rig(SimpleChainRig):
ControlLayersOption.TWEAK.parameters_ui(layout, params)
+ if params.make_extra_ik_control:
+ ControlLayersOption.EXTRA_IK.parameters_ui(layout, params)
+
#############################
# Finger FK to IK operator ##
#############################
diff --git a/rigify/utils/layers.py b/rigify/utils/layers.py
index bc5a8c56..27c67f0b 100644
--- a/rigify/utils/layers.py
+++ b/rigify/utils/layers.py
@@ -157,6 +157,12 @@ class ControlLayersOption:
ControlLayersOption.FK = ControlLayersOption('fk', description="Layers for the FK controls to be on")
ControlLayersOption.TWEAK = ControlLayersOption('tweak', description="Layers for the tweak controls to be on")
+ControlLayersOption.EXTRA_IK = ControlLayersOption(
+ 'extra_ik', toggle_default=False,
+ toggle_name="Extra IK Layers",
+ description="Layers for the optional IK controls to be on",
+)
+
# Layer parameters used by the super_face rig.
ControlLayersOption.FACE_PRIMARY = ControlLayersOption('primary', description="Layers for the primary controls to be on")
ControlLayersOption.FACE_SECONDARY = ControlLayersOption('secondary', description="Layers for the secondary controls to be on")
diff --git a/rigify/utils/mechanism.py b/rigify/utils/mechanism.py
index 00aef154..0b5c8d93 100644
--- a/rigify/utils/mechanism.py
+++ b/rigify/utils/mechanism.py
@@ -463,14 +463,20 @@ def reactivate_custom_properties(obj):
def copy_custom_properties(src, dest, *, prefix='', dest_prefix='', link_driver=False, overridable=True):
"""Copy custom properties with filtering by prefix. Optionally link using drivers."""
res = []
- exclude = {'rigify_parameters', 'rigify_type'}
+
+ # Exclude addon-defined properties.
+ exclude = {prop.identifier for prop in src.bl_rna.properties if prop.is_runtime}
for key, value in src.items():
if key.startswith(prefix) and key not in exclude:
new_key = dest_prefix + key[len(prefix):]
- ui_data_src = src.id_properties_ui(key)
-
+ try:
+ ui_data_src = src.id_properties_ui(key)
+ except TypeError:
+ # Some property types, eg. Python dictionaries
+ # don't support id_properties_ui.
+ continue
if src != dest or new_key != key:
dest[new_key] = value
diff --git a/space_view3d_copy_attributes.py b/space_view3d_copy_attributes.py
index 29da77ab..9496ed1d 100644
--- a/space_view3d_copy_attributes.py
+++ b/space_view3d_copy_attributes.py
@@ -20,11 +20,11 @@
bl_info = {
"name": "Copy Attributes Menu",
- "author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman",
- "version": (0, 4, 9),
- "blender": (2, 80, 0),
+ "author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman, Demeter Dzadik",
+ "version": (0, 5, 0),
+ "blender": (3, 0, 0),
"location": "View3D > Ctrl-C",
- "description": "Copy Attributes Menu from Blender 2.4",
+ "description": "Copy Attributes Menu",
"doc_url": "{BLENDER_MANUAL_URL}/addons/interface/copy_attributes.html",
"category": "Interface",
}
@@ -248,6 +248,79 @@ def pose_invoke_func(self, context, event):
return {'RUNNING_MODAL'}
+CustomPropSelectionBoolsProperty = BoolVectorProperty(
+ size=32,
+ options={'SKIP_SAVE'}
+)
+
+class CopySelection:
+ """Base class for copying properties from active to selected based on a selection."""
+
+ selection: CustomPropSelectionBoolsProperty
+
+ def draw_bools(self, button_names):
+ """Draws the boolean toggle list with a list of strings for the button texts."""
+ layout = self.layout
+ for idx, name in enumerate(button_names):
+ layout.prop(self, "selection", index=idx, text=name,
+ toggle=True)
+
+def copy_custom_property(source, destination, prop_name):
+ """Copy a custom property called prop_name, from source to destination.
+ source and destination must be a Blender data type that can hold custom properties.
+ For a list of such data types, see:
+ https://docs.blender.org/manual/en/latest/files/data_blocks.html#files-data-blocks-custom-properties
+ """
+
+ # Create the property.
+ destination[prop_name] = source[prop_name]
+ # Copy the settings of the property.
+ try:
+ dst_prop_manager = destination.id_properties_ui(prop_name)
+ except TypeError:
+ # Python values like lists or dictionaries don't have any settings to copy.
+ # They just consist of a value and nothing else.
+ return
+
+ src_prop_manager = source.id_properties_ui(prop_name)
+ assert src_prop_manager, f'Property "{prop_name}" not found in {source}'
+
+ dst_prop_manager.update_from(src_prop_manager)
+
+ # Copy the Library Overridable flag, which is stored elsewhere.
+ prop_rna_path = f'["{prop_name}"]'
+ is_lib_overridable = source.is_property_overridable_library(prop_rna_path)
+ destination.property_overridable_library_set(prop_rna_path, is_lib_overridable)
+
+class CopyCustomProperties(CopySelection):
+ """Base class for copying a selection of custom properties."""
+
+ def copy_selected_custom_props(self, active, selected):
+ keys = list(active.keys())
+ for item in selected:
+ if item == active:
+ continue
+ for index, is_selected in enumerate(self.selection):
+ if is_selected:
+ copy_custom_property(active, item, keys[index])
+
+class CopySelectedBoneCustomProperties(CopyCustomProperties, Operator):
+ """Copy Chosen custom properties from active to selected"""
+ bl_idname = "pose.copy_selected_custom_props"
+ bl_label = "Copy Selected Custom Properties"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ poll = pose_poll_func
+ invoke = pose_invoke_func
+
+ def draw(self, context):
+ self.draw_bools(context.active_pose_bone.keys())
+
+ def execute(self, context):
+ self.copy_selected_custom_props(context.active_pose_bone, context.selected_pose_bones)
+ return {'FINISHED'}
+
+
class CopySelectedPoseConstraints(Operator):
"""Copy Chosen constraints from active to selected"""
bl_idname = "pose.copy_selected_constraints"
@@ -291,6 +364,7 @@ class VIEW3D_MT_posecopypopup(Menu):
for op in pose_copies:
layout.operator("pose.copy_" + op[0])
layout.operator("pose.copy_selected_constraints")
+ layout.operator("pose.copy_selected_custom_props")
layout.operator("pose.copy", text="copy pose")
@@ -614,6 +688,22 @@ class CopySelectedObjectModifiers(Operator):
return{'FINISHED'}
+class CopySelectedObjectCustomProperties(CopyCustomProperties, Operator):
+ """Copy Chosen custom properties from active to selected objects"""
+ bl_idname = "object.copy_selected_custom_props"
+ bl_label = "Copy Selected Custom Properties"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ poll = object_poll_func
+ invoke = object_invoke_func
+
+ def draw(self, context):
+ self.draw_bools(context.object.keys())
+
+ def execute(self, context):
+ self.copy_selected_custom_props(context.object, context.selected_objects)
+ return {'FINISHED'}
+
object_ops = []
genops(object_copies, object_ops, "object.copy_", object_poll_func, obLoopExec)
@@ -638,6 +728,7 @@ class VIEW3D_MT_copypopup(Menu):
layout.operator("object.copy_" + op[0])
layout.operator("object.copy_selected_constraints")
layout.operator("object.copy_selected_modifiers")
+ layout.operator("object.copy_selected_custom_props")
# Begin Mesh copy settings:
@@ -810,9 +901,11 @@ class MESH_OT_CopyFaceSettings(Operator):
classes = (
CopySelectedPoseConstraints,
+ CopySelectedBoneCustomProperties,
VIEW3D_MT_posecopypopup,
CopySelectedObjectConstraints,
CopySelectedObjectModifiers,
+ CopySelectedObjectCustomProperties,
VIEW3D_MT_copypopup,
MESH_MT_CopyFaceSettings,
MESH_MT_CopyUVCoordsFromLayer,