# SPDX-License-Identifier: GPL-2.0-or-later # Note: Property group was moved to __init__ bl_info = { "name": "Vertex Align", "author": "", "version": (0, 1, 7), "blender": (2, 61, 0), "location": "View3D > Tool Shelf", "description": "", "warning": "", "doc_url": "", "category": "Mesh", } import bpy from bpy.props import ( BoolVectorProperty, FloatVectorProperty, ) from mathutils import Vector from bpy.types import Operator # Edit Mode Toggle def edit_mode_out(): bpy.ops.object.mode_set(mode='OBJECT') def edit_mode_in(): bpy.ops.object.mode_set(mode='EDIT') def get_mesh_data_(): edit_mode_out() ob_act = bpy.context.active_object me = ob_act.data edit_mode_in() return me def list_clear_(l): l[:] = [] return l class va_buf(): list_v = [] list_0 = [] # Store The Vertex coordinates class Vertex_align_store(Operator): bl_idname = "vertex_align.store_id" bl_label = "Active Vertex" bl_description = ("Store Selected Vertex coordinates as an align point\n" "Single Selected Vertex only") @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') def execute(self, context): try: me = get_mesh_data_() list_0 = [v.index for v in me.vertices if v.select] if len(list_0) == 1: list_clear_(va_buf.list_v) for v in me.vertices: if v.select: va_buf.list_v.append(v.index) bpy.ops.mesh.select_all(action='DESELECT') else: self.report({'WARNING'}, "Please select just One Vertex") return {'CANCELLED'} except: self.report({'WARNING'}, "Storing selection could not be completed") return {'CANCELLED'} self.report({'INFO'}, "Selected Vertex coordinates are stored") return {'FINISHED'} # Align to original class Vertex_align_original(Operator): bl_idname = "vertex_align.align_original" bl_label = "Align to original" bl_description = "Align selection to stored single vertex coordinates" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') def draw(self, context): layout = self.layout layout.label(text="Axis:") row = layout.row(align=True) row.prop(context.scene.mesh_extra_tools, "vert_align_axis", text="X", index=0, toggle=True) row.prop(context.scene.mesh_extra_tools, "vert_align_axis", text="Y", index=1, toggle=True) row.prop(context.scene.mesh_extra_tools, "vert_align_axis", text="Z", index=2, toggle=True) def execute(self, context): edit_mode_out() ob_act = context.active_object me = ob_act.data cen1 = context.scene.mesh_extra_tools.vert_align_axis list_0 = [v.index for v in me.vertices if v.select] if len(va_buf.list_v) == 0: self.report({'INFO'}, "Original vertex not stored in memory. Operation Cancelled") edit_mode_in() return {'CANCELLED'} elif len(va_buf.list_v) != 0: if len(list_0) == 0: self.report({'INFO'}, "No vertices selected. Operation Cancelled") edit_mode_in() return {'CANCELLED'} elif len(list_0) != 0: vo = (me.vertices[va_buf.list_v[0]].co).copy() if cen1[0] is True: for i in list_0: v = (me.vertices[i].co).copy() me.vertices[i].co = Vector((vo[0], v[1], v[2])) if cen1[1] is True: for i in list_0: v = (me.vertices[i].co).copy() me.vertices[i].co = Vector((v[0], vo[1], v[2])) if cen1[2] is True: for i in list_0: v = (me.vertices[i].co).copy() me.vertices[i].co = Vector((v[0], v[1], vo[2])) edit_mode_in() return {'FINISHED'} # Align to custom coordinates class Vertex_align_coord_list(Operator): bl_idname = "vertex_align.coord_list_id" bl_label = "" bl_description = "Align to custom coordinates" @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') def execute(self, context): edit_mode_out() ob_act = context.active_object me = ob_act.data list_clear_(va_buf.list_0) va_buf.list_0 = [v.index for v in me.vertices if v.select][:] if len(va_buf.list_0) == 0: self.report({'INFO'}, "No vertices selected. Operation Cancelled") edit_mode_in() return {'CANCELLED'} elif len(va_buf.list_0) != 0: bpy.ops.vertex_align.coord_menu_id('INVOKE_DEFAULT') edit_mode_in() return {'FINISHED'} # Align to custom coordinates menu class Vertex_align_coord_menu(Operator): bl_idname = "vertex_align.coord_menu_id" bl_label = "Tweak custom coordinates" bl_description = "Change the custom coordinates for aligning" bl_options = {'REGISTER', 'UNDO'} def_axis_coord: FloatVectorProperty( name="", description="Enter the values of coordinates", default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, step=1, size=3, subtype='XYZ', precision=3 ) use_axis_coord = BoolVectorProperty( name="Axis", description="Choose Custom Coordinates axis", default=(False,) * 3, size=3, ) is_not_undo = False @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH') def using_store(self, context): scene = context.scene return scene.mesh_extra_tools.vert_align_use_stored def draw(self, context): layout = self.layout if self.using_store(context) and self.is_not_undo: layout.label(text="Using Stored Coordinates", icon="INFO") row = layout.split(0.25) row.prop(self, "use_axis_coord", index=0, text="X") row.prop(self, "def_axis_coord", index=0) row = layout.split(0.25) row.prop(self, "use_axis_coord", index=1, text="Y") row.prop(self, "def_axis_coord", index=1) row = layout.split(0.25) row.prop(self, "use_axis_coord", index=2, text="Z") row.prop(self, "def_axis_coord", index=2) def invoke(self, context, event): self.is_not_undo = True scene = context.scene if self.using_store(context): self.def_axis_coord = scene.mesh_extra_tools.vert_align_store_axis return context.window_manager.invoke_props_dialog(self, width=200) def execute(self, context): self.is_not_undo = False edit_mode_out() ob_act = context.active_object me = ob_act.data for i in va_buf.list_0: v = (me.vertices[i].co).copy() tmp = Vector((v[0], v[1], v[2])) if self.use_axis_coord[0] is True: tmp[0] = self.def_axis_coord[0] if self.use_axis_coord[1] is True: tmp[1] = self.def_axis_coord[1] if self.use_axis_coord[2] is True: tmp[2] = self.def_axis_coord[2] me.vertices[i].co = tmp edit_mode_in() return {'FINISHED'} # Register classes = ( Vertex_align_store, Vertex_align_original, Vertex_align_coord_list, Vertex_align_coord_menu, ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) if __name__ == "__main__": register()