1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Note: Property group was moved to __init__
6 "name": "Vertex Align",
10 "location": "View3D > Tool Shelf",
19 from bpy
.props
import (
23 from mathutils
import Vector
24 from bpy
.types
import Operator
29 bpy
.ops
.object.mode_set(mode
='OBJECT')
33 bpy
.ops
.object.mode_set(mode
='EDIT')
38 ob_act
= bpy
.context
.active_object
54 # Store The Vertex coordinates
55 class Vertex_align_store(Operator
):
56 bl_idname
= "vertex_align.store_id"
57 bl_label
= "Active Vertex"
58 bl_description
= ("Store Selected Vertex coordinates as an align point\n"
59 "Single Selected Vertex only")
62 def poll(cls
, context
):
63 obj
= context
.active_object
64 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
66 def execute(self
, context
):
69 list_0
= [v
.index
for v
in me
.vertices
if v
.select
]
72 list_clear_(va_buf
.list_v
)
75 va_buf
.list_v
.append(v
.index
)
76 bpy
.ops
.mesh
.select_all(action
='DESELECT')
78 self
.report({'WARNING'}, "Please select just One Vertex")
81 self
.report({'WARNING'}, "Storing selection could not be completed")
84 self
.report({'INFO'}, "Selected Vertex coordinates are stored")
90 class Vertex_align_original(Operator
):
91 bl_idname
= "vertex_align.align_original"
92 bl_label
= "Align to original"
93 bl_description
= "Align selection to stored single vertex coordinates"
94 bl_options
= {'REGISTER', 'UNDO'}
97 def poll(cls
, context
):
98 obj
= context
.active_object
99 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
101 def draw(self
, context
):
103 layout
.label(text
="Axis:")
105 row
= layout
.row(align
=True)
106 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
107 text
="X", index
=0, toggle
=True)
108 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
109 text
="Y", index
=1, toggle
=True)
110 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
111 text
="Z", index
=2, toggle
=True)
113 def execute(self
, context
):
115 ob_act
= context
.active_object
117 cen1
= context
.scene
.mesh_extra_tools
.vert_align_axis
118 list_0
= [v
.index
for v
in me
.vertices
if v
.select
]
120 if len(va_buf
.list_v
) == 0:
121 self
.report({'INFO'},
122 "Original vertex not stored in memory. Operation Cancelled")
126 elif len(va_buf
.list_v
) != 0:
128 self
.report({'INFO'}, "No vertices selected. Operation Cancelled")
132 elif len(list_0
) != 0:
133 vo
= (me
.vertices
[va_buf
.list_v
[0]].co
).copy()
136 v
= (me
.vertices
[i
].co
).copy()
137 me
.vertices
[i
].co
= Vector((vo
[0], v
[1], v
[2]))
140 v
= (me
.vertices
[i
].co
).copy()
141 me
.vertices
[i
].co
= Vector((v
[0], vo
[1], v
[2]))
144 v
= (me
.vertices
[i
].co
).copy()
145 me
.vertices
[i
].co
= Vector((v
[0], v
[1], vo
[2]))
151 # Align to custom coordinates
152 class Vertex_align_coord_list(Operator
):
153 bl_idname
= "vertex_align.coord_list_id"
155 bl_description
= "Align to custom coordinates"
158 def poll(cls
, context
):
159 obj
= context
.active_object
160 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
162 def execute(self
, context
):
164 ob_act
= context
.active_object
166 list_clear_(va_buf
.list_0
)
167 va_buf
.list_0
= [v
.index
for v
in me
.vertices
if v
.select
][:]
169 if len(va_buf
.list_0
) == 0:
170 self
.report({'INFO'}, "No vertices selected. Operation Cancelled")
174 elif len(va_buf
.list_0
) != 0:
175 bpy
.ops
.vertex_align
.coord_menu_id('INVOKE_DEFAULT')
182 # Align to custom coordinates menu
183 class Vertex_align_coord_menu(Operator
):
184 bl_idname
= "vertex_align.coord_menu_id"
185 bl_label
= "Tweak custom coordinates"
186 bl_description
= "Change the custom coordinates for aligning"
187 bl_options
= {'REGISTER', 'UNDO'}
189 def_axis_coord
: FloatVectorProperty(
191 description
="Enter the values of coordinates",
192 default
=(0.0, 0.0, 0.0),
193 min=-100.0, max=100.0,
198 use_axis_coord
= BoolVectorProperty(
200 description
="Choose Custom Coordinates axis",
201 default
=(False,) * 3,
207 def poll(cls
, context
):
208 obj
= context
.active_object
209 return (obj
and obj
.type == 'MESH')
211 def using_store(self
, context
):
212 scene
= context
.scene
213 return scene
.mesh_extra_tools
.vert_align_use_stored
215 def draw(self
, context
):
218 if self
.using_store(context
) and self
.is_not_undo
:
219 layout
.label(text
="Using Stored Coordinates", icon
="INFO")
221 row
= layout
.split(0.25)
222 row
.prop(self
, "use_axis_coord", index
=0, text
="X")
223 row
.prop(self
, "def_axis_coord", index
=0)
225 row
= layout
.split(0.25)
226 row
.prop(self
, "use_axis_coord", index
=1, text
="Y")
227 row
.prop(self
, "def_axis_coord", index
=1)
229 row
= layout
.split(0.25)
230 row
.prop(self
, "use_axis_coord", index
=2, text
="Z")
231 row
.prop(self
, "def_axis_coord", index
=2)
233 def invoke(self
, context
, event
):
234 self
.is_not_undo
= True
235 scene
= context
.scene
236 if self
.using_store(context
):
237 self
.def_axis_coord
= scene
.mesh_extra_tools
.vert_align_store_axis
239 return context
.window_manager
.invoke_props_dialog(self
, width
=200)
241 def execute(self
, context
):
242 self
.is_not_undo
= False
244 ob_act
= context
.active_object
247 for i
in va_buf
.list_0
:
248 v
= (me
.vertices
[i
].co
).copy()
249 tmp
= Vector((v
[0], v
[1], v
[2]))
251 if self
.use_axis_coord
[0] is True:
252 tmp
[0] = self
.def_axis_coord
[0]
253 if self
.use_axis_coord
[1] is True:
254 tmp
[1] = self
.def_axis_coord
[1]
255 if self
.use_axis_coord
[2] is True:
256 tmp
[2] = self
.def_axis_coord
[2]
257 me
.vertices
[i
].co
= tmp
267 Vertex_align_original
,
268 Vertex_align_coord_list
,
269 Vertex_align_coord_menu
,
275 bpy
.utils
.register_class(cls
)
280 bpy
.utils
.unregister_class(cls
)
283 if __name__
== "__main__":