Changeset View
Changeset View
Standalone View
Standalone View
space_view3d_copy_attributes.py
| Show All 16 Lines | |||||
| # ##### END GPL LICENSE BLOCK ##### | # ##### END GPL LICENSE BLOCK ##### | ||||
| # <pep8 compliant> | # <pep8 compliant> | ||||
| bl_info = { | bl_info = { | ||||
| "name": "Copy Attributes Menu", | "name": "Copy Attributes Menu", | ||||
| "author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman", | "author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman", | ||||
| "version": (0, 4, 8), | "version": (0, 4, 8), | ||||
| "blender": (2, 63, 0), | "blender": (2, 80, 0), | ||||
| "location": "View3D > Ctrl-C", | "location": "View3D > Ctrl-C", | ||||
| "description": "Copy Attributes Menu from Blender 2.4", | "description": "Copy Attributes Menu from Blender 2.4", | ||||
| "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/" | "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/" | ||||
| "Scripts/3D_interaction/Copy_Attributes_Menu", | "Scripts/3D_interaction/Copy_Attributes_Menu", | ||||
| "category": "3D View", | "category": "3D View", | ||||
| } | } | ||||
| import bpy | import bpy | ||||
| from mathutils import Matrix | from mathutils import Matrix | ||||
| from bpy.types import ( | from bpy.types import ( | ||||
| Operator, | Operator, | ||||
| Menu, | Menu, | ||||
| ) | ) | ||||
| from bpy.props import ( | from bpy.props import ( | ||||
| BoolVectorProperty, | BoolVectorProperty, | ||||
| StringProperty, | StringProperty, | ||||
| ) | ) | ||||
| # First part of the operator Info message | # First part of the operator Info message | ||||
| INFO_MESSAGE = "Copy Attributes: " | INFO_MESSAGE = "Copy Attributes: " | ||||
| def build_exec(loopfunc, func): | def build_exec(loopfunc, func): | ||||
| """Generator function that returns exec functions for operators """ | """Generator function that returns exec functions for operators """ | ||||
| Show All 26 Lines | |||||
| def genops(copylist, oplist, prefix, poll_func, loopfunc): | def genops(copylist, oplist, prefix, poll_func, loopfunc): | ||||
| """Generate ops from the copy list and its associated functions""" | """Generate ops from the copy list and its associated functions""" | ||||
| for op in copylist: | for op in copylist: | ||||
| exec_func = build_exec(loopfunc, op[3]) | exec_func = build_exec(loopfunc, op[3]) | ||||
| invoke_func = build_invoke(loopfunc, op[3]) | invoke_func = build_invoke(loopfunc, op[3]) | ||||
| opclass = build_op(prefix + op[0], "Copy " + op[1], op[2], | opclass = build_op(prefix + op[0], "Copy " + op[1], op[2], | ||||
| poll_func, exec_func, invoke_func) | poll_func, exec_func, invoke_func) | ||||
| oplist.append(opclass) | oplist.append(opclass) | ||||
| def generic_copy(source, target, string=""): | def generic_copy(source, target, string=""): | ||||
| """Copy attributes from source to target that have string in them""" | """Copy attributes from source to target that have string in them""" | ||||
| for attr in dir(source): | for attr in dir(source): | ||||
| if attr.find(string) > -1: | if attr.find(string) > -1: | ||||
| try: | try: | ||||
| setattr(target, attr, getattr(source, attr)) | setattr(target, attr, getattr(source, attr)) | ||||
| except: | except: | ||||
| pass | pass | ||||
| return | return | ||||
| def getmat(bone, active, context, ignoreparent): | def getmat(bone, active, context, ignoreparent): | ||||
| """Helper function for visual transform copy, | """Helper function for visual transform copy, | ||||
| gets the active transform in bone space | gets the active transform in bone space | ||||
| """ | """ | ||||
| obj_act = context.active_object | obj_bone = bone.id_data | ||||
| data_bone = obj_act.data.bones[bone.name] | obj_active = active.id_data | ||||
| data_bone = obj_bone.data.bones[bone.name] | |||||
| # all matrices are in armature space unless commented otherwise | # all matrices are in armature space unless commented otherwise | ||||
| otherloc = active.matrix # final 4x4 mat of target, location. | active_to_selected = obj_bone.matrix_world.inverted() @ obj_active.matrix_world | ||||
| active_matrix = active_to_selected @ active.matrix | |||||
| otherloc = active_matrix # final 4x4 mat of target, location. | |||||
| bonemat_local = data_bone.matrix_local.copy() # self rest matrix | bonemat_local = data_bone.matrix_local.copy() # self rest matrix | ||||
| if data_bone.parent: | if data_bone.parent: | ||||
| parentposemat = obj_act.pose.bones[data_bone.parent.name].matrix.copy() | parentposemat = obj_bone.pose.bones[data_bone.parent.name].matrix.copy() | ||||
| parentbonemat = data_bone.parent.matrix_local.copy() | parentbonemat = data_bone.parent.matrix_local.copy() | ||||
| else: | else: | ||||
| parentposemat = parentbonemat = Matrix() | parentposemat = parentbonemat = Matrix() | ||||
| if parentbonemat == parentposemat or ignoreparent: | if parentbonemat == parentposemat or ignoreparent: | ||||
| newmat = bonemat_local.inverted() * otherloc | newmat = bonemat_local.inverted() @ otherloc | ||||
| else: | else: | ||||
| bonemat = parentbonemat.inverted() * bonemat_local | bonemat = parentbonemat.inverted() @ bonemat_local | ||||
| newmat = bonemat.inverted() * parentposemat.inverted() * otherloc | newmat = bonemat.inverted() @ parentposemat.inverted() @ otherloc | ||||
| return newmat | return newmat | ||||
| def rotcopy(item, mat): | def rotcopy(item, mat): | ||||
| """Copy rotation to item from matrix mat depending on item.rotation_mode""" | """Copy rotation to item from matrix mat depending on item.rotation_mode""" | ||||
| if item.rotation_mode == 'QUATERNION': | if item.rotation_mode == 'QUATERNION': | ||||
| item.rotation_quaternion = mat.to_3x3().to_quaternion() | item.rotation_quaternion = mat.to_3x3().to_quaternion() | ||||
| elif item.rotation_mode == 'AXIS_ANGLE': | elif item.rotation_mode == 'AXIS_ANGLE': | ||||
| Show All 27 Lines | def pLocScaExec(bone, active, context): | ||||
| bone.scale = active.scale | bone.scale = active.scale | ||||
| def pVisLocExec(bone, active, context): | def pVisLocExec(bone, active, context): | ||||
| bone.location = getmat(bone, active, context, False).to_translation() | bone.location = getmat(bone, active, context, False).to_translation() | ||||
| def pVisRotExec(bone, active, context): | def pVisRotExec(bone, active, context): | ||||
| obj_bone = bone.id_data | |||||
| rotcopy(bone, getmat(bone, active, | rotcopy(bone, getmat(bone, active, | ||||
| context, not context.active_object.data.bones[bone.name].use_inherit_rotation)) | context, not obj_bone.data.bones[bone.name].use_inherit_rotation)) | ||||
| def pVisScaExec(bone, active, context): | def pVisScaExec(bone, active, context): | ||||
| obj_bone = bone.id_data | |||||
| bone.scale = getmat(bone, active, context, | bone.scale = getmat(bone, active, context, | ||||
| not context.active_object.data.bones[bone.name].use_inherit_scale)\ | not obj_bone.data.bones[bone.name].use_inherit_scale)\ | ||||
| .to_scale() | .to_scale() | ||||
| def pDrwExec(bone, active, context): | def pDrwExec(bone, active, context): | ||||
| bone.custom_shape = active.custom_shape | bone.custom_shape = active.custom_shape | ||||
| bone.use_custom_shape_bone_size = active.use_custom_shape_bone_size | bone.use_custom_shape_bone_size = active.use_custom_shape_bone_size | ||||
| bone.custom_shape_scale = active.custom_shape_scale | bone.custom_shape_scale = active.custom_shape_scale | ||||
| bone.bone.show_wire = active.bone.show_wire | bone.bone.show_wire = active.bone.show_wire | ||||
| Show All 23 Lines | def pBBonesExec(bone, active, context): | ||||
| object = active.id_data | object = active.id_data | ||||
| generic_copy( | generic_copy( | ||||
| object.data.bones[active.name], | object.data.bones[active.name], | ||||
| object.data.bones[bone.name], | object.data.bones[bone.name], | ||||
| "bbone_") | "bbone_") | ||||
| pose_copies = ( | pose_copies = ( | ||||
| ('pose_loc_loc', "Local Location", | ('pose_loc_loc', "Local Location", | ||||
| "Copy Location from Active to Selected", pLocLocExec), | "Copy Location from Active to Selected", pLocLocExec), | ||||
| ('pose_loc_rot', "Local Rotation", | ('pose_loc_rot', "Local Rotation", | ||||
| "Copy Rotation from Active to Selected", pLocRotExec), | "Copy Rotation from Active to Selected", pLocRotExec), | ||||
| ('pose_loc_sca', "Local Scale", | ('pose_loc_sca', "Local Scale", | ||||
| "Copy Scale from Active to Selected", pLocScaExec), | "Copy Scale from Active to Selected", pLocScaExec), | ||||
| ('pose_vis_loc', "Visual Location", | ('pose_vis_loc', "Visual Location", | ||||
| "Copy Location from Active to Selected", pVisLocExec), | "Copy Location from Active to Selected", pVisLocExec), | ||||
| ('pose_vis_rot', "Visual Rotation", | ('pose_vis_rot', "Visual Rotation", | ||||
| "Copy Rotation from Active to Selected", pVisRotExec), | "Copy Rotation from Active to Selected", pVisRotExec), | ||||
| ('pose_vis_sca', "Visual Scale", | ('pose_vis_sca', "Visual Scale", | ||||
| "Copy Scale from Active to Selected", pVisScaExec), | "Copy Scale from Active to Selected", pVisScaExec), | ||||
| ('pose_drw', "Bone Shape", | ('pose_drw', "Bone Shape", | ||||
| "Copy Bone Shape from Active to Selected", pDrwExec), | "Copy Bone Shape from Active to Selected", pDrwExec), | ||||
| ('pose_lok', "Protected Transform", | ('pose_lok', "Protected Transform", | ||||
| "Copy Protected Tranforms from Active to Selected", pLokExec), | "Copy Protected Tranforms from Active to Selected", pLokExec), | ||||
| ('pose_con', "Bone Constraints", | ('pose_con', "Bone Constraints", | ||||
| "Copy Object Constraints from Active to Selected", pConExec), | "Copy Object Constraints from Active to Selected", pConExec), | ||||
| ('pose_iks', "IK Limits", | ('pose_iks', "IK Limits", | ||||
| "Copy IK Limits from Active to Selected", pIKsExec), | "Copy IK Limits from Active to Selected", pIKsExec), | ||||
| ('bbone_settings', "BBone Settings", | ('bbone_settings', "BBone Settings", | ||||
| "Copy BBone Settings from Active to Selected", pBBonesExec), | "Copy BBone Settings from Active to Selected", pBBonesExec), | ||||
| ) | ) | ||||
| @classmethod | @classmethod | ||||
| def pose_poll_func(cls, context): | def pose_poll_func(cls, context): | ||||
| return(context.mode == 'POSE') | return(context.mode == 'POSE') | ||||
| def pose_invoke_func(self, context, event): | def pose_invoke_func(self, context, event): | ||||
| wm = context.window_manager | wm = context.window_manager | ||||
| wm.invoke_props_dialog(self) | wm.invoke_props_dialog(self) | ||||
| return {'RUNNING_MODAL'} | return {'RUNNING_MODAL'} | ||||
| class CopySelectedPoseConstraints(Operator): | class CopySelectedPoseConstraints(Operator): | ||||
| """Copy Chosen constraints from active to selected""" | """Copy Chosen constraints from active to selected""" | ||||
| bl_idname = "pose.copy_selected_constraints" | bl_idname = "pose.copy_selected_constraints" | ||||
| bl_label = "Copy Selected Constraints" | bl_label = "Copy Selected Constraints" | ||||
| selection = BoolVectorProperty( | selection: BoolVectorProperty( | ||||
| size=32, | size=32, | ||||
| options={'SKIP_SAVE'} | options={'SKIP_SAVE'} | ||||
| ) | ) | ||||
| poll = pose_poll_func | poll = pose_poll_func | ||||
| invoke = pose_invoke_func | invoke = pose_invoke_func | ||||
| def draw(self, context): | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| for idx, const in enumerate(context.active_pose_bone.constraints): | for idx, const in enumerate(context.active_pose_bone.constraints): | ||||
| layout.prop(self, "selection", index=idx, text=const.name, | layout.prop(self, "selection", index=idx, text=const.name, | ||||
| toggle=True) | toggle=True) | ||||
| def execute(self, context): | def execute(self, context): | ||||
| active = context.active_pose_bone | active = context.active_pose_bone | ||||
| selected = context.selected_pose_bones[:] | selected = context.selected_pose_bones[:] | ||||
| selected.remove(active) | selected.remove(active) | ||||
| for bone in selected: | for bone in selected: | ||||
| for index, flag in enumerate(self.selection): | for index, flag in enumerate(self.selection): | ||||
| if flag: | if flag: | ||||
| old_constraint = active.constraints[index] | old_constraint = active.constraints[index] | ||||
| new_constraint = bone.constraints.new( | new_constraint = bone.constraints.new( | ||||
| active.constraints[index].type | active.constraints[index].type | ||||
| ) | ) | ||||
| generic_copy(old_constraint, new_constraint) | generic_copy(old_constraint, new_constraint) | ||||
| return {'FINISHED'} | return {'FINISHED'} | ||||
| pose_ops = [] # list of pose mode copy operators | pose_ops = [] # list of pose mode copy operators | ||||
| genops(pose_copies, pose_ops, "pose.copy_", pose_poll_func, pLoopExec) | genops(pose_copies, pose_ops, "pose.copy_", pose_poll_func, pLoopExec) | ||||
| Show All 18 Lines | def obLoopExec(self, context, funk): | ||||
| for obj in selected: | for obj in selected: | ||||
| msg = funk(obj, active, context) | msg = funk(obj, active, context) | ||||
| if msg: | if msg: | ||||
| self.report({msg[0]}, INFO_MESSAGE + msg[1]) | self.report({msg[0]}, INFO_MESSAGE + msg[1]) | ||||
| def world_to_basis(active, ob, context): | def world_to_basis(active, ob, context): | ||||
| """put world coords of active as basis coords of ob""" | """put world coords of active as basis coords of ob""" | ||||
| local = ob.parent.matrix_world.inverted() * active.matrix_world | local = ob.parent.matrix_world.inverted() @ active.matrix_world | ||||
| P = ob.matrix_basis * ob.matrix_local.inverted() | P = ob.matrix_basis @ ob.matrix_local.inverted() | ||||
| mat = P * local | mat = P @ local | ||||
| return(mat) | return(mat) | ||||
| # The following functions are used o copy attributes from | # The following functions are used o copy attributes from | ||||
| # active to selected object | # active to selected object | ||||
| def obLoc(ob, active, context): | def obLoc(ob, active, context): | ||||
| ob.location = active.location | ob.location = active.location | ||||
| Show All 30 Lines | if ob.parent: | ||||
| mat = world_to_basis(active, ob, context) | mat = world_to_basis(active, ob, context) | ||||
| ob.scale = mat.to_scale() | ob.scale = mat.to_scale() | ||||
| else: | else: | ||||
| ob.scale = active.matrix_world.to_scale() | ob.scale = active.matrix_world.to_scale() | ||||
| return('INFO', "Object scale copied") | return('INFO', "Object scale copied") | ||||
| def obDrw(ob, active, context): | def obDrw(ob, active, context): | ||||
| ob.draw_type = active.draw_type | ob.display_type = active.display_type | ||||
| ob.show_axis = active.show_axis | ob.show_axis = active.show_axis | ||||
| ob.show_bounds = active.show_bounds | ob.show_bounds = active.show_bounds | ||||
| ob.draw_bounds_type = active.draw_bounds_type | ob.display_bounds_type = active.display_bounds_type | ||||
| ob.show_name = active.show_name | ob.show_name = active.show_name | ||||
| ob.show_texture_space = active.show_texture_space | ob.show_texture_space = active.show_texture_space | ||||
| ob.show_transparent = active.show_transparent | ob.show_transparent = active.show_transparent | ||||
| ob.show_wire = active.show_wire | ob.show_wire = active.show_wire | ||||
| ob.show_x_ray = active.show_x_ray | ob.show_in_front = active.show_in_front | ||||
| ob.empty_draw_type = active.empty_draw_type | ob.empty_display_type = active.empty_display_type | ||||
| ob.empty_draw_size = active.empty_draw_size | ob.empty_display_size = active.empty_display_size | ||||
| def obOfs(ob, active, context): | def obOfs(ob, active, context): | ||||
| ob.time_offset = active.time_offset | ob.time_offset = active.time_offset | ||||
| return('INFO', "Time offset copied") | return('INFO', "Time offset copied") | ||||
| def obDup(ob, active, context): | def obDup(ob, active, context): | ||||
| generic_copy(active, ob, "dupli") | generic_copy(active, ob, "dupli") | ||||
| return('INFO', "Duplication method copied") | return('INFO', "Duplication method copied") | ||||
| def obCol(ob, active, context): | def obCol(ob, active, context): | ||||
| ob.color = active.color | ob.color = active.color | ||||
| def obMas(ob, active, context): | |||||
| ob.game.mass = active.game.mass | |||||
| return('INFO', "Mass copied") | |||||
| def obLok(ob, active, context): | def obLok(ob, active, context): | ||||
| for index, state in enumerate(active.lock_location): | for index, state in enumerate(active.lock_location): | ||||
| ob.lock_location[index] = state | ob.lock_location[index] = state | ||||
| for index, state in enumerate(active.lock_rotation): | for index, state in enumerate(active.lock_rotation): | ||||
| ob.lock_rotation[index] = state | ob.lock_rotation[index] = state | ||||
| ob.lock_rotations_4d = active.lock_rotations_4d | ob.lock_rotations_4d = active.lock_rotations_4d | ||||
| ob.lock_rotation_w = active.lock_rotation_w | ob.lock_rotation_w = active.lock_rotation_w | ||||
| for index, state in enumerate(active.lock_scale): | for index, state in enumerate(active.lock_scale): | ||||
| Show All 26 Lines | |||||
| def obMod(ob, active, context): | def obMod(ob, active, context): | ||||
| for modifier in ob.modifiers: | for modifier in ob.modifiers: | ||||
| # remove existing before adding new: | # remove existing before adding new: | ||||
| ob.modifiers.remove(modifier) | ob.modifiers.remove(modifier) | ||||
| for old_modifier in active.modifiers.values(): | for old_modifier in active.modifiers.values(): | ||||
| new_modifier = ob.modifiers.new(name=old_modifier.name, | new_modifier = ob.modifiers.new(name=old_modifier.name, | ||||
| type=old_modifier.type) | type=old_modifier.type) | ||||
| generic_copy(old_modifier, new_modifier) | generic_copy(old_modifier, new_modifier) | ||||
| return('INFO', "Modifiers copied") | return('INFO', "Modifiers copied") | ||||
| def obGrp(ob, active, context): | def obGrp(ob, active, context): | ||||
| for grp in bpy.data.groups: | for grp in bpy.data.groups: | ||||
| if active.name in grp.objects and ob.name not in grp.objects: | if active.name in grp.objects and ob.name not in grp.objects: | ||||
| grp.objects.link(ob) | grp.objects.link(ob) | ||||
| Show All 37 Lines | if ob != active: | ||||
| if v.index == vi_source: | if v.index == vi_source: | ||||
| for i in range(0, len(vgroupIndex_weight)): | for i in range(0, len(vgroupIndex_weight)): | ||||
| groupName = vgroups_IndexName[vgroupIndex_weight[i][0]] | groupName = vgroups_IndexName[vgroupIndex_weight[i][0]] | ||||
| groups = ob.vertex_groups | groups = ob.vertex_groups | ||||
| for vgs in range(0, len(groups)): | for vgs in range(0, len(groups)): | ||||
| if groups[vgs].name == groupName: | if groups[vgs].name == groupName: | ||||
| groups[vgs].add((v.index,), | groups[vgs].add((v.index,), | ||||
| vgroupIndex_weight[i][1], "REPLACE") | vgroupIndex_weight[i][1], "REPLACE") | ||||
| return('INFO', "Weights copied") | return('INFO', "Weights copied") | ||||
| object_copies = ( | object_copies = ( | ||||
| # ('obj_loc', "Location", | # ('obj_loc', "Location", | ||||
| # "Copy Location from Active to Selected", obLoc), | # "Copy Location from Active to Selected", obLoc), | ||||
| # ('obj_rot', "Rotation", | # ('obj_rot', "Rotation", | ||||
| # "Copy Rotation from Active to Selected", obRot), | # "Copy Rotation from Active to Selected", obRot), | ||||
| # ('obj_sca', "Scale", | # ('obj_sca', "Scale", | ||||
| # "Copy Scale from Active to Selected", obSca), | # "Copy Scale from Active to Selected", obSca), | ||||
| ('obj_vis_loc', "Location", | ('obj_vis_loc', "Location", | ||||
| "Copy Location from Active to Selected", obVisLoc), | "Copy Location from Active to Selected", obVisLoc), | ||||
| ('obj_vis_rot', "Rotation", | ('obj_vis_rot', "Rotation", | ||||
| "Copy Rotation from Active to Selected", obVisRot), | "Copy Rotation from Active to Selected", obVisRot), | ||||
| ('obj_vis_sca', "Scale", | ('obj_vis_sca', "Scale", | ||||
| "Copy Scale from Active to Selected", obVisSca), | "Copy Scale from Active to Selected", obVisSca), | ||||
| ('obj_drw', "Draw Options", | ('obj_drw', "Draw Options", | ||||
| "Copy Draw Options from Active to Selected", obDrw), | "Copy Draw Options from Active to Selected", obDrw), | ||||
| ('obj_ofs', "Time Offset", | ('obj_ofs', "Time Offset", | ||||
| "Copy Time Offset from Active to Selected", obOfs), | "Copy Time Offset from Active to Selected", obOfs), | ||||
| ('obj_dup', "Dupli", | ('obj_dup', "Dupli", | ||||
| "Copy Dupli from Active to Selected", obDup), | "Copy Dupli from Active to Selected", obDup), | ||||
| ('obj_col', "Object Color", | ('obj_col', "Object Color", | ||||
| "Copy Object Color from Active to Selected", obCol), | "Copy Object Color from Active to Selected", obCol), | ||||
| ('obj_mas', "Mass", | |||||
| "Copy Mass from Active to Selected", obMas), | |||||
| # ('obj_dmp', "Damping", | # ('obj_dmp', "Damping", | ||||
| # "Copy Damping from Active to Selected"), | # "Copy Damping from Active to Selected"), | ||||
| # ('obj_all', "All Physical Attributes", | # ('obj_all', "All Physical Attributes", | ||||
| # "Copy Physical Attributes from Active to Selected"), | # "Copy Physical Attributes from Active to Selected"), | ||||
| # ('obj_prp', "Properties", | # ('obj_prp', "Properties", | ||||
| # "Copy Properties from Active to Selected"), | # "Copy Properties from Active to Selected"), | ||||
| # ('obj_log', "Logic Bricks", | # ('obj_log', "Logic Bricks", | ||||
| # "Copy Logic Bricks from Active to Selected"), | # "Copy Logic Bricks from Active to Selected"), | ||||
| ('obj_lok', "Protected Transform", | ('obj_lok', "Protected Transform", | ||||
| "Copy Protected Tranforms from Active to Selected", obLok), | "Copy Protected Tranforms from Active to Selected", obLok), | ||||
| ('obj_con', "Object Constraints", | ('obj_con', "Object Constraints", | ||||
| "Copy Object Constraints from Active to Selected", obCon), | "Copy Object Constraints from Active to Selected", obCon), | ||||
| # ('obj_nla', "NLA Strips", | # ('obj_nla', "NLA Strips", | ||||
| # "Copy NLA Strips from Active to Selected"), | # "Copy NLA Strips from Active to Selected"), | ||||
| # ('obj_tex', "Texture Space", | # ('obj_tex', "Texture Space", | ||||
| # "Copy Texture Space from Active to Selected", obTex), | # "Copy Texture Space from Active to Selected", obTex), | ||||
| # ('obj_sub', "Subsurf Settings", | # ('obj_sub', "Subsurf Settings", | ||||
| # "Copy Subsurf Setings from Active to Selected"), | # "Copy Subsurf Setings from Active to Selected"), | ||||
| # ('obj_smo', "AutoSmooth", | # ('obj_smo', "AutoSmooth", | ||||
| # "Copy AutoSmooth from Active to Selected"), | # "Copy AutoSmooth from Active to Selected"), | ||||
| ('obj_idx', "Pass Index", | ('obj_idx', "Pass Index", | ||||
| "Copy Pass Index from Active to Selected", obIdx), | "Copy Pass Index from Active to Selected", obIdx), | ||||
| ('obj_mod', "Modifiers", | ('obj_mod', "Modifiers", | ||||
| "Copy Modifiers from Active to Selected", obMod), | "Copy Modifiers from Active to Selected", obMod), | ||||
| ('obj_wei', "Vertex Weights", | ('obj_wei', "Vertex Weights", | ||||
| "Copy vertex weights based on indices", obWei), | "Copy vertex weights based on indices", obWei), | ||||
| ('obj_grp', "Group Links", | ('obj_grp', "Group Links", | ||||
| "Copy selected into active object's groups", obGrp) | "Copy selected into active object's groups", obGrp) | ||||
| ) | ) | ||||
| @classmethod | @classmethod | ||||
| def object_poll_func(cls, context): | def object_poll_func(cls, context): | ||||
| return (len(context.selected_objects) > 1) | return (len(context.selected_objects) > 1) | ||||
| def object_invoke_func(self, context, event): | def object_invoke_func(self, context, event): | ||||
| wm = context.window_manager | wm = context.window_manager | ||||
| wm.invoke_props_dialog(self) | wm.invoke_props_dialog(self) | ||||
| return {'RUNNING_MODAL'} | return {'RUNNING_MODAL'} | ||||
| class CopySelectedObjectConstraints(Operator): | class CopySelectedObjectConstraints(Operator): | ||||
| """Copy Chosen constraints from active to selected""" | """Copy Chosen constraints from active to selected""" | ||||
| bl_idname = "object.copy_selected_constraints" | bl_idname = "object.copy_selected_constraints" | ||||
| bl_label = "Copy Selected Constraints" | bl_label = "Copy Selected Constraints" | ||||
| selection = BoolVectorProperty( | selection: BoolVectorProperty( | ||||
| size=32, | size=32, | ||||
| options={'SKIP_SAVE'} | options={'SKIP_SAVE'} | ||||
| ) | ) | ||||
| poll = object_poll_func | poll = object_poll_func | ||||
| invoke = object_invoke_func | invoke = object_invoke_func | ||||
| def draw(self, context): | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| for idx, const in enumerate(context.active_object.constraints): | for idx, const in enumerate(context.active_object.constraints): | ||||
| layout.prop(self, "selection", index=idx, text=const.name, | layout.prop(self, "selection", index=idx, text=const.name, | ||||
| toggle=True) | toggle=True) | ||||
| def execute(self, context): | def execute(self, context): | ||||
| active = context.active_object | active = context.active_object | ||||
| selected = context.selected_objects[:] | selected = context.selected_objects[:] | ||||
| selected.remove(active) | selected.remove(active) | ||||
| for obj in selected: | for obj in selected: | ||||
| for index, flag in enumerate(self.selection): | for index, flag in enumerate(self.selection): | ||||
| if flag: | if flag: | ||||
| old_constraint = active.constraints[index] | old_constraint = active.constraints[index] | ||||
| new_constraint = obj.constraints.new( | new_constraint = obj.constraints.new( | ||||
| active.constraints[index].type | active.constraints[index].type | ||||
| ) | ) | ||||
| generic_copy(old_constraint, new_constraint) | generic_copy(old_constraint, new_constraint) | ||||
| return{'FINISHED'} | return{'FINISHED'} | ||||
| class CopySelectedObjectModifiers(Operator): | class CopySelectedObjectModifiers(Operator): | ||||
| """Copy Chosen modifiers from active to selected""" | """Copy Chosen modifiers from active to selected""" | ||||
| bl_idname = "object.copy_selected_modifiers" | bl_idname = "object.copy_selected_modifiers" | ||||
| bl_label = "Copy Selected Modifiers" | bl_label = "Copy Selected Modifiers" | ||||
| selection = BoolVectorProperty( | selection: BoolVectorProperty( | ||||
| size=32, | size=32, | ||||
| options={'SKIP_SAVE'} | options={'SKIP_SAVE'} | ||||
| ) | ) | ||||
| poll = object_poll_func | poll = object_poll_func | ||||
| invoke = object_invoke_func | invoke = object_invoke_func | ||||
| def draw(self, context): | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| for idx, const in enumerate(context.active_object.modifiers): | for idx, const in enumerate(context.active_object.modifiers): | ||||
| layout.prop(self, 'selection', index=idx, text=const.name, | layout.prop(self, 'selection', index=idx, text=const.name, | ||||
| toggle=True) | toggle=True) | ||||
| def execute(self, context): | def execute(self, context): | ||||
| active = context.active_object | active = context.active_object | ||||
| selected = context.selected_objects[:] | selected = context.selected_objects[:] | ||||
| selected.remove(active) | selected.remove(active) | ||||
| for obj in selected: | for obj in selected: | ||||
| for index, flag in enumerate(self.selection): | for index, flag in enumerate(self.selection): | ||||
| if flag: | if flag: | ||||
| old_modifier = active.modifiers[index] | old_modifier = active.modifiers[index] | ||||
| new_modifier = obj.modifiers.new( | new_modifier = obj.modifiers.new( | ||||
| type=active.modifiers[index].type, | type=active.modifiers[index].type, | ||||
| name=active.modifiers[index].name | name=active.modifiers[index].name | ||||
| ) | ) | ||||
| generic_copy(old_modifier, new_modifier) | generic_copy(old_modifier, new_modifier) | ||||
| return{'FINISHED'} | return{'FINISHED'} | ||||
| object_ops = [] | object_ops = [] | ||||
| genops(object_copies, object_ops, "object.copy_", object_poll_func, obLoopExec) | genops(object_copies, object_ops, "object.copy_", object_poll_func, obLoopExec) | ||||
| Show All 35 Lines | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| layout.operator("view3d.copybuffer", icon="COPY_ID") | layout.operator("view3d.copybuffer", icon="COPY_ID") | ||||
| layout.operator("view3d.pastebuffer", icon="COPY_ID") | layout.operator("view3d.pastebuffer", icon="COPY_ID") | ||||
| layout.separator() | layout.separator() | ||||
| op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | ||||
| text="Copy Material") | text="Copy Material") | ||||
| op['layer'] = '' | op['layer'] = '' | ||||
| op['mode'] = 'MAT' | op['mode'] = 'MAT' | ||||
| if mesh.uv_textures.active: | if mesh.uv_textures.active: | ||||
| op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | ||||
| text="Copy Active UV Image") | text="Copy Active UV Image") | ||||
| op['layer'] = '' | op['layer'] = '' | ||||
| op['mode'] = 'IMAGE' | op['mode'] = 'IMAGE' | ||||
| op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | ||||
| text="Copy Active UV Coords") | text="Copy Active UV Coords") | ||||
| op['layer'] = '' | op['layer'] = '' | ||||
| op['mode'] = 'UV' | op['mode'] = 'UV' | ||||
| if mesh.vertex_colors.active: | if mesh.vertex_colors.active: | ||||
| op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, | ||||
| text="Copy Active Vertex Colors") | text="Copy Active Vertex Colors") | ||||
| op['layer'] = '' | op['layer'] = '' | ||||
| op['mode'] = 'VCOL' | op['mode'] = 'VCOL' | ||||
| if uv or vc: | if uv or vc: | ||||
| layout.separator() | layout.separator() | ||||
| if uv: | if uv: | ||||
| layout.menu("MESH_MT_CopyImagesFromLayer") | layout.menu("MESH_MT_CopyImagesFromLayer") | ||||
| layout.menu("MESH_MT_CopyUVCoordsFromLayer") | layout.menu("MESH_MT_CopyUVCoordsFromLayer") | ||||
| if vc: | if vc: | ||||
| layout.menu("MESH_MT_CopyVertexColorsFromLayer") | layout.menu("MESH_MT_CopyVertexColorsFromLayer") | ||||
| # Data (UV map, Image and Vertex color) menus calling MESH_OT_CopyFaceSettings | # Data (UV map, Image and Vertex color) menus calling MESH_OT_CopyFaceSettings | ||||
| # Explicitly defined as using the generator code was broken in case of Menus | # Explicitly defined as using the generator code was broken in case of Menus | ||||
| # causing issues with access and registration | # causing issues with access and registration | ||||
| class MESH_MT_CopyImagesFromLayer(Menu): | class MESH_MT_CopyImagesFromLayer(Menu): | ||||
| bl_label = "Copy Other UV Image Layers" | bl_label = "Copy Other UV Image Layers" | ||||
| @classmethod | @classmethod | ||||
| def poll(cls, context): | def poll(cls, context): | ||||
| obj = context.active_object | obj = context.active_object | ||||
| return obj and obj.mode == "EDIT_MESH" and len( | return obj and obj.mode == "EDIT_MESH" and len( | ||||
| obj.data.uv_layers) > 1 | obj.data.uv_layers) > 1 | ||||
| def draw(self, context): | def draw(self, context): | ||||
| mesh = context.active_object.data | mesh = context.active_object.data | ||||
| _buildmenu(self, mesh, 'IMAGE', "IMAGE_COL") | _buildmenu(self, mesh, 'IMAGE', "IMAGE_COL") | ||||
| class MESH_MT_CopyUVCoordsFromLayer(Menu): | class MESH_MT_CopyUVCoordsFromLayer(Menu): | ||||
| bl_label = "Copy Other UV Coord Layers" | bl_label = "Copy Other UV Coord Layers" | ||||
| @classmethod | @classmethod | ||||
| def poll(cls, context): | def poll(cls, context): | ||||
| obj = context.active_object | obj = context.active_object | ||||
| return obj and obj.mode == "EDIT_MESH" and len( | return obj and obj.mode == "EDIT_MESH" and len( | ||||
| obj.data.uv_layers) > 1 | obj.data.uv_layers) > 1 | ||||
| def draw(self, context): | def draw(self, context): | ||||
| mesh = context.active_object.data | mesh = context.active_object.data | ||||
| _buildmenu(self, mesh, 'UV', "GROUP_UVS") | _buildmenu(self, mesh, 'UV', "GROUP_UVS") | ||||
| class MESH_MT_CopyVertexColorsFromLayer(Menu): | class MESH_MT_CopyVertexColorsFromLayer(Menu): | ||||
| bl_label = "Copy Other Vertex Colors Layers" | bl_label = "Copy Other Vertex Colors Layers" | ||||
| @classmethod | @classmethod | ||||
| def poll(cls, context): | def poll(cls, context): | ||||
| obj = context.active_object | obj = context.active_object | ||||
| return obj and obj.mode == "EDIT_MESH" and len( | return obj and obj.mode == "EDIT_MESH" and len( | ||||
| obj.data.vertex_colors) > 1 | obj.data.vertex_colors) > 1 | ||||
| def draw(self, context): | def draw(self, context): | ||||
| mesh = context.active_object.data | mesh = context.active_object.data | ||||
| _buildmenu(self, mesh, 'VCOL', "GROUP_VCOL") | _buildmenu(self, mesh, 'VCOL', "GROUP_VCOL") | ||||
| def _buildmenu(self, mesh, mode, icon): | def _buildmenu(self, mesh, mode, icon): | ||||
| layout = self.layout | layout = self.layout | ||||
| Show All 10 Lines | |||||
| class MESH_OT_CopyFaceSettings(Operator): | class MESH_OT_CopyFaceSettings(Operator): | ||||
| """Copy settings from active face to all selected faces""" | """Copy settings from active face to all selected faces""" | ||||
| bl_idname = 'mesh.copy_face_settings' | bl_idname = 'mesh.copy_face_settings' | ||||
| bl_label = "Copy Face Settings" | bl_label = "Copy Face Settings" | ||||
| bl_options = {'REGISTER', 'UNDO'} | bl_options = {'REGISTER', 'UNDO'} | ||||
| mode = StringProperty( | mode: StringProperty( | ||||
| name="Mode", | name="Mode", | ||||
| options={"HIDDEN"}, | options={"HIDDEN"}, | ||||
| ) | ) | ||||
| layer = StringProperty( | layer: StringProperty( | ||||
| name="Layer", | name="Layer", | ||||
| options={"HIDDEN"}, | options={"HIDDEN"}, | ||||
| ) | ) | ||||
| @classmethod | @classmethod | ||||
| def poll(cls, context): | def poll(cls, context): | ||||
| return context.mode == 'EDIT_MESH' | return context.mode == 'EDIT_MESH' | ||||
| def execute(self, context): | def execute(self, context): | ||||
| mode = getattr(self, 'mode', '') | mode = getattr(self, 'mode', '') | ||||
| if mode not in {'MAT', 'VCOL', 'IMAGE', 'UV'}: | if mode not in {'MAT', 'VCOL', 'IMAGE', 'UV'}: | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | class MESH_OT_CopyFaceSettings(Operator): | ||||
| def _end(self, context, retval): | def _end(self, context, retval): | ||||
| if context.mode != 'EDIT_MESH': | if context.mode != 'EDIT_MESH': | ||||
| # Clean up by returning to edit mode like it was before. | # Clean up by returning to edit mode like it was before. | ||||
| bpy.ops.object.editmode_toggle() | bpy.ops.object.editmode_toggle() | ||||
| return(retval) | return(retval) | ||||
| classes = ( | |||||
| CopySelectedPoseConstraints, | |||||
| VIEW3D_MT_posecopypopup, | |||||
| CopySelectedObjectConstraints, | |||||
| CopySelectedObjectModifiers, | |||||
| VIEW3D_MT_copypopup, | |||||
| MESH_MT_CopyFaceSettings, | |||||
| MESH_MT_CopyImagesFromLayer, | |||||
| MESH_MT_CopyUVCoordsFromLayer, | |||||
| MESH_MT_CopyVertexColorsFromLayer, | |||||
| MESH_OT_CopyFaceSettings, | |||||
| *pose_ops, | |||||
| *object_ops, | |||||
| ) | |||||
| def register(): | def register(): | ||||
| bpy.utils.register_module(__name__) | from bpy.utils import register_class | ||||
| for cls in classes: | |||||
| register_class(cls) | |||||
| # mostly to get the keymap working | # mostly to get the keymap working | ||||
| kc = bpy.context.window_manager.keyconfigs.addon | kc = bpy.context.window_manager.keyconfigs.addon | ||||
| if kc: | if kc: | ||||
| km = kc.keymaps.new(name="Object Mode") | km = kc.keymaps.new(name="Object Mode") | ||||
| kmi = km.keymap_items.new('wm.call_menu', 'C', 'PRESS', ctrl=True) | kmi = km.keymap_items.new('wm.call_menu', 'C', 'PRESS', ctrl=True) | ||||
| kmi.properties.name = 'VIEW3D_MT_copypopup' | kmi.properties.name = 'VIEW3D_MT_copypopup' | ||||
| Show All 32 Lines | if kc: | ||||
| km = kc.keymaps.get('Object Mode') | km = kc.keymaps.get('Object Mode') | ||||
| if km is not None: | if km is not None: | ||||
| for kmi in km.keymap_items: | for kmi in km.keymap_items: | ||||
| if kmi.idname == 'wm.call_menu': | if kmi.idname == 'wm.call_menu': | ||||
| if kmi.properties.name == 'VIEW3D_MT_copypopup': | if kmi.properties.name == 'VIEW3D_MT_copypopup': | ||||
| km.keymap_items.remove(kmi) | km.keymap_items.remove(kmi) | ||||
| bpy.utils.unregister_module(__name__) | from bpy.utils import unregister_class | ||||
| for cls in classes: | |||||
| unregister_class(cls) | |||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||
| register() | register() | ||||