1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Note: Property group was moved to __init__
8 "name": "Vertex Align",
11 "blender": (2, 61, 0),
12 "location": "View3D > Tool Shelf",
21 from bpy
.props
import (
25 from mathutils
import Vector
26 from bpy
.types
import Operator
31 bpy
.ops
.object.mode_set(mode
='OBJECT')
35 bpy
.ops
.object.mode_set(mode
='EDIT')
40 ob_act
= bpy
.context
.active_object
56 # Store The Vertex coordinates
57 class Vertex_align_store(Operator
):
58 bl_idname
= "vertex_align.store_id"
59 bl_label
= "Active Vertex"
60 bl_description
= ("Store Selected Vertex coordinates as an align point\n"
61 "Single Selected Vertex only")
64 def poll(cls
, context
):
65 obj
= context
.active_object
66 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
68 def execute(self
, context
):
71 list_0
= [v
.index
for v
in me
.vertices
if v
.select
]
74 list_clear_(va_buf
.list_v
)
77 va_buf
.list_v
.append(v
.index
)
78 bpy
.ops
.mesh
.select_all(action
='DESELECT')
80 self
.report({'WARNING'}, "Please select just One Vertex")
83 self
.report({'WARNING'}, "Storing selection could not be completed")
86 self
.report({'INFO'}, "Selected Vertex coordinates are stored")
92 class Vertex_align_original(Operator
):
93 bl_idname
= "vertex_align.align_original"
94 bl_label
= "Align to original"
95 bl_description
= "Align selection to stored single vertex coordinates"
96 bl_options
= {'REGISTER', 'UNDO'}
99 def poll(cls
, context
):
100 obj
= context
.active_object
101 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
103 def draw(self
, context
):
105 layout
.label(text
="Axis:")
107 row
= layout
.row(align
=True)
108 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
109 text
="X", index
=0, toggle
=True)
110 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
111 text
="Y", index
=1, toggle
=True)
112 row
.prop(context
.scene
.mesh_extra_tools
, "vert_align_axis",
113 text
="Z", index
=2, toggle
=True)
115 def execute(self
, context
):
117 ob_act
= context
.active_object
119 cen1
= context
.scene
.mesh_extra_tools
.vert_align_axis
120 list_0
= [v
.index
for v
in me
.vertices
if v
.select
]
122 if len(va_buf
.list_v
) == 0:
123 self
.report({'INFO'},
124 "Original vertex not stored in memory. Operation Cancelled")
128 elif len(va_buf
.list_v
) != 0:
130 self
.report({'INFO'}, "No vertices selected. Operation Cancelled")
134 elif len(list_0
) != 0:
135 vo
= (me
.vertices
[va_buf
.list_v
[0]].co
).copy()
138 v
= (me
.vertices
[i
].co
).copy()
139 me
.vertices
[i
].co
= Vector((vo
[0], v
[1], v
[2]))
142 v
= (me
.vertices
[i
].co
).copy()
143 me
.vertices
[i
].co
= Vector((v
[0], vo
[1], v
[2]))
146 v
= (me
.vertices
[i
].co
).copy()
147 me
.vertices
[i
].co
= Vector((v
[0], v
[1], vo
[2]))
153 # Align to custom coordinates
154 class Vertex_align_coord_list(Operator
):
155 bl_idname
= "vertex_align.coord_list_id"
157 bl_description
= "Align to custom coordinates"
160 def poll(cls
, context
):
161 obj
= context
.active_object
162 return (obj
and obj
.type == 'MESH' and context
.mode
== 'EDIT_MESH')
164 def execute(self
, context
):
166 ob_act
= context
.active_object
168 list_clear_(va_buf
.list_0
)
169 va_buf
.list_0
= [v
.index
for v
in me
.vertices
if v
.select
][:]
171 if len(va_buf
.list_0
) == 0:
172 self
.report({'INFO'}, "No vertices selected. Operation Cancelled")
176 elif len(va_buf
.list_0
) != 0:
177 bpy
.ops
.vertex_align
.coord_menu_id('INVOKE_DEFAULT')
184 # Align to custom coordinates menu
185 class Vertex_align_coord_menu(Operator
):
186 bl_idname
= "vertex_align.coord_menu_id"
187 bl_label
= "Tweak custom coordinates"
188 bl_description
= "Change the custom coordinates for aligning"
189 bl_options
= {'REGISTER', 'UNDO'}
191 def_axis_coord
: FloatVectorProperty(
193 description
="Enter the values of coordinates",
194 default
=(0.0, 0.0, 0.0),
195 min=-100.0, max=100.0,
200 use_axis_coord
= BoolVectorProperty(
202 description
="Choose Custom Coordinates axis",
203 default
=(False,) * 3,
209 def poll(cls
, context
):
210 obj
= context
.active_object
211 return (obj
and obj
.type == 'MESH')
213 def using_store(self
, context
):
214 scene
= context
.scene
215 return scene
.mesh_extra_tools
.vert_align_use_stored
217 def draw(self
, context
):
220 if self
.using_store(context
) and self
.is_not_undo
:
221 layout
.label(text
="Using Stored Coordinates", icon
="INFO")
223 row
= layout
.split(0.25)
224 row
.prop(self
, "use_axis_coord", index
=0, text
="X")
225 row
.prop(self
, "def_axis_coord", index
=0)
227 row
= layout
.split(0.25)
228 row
.prop(self
, "use_axis_coord", index
=1, text
="Y")
229 row
.prop(self
, "def_axis_coord", index
=1)
231 row
= layout
.split(0.25)
232 row
.prop(self
, "use_axis_coord", index
=2, text
="Z")
233 row
.prop(self
, "def_axis_coord", index
=2)
235 def invoke(self
, context
, event
):
236 self
.is_not_undo
= True
237 scene
= context
.scene
238 if self
.using_store(context
):
239 self
.def_axis_coord
= scene
.mesh_extra_tools
.vert_align_store_axis
241 return context
.window_manager
.invoke_props_dialog(self
, width
=200)
243 def execute(self
, context
):
244 self
.is_not_undo
= False
246 ob_act
= context
.active_object
249 for i
in va_buf
.list_0
:
250 v
= (me
.vertices
[i
].co
).copy()
251 tmp
= Vector((v
[0], v
[1], v
[2]))
253 if self
.use_axis_coord
[0] is True:
254 tmp
[0] = self
.def_axis_coord
[0]
255 if self
.use_axis_coord
[1] is True:
256 tmp
[1] = self
.def_axis_coord
[1]
257 if self
.use_axis_coord
[2] is True:
258 tmp
[2] = self
.def_axis_coord
[2]
259 me
.vertices
[i
].co
= tmp
269 Vertex_align_original
,
270 Vertex_align_coord_list
,
271 Vertex_align_coord_menu
,
277 bpy
.utils
.register_class(cls
)
282 bpy
.utils
.unregister_class(cls
)
285 if __name__
== "__main__":