I'm fiddling around with an add-on to set Vertice Axis, and the add-on seems to work.
The addon creates a button in Tool Panel, and a menu entry in Mesh-Vertices.
The Problem is the missing 'add shortcut' entry in the right-click-menu.
I have tried for days to figure it out. If I add the entry manually in the shortcut menu with the rna 'mesh.move_verts_axis' it works.
import bpy
import bmesh
def _setupVertEdit():
_set3DViewModeEdit()
_initMeshEdit()
return
def _initMeshEdit():
global gObj, gObjData, gBMesh, gMat_world
gObj = bpy.context.active_object
gObjData = gObj.data
gBMesh=bmesh.from_edit_mesh(gObjData)
gMat_world = gObj.matrix_world
return
def _get3DViewMode():
return bpy.ops.mesh.select_mode()
def _set3DViewModeEdit():
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(type="VERT")
return
def _updateData():
bmesh.update_edit_mesh(gObjData)
return
def _countVerts():
return (len(gObjData.vertices))
def _getSelectedVerts():
return [ v for v in gBMesh.verts if v.select ]
def _countSelectedVerts():
return (len(_getSelectedVerts()))
def _getActiveVert(optSel=0):
elem = gBMesh.select_history.active
if elem is not None and isinstance(elem, bmesh.types.BMVert):
return elem
elif optSel == 'sel' and _countSelectedVerts() > 0:
elem = gBMesh.verts[0]
gBMesh.select_history.add(elem)
return elem
return None
def _SetActiveVert(vert):
if (type(vert)=='int'):
gBMesh.select_history.add(gBMesh.verts[vert])
else:
gBMesh.select_history.add(vert)
_updateData()
return
def _selectVert(vert):
gBMesh.verts[vert].select = True
return
def _deSelectVert(vert):
gBMesh.verts[vert].select = False
return
def _getVertCoor(vert):
return gBMesh.verts[vert].co
def _getVertCoorGlo(vert):
gBMesh.verts.ensure_lookup_table()
return gMat_world * gBMesh.verts[vert].co
def _setVectorCoor(vert,x=0,y=0,z=0):
if x>0:
gBMesh.verts[vert].co.x=x
if y>0:
gBMesh.verts[vert].co.y=y
if z>0:
gBMesh.verts[vert].co.z=z
return
def _setVectorCoorGlo(vert,x=None,y=None,z=None):
vert = gBMesh.verts[vert]
pos_world = gMat_world * vert.co
if x!=None:
pos_world.x = x
vert.co = gMat_world.inverted() * pos_world
if y!=None:
pos_world.y = y
vert.co = gMat_world.inverted() * pos_world
if z!=None:
pos_world.z = z
vert.co = gMat_world.inverted() * pos_world
return
def _adaptVerts(vert1,vert2,x=False,y=False,z=False):
if x:
_setVectorCoorGlo(vert1,x=_getVertCoorGlo(vert2).x)
if y:
_setVectorCoorGlo(vert1,y=_getVertCoorGlo(vert2).y)
if z:
_setVectorCoorGlo(vert1,z=_getVertCoorGlo(vert2).z)
return
def _setVertsAxis(axis):
selV=_getSelectedVerts()
actV=_getActiveVert(optSel='sel')
if axis=='x':
for vert in selV:
_adaptVerts(vert.index,actV.index,x=True)
if axis=='y':
for vert in selV:
_adaptVerts(vert.index,actV.index,y=True)
if axis=='z':
for vert in selV:
_adaptVerts(vert.index,actV.index,z=True)
_updateData()
return
def checkVerts():
global lVerts
lVerts=_countSelectedVerts()
# print('Selected Verts: '+str(lVerts))
if lVerts<2:
return False
if _getActiveVert() == None:
return False
return True
def getVertsData():
obj = bpy.context.active_object
return 'Mesh: '+obj.name+', '+str(lVerts)+' Verts selected, move Axis ...'
def moveVerts(boolX,boolY,boolZ):
if boolX:
_setVertsAxis('x')
if boolY:
_setVertsAxis('y')
if boolZ:
_setVertsAxis('z')
_updateData()
return
def menu_func(self, context):
self.layout.separator()
self.layout.operator(OBJECT_OT_VertsButton.bl_idname)
self.layout.separator()
# store keymaps here to access after registration
addon_keymaps = []
# Registration
# All panels and operators must be registered with Blender; otherwise
# they do not show up. The simplest way to register everything in the
# file is with a call to bpy.utils.register_module(__name__).
#
def register():
bpy.utils.register_module(__name__)
bpy.types.VIEW3D_MT_edit_mesh_vertices.append(menu_func)
# this does not work !!!
# handle the keymap
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Mesh', space_type='EMPTY')
kmi = km.keymap_items.new('mesh.move_verts_axis', 'SPACE', 'PRESS', shift=True, ctrl=True)
kmi.properties.boolX = False
kmi.properties.boolY = False
kmi.properties.boolZ = False
addon_keymaps.append(km)
print('register done')
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.VIEW3D_MT_edit_mesh_vertices.remove(menu_func)
# handle the keymap
wm = bpy.context.window_manager
for km in addon_keymaps:
wm.keyconfigs.addon.keymaps.remove(km)
# clear the list
del addon_keymaps[:]
print('unregister done')
# bpy.utils.unregister_class(OBJECT_OT_VertsButton)
# bpy.utils.unregister_class(ToolsPanel)
# bpy.utils.unregister_class(SetVertsDialogOperator)
#
# Menu in tools region
#
class ToolsPanel(bpy.types.Panel):
bl_label = "Adjust"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = 'Tools'
bl_context = "mesh_edit"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
self.layout.operator("op.adjust_verts")
#
# The button Function
#
class OBJECT_OT_VertsButton(bpy.types.Operator):
bl_idname = "op.adjust_verts"
bl_label = "Set Verts"
def execute(self, context):
# if checkVerts():
bpy.ops.mesh.move_verts_axis('INVOKE_DEFAULT')
return {'FINISHED'}
# Dialog from Toolpanel-Button 'Set Verts'
# https://www.blender.org/api/blender_python_api_2_57_release/bpy.types.Operator.html
class SetVertsDialogOperator(bpy.types.Operator):
bl_idname = "mesh.move_verts_axis"
bl_label = 'Move verts to Active Vert Axis'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
bl_options = {'REGISTER', 'UNDO'} #Important for F6-Menu
# Properties default=False
boolX = bpy.props.BoolProperty(name="X", description="Move selected Verts to Active Vert X-Axis", default=False)
boolY = bpy.props.BoolProperty(name="Y", description="Move selected Verts to Active Vert Y-Axis", default=False)
boolZ = bpy.props.BoolProperty(name="Z", description="Move selected Verts to Active Vert Z-Axis", default=False)
# Execution
def execute(self, context):
# print('execute:' + str(self.boolX))
_initMeshEdit()
moveVerts(self.boolX, self.boolY, self.boolZ)
# this does not work !!!
# message = "Popup Values: %d, %d, %d" % \
# (self.boolX, self.boolY, self.boolZ)
# self.report({'INFO'}, message)
return {'FINISHED'}
def invoke(self, context, event):
# print('invoke:')
wm = context.window_manager
return wm.invoke_props_dialog(self)
def draw(self, context):
_initMeshEdit()
if checkVerts():
check_msg = getVertsData()
self.layout.label(check_msg)
# row = self.layout.split(0.35)
row = self.layout.row()
row.prop(self, "boolX")
row.prop(self, "boolY")
row.prop(self, "boolZ")
else:
self.layout.label('* Need more than one selected Verts')
self.layout.label('* 1 vert must be active [shift click]')
if __name__ == "__main__":
register()
bl_idname
asmesh.something
and notop.something
, it's the customop.
path messing things up (which arguably it shouldn't ). $\endgroup$addon_keymaps.append((km, kmi))
$\endgroup$