Newer
Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
"name": "Copy Attributes Menu",
"author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman",
"version": (0, 4, 8),
"location": "View3D > Ctrl-C",
"description": "Copy Attributes Menu from Blender 2.4",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/3D_interaction/Copy_Attributes_Menu",
"category": "3D View",
}
import bpy
from bpy.types import (
from bpy.props import (
# First part of the operator Info message
INFO_MESSAGE = "Copy Attributes: "
def build_exec(loopfunc, func):
"""Generator function that returns exec functions for operators """
def exec_func(self, context):
loopfunc(self, context, func)
return {'FINISHED'}
return exec_func
def build_invoke(loopfunc, func):
"""Generator function that returns invoke functions for operators"""
def invoke_func(self, context, event):
loopfunc(self, context, func)
return {'FINISHED'}
return invoke_func
def build_op(idname, label, description, fpoll, fexec, finvoke):
"""Generator function that returns the basic operator"""
class myopic(Operator):
bl_idname = idname
bl_label = label
bl_description = description
execute = fexec
poll = fpoll
invoke = finvoke
return myopic
def genops(copylist, oplist, prefix, poll_func, loopfunc):
"""Generate ops from the copy list and its associated functions"""
for op in copylist:
exec_func = build_exec(loopfunc, op[3])
invoke_func = build_invoke(loopfunc, op[3])
opclass = build_op(prefix + op[0], "Copy " + op[1], op[2],
oplist.append(opclass)
def generic_copy(source, target, string=""):
"""Copy attributes from source to target that have string in them"""
for attr in dir(source):
if attr.find(string) > -1:
try:
setattr(target, attr, getattr(source, attr))
except:
pass
return
def getmat(bone, active, context, ignoreparent):
"""Helper function for visual transform copy,
gets the active transform in bone space
obj_act = context.active_object
data_bone = obj_act.data.bones[bone.name]
# all matrices are in armature space unless commented otherwise
otherloc = active.matrix # final 4x4 mat of target, location.
bonemat_local = data_bone.matrix_local.copy() # self rest matrix
if data_bone.parent:
parentposemat = obj_act.pose.bones[data_bone.parent.name].matrix.copy()
parentbonemat = data_bone.parent.matrix_local.copy()
parentposemat = parentbonemat = Matrix()
if parentbonemat == parentposemat or ignoreparent:
newmat = bonemat_local.inverted() @ otherloc
bonemat = parentbonemat.inverted() @ bonemat_local
newmat = bonemat.inverted() @ parentposemat.inverted() @ otherloc
return newmat
def rotcopy(item, mat):
"""Copy rotation to item from matrix mat depending on item.rotation_mode"""
if item.rotation_mode == 'QUATERNION':
item.rotation_quaternion = mat.to_3x3().to_quaternion()
elif item.rotation_mode == 'AXIS_ANGLE':
rot = mat.to_3x3().to_quaternion().to_axis_angle() # returns (Vector((x, y, z)), w)
Bartek Skorupa
committed
axis_angle = rot[1], rot[0][0], rot[0][1], rot[0][2] # convert to w, x, y, z
item.rotation_axis_angle = axis_angle
item.rotation_euler = mat.to_3x3().to_euler(item.rotation_mode)
def pLoopExec(self, context, funk):
"""Loop over selected bones and execute funk on them"""
active = context.active_pose_bone
selected = context.selected_pose_bones
selected.remove(active)
for bone in selected:
funk(bone, active, context)
# The following functions are used o copy attributes frome active to bone
def pLocLocExec(bone, active, context):
bone.location = active.location
def pLocRotExec(bone, active, context):
rotcopy(bone, active.matrix_basis.to_3x3())
def pLocScaExec(bone, active, context):
bone.scale = active.scale
def pVisLocExec(bone, active, context):
bone.location = getmat(bone, active, context, False).to_translation()
def pVisRotExec(bone, active, context):
rotcopy(bone, getmat(bone, active,
context, not context.active_object.data.bones[bone.name].use_inherit_rotation))
def pVisScaExec(bone, active, context):
bone.scale = getmat(bone, active, context,
not context.active_object.data.bones[bone.name].use_inherit_scale)\
.to_scale()
def pDrwExec(bone, active, context):
bone.custom_shape = active.custom_shape
bone.use_custom_shape_bone_size = active.use_custom_shape_bone_size
bone.custom_shape_scale = active.custom_shape_scale
Daniel Salazar
committed
bone.bone.show_wire = active.bone.show_wire
def pLokExec(bone, active, context):
for index, state in enumerate(active.lock_location):
bone.lock_location[index] = state
for index, state in enumerate(active.lock_rotation):
bone.lock_rotation[index] = state
bone.lock_rotations_4d = active.lock_rotations_4d
bone.lock_rotation_w = active.lock_rotation_w
for index, state in enumerate(active.lock_scale):
bone.lock_scale[index] = state
def pConExec(bone, active, context):
for old_constraint in active.constraints.values():
new_constraint = bone.constraints.new(old_constraint.type)
generic_copy(old_constraint, new_constraint)
def pIKsExec(bone, active, context):
generic_copy(active, bone, "ik_")
def pBBonesExec(bone, active, context):
object = active.id_data
generic_copy(
object.data.bones[bone.name],
"bbone_")
pose_copies = (
('pose_loc_loc', "Local Location",
"Copy Location from Active to Selected", pLocLocExec),
('pose_loc_rot', "Local Rotation",
"Copy Rotation from Active to Selected", pLocRotExec),
('pose_loc_sca', "Local Scale",
"Copy Scale from Active to Selected", pLocScaExec),
('pose_vis_loc', "Visual Location",
"Copy Location from Active to Selected", pVisLocExec),
('pose_vis_rot', "Visual Rotation",
"Copy Rotation from Active to Selected", pVisRotExec),
('pose_vis_sca', "Visual Scale",
"Copy Scale from Active to Selected", pVisScaExec),
('pose_drw', "Bone Shape",
"Copy Bone Shape from Active to Selected", pDrwExec),
('pose_lok', "Protected Transform",
"Copy Protected Tranforms from Active to Selected", pLokExec),
('pose_con', "Bone Constraints",
"Copy Object Constraints from Active to Selected", pConExec),
('pose_iks', "IK Limits",
"Copy IK Limits from Active to Selected", pIKsExec),
('bbone_settings', "BBone Settings",
"Copy BBone Settings from Active to Selected", pBBonesExec),
)
@classmethod
def pose_poll_func(cls, context):
return(context.mode == 'POSE')
def pose_invoke_func(self, context, event):
wm = context.window_manager
wm.invoke_props_dialog(self)
return {'RUNNING_MODAL'}
class CopySelectedPoseConstraints(Operator):
"""Copy Chosen constraints from active to selected"""
bl_idname = "pose.copy_selected_constraints"
bl_label = "Copy Selected Constraints"
selection: BoolVectorProperty(
poll = pose_poll_func
invoke = pose_invoke_func
def draw(self, context):
layout = self.layout
for idx, const in enumerate(context.active_pose_bone.constraints):
Campbell Barton
committed
layout.prop(self, "selection", index=idx, text=const.name,
def execute(self, context):
active = context.active_pose_bone
selected = context.selected_pose_bones[:]
selected.remove(active)
for bone in selected:
for index, flag in enumerate(self.selection):
if flag:
old_constraint = active.constraints[index]
new_constraint = bone.constraints.new(
generic_copy(old_constraint, new_constraint)
return {'FINISHED'}
pose_ops = [] # list of pose mode copy operators
genops(pose_copies, pose_ops, "pose.copy_", pose_poll_func, pLoopExec)
class VIEW3D_MT_posecopypopup(Menu):
bl_label = "Copy Attributes"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("view3d.copybuffer", icon="COPY_ID")
for op in pose_copies:
layout.operator("pose.copy_" + op[0])
layout.operator("pose.copy_selected_constraints")
layout.operator("pose.copy", text="copy pose")
def obLoopExec(self, context, funk):
"""Loop over selected objects and execute funk on them"""
active = context.active_object
selected = context.selected_objects[:]
selected.remove(active)
for obj in selected:
msg = funk(obj, active, context)
if msg:
self.report({msg[0]}, INFO_MESSAGE + msg[1])
def world_to_basis(active, ob, context):
"""put world coords of active as basis coords of ob"""
local = ob.parent.matrix_world.inverted() @ active.matrix_world
P = ob.matrix_basis @ ob.matrix_local.inverted()
mat = P @ local
return(mat)
# The following functions are used o copy attributes from
# active to selected object
def obLoc(ob, active, context):
ob.location = active.location
def obRot(ob, active, context):
rotcopy(ob, active.matrix_local.to_3x3())
def obSca(ob, active, context):
ob.scale = active.scale
def obVisLoc(ob, active, context):
if ob.parent:
mat = world_to_basis(active, ob, context)
ob.location = mat.to_translation()
else:
ob.location = active.matrix_world.to_translation()
return('INFO', "Object location copied")
def obVisRot(ob, active, context):
if ob.parent:
mat = world_to_basis(active, ob, context)
rotcopy(ob, mat.to_3x3())
else:
rotcopy(ob, active.matrix_world.to_3x3())
return('INFO', "Object rotation copied")
def obVisSca(ob, active, context):
if ob.parent:
mat = world_to_basis(active, ob, context)
ob.scale = mat.to_scale()
else:
ob.scale = active.matrix_world.to_scale()
return('INFO', "Object scale copied")
def obDrw(ob, active, context):
ob.display_type = active.display_type
ob.show_axis = active.show_axis
ob.show_bounds = active.show_bounds
ob.display_bounds_type = active.display_bounds_type
ob.show_name = active.show_name
ob.show_texture_space = active.show_texture_space
ob.show_transparent = active.show_transparent
ob.show_wire = active.show_wire
ob.show_in_front = active.show_in_front
ob.empty_display_type = active.empty_display_type
ob.empty_display_size = active.empty_display_size
def obOfs(ob, active, context):
ob.time_offset = active.time_offset
return('INFO', "Time offset copied")
def obDup(ob, active, context):
generic_copy(active, ob, "dupli")
return('INFO', "Duplication method copied")
def obCol(ob, active, context):
ob.color = active.color
def obLok(ob, active, context):
for index, state in enumerate(active.lock_location):
ob.lock_location[index] = state
for index, state in enumerate(active.lock_rotation):
ob.lock_rotation[index] = state
Bassam Kurdali
committed
ob.lock_rotations_4d = active.lock_rotations_4d
ob.lock_rotation_w = active.lock_rotation_w
for index, state in enumerate(active.lock_scale):
ob.lock_scale[index] = state
return('INFO', "Transform locks copied")
def obCon(ob, active, context):
# for consistency with 2.49, delete old constraints first
for removeconst in ob.constraints:
ob.constraints.remove(removeconst)
for old_constraint in active.constraints.values():
new_constraint = ob.constraints.new(old_constraint.type)
generic_copy(old_constraint, new_constraint)
return('INFO', "Constraints copied")
def obTex(ob, active, context):
if 'texspace_location' in dir(ob.data) and 'texspace_location' in dir(
active.data):
ob.data.texspace_location[:] = active.data.texspace_location[:]
if 'texspace_size' in dir(ob.data) and 'texspace_size' in dir(active.data):
ob.data.texspace_size[:] = active.data.texspace_size[:]
return('INFO', "Texture space copied")
def obIdx(ob, active, context):
ob.pass_index = active.pass_index
return('INFO', "Pass index copied")
def obMod(ob, active, context):
for modifier in ob.modifiers:
# remove existing before adding new:
ob.modifiers.remove(modifier)
for old_modifier in active.modifiers.values():
new_modifier = ob.modifiers.new(name=old_modifier.name,
generic_copy(old_modifier, new_modifier)
return('INFO', "Modifiers copied")
def obGrp(ob, active, context):
for grp in bpy.data.groups:
if active.name in grp.objects and ob.name not in grp.objects:
grp.objects.link(ob)
return('INFO', "Groups copied")
def obWei(ob, active, context):
me_source = active.data
me_target = ob.data
# sanity check: do source and target have the same amount of verts?
if len(me_source.vertices) != len(me_target.vertices):
return('ERROR', "objects have different vertex counts, doing nothing")
vgroups_IndexName = {}
for i in range(0, len(active.vertex_groups)):
groups = active.vertex_groups[i]
vgroups_IndexName[groups.index] = groups.name
data = {} # vert_indices, [(vgroup_index, weights)]
for v in me_source.vertices:
vg = v.groups
vi = v.index
if len(vg) > 0:
vgroup_collect = []
for i in range(0, len(vg)):
vgroup_collect.append((vg[i].group, vg[i].weight))
data[vi] = vgroup_collect
# write data to target
if ob != active:
# add missing vertex groups
for vgroup_name in vgroups_IndexName.values():
# check if group already exists...
already_present = 0
for i in range(0, len(ob.vertex_groups)):
if ob.vertex_groups[i].name == vgroup_name:
already_present = 1
# ... if not, then add
if already_present == 0:
ob.vertex_groups.new(name=vgroup_name)
# write weights
for v in me_target.vertices:
for vi_source, vgroupIndex_weight in data.items():
if v.index == vi_source:
for i in range(0, len(vgroupIndex_weight)):
groupName = vgroups_IndexName[vgroupIndex_weight[i][0]]
groups = ob.vertex_groups
for vgs in range(0, len(groups)):
if groups[vgs].name == groupName:
groups[vgs].add((v.index,),
return('INFO', "Weights copied")
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# ('obj_loc', "Location",
# "Copy Location from Active to Selected", obLoc),
# ('obj_rot', "Rotation",
# "Copy Rotation from Active to Selected", obRot),
# ('obj_sca', "Scale",
# "Copy Scale from Active to Selected", obSca),
('obj_vis_loc', "Location",
"Copy Location from Active to Selected", obVisLoc),
('obj_vis_rot', "Rotation",
"Copy Rotation from Active to Selected", obVisRot),
('obj_vis_sca', "Scale",
"Copy Scale from Active to Selected", obVisSca),
('obj_drw', "Draw Options",
"Copy Draw Options from Active to Selected", obDrw),
('obj_ofs', "Time Offset",
"Copy Time Offset from Active to Selected", obOfs),
('obj_dup', "Dupli",
"Copy Dupli from Active to Selected", obDup),
('obj_col', "Object Color",
"Copy Object Color from Active to Selected", obCol),
# ('obj_dmp', "Damping",
# "Copy Damping from Active to Selected"),
# ('obj_all', "All Physical Attributes",
# "Copy Physical Attributes from Active to Selected"),
# ('obj_prp', "Properties",
# "Copy Properties from Active to Selected"),
# ('obj_log', "Logic Bricks",
# "Copy Logic Bricks from Active to Selected"),
('obj_lok', "Protected Transform",
"Copy Protected Tranforms from Active to Selected", obLok),
('obj_con', "Object Constraints",
"Copy Object Constraints from Active to Selected", obCon),
# ('obj_nla', "NLA Strips",
# "Copy NLA Strips from Active to Selected"),
# ('obj_tex', "Texture Space",
# "Copy Texture Space from Active to Selected", obTex),
# ('obj_sub', "Subsurf Settings",
# "Copy Subsurf Setings from Active to Selected"),
# ('obj_smo', "AutoSmooth",
# "Copy AutoSmooth from Active to Selected"),
('obj_idx', "Pass Index",
"Copy Pass Index from Active to Selected", obIdx),
('obj_mod', "Modifiers",
"Copy Modifiers from Active to Selected", obMod),
('obj_wei', "Vertex Weights",
"Copy vertex weights based on indices", obWei),
('obj_grp', "Group Links",
"Copy selected into active object's groups", obGrp)
)
@classmethod
def object_poll_func(cls, context):
return (len(context.selected_objects) > 1)
def object_invoke_func(self, context, event):
wm = context.window_manager
wm.invoke_props_dialog(self)
return {'RUNNING_MODAL'}
class CopySelectedObjectConstraints(Operator):
"""Copy Chosen constraints from active to selected"""
bl_idname = "object.copy_selected_constraints"
bl_label = "Copy Selected Constraints"
selection: BoolVectorProperty(
poll = object_poll_func
invoke = object_invoke_func
def draw(self, context):
layout = self.layout
for idx, const in enumerate(context.active_object.constraints):
Campbell Barton
committed
layout.prop(self, "selection", index=idx, text=const.name,
def execute(self, context):
active = context.active_object
selected = context.selected_objects[:]
selected.remove(active)
for obj in selected:
for index, flag in enumerate(self.selection):
if flag:
old_constraint = active.constraints[index]
new_constraint = obj.constraints.new(
generic_copy(old_constraint, new_constraint)
return{'FINISHED'}
class CopySelectedObjectModifiers(Operator):
"""Copy Chosen modifiers from active to selected"""
bl_idname = "object.copy_selected_modifiers"
bl_label = "Copy Selected Modifiers"
selection: BoolVectorProperty(
poll = object_poll_func
invoke = object_invoke_func
def draw(self, context):
layout = self.layout
for idx, const in enumerate(context.active_object.modifiers):
Campbell Barton
committed
layout.prop(self, 'selection', index=idx, text=const.name,
def execute(self, context):
active = context.active_object
selected = context.selected_objects[:]
selected.remove(active)
for obj in selected:
for index, flag in enumerate(self.selection):
if flag:
old_modifier = active.modifiers[index]
new_modifier = obj.modifiers.new(
type=active.modifiers[index].type,
name=active.modifiers[index].name
)
generic_copy(old_modifier, new_modifier)
return{'FINISHED'}
object_ops = []
genops(object_copies, object_ops, "object.copy_", object_poll_func, obLoopExec)
class VIEW3D_MT_copypopup(Menu):
bl_label = "Copy Attributes"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("view3d.copybuffer", icon="COPY_ID")
if (len(context.selected_objects) <= 1):
layout.separator()
layout.label(text="Please select at least two objects", icon="INFO")
layout.separator()
for entry, op in enumerate(object_copies):
if entry and entry % 4 == 0:
layout.separator()
layout.operator("object.copy_" + op[0])
layout.operator("object.copy_selected_constraints")
layout.operator("object.copy_selected_modifiers")
# Begin Mesh copy settings:
class MESH_MT_CopyFaceSettings(Menu):
bl_label = "Copy Face Settings"
@classmethod
def poll(cls, context):
return context.mode == 'EDIT_MESH'
def draw(self, context):
mesh = context.object.data
uv = len(mesh.uv_textures) > 1
vc = len(mesh.vertex_colors) > 1
layout = self.layout
layout.operator("view3d.copybuffer", icon="COPY_ID")
layout.operator("view3d.pastebuffer", icon="COPY_ID")
layout.separator()
op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname,
if mesh.uv_textures.active:
op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname,
op['layer'] = ''
op['mode'] = 'IMAGE'
op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname,
if mesh.vertex_colors.active:
op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname,
op['layer'] = ''
op['mode'] = 'VCOL'
if uv or vc:
layout.separator()
if uv:
layout.menu("MESH_MT_CopyImagesFromLayer")
layout.menu("MESH_MT_CopyUVCoordsFromLayer")
if vc:
layout.menu("MESH_MT_CopyVertexColorsFromLayer")
# 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
# causing issues with access and registration
class MESH_MT_CopyImagesFromLayer(Menu):
bl_label = "Copy Other UV Image Layers"
@classmethod
def poll(cls, context):
obj = context.active_object
return obj and obj.mode == "EDIT_MESH" and len(
def draw(self, context):
mesh = context.active_object.data
_buildmenu(self, mesh, 'IMAGE', "IMAGE_COL")
class MESH_MT_CopyUVCoordsFromLayer(Menu):
bl_label = "Copy Other UV Coord Layers"
@classmethod
def poll(cls, context):
obj = context.active_object
return obj and obj.mode == "EDIT_MESH" and len(
def draw(self, context):
mesh = context.active_object.data
_buildmenu(self, mesh, 'UV', "GROUP_UVS")
class MESH_MT_CopyVertexColorsFromLayer(Menu):
bl_label = "Copy Other Vertex Colors Layers"
@classmethod
def poll(cls, context):
obj = context.active_object
return obj and obj.mode == "EDIT_MESH" and len(
def draw(self, context):
mesh = context.active_object.data
_buildmenu(self, mesh, 'VCOL', "GROUP_VCOL")
def _buildmenu(self, mesh, mode, icon):
layout = self.layout
if mode == 'VCOL':
layers = mesh.vertex_colors
else:
layers = mesh.uv_textures
for layer in layers:
if not layer.active:
op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname,
text=layer.name, icon=icon)
op['layer'] = layer.name
op['mode'] = mode
class MESH_OT_CopyFaceSettings(Operator):
"""Copy settings from active face to all selected faces"""
bl_idname = 'mesh.copy_face_settings'
bl_label = "Copy Face Settings"
bl_options = {'REGISTER', 'UNDO'}
mode: StringProperty(
layer: StringProperty(
@classmethod
def poll(cls, context):
return context.mode == 'EDIT_MESH'
def execute(self, context):
if mode not in {'MAT', 'VCOL', 'IMAGE', 'UV'}:
self.report({'ERROR'}, "No mode specified or invalid mode")
return self._end(context, {'CANCELLED'})
layername = getattr(self, 'layer', '')
mesh = context.object.data
# Switching out of edit mode updates the selected state of faces and
# makes the data from the uv texture and vertex color layers available.
bpy.ops.object.editmode_toggle()
if mode == 'MAT':
else:
if mode == 'VCOL':
layers = mesh.vertex_colors
act_layer = mesh.vertex_colors.active
layers = mesh.uv_textures
act_layer = mesh.uv_textures.active
elif mode == 'UV':
layers = mesh.uv_layers
act_layer = mesh.uv_layers.active
if not layers or (layername and layername not in layers):
self.report({'ERROR'}, "Invalid UV or color layer. Operation Cancelled")
return self._end(context, {'CANCELLED'})
from_data = layers[layername or act_layer.name].data
to_data = act_layer.data
if f.select:
if to_data != from_data:
# Copying from another layer.
# from_face is to_face's counterpart from other layer.
from_index = f.index
elif f.index == from_index:
# Otherwise skip copying a face to itself.
continue
if mode == 'MAT':
f.material_index = polys[from_index].material_index
elif mode == 'IMAGE':
to_data[f.index].image = from_data[from_index].image
if len(f.loop_indices) != len(polys[from_index].loop_indices):
self.report({'WARNING'}, "Different number of vertices.")
for i in range(len(f.loop_indices)):
to_vertex = f.loop_indices[i]
from_vertex = polys[from_index].loop_indices[i]
if mode == 'VCOL':
to_data[to_vertex].color = from_data[from_vertex].color
elif mode == 'UV':
to_data[to_vertex].uv = from_data[from_vertex].uv
return self._end(context, {'FINISHED'})
def _end(self, context, retval):
if context.mode != 'EDIT_MESH':
# Clean up by returning to edit mode like it was before.
bpy.ops.object.editmode_toggle()
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():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
Campbell Barton
committed
# mostly to get the keymap working
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
km = kc.keymaps.new(name="Object Mode")
Campbell Barton
committed
kmi = km.keymap_items.new('wm.call_menu', 'C', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_copypopup'
km = kc.keymaps.new(name="Pose")
kmi = km.keymap_items.get("pose.copy")
if kmi is not None:
kmi.idname = 'wm.call_menu'
else:
kmi = km.keymap_items.new('wm.call_menu', 'C', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_posecopypopup'
km = kc.keymaps.new(name="Mesh")
kmi = km.keymap_items.new('wm.call_menu', 'C', 'PRESS')
kmi.ctrl = True
kmi.properties.name = 'MESH_MT_CopyFaceSettings'
def unregister():
# mostly to remove the keymap
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
kms = kc.keymaps.get('Pose')
if kms is not None:
for item in kms.keymap_items:
if item.name == 'Call Menu' and item.idname == 'wm.call_menu' and \
item.properties.name == 'VIEW3D_MT_posecopypopup':
item.idname = 'pose.copy'
break
km = kc.keymaps.get('Mesh')
if km is not None:
for kmi in km.keymap_items:
if kmi.idname == 'wm.call_menu':
if kmi.properties.name == 'MESH_MT_CopyFaceSettings':
km.keymap_items.remove(kmi)
km = kc.keymaps.get('Object Mode')
if km is not None:
for kmi in km.keymap_items:
if kmi.idname == 'wm.call_menu':
if kmi.properties.name == 'VIEW3D_MT_copypopup':
km.keymap_items.remove(kmi)
from bpy.utils import unregister_class
for cls in classes:
unregister_class(cls)
if __name__ == "__main__":